diff options
author | Mike Frysinger <vapier@gentoo.org> | 2006-05-08 03:20:50 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2006-05-08 03:20:50 +0000 |
commit | 7031f62d9b750568b5e98bdb8c59c3c1a72e073d (patch) | |
tree | b8d037a539281e7f7592e3045fa59e445495f603 | |
parent | 15fe2e11d7886d04450cabc8b40f0d396b6b6d85 (diff) | |
download | busybox-w32-7031f62d9b750568b5e98bdb8c59c3c1a72e073d.tar.gz busybox-w32-7031f62d9b750568b5e98bdb8c59c3c1a72e073d.tar.bz2 busybox-w32-7031f62d9b750568b5e98bdb8c59c3c1a72e073d.zip |
add back in udhcp support
62 files changed, 5815 insertions, 0 deletions
diff --git a/include/applets.h b/include/applets.h index 3e833eb29..bbff772f0 100644 --- a/include/applets.h +++ b/include/applets.h | |||
@@ -95,6 +95,7 @@ USE_DPKG(APPLET(dpkg, dpkg, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | |||
95 | USE_DPKG_DEB(APPLET_ODDNAME(dpkg-deb, dpkg_deb, _BB_DIR_USR_BIN, _BB_SUID_NEVER, dpkg_deb)) | 95 | USE_DPKG_DEB(APPLET_ODDNAME(dpkg-deb, dpkg_deb, _BB_DIR_USR_BIN, _BB_SUID_NEVER, dpkg_deb)) |
96 | USE_DU(APPLET(du, du, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 96 | USE_DU(APPLET(du, du, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
97 | USE_DUMPKMAP(APPLET(dumpkmap, dumpkmap, _BB_DIR_BIN, _BB_SUID_NEVER)) | 97 | USE_DUMPKMAP(APPLET(dumpkmap, dumpkmap, _BB_DIR_BIN, _BB_SUID_NEVER)) |
98 | USE_DUMPLEASES(APPLET(dumpleases, dumpleases, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | ||
98 | USE_E2FSCK(APPLET(e2fsck, e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER)) | 99 | USE_E2FSCK(APPLET(e2fsck, e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER)) |
99 | USE_E2LABEL(APPLET_NOUSAGE(e2label, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER)) | 100 | USE_E2LABEL(APPLET_NOUSAGE(e2label, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER)) |
100 | USE_ECHO(APPLET(echo, echo, _BB_DIR_BIN, _BB_SUID_NEVER)) | 101 | USE_ECHO(APPLET(echo, echo, _BB_DIR_BIN, _BB_SUID_NEVER)) |
@@ -273,6 +274,8 @@ USE_TRACEROUTE(APPLET(traceroute, traceroute, _BB_DIR_USR_BIN, _BB_SUID_MAYBE)) | |||
273 | USE_TRUE(APPLET(true, true, _BB_DIR_BIN, _BB_SUID_NEVER)) | 274 | USE_TRUE(APPLET(true, true, _BB_DIR_BIN, _BB_SUID_NEVER)) |
274 | USE_TTY(APPLET(tty, tty, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 275 | USE_TTY(APPLET(tty, tty, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
275 | USE_TUNE2FS(APPLET(tune2fs, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER)) | 276 | USE_TUNE2FS(APPLET(tune2fs, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER)) |
277 | USE_UDHCPC(APPLET(udhcpc, udhcpc, _BB_DIR_SBIN, _BB_SUID_NEVER)) | ||
278 | USE_UDHCPD(APPLET(udhcpd, udhcpd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) | ||
276 | USE_UMOUNT(APPLET(umount, umount, _BB_DIR_BIN, _BB_SUID_NEVER)) | 279 | USE_UMOUNT(APPLET(umount, umount, _BB_DIR_BIN, _BB_SUID_NEVER)) |
277 | USE_UNAME(APPLET(uname, uname, _BB_DIR_BIN, _BB_SUID_NEVER)) | 280 | USE_UNAME(APPLET(uname, uname, _BB_DIR_BIN, _BB_SUID_NEVER)) |
278 | USE_UNCOMPRESS(APPLET(uncompress, uncompress, _BB_DIR_BIN, _BB_SUID_NEVER)) | 281 | USE_UNCOMPRESS(APPLET(uncompress, uncompress, _BB_DIR_BIN, _BB_SUID_NEVER)) |
diff --git a/networking/udhcp/AUTHORS b/networking/udhcp/AUTHORS new file mode 100644 index 000000000..f3f43364a --- /dev/null +++ b/networking/udhcp/AUTHORS | |||
@@ -0,0 +1,13 @@ | |||
1 | udhcp server/client package | ||
2 | ----------------------- | ||
3 | |||
4 | Russ Dill <Russ.Dill@asu.edu> | ||
5 | Matthew Ramsay <matthewr@moreton.com.au> | ||
6 | Chris Trew <christ@moreton.com.au> | ||
7 | |||
8 | Other Credits: | ||
9 | -------------- | ||
10 | Moreton Bay (http://www.moretonbay.com/) | ||
11 | Vladimir Oleynik <dzo@simtrea.ru> Size optimizations | ||
12 | |||
13 | |||
diff --git a/networking/udhcp/COPYING b/networking/udhcp/COPYING new file mode 100644 index 000000000..a43ea2126 --- /dev/null +++ b/networking/udhcp/COPYING | |||
@@ -0,0 +1,339 @@ | |||
1 | GNU GENERAL PUBLIC LICENSE | ||
2 | Version 2, June 1991 | ||
3 | |||
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. | ||
5 | 675 Mass Ave, Cambridge, MA 02139, USA | ||
6 | Everyone is permitted to copy and distribute verbatim copies | ||
7 | of this license document, but changing it is not allowed. | ||
8 | |||
9 | Preamble | ||
10 | |||
11 | The licenses for most software are designed to take away your | ||
12 | freedom to share and change it. By contrast, the GNU General Public | ||
13 | License is intended to guarantee your freedom to share and change free | ||
14 | software--to make sure the software is free for all its users. This | ||
15 | General Public License applies to most of the Free Software | ||
16 | Foundation's software and to any other program whose authors commit to | ||
17 | using it. (Some other Free Software Foundation software is covered by | ||
18 | the GNU Library General Public License instead.) You can apply it to | ||
19 | your programs, too. | ||
20 | |||
21 | When we speak of free software, we are referring to freedom, not | ||
22 | price. Our General Public Licenses are designed to make sure that you | ||
23 | have the freedom to distribute copies of free software (and charge for | ||
24 | this service if you wish), that you receive source code or can get it | ||
25 | if you want it, that you can change the software or use pieces of it | ||
26 | in new free programs; and that you know you can do these things. | ||
27 | |||
28 | To protect your rights, we need to make restrictions that forbid | ||
29 | anyone to deny you these rights or to ask you to surrender the rights. | ||
30 | These restrictions translate to certain responsibilities for you if you | ||
31 | distribute copies of the software, or if you modify it. | ||
32 | |||
33 | For example, if you distribute copies of such a program, whether | ||
34 | gratis or for a fee, you must give the recipients all the rights that | ||
35 | you have. You must make sure that they, too, receive or can get the | ||
36 | source code. And you must show them these terms so they know their | ||
37 | rights. | ||
38 | |||
39 | We protect your rights with two steps: (1) copyright the software, and | ||
40 | (2) offer you this license which gives you legal permission to copy, | ||
41 | distribute and/or modify the software. | ||
42 | |||
43 | Also, for each author's protection and ours, we want to make certain | ||
44 | that everyone understands that there is no warranty for this free | ||
45 | software. If the software is modified by someone else and passed on, we | ||
46 | want its recipients to know that what they have is not the original, so | ||
47 | that any problems introduced by others will not reflect on the original | ||
48 | authors' reputations. | ||
49 | |||
50 | Finally, any free program is threatened constantly by software | ||
51 | patents. We wish to avoid the danger that redistributors of a free | ||
52 | program will individually obtain patent licenses, in effect making the | ||
53 | program proprietary. To prevent this, we have made it clear that any | ||
54 | patent must be licensed for everyone's free use or not licensed at all. | ||
55 | |||
56 | The precise terms and conditions for copying, distribution and | ||
57 | modification follow. | ||
58 | |||
59 | GNU GENERAL PUBLIC LICENSE | ||
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||
61 | |||
62 | 0. This License applies to any program or other work which contains | ||
63 | a notice placed by the copyright holder saying it may be distributed | ||
64 | under the terms of this General Public License. The "Program", below, | ||
65 | refers to any such program or work, and a "work based on the Program" | ||
66 | means either the Program or any derivative work under copyright law: | ||
67 | that is to say, a work containing the Program or a portion of it, | ||
68 | either verbatim or with modifications and/or translated into another | ||
69 | language. (Hereinafter, translation is included without limitation in | ||
70 | the term "modification".) Each licensee is addressed as "you". | ||
71 | |||
72 | Activities other than copying, distribution and modification are not | ||
73 | covered by this License; they are outside its scope. The act of | ||
74 | running the Program is not restricted, and the output from the Program | ||
75 | is covered only if its contents constitute a work based on the | ||
76 | Program (independent of having been made by running the Program). | ||
77 | Whether that is true depends on what the Program does. | ||
78 | |||
79 | 1. You may copy and distribute verbatim copies of the Program's | ||
80 | source code as you receive it, in any medium, provided that you | ||
81 | conspicuously and appropriately publish on each copy an appropriate | ||
82 | copyright notice and disclaimer of warranty; keep intact all the | ||
83 | notices that refer to this License and to the absence of any warranty; | ||
84 | and give any other recipients of the Program a copy of this License | ||
85 | along with the Program. | ||
86 | |||
87 | You may charge a fee for the physical act of transferring a copy, and | ||
88 | you may at your option offer warranty protection in exchange for a fee. | ||
89 | |||
90 | 2. You may modify your copy or copies of the Program or any portion | ||
91 | of it, thus forming a work based on the Program, and copy and | ||
92 | distribute such modifications or work under the terms of Section 1 | ||
93 | above, provided that you also meet all of these conditions: | ||
94 | |||
95 | a) You must cause the modified files to carry prominent notices | ||
96 | stating that you changed the files and the date of any change. | ||
97 | |||
98 | b) You must cause any work that you distribute or publish, that in | ||
99 | whole or in part contains or is derived from the Program or any | ||
100 | part thereof, to be licensed as a whole at no charge to all third | ||
101 | parties under the terms of this License. | ||
102 | |||
103 | c) If the modified program normally reads commands interactively | ||
104 | when run, you must cause it, when started running for such | ||
105 | interactive use in the most ordinary way, to print or display an | ||
106 | announcement including an appropriate copyright notice and a | ||
107 | notice that there is no warranty (or else, saying that you provide | ||
108 | a warranty) and that users may redistribute the program under | ||
109 | these conditions, and telling the user how to view a copy of this | ||
110 | License. (Exception: if the Program itself is interactive but | ||
111 | does not normally print such an announcement, your work based on | ||
112 | the Program is not required to print an announcement.) | ||
113 | |||
114 | These requirements apply to the modified work as a whole. If | ||
115 | identifiable sections of that work are not derived from the Program, | ||
116 | and can be reasonably considered independent and separate works in | ||
117 | themselves, then this License, and its terms, do not apply to those | ||
118 | sections when you distribute them as separate works. But when you | ||
119 | distribute the same sections as part of a whole which is a work based | ||
120 | on the Program, the distribution of the whole must be on the terms of | ||
121 | this License, whose permissions for other licensees extend to the | ||
122 | entire whole, and thus to each and every part regardless of who wrote it. | ||
123 | |||
124 | Thus, it is not the intent of this section to claim rights or contest | ||
125 | your rights to work written entirely by you; rather, the intent is to | ||
126 | exercise the right to control the distribution of derivative or | ||
127 | collective works based on the Program. | ||
128 | |||
129 | In addition, mere aggregation of another work not based on the Program | ||
130 | with the Program (or with a work based on the Program) on a volume of | ||
131 | a storage or distribution medium does not bring the other work under | ||
132 | the scope of this License. | ||
133 | |||
134 | 3. You may copy and distribute the Program (or a work based on it, | ||
135 | under Section 2) in object code or executable form under the terms of | ||
136 | Sections 1 and 2 above provided that you also do one of the following: | ||
137 | |||
138 | a) Accompany it with the complete corresponding machine-readable | ||
139 | source code, which must be distributed under the terms of Sections | ||
140 | 1 and 2 above on a medium customarily used for software interchange; or, | ||
141 | |||
142 | b) Accompany it with a written offer, valid for at least three | ||
143 | years, to give any third party, for a charge no more than your | ||
144 | cost of physically performing source distribution, a complete | ||
145 | machine-readable copy of the corresponding source code, to be | ||
146 | distributed under the terms of Sections 1 and 2 above on a medium | ||
147 | customarily used for software interchange; or, | ||
148 | |||
149 | c) Accompany it with the information you received as to the offer | ||
150 | to distribute corresponding source code. (This alternative is | ||
151 | allowed only for noncommercial distribution and only if you | ||
152 | received the program in object code or executable form with such | ||
153 | an offer, in accord with Subsection b above.) | ||
154 | |||
155 | The source code for a work means the preferred form of the work for | ||
156 | making modifications to it. For an executable work, complete source | ||
157 | code means all the source code for all modules it contains, plus any | ||
158 | associated interface definition files, plus the scripts used to | ||
159 | control compilation and installation of the executable. However, as a | ||
160 | special exception, the source code distributed need not include | ||
161 | anything that is normally distributed (in either source or binary | ||
162 | form) with the major components (compiler, kernel, and so on) of the | ||
163 | operating system on which the executable runs, unless that component | ||
164 | itself accompanies the executable. | ||
165 | |||
166 | If distribution of executable or object code is made by offering | ||
167 | access to copy from a designated place, then offering equivalent | ||
168 | access to copy the source code from the same place counts as | ||
169 | distribution of the source code, even though third parties are not | ||
170 | compelled to copy the source along with the object code. | ||
171 | |||
172 | 4. You may not copy, modify, sublicense, or distribute the Program | ||
173 | except as expressly provided under this License. Any attempt | ||
174 | otherwise to copy, modify, sublicense or distribute the Program is | ||
175 | void, and will automatically terminate your rights under this License. | ||
176 | However, parties who have received copies, or rights, from you under | ||
177 | this License will not have their licenses terminated so long as such | ||
178 | parties remain in full compliance. | ||
179 | |||
180 | 5. You are not required to accept this License, since you have not | ||
181 | signed it. However, nothing else grants you permission to modify or | ||
182 | distribute the Program or its derivative works. These actions are | ||
183 | prohibited by law if you do not accept this License. Therefore, by | ||
184 | modifying or distributing the Program (or any work based on the | ||
185 | Program), you indicate your acceptance of this License to do so, and | ||
186 | all its terms and conditions for copying, distributing or modifying | ||
187 | the Program or works based on it. | ||
188 | |||
189 | 6. Each time you redistribute the Program (or any work based on the | ||
190 | Program), the recipient automatically receives a license from the | ||
191 | original licensor to copy, distribute or modify the Program subject to | ||
192 | these terms and conditions. You may not impose any further | ||
193 | restrictions on the recipients' exercise of the rights granted herein. | ||
194 | You are not responsible for enforcing compliance by third parties to | ||
195 | this License. | ||
196 | |||
197 | 7. If, as a consequence of a court judgment or allegation of patent | ||
198 | infringement or for any other reason (not limited to patent issues), | ||
199 | conditions are imposed on you (whether by court order, agreement or | ||
200 | otherwise) that contradict the conditions of this License, they do not | ||
201 | excuse you from the conditions of this License. If you cannot | ||
202 | distribute so as to satisfy simultaneously your obligations under this | ||
203 | License and any other pertinent obligations, then as a consequence you | ||
204 | may not distribute the Program at all. For example, if a patent | ||
205 | license would not permit royalty-free redistribution of the Program by | ||
206 | all those who receive copies directly or indirectly through you, then | ||
207 | the only way you could satisfy both it and this License would be to | ||
208 | refrain entirely from distribution of the Program. | ||
209 | |||
210 | If any portion of this section is held invalid or unenforceable under | ||
211 | any particular circumstance, the balance of the section is intended to | ||
212 | apply and the section as a whole is intended to apply in other | ||
213 | circumstances. | ||
214 | |||
215 | It is not the purpose of this section to induce you to infringe any | ||
216 | patents or other property right claims or to contest validity of any | ||
217 | such claims; this section has the sole purpose of protecting the | ||
218 | integrity of the free software distribution system, which is | ||
219 | implemented by public license practices. Many people have made | ||
220 | generous contributions to the wide range of software distributed | ||
221 | through that system in reliance on consistent application of that | ||
222 | system; it is up to the author/donor to decide if he or she is willing | ||
223 | to distribute software through any other system and a licensee cannot | ||
224 | impose that choice. | ||
225 | |||
226 | This section is intended to make thoroughly clear what is believed to | ||
227 | be a consequence of the rest of this License. | ||
228 | |||
229 | 8. If the distribution and/or use of the Program is restricted in | ||
230 | certain countries either by patents or by copyrighted interfaces, the | ||
231 | original copyright holder who places the Program under this License | ||
232 | may add an explicit geographical distribution limitation excluding | ||
233 | those countries, so that distribution is permitted only in or among | ||
234 | countries not thus excluded. In such case, this License incorporates | ||
235 | the limitation as if written in the body of this License. | ||
236 | |||
237 | 9. The Free Software Foundation may publish revised and/or new versions | ||
238 | of the General Public License from time to time. Such new versions will | ||
239 | be similar in spirit to the present version, but may differ in detail to | ||
240 | address new problems or concerns. | ||
241 | |||
242 | Each version is given a distinguishing version number. If the Program | ||
243 | specifies a version number of this License which applies to it and "any | ||
244 | later version", you have the option of following the terms and conditions | ||
245 | either of that version or of any later version published by the Free | ||
246 | Software Foundation. If the Program does not specify a version number of | ||
247 | this License, you may choose any version ever published by the Free Software | ||
248 | Foundation. | ||
249 | |||
250 | 10. If you wish to incorporate parts of the Program into other free | ||
251 | programs whose distribution conditions are different, write to the author | ||
252 | to ask for permission. For software which is copyrighted by the Free | ||
253 | Software Foundation, write to the Free Software Foundation; we sometimes | ||
254 | make exceptions for this. Our decision will be guided by the two goals | ||
255 | of preserving the free status of all derivatives of our free software and | ||
256 | of promoting the sharing and reuse of software generally. | ||
257 | |||
258 | NO WARRANTY | ||
259 | |||
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | ||
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | ||
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | ||
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | ||
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | ||
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | ||
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | ||
268 | REPAIR OR CORRECTION. | ||
269 | |||
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | ||
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | ||
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | ||
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | ||
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | ||
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | ||
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | ||
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | ||
278 | POSSIBILITY OF SUCH DAMAGES. | ||
279 | |||
280 | END OF TERMS AND CONDITIONS | ||
281 | |||
282 | Appendix: How to Apply These Terms to Your New Programs | ||
283 | |||
284 | If you develop a new program, and you want it to be of the greatest | ||
285 | possible use to the public, the best way to achieve this is to make it | ||
286 | free software which everyone can redistribute and change under these terms. | ||
287 | |||
288 | To do so, attach the following notices to the program. It is safest | ||
289 | to attach them to the start of each source file to most effectively | ||
290 | convey the exclusion of warranty; and each file should have at least | ||
291 | the "copyright" line and a pointer to where the full notice is found. | ||
292 | |||
293 | <one line to give the program's name and a brief idea of what it does.> | ||
294 | Copyright (C) 19yy <name of author> | ||
295 | |||
296 | This program is free software; you can redistribute it and/or modify | ||
297 | it under the terms of the GNU General Public License as published by | ||
298 | the Free Software Foundation; either version 2 of the License, or | ||
299 | (at your option) any later version. | ||
300 | |||
301 | This program is distributed in the hope that it will be useful, | ||
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
304 | GNU General Public License for more details. | ||
305 | |||
306 | You should have received a copy of the GNU General Public License | ||
307 | along with this program; if not, write to the Free Software | ||
308 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
309 | |||
310 | Also add information on how to contact you by electronic and paper mail. | ||
311 | |||
312 | If the program is interactive, make it output a short notice like this | ||
313 | when it starts in an interactive mode: | ||
314 | |||
315 | Gnomovision version 69, Copyright (C) 19yy name of author | ||
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | ||
317 | This is free software, and you are welcome to redistribute it | ||
318 | under certain conditions; type `show c' for details. | ||
319 | |||
320 | The hypothetical commands `show w' and `show c' should show the appropriate | ||
321 | parts of the General Public License. Of course, the commands you use may | ||
322 | be called something other than `show w' and `show c'; they could even be | ||
323 | mouse-clicks or menu items--whatever suits your program. | ||
324 | |||
325 | You should also get your employer (if you work as a programmer) or your | ||
326 | school, if any, to sign a "copyright disclaimer" for the program, if | ||
327 | necessary. Here is a sample; alter the names: | ||
328 | |||
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program | ||
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. | ||
331 | |||
332 | <signature of Ty Coon>, 1 April 1989 | ||
333 | Ty Coon, President of Vice | ||
334 | |||
335 | This General Public License does not permit incorporating your program into | ||
336 | proprietary programs. If your program is a subroutine library, you may | ||
337 | consider it more useful to permit linking proprietary applications with the | ||
338 | library. If this is what you want to do, use the GNU Library General | ||
339 | Public License instead of this License. | ||
diff --git a/networking/udhcp/ChangeLog b/networking/udhcp/ChangeLog new file mode 100644 index 000000000..bf2982f4b --- /dev/null +++ b/networking/udhcp/ChangeLog | |||
@@ -0,0 +1,260 @@ | |||
1 | 0.9.9 (pending) | ||
2 | + Various other size optimizations (Vladimir) | ||
3 | + Change strerror(errno) to %m (Vladimir N. Oleynik <dzo@simtreas.ru>) | ||
4 | + Fixed a little endian problem in mton (Bastian Blank <waldi@debian.org>) | ||
5 | + Fixed a arpping alignment problem (Rui He <rhe@3eti.com>) | ||
6 | + Added sanity check for max_leases (udhcp bug #1285) (me) | ||
7 | + Finally got rid of the trailing space in enviromental vars (me) | ||
8 | + added an new enviromental variable: $mask. It contains the number | ||
9 | of subnet bits for tools like ip route that require it. | ||
10 | (Bastian Blank <waldi@debian.org>, me) | ||
11 | |||
12 | 0.9.8 (021031) | ||
13 | + split up README files (me) | ||
14 | + use /dev/urandom to seed xid's (instead of time(0)) (me) | ||
15 | + fixed renew behavior (me) | ||
16 | + udhcp now fits nicely into busybox | ||
17 | (Glenn McGrath <bug1@iinet.net.au> as well as myself) | ||
18 | + updated client manpage (me) | ||
19 | + both client and server now use sockets for signal handling, | ||
20 | hopefully, this will be the last needed change in signal | ||
21 | handling, I'm fairly certain all the possible races are now | ||
22 | closed. (me) | ||
23 | + The server now restarts the auto_time timer when it receives | ||
24 | a SIGUSR1 (write out config file). (me) | ||
25 | + Improve signal handling (David Poole) | ||
26 | + Fix to config file parsing (Matt Kraai) | ||
27 | + Fix load lease logic (me) | ||
28 | + Fix clear_lease logic (me) | ||
29 | + -h is now an alias for -H (udhcp bug #1253) | ||
30 | + Shorter timeout on not receiving offers (me) | ||
31 | + Improved signal behavior by client (me) | ||
32 | + Would never assign end address (Keith Smith <keith@ksmith.com>) | ||
33 | + Was improperly reporting yiaddr as siaddr (ben-udhcp@bdlow.net) | ||
34 | udhcp bug#1256 | ||
35 | + Fixed reading of client id (David Poole <davep@portsmith.com>) | ||
36 | + change sys_errlist[] to strerror() as it aparently doesn't exist | ||
37 | (Erik Andersen <andersee@codepoet.org>) | ||
38 | + fixed get_raw_packet so it returns -2 on non fatal errors | ||
39 | (Ted Lemon <Ted.Lemon@nominum.com>) | ||
40 | + Improved (hopefully) NAKing behavior (me) | ||
41 | + Added -b option (Jouni Malinen) | ||
42 | + Compute checksums correctly on big endian hosts | ||
43 | (Jouni Malinen <jkmaline@cc.hut.fi>) | ||
44 | |||
45 | 0.9.7 (020526) | ||
46 | + Use add_lease in read_leases, sanitizes leases more, and clears out exprired | ||
47 | ones if there is no more room (me) | ||
48 | + Moved udhcpd.leases to /var/lib/misc/udhcpd.leases (Debian bug #147747) | ||
49 | + Change (obsolete) AF_INET in arping.c to PF_PACKET (Debian bug #127049) | ||
50 | + Added script hook for DHCPNAK (nak), as well as providing the message option | ||
51 | (me) | ||
52 | + Generate the paramaters request list by seeing what options in options.c are | ||
53 | ored with OPTION_REQ in options.c | ||
54 | + Fix dhcp renew forgetfullness on client (bug #1230) | ||
55 | + Fix dhcp release bug on client (bug #1231) | ||
56 | + Set option request list for DHCP renew (bug #1233) | ||
57 | + Set BOOTREQUEST/REPLY properly | ||
58 | + Change client-identifier field to popularly expected behavior (me) | ||
59 | + Only reopen port on errors (me) | ||
60 | + Change fork/close/setsid structures to daemon() (me) | ||
61 | + Allow user to specify udhcpd config file at run time (Steven, me) | ||
62 | + Write pidfile after changing it (Steven CTR Carr <Steven.CTR.Carr@tc.faa.gov>) | ||
63 | + Added env var docs to udhcpc man page (Matt) | ||
64 | + Standardized lowercase udhcp in documentation (me) | ||
65 | + Accept packets without a UDP checksum (me) | ||
66 | + Accept packets with extra garbage (me) | ||
67 | + Better error handling in files.c (me) | ||
68 | + Combined read_interface function to reduce COMBINED_BINARY size (me) | ||
69 | + Drop calc_length(), some servers choke on smaller packets (me) | ||
70 | + Try to clean some fat out (me) | ||
71 | |||
72 | 0.9.6 (011001) | ||
73 | + Added bootp paramaters to server (me) | ||
74 | + Added bootp paramaters to client (me) | ||
75 | + Added vendor id to client (me) | ||
76 | + Better pidfile handling in client and server (me) | ||
77 | + Added man pages (Matt Kraai <kraai@alumni.carnegiemellon.edu>) | ||
78 | |||
79 | 0.9.5 (010914) | ||
80 | + Fixed $HOME and $PATH env passing (me) | ||
81 | + Fixed client to only listen for raw packets on correct interface (me) | ||
82 | + added --quit,-q option to quit after a lease is obtained (me) | ||
83 | + Fixed 100% CPU utilization by client when interface is down (me) | ||
84 | |||
85 | 0.9.4 (010827) | ||
86 | + Force broadcast to broken clients that request unicast (ie, MSFT 98) | ||
87 | + Make install rules (Adam J. Richter <adam@yggdrasil.com>) | ||
88 | + One scripts, instead of many (Adam) | ||
89 | + Removed script paramater info files (env vars only) (Adam) | ||
90 | + Controlling of forking behavior in client (Adam) | ||
91 | + General script.c/dhcpc.c cleanups (Adam) | ||
92 | |||
93 | 0.9.3 (010820) | ||
94 | + Increased debugging verbosity (me) | ||
95 | + Cut trailing whitespace when reading config file (me) | ||
96 | + added hostname option to client (me) | ||
97 | + fixed a strncpy bug in script.c (me) | ||
98 | + fixed a leaky socket in dhcpc.c (me) | ||
99 | + fixed a leaky socket in dhcpd.c (me) | ||
100 | |||
101 | 0.9.2 (010810) | ||
102 | + Added raw sockets to client (me) | ||
103 | + alignment fixes (Mark Huang) | ||
104 | + compiler warning fixes (Mark Huang) | ||
105 | + client now sends parameter list (Mark Huang/me) | ||
106 | + added ipttl option | ||
107 | + Does now not request broadcast packets | ||
108 | |||
109 | 0.9.1 (010806) | ||
110 | + Added udhcpc client | ||
111 | + reorganized functions/files | ||
112 | + listening socket now only binds to one interface | ||
113 | |||
114 | 0.9.0 (010720) Major rewrite, current changes, goals: | ||
115 | + should not segfault on bogus packets. | ||
116 | + Options can be read from sname and file fields. | ||
117 | + supports all DHCP messages (release, decline, inform). | ||
118 | + IP block is now specified by a range of IP's. | ||
119 | + Leases file now contains lease time (relative, or absolute). | ||
120 | + Just about any DHCP option is now supported. | ||
121 | + DNS entries are no longer read from resolv.conf | ||
122 | + Lease file can be written periodically when the process receives a SIGUSR1 | ||
123 | + arpping should be supported on all arches. | ||
124 | + support for DHCP relays. | ||
125 | + DHCP messages can be unicast if the client requests it. | ||
126 | + many, many, many other things. | ||
127 | |||
128 | 0.8.29 (000323) | ||
129 | + stable(?) release | ||
130 | |||
131 | |||
132 | 0.8.28 (000323) | ||
133 | + removed alarm as it was causing server to go down | ||
134 | + removed debugging | ||
135 | + break down dhcpd.c into manageable files | ||
136 | |||
137 | |||
138 | 0.8.27 (000221) | ||
139 | + OFFER also sends gateway/subnet (for picky dhcp clients) | ||
140 | + multiple DNS now handled from resolv.conf if available | ||
141 | + multiple WINS (from dhcpd.conf) | ||
142 | |||
143 | 0.8.25 (000120) | ||
144 | + now compiles *and* runs on a generic linux system | ||
145 | tested with a windows 98 client and the sample config | ||
146 | files in the samples directory. | ||
147 | |||
148 | 0.8.24 (000117) | ||
149 | + makeiplist tool has basic functionality in place | ||
150 | + new sample config files | ||
151 | + route add -host 255.255.255.255 dev eth0 added for generic linux | ||
152 | |||
153 | 0.8.23 (000117) | ||
154 | + NETtel specific fix for ignoring dhcp requests on 2nd interface | ||
155 | |||
156 | 0.8.22 (000113) | ||
157 | + minor changes to compile under a generic linux system | ||
158 | + minor config file location changes for a generic linux system | ||
159 | + makeiplist fixes.. still incomplete.. but etting closer | ||
160 | |||
161 | 0.8.21 (000113) | ||
162 | + now sends the correct server ip instead of hardcoded value | ||
163 | + minor debugging fixes for critical messages | ||
164 | |||
165 | 0.8.20 (000106) | ||
166 | + cut out dhcp server checking.. this was causing dialout ppp | ||
167 | sessions with idle time set to never time out. | ||
168 | + also removed the 10 second pause before launching.. as this | ||
169 | was originally to stop it replying to a dhcp client | ||
170 | on a NETtel which was really a bad way to do it in the | ||
171 | first place :-) | ||
172 | |||
173 | 0.8.19 (000104) | ||
174 | + fixes for route add -host on a machine that needs to run both | ||
175 | a DHCP client and server (dual eth box) | ||
176 | |||
177 | 0.8.18 (991220) | ||
178 | |||
179 | + Race conditions fixed by disabling alarm whilst the server is busy | ||
180 | + Fixed continous clearing of the offered array so that it is only cleared | ||
181 | when it is dirty - (could change the position of when dirty is set) | ||
182 | |||
183 | 0.8.17 (991212) | ||
184 | |||
185 | - has problems clearing out the offered array | ||
186 | |||
187 | 0.8.16 (991203) | ||
188 | + Non blocking error is changes to informational as it is not really | ||
189 | an error | ||
190 | |||
191 | 0.8.15 (991129) | ||
192 | + Servs the dns field 3 times (Nettel only) so that windows servers | ||
193 | dont time out whilst nettel is booting | ||
194 | |||
195 | 0.8.14 (991126) | ||
196 | + added owner check for the offered array so clean out time may be | ||
197 | increased | ||
198 | + added new func to print out chadder/MAC | ||
199 | |||
200 | 0.8.13 (991125) | ||
201 | + added win95 support (w95 changed xid halfway through conversation) | ||
202 | + had to change the offered array to use hardware addresses instead of xid | ||
203 | + fixed re offered bug | ||
204 | + added more debugging | ||
205 | |||
206 | 0.8.12 (991111) | ||
207 | + debugging was real bad.. cleaned up a bit.. needs overhaul | ||
208 | |||
209 | |||
210 | 0.8.11 (991110) | ||
211 | + fixed up offeredAddr array to actually be used now!! offeredAddr is | ||
212 | used to see if another simultaneous connecting client was offered | ||
213 | an address that we are about to offer another client (multiple | ||
214 | client bug) | ||
215 | + removed re_offered variable as it breaks multiple client support | ||
216 | + added lease time to ACK -- doesn't work if in OFFER | ||
217 | + decreased internal array clear delay to 60 seconds | ||
218 | + minor findAddr bug (returning -1 instead of 0) | ||
219 | + if clients xid already in offeredAddr offer the same addr and don't add a | ||
220 | new addr to offered (caused by a client issuing multiple DISCOVERs) | ||
221 | |||
222 | 0.8.10 (991105) | ||
223 | + \n bug in arpping | ||
224 | + minor debugging changes (removed printfs etc) | ||
225 | + started browseiplist (not finished) | ||
226 | |||
227 | 0.8.9 (19991105) | ||
228 | + fixed options array size bug (options were cut off) | ||
229 | |||
230 | 0.8.8 (19991105) | ||
231 | + ignores requests from dhcpcd on the same machine | ||
232 | |||
233 | 0.8.7 (19991104) | ||
234 | + don't die if we can't bind to search for existing DHCP server | ||
235 | + slightly more verbose syslogging | ||
236 | |||
237 | 0.8.6 (19991103) | ||
238 | + added makeiplist (not finished -- core dumps) | ||
239 | + minor debug changes | ||
240 | |||
241 | 0.8.5 (19991029) | ||
242 | + exits if another DHCP server is already on the network | ||
243 | + added Linux Makefile | ||
244 | |||
245 | 0.8.4 (19991026) | ||
246 | + minor bug fix in findaddr preventing an addr being found | ||
247 | |||
248 | 0.8.3 (19991025) | ||
249 | + fixed up debugging | ||
250 | + minor hwaddr issues | ||
251 | |||
252 | 0.8.2 (19991022) | ||
253 | + free leases (new arpping code from dhcpcd) | ||
254 | + fixed bug where crashes if no leases/iplist file | ||
255 | + syslogging and debugging switch | ||
256 | + serve DNS from resolv.conf | ||
257 | + fixed bug where new lease added if same mac offered | ||
258 | + now checks the ip is free b4 offering | ||
259 | + now supports wins server | ||
260 | |||
diff --git a/networking/udhcp/Config.in b/networking/udhcp/Config.in new file mode 100644 index 000000000..fc07a9b7f --- /dev/null +++ b/networking/udhcp/Config.in | |||
@@ -0,0 +1,62 @@ | |||
1 | # | ||
2 | # For a description of the syntax of this configuration file, | ||
3 | # see scripts/kbuild/config-language.txt. | ||
4 | # | ||
5 | |||
6 | menu "udhcp Server/Client" | ||
7 | |||
8 | config CONFIG_UDHCPD | ||
9 | bool "udhcp Server (udhcpd)" | ||
10 | default n | ||
11 | help | ||
12 | uDHCPd is a DHCP server geared primarily toward embedded systems, | ||
13 | while striving to be fully functional and RFC compliant. | ||
14 | |||
15 | See http://udhcp.busybox.net for further details. | ||
16 | |||
17 | config CONFIG_UDHCPC | ||
18 | bool "udhcp Client (udhcpc)" | ||
19 | default n | ||
20 | help | ||
21 | uDHCPc is a DHCP client geared primarily toward embedded systems, | ||
22 | while striving to be fully functional and RFC compliant. | ||
23 | |||
24 | The udhcp client negotiates a lease with the DHCP server and | ||
25 | notifies a set of scripts when a lease is obtained or lost. | ||
26 | |||
27 | See http://udhcp.busybox.net for further details. | ||
28 | |||
29 | config CONFIG_DUMPLEASES | ||
30 | bool "Lease display utility (dumpleases)" | ||
31 | default n | ||
32 | depends on CONFIG_UDHCPD | ||
33 | help | ||
34 | dumpleases displays the leases written out by the udhcpd server. | ||
35 | Lease times are stored in the file by time remaining in lease, or | ||
36 | by the absolute time that it expires in seconds from epoch. | ||
37 | |||
38 | See http://udhcp.busybox.net for further details. | ||
39 | |||
40 | config CONFIG_FEATURE_UDHCP_SYSLOG | ||
41 | bool " Log udhcp messages to syslog (instead of stdout)" | ||
42 | default n | ||
43 | depends on CONFIG_UDHCPD || CONFIG_UDHCPC | ||
44 | help | ||
45 | If selected, udhcpd will log all its messages to syslog, otherwise, | ||
46 | it will attempt to log them to stdout. | ||
47 | |||
48 | See http://udhcp.busybox.net for further details. | ||
49 | |||
50 | config CONFIG_FEATURE_UDHCP_DEBUG | ||
51 | bool " Compile udhcp with noisy debugging messages" | ||
52 | default n | ||
53 | depends on CONFIG_UDHCPD || CONFIG_UDHCPC | ||
54 | help | ||
55 | If selected, udhcpd will output extra debugging output. If using | ||
56 | this option, compile uDHCP with "-g", and do not fork the daemon to | ||
57 | the background. | ||
58 | |||
59 | See http://udhcp.busybox.net for further details. | ||
60 | |||
61 | endmenu | ||
62 | |||
diff --git a/networking/udhcp/Makefile b/networking/udhcp/Makefile new file mode 100644 index 000000000..469ac3dc1 --- /dev/null +++ b/networking/udhcp/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | ifneq ($(wildcard ../../networking/Config.in),) | ||
2 | include Makefile.busybox | ||
3 | else | ||
4 | include Makefile.udhcp | ||
5 | endif | ||
diff --git a/networking/udhcp/Makefile.busybox b/networking/udhcp/Makefile.busybox new file mode 100644 index 000000000..7c027edc0 --- /dev/null +++ b/networking/udhcp/Makefile.busybox | |||
@@ -0,0 +1,36 @@ | |||
1 | # Makefile for busybox | ||
2 | # | ||
3 | # Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published by | ||
7 | # the Free Software Foundation; either version 2 of the License, or | ||
8 | # (at your option) any later version. | ||
9 | # | ||
10 | # This program is distributed in the hope that it will be useful, | ||
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | # General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with this program; if not, write to the Free Software | ||
17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | # | ||
19 | |||
20 | ifndef top_srcdir | ||
21 | top_srcdir=../.. | ||
22 | endif | ||
23 | ifndef top_builddir | ||
24 | top_builddir=../.. | ||
25 | endif | ||
26 | srcdir=$(top_srcdir)/networking/udhcp | ||
27 | UDHCP_DIR:=./ | ||
28 | include $(top_builddir)/Rules.mak | ||
29 | include $(top_builddir)/.config | ||
30 | include Makefile.in | ||
31 | all: $(libraries-y) | ||
32 | -include $(top_builddir)/.depend | ||
33 | |||
34 | clean: | ||
35 | rm -f *.o *.a $(AR_TARGET) | ||
36 | |||
diff --git a/networking/udhcp/Makefile.in b/networking/udhcp/Makefile.in new file mode 100644 index 000000000..df32247c6 --- /dev/null +++ b/networking/udhcp/Makefile.in | |||
@@ -0,0 +1,53 @@ | |||
1 | # Makefile for busybox | ||
2 | # | ||
3 | # Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> | ||
4 | # | ||
5 | # Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | ||
6 | # | ||
7 | |||
8 | UDHCP_AR:=udhcp.a | ||
9 | ifndef $(UDHCP_DIR) | ||
10 | UDHCP_DIR:=$(top_builddir)/networking/udhcp/ | ||
11 | endif | ||
12 | srcdir=$(top_srcdir)/networking/udhcp | ||
13 | |||
14 | #ok, so I forgot how to do an or, but this is a quick and dirty hack | ||
15 | ifeq ($(strip $(CONFIG_UDHCPC)),y) | ||
16 | CONFIG_UDHCP_SHARED=y | ||
17 | else | ||
18 | ifeq ($(strip $(CONFIG_UDHCPD)),y) | ||
19 | CONFIG_UDHCP_SHARED=y | ||
20 | else | ||
21 | CONFIG_UDHCP_SHARED=n | ||
22 | endif | ||
23 | endif | ||
24 | |||
25 | UDHCP-y:= | ||
26 | UDHCP-$(CONFIG_UDHCP_SHARED) += common.c options.c packet.c pidfile.c \ | ||
27 | signalpipe.c socket.c | ||
28 | UDHCP-$(CONFIG_UDHCPC) += dhcpc.c clientpacket.c clientsocket.c \ | ||
29 | script.c | ||
30 | UDHCP-$(CONFIG_UDHCPD) += dhcpd.c arpping.c files.c leases.c \ | ||
31 | serverpacket.c static_leases.c | ||
32 | UDHCP-$(CONFIG_DUMPLEASES) += dumpleases.c | ||
33 | UDHCP_OBJS:=$(patsubst %.c,$(UDHCP_DIR)%.o, $(UDHCP-y)) | ||
34 | |||
35 | ifneq ($(strip $(UDHCP-y)),) | ||
36 | libraries-y+=$(UDHCP_DIR)$(UDHCP_AR) | ||
37 | endif | ||
38 | |||
39 | UDHCP-y:=$(patsubst %,$(srcdir)/%,$(UDHCP-y)) | ||
40 | UDHCP-a:=$(wildcard $(srcdir)/*.c) | ||
41 | APPLET_SRC-y+=$(UDHCP-y) | ||
42 | APPLET_SRC-a+=$(UDHCP-a) | ||
43 | |||
44 | UDHCP_INCLUDES:=$(srcdir) | ||
45 | |||
46 | APPLETS_DEFINE-y+=-DIN_BUSYBOX -I$(UDHCP_INCLUDES) | ||
47 | APPLETS_DEFINE-a+=-DIN_BUSYBOX -I$(UDHCP_INCLUDES) | ||
48 | |||
49 | $(UDHCP_DIR)$(UDHCP_AR): $(UDHCP_OBJS) | ||
50 | $(do_ar) | ||
51 | |||
52 | $(UDHCP_OBJS): $(UDHCP_DIR)%.o : $(srcdir)/%.c | ||
53 | $(compile.c) -DIN_BUSYBOX | ||
diff --git a/networking/udhcp/Makefile.udhcp b/networking/udhcp/Makefile.udhcp new file mode 100644 index 000000000..1ba31c11c --- /dev/null +++ b/networking/udhcp/Makefile.udhcp | |||
@@ -0,0 +1,110 @@ | |||
1 | # udhcp makefile | ||
2 | |||
3 | DESTDIR = | ||
4 | prefix = /usr | ||
5 | SBINDIR = /sbin | ||
6 | USRSBINDIR = $(DESTDIR)$(prefix)/sbin | ||
7 | USRBINDIR = $(DESTDIR)$(prefix)/bin | ||
8 | USRSHAREDIR = $(DESTDIR)$(prefix)/share | ||
9 | |||
10 | # Uncomment this to get a shared binary. Call as udhcpd for the server, | ||
11 | # and udhcpc for the client | ||
12 | #COMBINED_BINARY=1 | ||
13 | |||
14 | # Uncomment this for extra output and to compile with debugging symbols | ||
15 | #UDHCP_DEBUG=1 | ||
16 | |||
17 | # Uncomment this to output messages to syslog, otherwise, messages go to stdout | ||
18 | #UDHCP_SYSLOG=1 | ||
19 | |||
20 | # Set to the prefix of your cross-compiler | ||
21 | #CROSS_COMPILE=arm-uclibc- | ||
22 | |||
23 | |||
24 | #---------------------------------------------------# | ||
25 | # You should not have to change anything below here # | ||
26 | #---------------------------------------------------# | ||
27 | |||
28 | CC = $(CROSS_COMPILE)gcc | ||
29 | LD = $(CROSS_COMPILE)gcc | ||
30 | INSTALL = install | ||
31 | |||
32 | OBJS_SHARED = common.o options.o packet.o pidfile.o signalpipe.o socket.o | ||
33 | DHCPD_OBJS = dhcpd.o arpping.o files.o leases.o serverpacket.o static_leases.o | ||
34 | DHCPC_OBJS = dhcpc.o clientpacket.o clientsocket.o script.o | ||
35 | |||
36 | ifdef COMBINED_BINARY | ||
37 | EXEC1 = udhcpd | ||
38 | OBJS1 = $(DHCPD_OBJS) $(DHCPC_OBJS) $(OBJS_SHARED) frontend.o | ||
39 | CFLAGS += -DCOMBINED_BINARY | ||
40 | else | ||
41 | EXEC1 = udhcpd | ||
42 | OBJS1 = $(DHCPD_OBJS) $(OBJS_SHARED) | ||
43 | |||
44 | EXEC2 = udhcpc | ||
45 | OBJS2 = $(DHCPC_OBJS) $(OBJS_SHARED) | ||
46 | endif | ||
47 | |||
48 | EXEC3 = dumpleases | ||
49 | OBJS3 = dumpleases.o | ||
50 | |||
51 | BOOT_PROGRAM = udhcpc | ||
52 | DAEMON = udhcpd | ||
53 | COMMAND = dumpleases | ||
54 | |||
55 | ifdef UDHCP_SYSLOG | ||
56 | CFLAGS += -DUDHCP_SYSLOG | ||
57 | endif | ||
58 | |||
59 | CFLAGS += -W -Wall -Wstrict-prototypes -D_GNU_SOURCE | ||
60 | |||
61 | ifdef UDHCP_DEBUG | ||
62 | CFLAGS += -g -DUDHCP_DEBUG | ||
63 | STRIP=true | ||
64 | else | ||
65 | CFLAGS += -Os -fomit-frame-pointer | ||
66 | STRIP=$(CROSS_COMPILE)strip | ||
67 | endif | ||
68 | |||
69 | all: $(EXEC1) $(EXEC2) $(EXEC3) | ||
70 | $(STRIP) --remove-section=.note --remove-section=.comment $(EXEC1) $(EXEC2) $(EXEC3) | ||
71 | |||
72 | $(OBJS1) $(OBJS2) $(OBJS3): *.h Makefile | ||
73 | $(EXEC1) $(EXEC2) $(EXEC3): Makefile | ||
74 | |||
75 | .c.o: | ||
76 | $(CC) -c $(CFLAGS) $< | ||
77 | |||
78 | $(EXEC1): $(OBJS1) | ||
79 | $(LD) $(CFLAGS) $(LDFLAGS) $(OBJS1) -o $(EXEC1) | ||
80 | |||
81 | $(EXEC2): $(OBJS2) | ||
82 | $(LD) $(CFLAGS) $(LDFLAGS) $(OBJS2) -o $(EXEC2) | ||
83 | |||
84 | $(EXEC3): $(OBJS3) | ||
85 | $(LD) $(CFLAGS) $(LDFLAGS) $(OBJS3) -o $(EXEC3) | ||
86 | |||
87 | |||
88 | install: all | ||
89 | mkdir -p $(USRSBINDIR) $(USRBINDIR) | ||
90 | $(INSTALL) -m 755 $(DAEMON) $(USRSBINDIR) | ||
91 | $(INSTALL) -m 755 $(COMMAND) $(USRBINDIR) | ||
92 | ifdef COMBINED_BINARY | ||
93 | ln -sf $(DAEMON) $(USRSBINDIR)/$(BOOT_PROGRAM) | ||
94 | else | ||
95 | $(INSTALL) -m 755 $(BOOT_PROGRAM) $(USRSBINDIR) | ||
96 | endif | ||
97 | mkdir -p $(USRSHAREDIR)/udhcpc | ||
98 | for name in bound deconfig nak renew script ; do \ | ||
99 | $(INSTALL) -m 755 samples/sample.$$name \ | ||
100 | $(USRSHAREDIR)/udhcpc/default.$$name ; \ | ||
101 | done | ||
102 | mkdir -p $(USRSHAREDIR)/man/man1 | ||
103 | $(INSTALL) -m 644 dumpleases.1 $(USRSHAREDIR)/man/man1 | ||
104 | mkdir -p $(USRSHAREDIR)/man/man5 | ||
105 | $(INSTALL) -m 644 udhcpd.conf.5 $(USRSHAREDIR)/man/man5 | ||
106 | mkdir -p $(USRSHAREDIR)/man/man8 | ||
107 | $(INSTALL) -m 644 udhcpc.8 udhcpd.8 $(USRSHAREDIR)/man/man8 | ||
108 | |||
109 | clean: | ||
110 | -rm -f udhcpd udhcpc dumpleases *.o *.a core | ||
diff --git a/networking/udhcp/README b/networking/udhcp/README new file mode 100644 index 000000000..dd992949a --- /dev/null +++ b/networking/udhcp/README | |||
@@ -0,0 +1,53 @@ | |||
1 | udhcp server/client package readme | ||
2 | ------------------------- | ||
3 | |||
4 | The udhcp server/client package is primarily geared towards embedded | ||
5 | systems. It does however, strive to be fully functional, and RFC | ||
6 | compliant. | ||
7 | |||
8 | |||
9 | compile time options | ||
10 | ------------------- | ||
11 | |||
12 | The Makefile contains three of the compile time options: | ||
13 | |||
14 | UDHCP_DEBUG: If UDHCP_DEBUG is defined, udhcpd will output extra | ||
15 | debugging output, compile with -g, and not fork to the background when | ||
16 | run. | ||
17 | UDHCP_SYSLOG: If UDHCP_SYSLOG is defined, udhcpd will log all its | ||
18 | messages syslog, otherwise, it will attempt to log them to stdout. | ||
19 | |||
20 | COMBINED_BINARY: If COMBINED_BINARY is define, one binary, udhcpd, | ||
21 | is created. If called as udhcpd, the dhcp server will be started. | ||
22 | If called as udhcpc, the dhcp client will be started. | ||
23 | |||
24 | dhcpd.h contains the other three compile time options: | ||
25 | |||
26 | LEASE_TIME: The default lease time if not specified in the config | ||
27 | file. | ||
28 | |||
29 | LEASES_FILE: The default file for storing leases. | ||
30 | |||
31 | DHCPD_CONFIG_FILE: The defualt config file to use. | ||
32 | |||
33 | options.c contains a set of dhcp options for the client: | ||
34 | |||
35 | name[10]: The name of the option as it will appear in scripts | ||
36 | |||
37 | flags: The type of option, as well as if it will be requested | ||
38 | by the client (OPTION_REQ) | ||
39 | |||
40 | code: The DHCP code for this option | ||
41 | |||
42 | |||
43 | busybox drop-in | ||
44 | -------------- | ||
45 | udhcp is now a drop-in component for busybox (http://busybox.net). | ||
46 | To update busybox to the latest revision, simply do a: | ||
47 | |||
48 | cp *.[ch] README AUTHORS COPYING ChangeLog TODO \ | ||
49 | <busybox_source>/networking/udhcp | ||
50 | |||
51 | The only two files udhcp does not provide are config.in and | ||
52 | Makefile.in, so these may need to be updated from time to time. | ||
53 | |||
diff --git a/networking/udhcp/README.dumpleases b/networking/udhcp/README.dumpleases new file mode 100644 index 000000000..6367710c4 --- /dev/null +++ b/networking/udhcp/README.dumpleases | |||
@@ -0,0 +1,17 @@ | |||
1 | udhcp lease dump (dumpleases) | ||
2 | ---------------------------- | ||
3 | |||
4 | dumpleases displays the leases written out by the udhcpd server. Lease | ||
5 | times are stored in the file by time remaining in lease (for systems | ||
6 | without clock that works when there is no power), or by the absolute | ||
7 | time that it expires in seconds from epoch. dumpleases accepts the | ||
8 | following command line options: | ||
9 | |||
10 | -a, --absolute Interpret lease times as expiration time. | ||
11 | -r, --remaining Interpret lease times as remaining time. | ||
12 | -f, --file=FILE Read lease information from FILE. | ||
13 | -h, --help Display help. | ||
14 | |||
15 | Note that if udhcpd has not written a leases file recently, the output | ||
16 | of may not be up to date. | ||
17 | |||
diff --git a/networking/udhcp/README.udhcpc b/networking/udhcp/README.udhcpc new file mode 100644 index 000000000..0417ff2ab --- /dev/null +++ b/networking/udhcp/README.udhcpc | |||
@@ -0,0 +1,144 @@ | |||
1 | udhcp client (udhcpc) | ||
2 | -------------------- | ||
3 | |||
4 | The udhcp client negotiates a lease with the DHCP server and notifies | ||
5 | a set of scripts when a leases is obtained or lost. | ||
6 | |||
7 | |||
8 | command line options | ||
9 | ------------------- | ||
10 | |||
11 | The command line options for the udhcp client are: | ||
12 | |||
13 | -c, --clientid=CLIENTID Set client identifier. Type is first char. | ||
14 | -C, --clientid-none Suppress default client identifier | ||
15 | -V, --vendorclass=CLASSID Set vendor class identifier | ||
16 | -H, --hostname=HOSTNAME Client hostname | ||
17 | -h, Alias for -H | ||
18 | -F, --fqdn=FQDN Client fully qualified domain name | ||
19 | -f, --foreground Do not fork after getting lease | ||
20 | -b, --background Fork to background if lease cannot be | ||
21 | immediately negotiated. | ||
22 | -i, --interface=INTERFACE Interface to use (default: eth0) | ||
23 | -n, --now Exit with failure if lease cannot be | ||
24 | immediately negotiated. | ||
25 | -p, --pidfile=file Store process ID of daemon in file | ||
26 | -q, --quit Quit after obtaining lease | ||
27 | -r, --request=IP IP address to request (default: none) | ||
28 | -s, --script=file Run file at dhcp events (default: | ||
29 | /usr/share/udhcpc/default.script) | ||
30 | -v, --version Display version | ||
31 | |||
32 | |||
33 | If the requested IP address cannot be obtained, the client accepts the | ||
34 | address that the server offers. | ||
35 | |||
36 | |||
37 | udhcp client scripts | ||
38 | ------------------- | ||
39 | |||
40 | When an event occurs, udhcpc calls the action script. udhcpc never does | ||
41 | any configuration of the network interface itself, but instead relies on | ||
42 | a set of scripts. The script by default is | ||
43 | /usr/share/udhcpc/default.script but this can be changed via the command | ||
44 | line arguments. The three possible arguments to the script are: | ||
45 | |||
46 | deconfig: This argument is used when udhcpc starts, and | ||
47 | when a leases is lost. The script must put the interface in an | ||
48 | up, but deconfigured state, ie: ifconfig $interface 0.0.0.0. | ||
49 | |||
50 | bound: This argument is used when udhcpc moves from an | ||
51 | unbound, to a bound state. All of the paramaters are set in | ||
52 | enviromental variables, The script should configure the interface, | ||
53 | and set any other relavent parameters (default gateway, dns server, | ||
54 | etc). | ||
55 | |||
56 | renew: This argument is used when a DHCP lease is renewed. All of | ||
57 | the paramaters are set in enviromental variables. This argument is | ||
58 | used when the interface is already configured, so the IP address, | ||
59 | will not change, however, the other DHCP paramaters, such as the | ||
60 | default gateway, subnet mask, and dns server may change. | ||
61 | |||
62 | nak: This argument is used with udhcpc receives a NAK message. | ||
63 | The script with the deconfig argument will be called directly | ||
64 | afterwards, so no changes to the network interface are neccessary. | ||
65 | This hook is provided for purely informational purposes (the | ||
66 | message option may contain a reason for the NAK). | ||
67 | |||
68 | The paramaters for enviromental variables are as follows: | ||
69 | |||
70 | $HOME - The set $HOME env or "/" | ||
71 | $PATH - the set $PATH env or "/bin:/usr/bin:/sbin:/usr/sbin" | ||
72 | $1 - What action the script should perform | ||
73 | interface - The interface this was obtained on | ||
74 | ip - The obtained IP | ||
75 | mask - The number of bits in the netmask (ie: 24) | ||
76 | siaddr - The bootp next server option | ||
77 | sname - The bootp server name option | ||
78 | boot_file - The bootp boot file option | ||
79 | subnet - The assigend subnet mask | ||
80 | timezone - Offset in seconds from UTC | ||
81 | router - A list of routers | ||
82 | timesvr - A list of time servers | ||
83 | namesvr - A list of IEN 116 name servers | ||
84 | dns - A list of DNS server | ||
85 | logsvr - A list of MIT-LCS UDP log servers | ||
86 | cookiesvr - A list of RFC 865 cookie servers | ||
87 | lprsvr - A list of LPR servers | ||
88 | hostname - The assigned hostname | ||
89 | bootsize - The length in 512 octect blocks of the bootfile | ||
90 | domain - The domain name of the network | ||
91 | swapsvr - The IP address of the client's swap server | ||
92 | rootpath - The path name of the client's root disk | ||
93 | ipttl - The TTL to use for this network | ||
94 | mtu - The MTU to use for this network | ||
95 | broadcast - The broadcast address for this network | ||
96 | ntpsrv - A list of NTP servers | ||
97 | wins - A list of WINS servers | ||
98 | lease - The lease time, in seconds | ||
99 | dhcptype - DHCP message type (safely ignored) | ||
100 | serverid - The IP of the server | ||
101 | message - Reason for a DHCPNAK | ||
102 | tftp - The TFTP server name | ||
103 | bootfile - The bootfile name | ||
104 | |||
105 | additional options are easily added in options.c. | ||
106 | |||
107 | |||
108 | note on udhcpc's random seed | ||
109 | --------------------------- | ||
110 | |||
111 | udhcpc will seed its random number generator (used for generating xid's) | ||
112 | by reading /dev/urandom. If you have a lot of embedded systems on the same | ||
113 | network, with no entropy, you can either seed /dev/urandom by a method of | ||
114 | your own, or doing the following on startup: | ||
115 | |||
116 | ifconfig eth0 > /dev/urandom | ||
117 | |||
118 | in order to seed /dev/urandom with some data (mac address) unique to your | ||
119 | system. If reading /dev/urandom fails, udhcpc will fall back to its old | ||
120 | behavior of seeding with time(0). | ||
121 | |||
122 | |||
123 | signals accepted by udhcpc | ||
124 | ------------------------- | ||
125 | |||
126 | udhcpc also responds to SIGUSR1 and SIGUSR2. SIGUSR1 will force a renew state, | ||
127 | and SIGUSR2 will force a release of the current lease, and cause udhcpc to | ||
128 | go into an inactive state (until it is killed, or receives a SIGUSR1). You do | ||
129 | not need to sleep between sending signals, as signals received are processed | ||
130 | sequencially in the order they are received. | ||
131 | |||
132 | |||
133 | compile time options | ||
134 | ------------------- | ||
135 | |||
136 | options.c contains a set of dhcp options for the client: | ||
137 | |||
138 | name[10]: The name of the option as it will appear in scripts | ||
139 | |||
140 | flags: The type of option, as well as if it will be requested | ||
141 | by the client (OPTION_REQ) | ||
142 | |||
143 | code: The DHCP code for this option | ||
144 | |||
diff --git a/networking/udhcp/README.udhcpd b/networking/udhcp/README.udhcpd new file mode 100644 index 000000000..169de78ec --- /dev/null +++ b/networking/udhcp/README.udhcpd | |||
@@ -0,0 +1,59 @@ | |||
1 | udhcp server (udhcpd) | ||
2 | -------------------- | ||
3 | |||
4 | The only command line argument to udhcpd is an optional specifed | ||
5 | config file. If no config file is specified, udhcpd uses the default | ||
6 | config file, /etc/udhcpd.conf. Ex: | ||
7 | |||
8 | udhcpd /etc/udhcpd.eth1.conf | ||
9 | |||
10 | The udhcp server employs a number of simple config files: | ||
11 | |||
12 | udhcpd.leases | ||
13 | ------------ | ||
14 | |||
15 | The udhcpd.leases behavior is designed for an embedded system. The | ||
16 | file is written either every auto_time seconds, or when a SIGUSR1 | ||
17 | is received (the auto_time timer restarts if a SIGUSR1 is received). | ||
18 | If you send a SIGTERM to udhcpd directly after a SIGUSR1, udhcpd will | ||
19 | finish writing the leases file and wait for the aftermentioned script | ||
20 | to be executed and finish before quiting, so you do not need to sleep | ||
21 | between sending signals. When the file is written, a script can be | ||
22 | optionally called to commit the file to flash. Lease times are stored | ||
23 | in the file by time remaining in lease (for systems without clock | ||
24 | that works when there is no power), or by the absolute time that it | ||
25 | expires in seconds from epoch. In the remaining format, expired leases | ||
26 | are stored as zero. The file is of the format: | ||
27 | |||
28 | 16 byte MAC | ||
29 | 4 byte ip address | ||
30 | u32 expire time | ||
31 | 16 byte MAC | ||
32 | 4 byte ip address | ||
33 | u32 expire time | ||
34 | . | ||
35 | etc. | ||
36 | |||
37 | example: hexdump udhcpd.leases | ||
38 | |||
39 | 0000000 1000 c95a 27d9 0000 0000 0000 0000 0000 | ||
40 | 0000010 a8c0 150a 0d00 2d29 5000 23fc 8566 0000 | ||
41 | 0000020 0000 0000 0000 0000 a8c0 140a 0d00 4e29 | ||
42 | 0000030 | ||
43 | |||
44 | |||
45 | udhcpd.conf | ||
46 | ---------- | ||
47 | |||
48 | The format is fairly simple, there is a sample file with all the | ||
49 | available options and comments describing them in samples/udhcpd.conf | ||
50 | |||
51 | compile time options | ||
52 | ------------------- | ||
53 | |||
54 | dhcpd.h contains the other two compile time options: | ||
55 | |||
56 | LEASE_TIME: The default lease time if not specified in the config | ||
57 | file. | ||
58 | |||
59 | DHCPD_CONFIG_FILE: The defualt config file to use. | ||
diff --git a/networking/udhcp/TODO b/networking/udhcp/TODO new file mode 100644 index 000000000..6febe5ab4 --- /dev/null +++ b/networking/udhcp/TODO | |||
@@ -0,0 +1,16 @@ | |||
1 | TODO | ||
2 | ---- | ||
3 | + Check for valid IP, netmask, hostname, paths, strings, etc | ||
4 | + Integrade README.*'s with manpages | ||
5 | + using time(0) breaks if the system clock changes, find a portable solution | ||
6 | + make failure of reading functions revert to previous value, not the default | ||
7 | + sanity code for option[OPT_LEN] | ||
8 | + fix aliasing (ie: eth0:0) | ||
9 | + better standard linux distro support | ||
10 | + make sure packet generation works on a wide varitey of arches | ||
11 | + Interoperability testing | ||
12 | + Hooks within the DHCP server | ||
13 | * Server notification when a lease is added/removed | ||
14 | + Additional bootp support in client/server | ||
15 | + Make serverid option in server configurable | ||
16 | + Possibly add failure message to DHCP NAK | ||
diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c new file mode 100644 index 000000000..df626f159 --- /dev/null +++ b/networking/udhcp/arpping.c | |||
@@ -0,0 +1,106 @@ | |||
1 | /* | ||
2 | * arpping.c | ||
3 | * | ||
4 | * Mostly stolen from: dhcpcd - DHCP client daemon | ||
5 | * by Yoichi Hariguchi <yoichi@fore.com> | ||
6 | */ | ||
7 | |||
8 | #include <sys/time.h> | ||
9 | #include <time.h> | ||
10 | #include <sys/socket.h> | ||
11 | #include <netinet/if_ether.h> | ||
12 | #include <net/if_arp.h> | ||
13 | #include <netinet/in.h> | ||
14 | #include <string.h> | ||
15 | #include <unistd.h> | ||
16 | #include <errno.h> | ||
17 | |||
18 | #include "dhcpd.h" | ||
19 | #include "arpping.h" | ||
20 | #include "common.h" | ||
21 | |||
22 | /* args: yiaddr - what IP to ping | ||
23 | * ip - our ip | ||
24 | * mac - our arp address | ||
25 | * interface - interface to use | ||
26 | * retn: 1 addr free | ||
27 | * 0 addr used | ||
28 | * -1 error | ||
29 | */ | ||
30 | |||
31 | /* FIXME: match response against chaddr */ | ||
32 | int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *mac, char *interface) | ||
33 | { | ||
34 | |||
35 | int timeout = 2; | ||
36 | int optval = 1; | ||
37 | int s; /* socket */ | ||
38 | int rv = 1; /* return value */ | ||
39 | struct sockaddr addr; /* for interface name */ | ||
40 | struct arpMsg arp; | ||
41 | fd_set fdset; | ||
42 | struct timeval tm; | ||
43 | time_t prevTime; | ||
44 | |||
45 | |||
46 | if ((s = socket (PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) == -1) { | ||
47 | #ifdef IN_BUSYBOX | ||
48 | LOG(LOG_ERR, bb_msg_can_not_create_raw_socket); | ||
49 | #else | ||
50 | LOG(LOG_ERR, "Could not open raw socket"); | ||
51 | #endif | ||
52 | return -1; | ||
53 | } | ||
54 | |||
55 | if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) { | ||
56 | LOG(LOG_ERR, "Could not setsocketopt on raw socket"); | ||
57 | close(s); | ||
58 | return -1; | ||
59 | } | ||
60 | |||
61 | /* send arp request */ | ||
62 | memset(&arp, 0, sizeof(arp)); | ||
63 | memcpy(arp.h_dest, MAC_BCAST_ADDR, 6); /* MAC DA */ | ||
64 | memcpy(arp.h_source, mac, 6); /* MAC SA */ | ||
65 | arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */ | ||
66 | arp.htype = htons(ARPHRD_ETHER); /* hardware type */ | ||
67 | arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */ | ||
68 | arp.hlen = 6; /* hardware address length */ | ||
69 | arp.plen = 4; /* protocol address length */ | ||
70 | arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ | ||
71 | memcpy(arp.sInaddr, &ip, sizeof(ip)); /* source IP address */ | ||
72 | memcpy(arp.sHaddr, mac, 6); /* source hardware address */ | ||
73 | memcpy(arp.tInaddr, &yiaddr, sizeof(yiaddr)); /* target IP address */ | ||
74 | |||
75 | memset(&addr, 0, sizeof(addr)); | ||
76 | strcpy(addr.sa_data, interface); | ||
77 | if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) | ||
78 | rv = 0; | ||
79 | |||
80 | /* wait arp reply, and check it */ | ||
81 | tm.tv_usec = 0; | ||
82 | prevTime = uptime(); | ||
83 | while (timeout > 0) { | ||
84 | FD_ZERO(&fdset); | ||
85 | FD_SET(s, &fdset); | ||
86 | tm.tv_sec = timeout; | ||
87 | if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) { | ||
88 | DEBUG(LOG_ERR, "Error on ARPING request: %m"); | ||
89 | if (errno != EINTR) rv = 0; | ||
90 | } else if (FD_ISSET(s, &fdset)) { | ||
91 | if (recv(s, &arp, sizeof(arp), 0) < 0 ) rv = 0; | ||
92 | if (arp.operation == htons(ARPOP_REPLY) && | ||
93 | memcmp(arp.tHaddr, mac, 6) == 0 && | ||
94 | *((uint32_t *) arp.sInaddr) == yiaddr) { | ||
95 | DEBUG(LOG_INFO, "Valid arp reply receved for this address"); | ||
96 | rv = 0; | ||
97 | break; | ||
98 | } | ||
99 | } | ||
100 | timeout -= uptime() - prevTime; | ||
101 | prevTime = uptime(); | ||
102 | } | ||
103 | close(s); | ||
104 | DEBUG(LOG_INFO, "%salid arp replies for this address", rv ? "No v" : "V"); | ||
105 | return rv; | ||
106 | } | ||
diff --git a/networking/udhcp/arpping.h b/networking/udhcp/arpping.h new file mode 100644 index 000000000..30959ca99 --- /dev/null +++ b/networking/udhcp/arpping.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * arpping .h | ||
3 | */ | ||
4 | |||
5 | #ifndef ARPPING_H | ||
6 | #define ARPPING_H | ||
7 | |||
8 | #include <netinet/if_ether.h> | ||
9 | #include <net/if_arp.h> | ||
10 | #include <net/if.h> | ||
11 | #include <netinet/in.h> | ||
12 | |||
13 | struct arpMsg { | ||
14 | /* Ethernet header */ | ||
15 | u_char h_dest[6]; /* destination ether addr */ | ||
16 | u_char h_source[6]; /* source ether addr */ | ||
17 | u_short h_proto; /* packet type ID field */ | ||
18 | |||
19 | /* ARP packet */ | ||
20 | uint16_t htype; /* hardware type (must be ARPHRD_ETHER) */ | ||
21 | uint16_t ptype; /* protocol type (must be ETH_P_IP) */ | ||
22 | uint8_t hlen; /* hardware address length (must be 6) */ | ||
23 | uint8_t plen; /* protocol address length (must be 4) */ | ||
24 | uint16_t operation; /* ARP opcode */ | ||
25 | uint8_t sHaddr[6]; /* sender's hardware address */ | ||
26 | uint8_t sInaddr[4]; /* sender's IP address */ | ||
27 | uint8_t tHaddr[6]; /* target's hardware address */ | ||
28 | uint8_t tInaddr[4]; /* target's IP address */ | ||
29 | uint8_t pad[18]; /* pad for min. Ethernet payload (60 bytes) */ | ||
30 | } ATTRIBUTE_PACKED; | ||
31 | |||
32 | /* function prototypes */ | ||
33 | int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *arp, char *interface); | ||
34 | |||
35 | #endif | ||
diff --git a/networking/udhcp/clientpacket.c b/networking/udhcp/clientpacket.c new file mode 100644 index 000000000..88d4d88dc --- /dev/null +++ b/networking/udhcp/clientpacket.c | |||
@@ -0,0 +1,245 @@ | |||
1 | /* clientpacket.c | ||
2 | * | ||
3 | * Packet generation and dispatching functions for the DHCP client. | ||
4 | * | ||
5 | * Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <string.h> | ||
23 | #include <sys/socket.h> | ||
24 | #include <features.h> | ||
25 | #if (__GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || defined _NEWLIB_VERSION | ||
26 | #include <netpacket/packet.h> | ||
27 | #include <net/ethernet.h> | ||
28 | #else | ||
29 | #include <asm/types.h> | ||
30 | #include <linux/if_packet.h> | ||
31 | #include <linux/if_ether.h> | ||
32 | #endif | ||
33 | #include <stdlib.h> | ||
34 | #include <time.h> | ||
35 | #include <unistd.h> | ||
36 | #include <netinet/in.h> | ||
37 | #include <arpa/inet.h> | ||
38 | #include <fcntl.h> | ||
39 | |||
40 | |||
41 | #include "dhcpd.h" | ||
42 | #include "clientpacket.h" | ||
43 | #include "options.h" | ||
44 | #include "dhcpc.h" | ||
45 | #include "common.h" | ||
46 | |||
47 | |||
48 | /* Create a random xid */ | ||
49 | unsigned long random_xid(void) | ||
50 | { | ||
51 | static int initialized; | ||
52 | if (!initialized) { | ||
53 | int fd; | ||
54 | unsigned long seed; | ||
55 | |||
56 | fd = open("/dev/urandom", 0); | ||
57 | if (fd < 0 || read(fd, &seed, sizeof(seed)) < 0) { | ||
58 | LOG(LOG_WARNING, "Could not load seed from /dev/urandom: %m"); | ||
59 | seed = time(0); | ||
60 | } | ||
61 | if (fd >= 0) close(fd); | ||
62 | srand(seed); | ||
63 | initialized++; | ||
64 | } | ||
65 | return rand(); | ||
66 | } | ||
67 | |||
68 | |||
69 | /* initialize a packet with the proper defaults */ | ||
70 | static void init_packet(struct dhcpMessage *packet, char type) | ||
71 | { | ||
72 | init_header(packet, type); | ||
73 | memcpy(packet->chaddr, client_config.arp, 6); | ||
74 | if (client_config.clientid) | ||
75 | add_option_string(packet->options, client_config.clientid); | ||
76 | if (client_config.hostname) add_option_string(packet->options, client_config.hostname); | ||
77 | if (client_config.fqdn) add_option_string(packet->options, client_config.fqdn); | ||
78 | add_option_string(packet->options, client_config.vendorclass); | ||
79 | } | ||
80 | |||
81 | |||
82 | /* Add a parameter request list for stubborn DHCP servers. Pull the data | ||
83 | * from the struct in options.c. Don't do bounds checking here because it | ||
84 | * goes towards the head of the packet. */ | ||
85 | static void add_requests(struct dhcpMessage *packet) | ||
86 | { | ||
87 | int end = end_option(packet->options); | ||
88 | int i, len = 0; | ||
89 | |||
90 | packet->options[end + OPT_CODE] = DHCP_PARAM_REQ; | ||
91 | for (i = 0; dhcp_options[i].code; i++) | ||
92 | if (dhcp_options[i].flags & OPTION_REQ) | ||
93 | packet->options[end + OPT_DATA + len++] = dhcp_options[i].code; | ||
94 | packet->options[end + OPT_LEN] = len; | ||
95 | packet->options[end + OPT_DATA + len] = DHCP_END; | ||
96 | |||
97 | } | ||
98 | |||
99 | |||
100 | /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ | ||
101 | int send_discover(unsigned long xid, unsigned long requested) | ||
102 | { | ||
103 | struct dhcpMessage packet; | ||
104 | |||
105 | init_packet(&packet, DHCPDISCOVER); | ||
106 | packet.xid = xid; | ||
107 | if (requested) | ||
108 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); | ||
109 | |||
110 | add_requests(&packet); | ||
111 | LOG(LOG_DEBUG, "Sending discover..."); | ||
112 | return raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, | ||
113 | SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); | ||
114 | } | ||
115 | |||
116 | |||
117 | /* Broadcasts a DHCP request message */ | ||
118 | int send_selecting(unsigned long xid, unsigned long server, unsigned long requested) | ||
119 | { | ||
120 | struct dhcpMessage packet; | ||
121 | struct in_addr addr; | ||
122 | |||
123 | init_packet(&packet, DHCPREQUEST); | ||
124 | packet.xid = xid; | ||
125 | |||
126 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); | ||
127 | add_simple_option(packet.options, DHCP_SERVER_ID, server); | ||
128 | |||
129 | add_requests(&packet); | ||
130 | addr.s_addr = requested; | ||
131 | LOG(LOG_DEBUG, "Sending select for %s...", inet_ntoa(addr)); | ||
132 | return raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, | ||
133 | SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); | ||
134 | } | ||
135 | |||
136 | |||
137 | /* Unicasts or broadcasts a DHCP renew message */ | ||
138 | int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr) | ||
139 | { | ||
140 | struct dhcpMessage packet; | ||
141 | int ret = 0; | ||
142 | |||
143 | init_packet(&packet, DHCPREQUEST); | ||
144 | packet.xid = xid; | ||
145 | packet.ciaddr = ciaddr; | ||
146 | |||
147 | add_requests(&packet); | ||
148 | LOG(LOG_DEBUG, "Sending renew..."); | ||
149 | if (server) | ||
150 | ret = kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); | ||
151 | else ret = raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, | ||
152 | SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); | ||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | |||
157 | /* Unicasts a DHCP release message */ | ||
158 | int send_release(unsigned long server, unsigned long ciaddr) | ||
159 | { | ||
160 | struct dhcpMessage packet; | ||
161 | |||
162 | init_packet(&packet, DHCPRELEASE); | ||
163 | packet.xid = random_xid(); | ||
164 | packet.ciaddr = ciaddr; | ||
165 | |||
166 | add_simple_option(packet.options, DHCP_REQUESTED_IP, ciaddr); | ||
167 | add_simple_option(packet.options, DHCP_SERVER_ID, server); | ||
168 | |||
169 | LOG(LOG_DEBUG, "Sending release..."); | ||
170 | return kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); | ||
171 | } | ||
172 | |||
173 | |||
174 | /* return -1 on errors that are fatal for the socket, -2 for those that aren't */ | ||
175 | int get_raw_packet(struct dhcpMessage *payload, int fd) | ||
176 | { | ||
177 | int bytes; | ||
178 | struct udp_dhcp_packet packet; | ||
179 | uint32_t source, dest; | ||
180 | uint16_t check; | ||
181 | |||
182 | memset(&packet, 0, sizeof(struct udp_dhcp_packet)); | ||
183 | bytes = read(fd, &packet, sizeof(struct udp_dhcp_packet)); | ||
184 | if (bytes < 0) { | ||
185 | DEBUG(LOG_INFO, "couldn't read on raw listening socket -- ignoring"); | ||
186 | usleep(500000); /* possible down interface, looping condition */ | ||
187 | return -1; | ||
188 | } | ||
189 | |||
190 | if (bytes < (int) (sizeof(struct iphdr) + sizeof(struct udphdr))) { | ||
191 | DEBUG(LOG_INFO, "message too short, ignoring"); | ||
192 | return -2; | ||
193 | } | ||
194 | |||
195 | if (bytes < ntohs(packet.ip.tot_len)) { | ||
196 | DEBUG(LOG_INFO, "Truncated packet"); | ||
197 | return -2; | ||
198 | } | ||
199 | |||
200 | /* ignore any extra garbage bytes */ | ||
201 | bytes = ntohs(packet.ip.tot_len); | ||
202 | |||
203 | /* Make sure its the right packet for us, and that it passes sanity checks */ | ||
204 | if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION || | ||
205 | packet.ip.ihl != sizeof(packet.ip) >> 2 || packet.udp.dest != htons(CLIENT_PORT) || | ||
206 | bytes > (int) sizeof(struct udp_dhcp_packet) || | ||
207 | ntohs(packet.udp.len) != (uint16_t) (bytes - sizeof(packet.ip))) { | ||
208 | DEBUG(LOG_INFO, "unrelated/bogus packet"); | ||
209 | return -2; | ||
210 | } | ||
211 | |||
212 | /* check IP checksum */ | ||
213 | check = packet.ip.check; | ||
214 | packet.ip.check = 0; | ||
215 | if (check != checksum(&(packet.ip), sizeof(packet.ip))) { | ||
216 | DEBUG(LOG_INFO, "bad IP header checksum, ignoring"); | ||
217 | return -1; | ||
218 | } | ||
219 | |||
220 | /* verify the UDP checksum by replacing the header with a psuedo header */ | ||
221 | source = packet.ip.saddr; | ||
222 | dest = packet.ip.daddr; | ||
223 | check = packet.udp.check; | ||
224 | packet.udp.check = 0; | ||
225 | memset(&packet.ip, 0, sizeof(packet.ip)); | ||
226 | |||
227 | packet.ip.protocol = IPPROTO_UDP; | ||
228 | packet.ip.saddr = source; | ||
229 | packet.ip.daddr = dest; | ||
230 | packet.ip.tot_len = packet.udp.len; /* cheat on the psuedo-header */ | ||
231 | if (check && check != checksum(&packet, bytes)) { | ||
232 | DEBUG(LOG_ERR, "packet with bad UDP checksum received, ignoring"); | ||
233 | return -2; | ||
234 | } | ||
235 | |||
236 | memcpy(payload, &(packet.data), bytes - (sizeof(packet.ip) + sizeof(packet.udp))); | ||
237 | |||
238 | if (ntohl(payload->cookie) != DHCP_MAGIC) { | ||
239 | LOG(LOG_ERR, "received bogus message (bad magic) -- ignoring"); | ||
240 | return -2; | ||
241 | } | ||
242 | DEBUG(LOG_INFO, "oooooh!!! got some!"); | ||
243 | return bytes - (sizeof(packet.ip) + sizeof(packet.udp)); | ||
244 | |||
245 | } | ||
diff --git a/networking/udhcp/clientpacket.h b/networking/udhcp/clientpacket.h new file mode 100644 index 000000000..8e5441bc7 --- /dev/null +++ b/networking/udhcp/clientpacket.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef _CLIENTPACKET_H | ||
2 | #define _CLIENTPACKET_H | ||
3 | |||
4 | #include "packet.h" | ||
5 | |||
6 | unsigned long random_xid(void); | ||
7 | int send_discover(unsigned long xid, unsigned long requested); | ||
8 | int send_selecting(unsigned long xid, unsigned long server, unsigned long requested); | ||
9 | int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr); | ||
10 | int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr); | ||
11 | int send_release(unsigned long server, unsigned long ciaddr); | ||
12 | int get_raw_packet(struct dhcpMessage *payload, int fd); | ||
13 | |||
14 | #endif | ||
diff --git a/networking/udhcp/clientsocket.c b/networking/udhcp/clientsocket.c new file mode 100644 index 000000000..5d08421b3 --- /dev/null +++ b/networking/udhcp/clientsocket.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * clientsocket.c -- DHCP client socket creation | ||
3 | * | ||
4 | * udhcp client | ||
5 | * | ||
6 | * Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <sys/types.h> | ||
24 | #include <sys/socket.h> | ||
25 | #include <unistd.h> | ||
26 | #include <netinet/in.h> | ||
27 | #include <features.h> | ||
28 | #if (__GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || defined _NEWLIB_VERSION | ||
29 | #include <netpacket/packet.h> | ||
30 | #include <net/ethernet.h> | ||
31 | #else | ||
32 | #include <asm/types.h> | ||
33 | #include <linux/if_packet.h> | ||
34 | #include <linux/if_ether.h> | ||
35 | #endif | ||
36 | |||
37 | #include "clientsocket.h" | ||
38 | #include "common.h" | ||
39 | |||
40 | |||
41 | int raw_socket(int ifindex) | ||
42 | { | ||
43 | int fd; | ||
44 | struct sockaddr_ll sock; | ||
45 | |||
46 | DEBUG(LOG_INFO, "Opening raw socket on ifindex %d", ifindex); | ||
47 | if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { | ||
48 | DEBUG(LOG_ERR, "socket call failed: %m"); | ||
49 | return -1; | ||
50 | } | ||
51 | |||
52 | sock.sll_family = AF_PACKET; | ||
53 | sock.sll_protocol = htons(ETH_P_IP); | ||
54 | sock.sll_ifindex = ifindex; | ||
55 | if (bind(fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) { | ||
56 | DEBUG(LOG_ERR, "bind call failed: %m"); | ||
57 | close(fd); | ||
58 | return -1; | ||
59 | } | ||
60 | |||
61 | return fd; | ||
62 | } | ||
diff --git a/networking/udhcp/clientsocket.h b/networking/udhcp/clientsocket.h new file mode 100644 index 000000000..17a55c154 --- /dev/null +++ b/networking/udhcp/clientsocket.h | |||
@@ -0,0 +1,7 @@ | |||
1 | /* clientsocket.h */ | ||
2 | #ifndef _CLIENTSOCKET_H | ||
3 | #define _CLIENTSOCKET_H | ||
4 | |||
5 | int raw_socket(int ifindex); | ||
6 | |||
7 | #endif | ||
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c new file mode 100644 index 000000000..f36009a1c --- /dev/null +++ b/networking/udhcp/common.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* common.c | ||
3 | * | ||
4 | * Functions for debugging and logging as well as some other | ||
5 | * simple helper functions. | ||
6 | * | ||
7 | * Russ Dill <Russ.Dill@asu.edu> 2001-2003 | ||
8 | * Rewritten by Vladimir Oleynik <dzo@simtreas.ru> (C) 2003 | ||
9 | * | ||
10 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
11 | */ | ||
12 | |||
13 | #include <fcntl.h> | ||
14 | #include <unistd.h> | ||
15 | #include <errno.h> | ||
16 | #include <string.h> | ||
17 | #include <stdlib.h> | ||
18 | #include <signal.h> | ||
19 | #include <paths.h> | ||
20 | #include <sys/socket.h> | ||
21 | #include <stdarg.h> | ||
22 | |||
23 | #include "common.h" | ||
24 | #include "pidfile.h" | ||
25 | |||
26 | |||
27 | static int daemonized; | ||
28 | |||
29 | long uptime(void) | ||
30 | { | ||
31 | struct sysinfo info; | ||
32 | sysinfo(&info); | ||
33 | return info.uptime; | ||
34 | } | ||
35 | |||
36 | |||
37 | /* | ||
38 | * This function makes sure our first socket calls | ||
39 | * aren't going to fd 1 (printf badness...) and are | ||
40 | * not later closed by daemon() | ||
41 | */ | ||
42 | static inline void sanitize_fds(void) | ||
43 | { | ||
44 | int zero; | ||
45 | if ((zero = open(_PATH_DEVNULL, O_RDWR, 0)) < 0) return; | ||
46 | while (zero < 3) zero = dup(zero); | ||
47 | close(zero); | ||
48 | } | ||
49 | |||
50 | |||
51 | void background(const char *pidfile) | ||
52 | { | ||
53 | #ifdef __uClinux__ | ||
54 | LOG(LOG_ERR, "Cannot background in uclinux (yet)"); | ||
55 | #else /* __uClinux__ */ | ||
56 | int pid_fd; | ||
57 | |||
58 | /* hold lock during fork. */ | ||
59 | pid_fd = pidfile_acquire(pidfile); | ||
60 | if (daemon(0, 0) == -1) { /* bb_xdaemon? */ | ||
61 | perror("fork"); | ||
62 | exit(1); | ||
63 | } | ||
64 | daemonized++; | ||
65 | pidfile_write_release(pid_fd); | ||
66 | #endif /* __uClinux__ */ | ||
67 | } | ||
68 | |||
69 | |||
70 | #ifdef UDHCP_SYSLOG | ||
71 | |||
72 | void udhcp_logging(int level, const char *fmt, ...) | ||
73 | { | ||
74 | va_list p; | ||
75 | va_list p2; | ||
76 | |||
77 | va_start(p, fmt); | ||
78 | __va_copy(p2, p); | ||
79 | if(!daemonized) { | ||
80 | vprintf(fmt, p); | ||
81 | putchar('\n'); | ||
82 | } | ||
83 | vsyslog(level, fmt, p2); | ||
84 | va_end(p); | ||
85 | } | ||
86 | |||
87 | #else | ||
88 | |||
89 | |||
90 | static char *syslog_level_msg[] = { | ||
91 | [LOG_EMERG] = "EMERGENCY!", | ||
92 | [LOG_ALERT] = "ALERT!", | ||
93 | [LOG_CRIT] = "critical!", | ||
94 | [LOG_WARNING] = "warning", | ||
95 | [LOG_ERR] = "error", | ||
96 | [LOG_INFO] = "info", | ||
97 | [LOG_DEBUG] = "debug" | ||
98 | }; | ||
99 | |||
100 | |||
101 | void udhcp_logging(int level, const char *fmt, ...) | ||
102 | { | ||
103 | va_list p; | ||
104 | |||
105 | va_start(p, fmt); | ||
106 | if(!daemonized) { | ||
107 | printf("%s, ", syslog_level_msg[level]); | ||
108 | vprintf(fmt, p); | ||
109 | putchar('\n'); | ||
110 | } | ||
111 | va_end(p); | ||
112 | } | ||
113 | #endif | ||
114 | |||
115 | |||
116 | void start_log_and_pid(const char *client_server, const char *pidfile) | ||
117 | { | ||
118 | int pid_fd; | ||
119 | |||
120 | /* Make sure our syslog fd isn't overwritten */ | ||
121 | sanitize_fds(); | ||
122 | |||
123 | /* do some other misc startup stuff while we are here to save bytes */ | ||
124 | pid_fd = pidfile_acquire(pidfile); | ||
125 | pidfile_write_release(pid_fd); | ||
126 | |||
127 | /* equivelent of doing a fflush after every \n */ | ||
128 | setlinebuf(stdout); | ||
129 | |||
130 | #ifdef UDHCP_SYSLOG | ||
131 | openlog(client_server, LOG_PID | LOG_CONS, LOG_LOCAL0); | ||
132 | #endif | ||
133 | |||
134 | udhcp_logging(LOG_INFO, "%s (v%s) started", client_server, VERSION); | ||
135 | } | ||
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h new file mode 100644 index 000000000..071a5c428 --- /dev/null +++ b/networking/udhcp/common.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* common.h | ||
2 | * | ||
3 | * Russ Dill <Russ.Dill@asu.edu> September 2001 | ||
4 | * Rewritten by Vladimir Oleynik <dzo@simtreas.ru> (C) 2003 | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef _COMMON_H | ||
22 | #define _COMMON_H | ||
23 | |||
24 | #include "version.h" | ||
25 | #include "libbb_udhcp.h" | ||
26 | |||
27 | |||
28 | #ifndef UDHCP_SYSLOG | ||
29 | enum syslog_levels { | ||
30 | LOG_EMERG = 0, | ||
31 | LOG_ALERT, | ||
32 | LOG_CRIT, | ||
33 | LOG_WARNING, | ||
34 | LOG_ERR, | ||
35 | LOG_INFO, | ||
36 | LOG_DEBUG | ||
37 | }; | ||
38 | #else | ||
39 | #include <syslog.h> | ||
40 | #endif | ||
41 | |||
42 | long uptime(void); | ||
43 | void background(const char *pidfile); | ||
44 | void start_log_and_pid(const char *client_server, const char *pidfile); | ||
45 | void udhcp_logging(int level, const char *fmt, ...); | ||
46 | |||
47 | #define LOG(level, str, args...) udhcp_logging(level, str, ## args) | ||
48 | |||
49 | #ifdef UDHCP_DEBUG | ||
50 | # define DEBUG(level, str, args...) LOG(level, str, ## args) | ||
51 | #else | ||
52 | # define DEBUG(level, str, args...) do {;} while(0) | ||
53 | #endif | ||
54 | |||
55 | #endif | ||
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c new file mode 100644 index 000000000..222bd6519 --- /dev/null +++ b/networking/udhcp/dhcpc.c | |||
@@ -0,0 +1,574 @@ | |||
1 | /* dhcpc.c | ||
2 | * | ||
3 | * udhcp DHCP client | ||
4 | * | ||
5 | * Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
6 | * | ||
7 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | ||
8 | */ | ||
9 | |||
10 | #include <sys/time.h> | ||
11 | #include <sys/file.h> | ||
12 | #include <unistd.h> | ||
13 | #include <getopt.h> | ||
14 | #include <stdlib.h> | ||
15 | #include <sys/socket.h> | ||
16 | #include <netinet/in.h> | ||
17 | #include <arpa/inet.h> | ||
18 | #include <signal.h> | ||
19 | #include <time.h> | ||
20 | #include <string.h> | ||
21 | #include <sys/ioctl.h> | ||
22 | #include <net/if.h> | ||
23 | #include <errno.h> | ||
24 | |||
25 | #include "common.h" | ||
26 | #include "dhcpd.h" | ||
27 | #include "dhcpc.h" | ||
28 | #include "options.h" | ||
29 | #include "clientpacket.h" | ||
30 | #include "clientsocket.h" | ||
31 | #include "script.h" | ||
32 | #include "socket.h" | ||
33 | #include "signalpipe.h" | ||
34 | |||
35 | static int state; | ||
36 | static unsigned long requested_ip; /* = 0 */ | ||
37 | static unsigned long server_addr; | ||
38 | static unsigned long timeout; | ||
39 | static int packet_num; /* = 0 */ | ||
40 | static int fd = -1; | ||
41 | |||
42 | #define LISTEN_NONE 0 | ||
43 | #define LISTEN_KERNEL 1 | ||
44 | #define LISTEN_RAW 2 | ||
45 | static int listen_mode; | ||
46 | |||
47 | struct client_config_t client_config = { | ||
48 | /* Default options. */ | ||
49 | .abort_if_no_lease = 0, | ||
50 | .foreground = 0, | ||
51 | .quit_after_lease = 0, | ||
52 | .background_if_no_lease = 0, | ||
53 | .interface = "eth0", | ||
54 | .pidfile = NULL, | ||
55 | .script = DEFAULT_SCRIPT, | ||
56 | .clientid = NULL, | ||
57 | .vendorclass = NULL, | ||
58 | .hostname = NULL, | ||
59 | .fqdn = NULL, | ||
60 | .ifindex = 0, | ||
61 | .retries = 3, | ||
62 | .timeout = 3, | ||
63 | .arp = "\0\0\0\0\0\0", /* appease gcc-3.0 */ | ||
64 | }; | ||
65 | |||
66 | #ifndef IN_BUSYBOX | ||
67 | static void ATTRIBUTE_NORETURN show_usage(void) | ||
68 | { | ||
69 | printf( | ||
70 | "Usage: udhcpc [OPTIONS]\n\n" | ||
71 | " -c, --clientid=CLIENTID Set client identifier - type is first char\n" | ||
72 | " -C, --clientid-none Suppress default client identifier\n" | ||
73 | " -V, --vendorclass=CLASSID Set vendor class identifier\n" | ||
74 | " -H, --hostname=HOSTNAME Client hostname\n" | ||
75 | " -h Alias for -H\n" | ||
76 | " -F, --fqdn=FQDN Client fully qualified domain name\n" | ||
77 | " -f, --foreground Do not fork after getting lease\n" | ||
78 | " -b, --background Fork to background if lease cannot be\n" | ||
79 | " immediately negotiated.\n" | ||
80 | " -i, --interface=INTERFACE Interface to use (default: eth0)\n" | ||
81 | " -n, --now Exit with failure if lease cannot be\n" | ||
82 | " immediately negotiated.\n" | ||
83 | " -p, --pidfile=file Store process ID of daemon in file\n" | ||
84 | " -q, --quit Quit after obtaining lease\n" | ||
85 | " -r, --request=IP IP address to request (default: none)\n" | ||
86 | " -s, --script=file Run file at dhcp events (default:\n" | ||
87 | " " DEFAULT_SCRIPT ")\n" | ||
88 | " -T, --timeout=seconds Try to get the lease for the amount of\n" | ||
89 | " seconds (default: 3)\n" | ||
90 | " -t, --retries=NUM Send up to NUM request packets\n" | ||
91 | " -v, --version Display version\n" | ||
92 | ); | ||
93 | exit(0); | ||
94 | } | ||
95 | #else | ||
96 | #define show_usage bb_show_usage | ||
97 | extern void show_usage(void) ATTRIBUTE_NORETURN; | ||
98 | #endif | ||
99 | |||
100 | |||
101 | /* just a little helper */ | ||
102 | static void change_mode(int new_mode) | ||
103 | { | ||
104 | DEBUG(LOG_INFO, "entering %s listen mode", | ||
105 | new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none"); | ||
106 | if (fd >= 0) close(fd); | ||
107 | fd = -1; | ||
108 | listen_mode = new_mode; | ||
109 | } | ||
110 | |||
111 | |||
112 | /* perform a renew */ | ||
113 | static void perform_renew(void) | ||
114 | { | ||
115 | LOG(LOG_INFO, "Performing a DHCP renew"); | ||
116 | switch (state) { | ||
117 | case BOUND: | ||
118 | change_mode(LISTEN_KERNEL); | ||
119 | case RENEWING: | ||
120 | case REBINDING: | ||
121 | state = RENEW_REQUESTED; | ||
122 | break; | ||
123 | case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ | ||
124 | run_script(NULL, "deconfig"); | ||
125 | case REQUESTING: | ||
126 | case RELEASED: | ||
127 | change_mode(LISTEN_RAW); | ||
128 | state = INIT_SELECTING; | ||
129 | break; | ||
130 | case INIT_SELECTING: | ||
131 | break; | ||
132 | } | ||
133 | |||
134 | /* start things over */ | ||
135 | packet_num = 0; | ||
136 | |||
137 | /* Kill any timeouts because the user wants this to hurry along */ | ||
138 | timeout = 0; | ||
139 | } | ||
140 | |||
141 | |||
142 | /* perform a release */ | ||
143 | static void perform_release(void) | ||
144 | { | ||
145 | char buffer[16]; | ||
146 | struct in_addr temp_addr; | ||
147 | |||
148 | /* send release packet */ | ||
149 | if (state == BOUND || state == RENEWING || state == REBINDING) { | ||
150 | temp_addr.s_addr = server_addr; | ||
151 | sprintf(buffer, "%s", inet_ntoa(temp_addr)); | ||
152 | temp_addr.s_addr = requested_ip; | ||
153 | LOG(LOG_INFO, "Unicasting a release of %s to %s", | ||
154 | inet_ntoa(temp_addr), buffer); | ||
155 | send_release(server_addr, requested_ip); /* unicast */ | ||
156 | run_script(NULL, "deconfig"); | ||
157 | } | ||
158 | LOG(LOG_INFO, "Entering released state"); | ||
159 | |||
160 | change_mode(LISTEN_NONE); | ||
161 | state = RELEASED; | ||
162 | timeout = 0x7fffffff; | ||
163 | } | ||
164 | |||
165 | |||
166 | static void client_background(void) | ||
167 | { | ||
168 | background(client_config.pidfile); | ||
169 | client_config.foreground = 1; /* Do not fork again. */ | ||
170 | client_config.background_if_no_lease = 0; | ||
171 | } | ||
172 | |||
173 | |||
174 | #ifdef COMBINED_BINARY | ||
175 | int udhcpc_main(int argc, char *argv[]) | ||
176 | #else | ||
177 | int main(int argc, char *argv[]) | ||
178 | #endif | ||
179 | { | ||
180 | uint8_t *temp, *message; | ||
181 | unsigned long t1 = 0, t2 = 0, xid = 0; | ||
182 | unsigned long start = 0, lease; | ||
183 | fd_set rfds; | ||
184 | int retval; | ||
185 | struct timeval tv; | ||
186 | int c, len; | ||
187 | struct dhcpMessage packet; | ||
188 | struct in_addr temp_addr; | ||
189 | long now; | ||
190 | int max_fd; | ||
191 | int sig; | ||
192 | int no_clientid = 0; | ||
193 | |||
194 | static const struct option arg_options[] = { | ||
195 | {"clientid", required_argument, 0, 'c'}, | ||
196 | {"clientid-none", no_argument, 0, 'C'}, | ||
197 | {"vendorclass", required_argument, 0, 'V'}, | ||
198 | {"foreground", no_argument, 0, 'f'}, | ||
199 | {"background", no_argument, 0, 'b'}, | ||
200 | {"hostname", required_argument, 0, 'H'}, | ||
201 | {"hostname", required_argument, 0, 'h'}, | ||
202 | {"fqdn", required_argument, 0, 'F'}, | ||
203 | {"interface", required_argument, 0, 'i'}, | ||
204 | {"now", no_argument, 0, 'n'}, | ||
205 | {"pidfile", required_argument, 0, 'p'}, | ||
206 | {"quit", no_argument, 0, 'q'}, | ||
207 | {"request", required_argument, 0, 'r'}, | ||
208 | {"script", required_argument, 0, 's'}, | ||
209 | {"timeout", required_argument, 0, 'T'}, | ||
210 | {"version", no_argument, 0, 'v'}, | ||
211 | {"retries", required_argument, 0, 't'}, | ||
212 | {0, 0, 0, 0} | ||
213 | }; | ||
214 | |||
215 | /* get options */ | ||
216 | while (1) { | ||
217 | int option_index = 0; | ||
218 | c = getopt_long(argc, argv, "c:CV:fbH:h:F:i:np:qr:s:T:t:v", arg_options, &option_index); | ||
219 | if (c == -1) break; | ||
220 | |||
221 | switch (c) { | ||
222 | case 'c': | ||
223 | if (no_clientid) show_usage(); | ||
224 | len = strlen(optarg) > 255 ? 255 : strlen(optarg); | ||
225 | free(client_config.clientid); | ||
226 | client_config.clientid = xmalloc(len + 2); | ||
227 | client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; | ||
228 | client_config.clientid[OPT_LEN] = len; | ||
229 | client_config.clientid[OPT_DATA] = '\0'; | ||
230 | strncpy((char*)client_config.clientid + OPT_DATA, optarg, len); | ||
231 | break; | ||
232 | case 'C': | ||
233 | if (client_config.clientid) show_usage(); | ||
234 | no_clientid = 1; | ||
235 | break; | ||
236 | case 'V': | ||
237 | len = strlen(optarg) > 255 ? 255 : strlen(optarg); | ||
238 | free(client_config.vendorclass); | ||
239 | client_config.vendorclass = xmalloc(len + 2); | ||
240 | client_config.vendorclass[OPT_CODE] = DHCP_VENDOR; | ||
241 | client_config.vendorclass[OPT_LEN] = len; | ||
242 | strncpy((char*)client_config.vendorclass + OPT_DATA, optarg, len); | ||
243 | break; | ||
244 | case 'f': | ||
245 | client_config.foreground = 1; | ||
246 | break; | ||
247 | case 'b': | ||
248 | client_config.background_if_no_lease = 1; | ||
249 | break; | ||
250 | case 'h': | ||
251 | case 'H': | ||
252 | len = strlen(optarg) > 255 ? 255 : strlen(optarg); | ||
253 | free(client_config.hostname); | ||
254 | client_config.hostname = xmalloc(len + 2); | ||
255 | client_config.hostname[OPT_CODE] = DHCP_HOST_NAME; | ||
256 | client_config.hostname[OPT_LEN] = len; | ||
257 | strncpy((char*)client_config.hostname + 2, optarg, len); | ||
258 | break; | ||
259 | case 'F': | ||
260 | len = strlen(optarg) > 255 ? 255 : strlen(optarg); | ||
261 | free(client_config.fqdn); | ||
262 | client_config.fqdn = xmalloc(len + 5); | ||
263 | client_config.fqdn[OPT_CODE] = DHCP_FQDN; | ||
264 | client_config.fqdn[OPT_LEN] = len + 3; | ||
265 | /* Flags: 0000NEOS | ||
266 | S: 1 => Client requests Server to update A RR in DNS as well as PTR | ||
267 | O: 1 => Server indicates to client that DNS has been updated regardless | ||
268 | E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com" | ||
269 | N: 1 => Client requests Server to not update DNS | ||
270 | */ | ||
271 | client_config.fqdn[OPT_LEN + 1] = 0x1; | ||
272 | client_config.fqdn[OPT_LEN + 2] = 0; | ||
273 | client_config.fqdn[OPT_LEN + 3] = 0; | ||
274 | strncpy((char*)client_config.fqdn + 5, optarg, len); | ||
275 | break; | ||
276 | case 'i': | ||
277 | client_config.interface = optarg; | ||
278 | break; | ||
279 | case 'n': | ||
280 | client_config.abort_if_no_lease = 1; | ||
281 | break; | ||
282 | case 'p': | ||
283 | client_config.pidfile = optarg; | ||
284 | break; | ||
285 | case 'q': | ||
286 | client_config.quit_after_lease = 1; | ||
287 | break; | ||
288 | case 'r': | ||
289 | requested_ip = inet_addr(optarg); | ||
290 | break; | ||
291 | case 's': | ||
292 | client_config.script = optarg; | ||
293 | break; | ||
294 | case 'T': | ||
295 | client_config.timeout = atoi(optarg); | ||
296 | break; | ||
297 | case 't': | ||
298 | client_config.retries = atoi(optarg); | ||
299 | break; | ||
300 | case 'v': | ||
301 | printf("udhcpcd, version %s\n\n", VERSION); | ||
302 | return 0; | ||
303 | break; | ||
304 | default: | ||
305 | show_usage(); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | /* Start the log, sanitize fd's, and write a pid file */ | ||
310 | start_log_and_pid("udhcpc", client_config.pidfile); | ||
311 | |||
312 | if (read_interface(client_config.interface, &client_config.ifindex, | ||
313 | NULL, client_config.arp) < 0) | ||
314 | return 1; | ||
315 | |||
316 | /* if not set, and not suppressed, setup the default client ID */ | ||
317 | if (!client_config.clientid && !no_clientid) { | ||
318 | client_config.clientid = xmalloc(6 + 3); | ||
319 | client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; | ||
320 | client_config.clientid[OPT_LEN] = 7; | ||
321 | client_config.clientid[OPT_DATA] = 1; | ||
322 | memcpy(client_config.clientid + 3, client_config.arp, 6); | ||
323 | } | ||
324 | |||
325 | if (!client_config.vendorclass) { | ||
326 | client_config.vendorclass = xmalloc(sizeof("udhcp "VERSION) + 2); | ||
327 | client_config.vendorclass[OPT_CODE] = DHCP_VENDOR; | ||
328 | client_config.vendorclass[OPT_LEN] = sizeof("udhcp "VERSION) - 1; | ||
329 | client_config.vendorclass[OPT_DATA] = 1; | ||
330 | memcpy(&client_config.vendorclass[OPT_DATA], | ||
331 | "udhcp "VERSION, sizeof("udhcp "VERSION) - 1); | ||
332 | } | ||
333 | |||
334 | |||
335 | /* setup the signal pipe */ | ||
336 | udhcp_sp_setup(); | ||
337 | |||
338 | state = INIT_SELECTING; | ||
339 | run_script(NULL, "deconfig"); | ||
340 | change_mode(LISTEN_RAW); | ||
341 | |||
342 | for (;;) { | ||
343 | |||
344 | tv.tv_sec = timeout - uptime(); | ||
345 | tv.tv_usec = 0; | ||
346 | |||
347 | if (listen_mode != LISTEN_NONE && fd < 0) { | ||
348 | if (listen_mode == LISTEN_KERNEL) | ||
349 | fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface); | ||
350 | else | ||
351 | fd = raw_socket(client_config.ifindex); | ||
352 | if (fd < 0) { | ||
353 | LOG(LOG_ERR, "FATAL: couldn't listen on socket, %m"); | ||
354 | return 0; | ||
355 | } | ||
356 | } | ||
357 | max_fd = udhcp_sp_fd_set(&rfds, fd); | ||
358 | |||
359 | if (tv.tv_sec > 0) { | ||
360 | DEBUG(LOG_INFO, "Waiting on select..."); | ||
361 | retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); | ||
362 | } else retval = 0; /* If we already timed out, fall through */ | ||
363 | |||
364 | now = uptime(); | ||
365 | if (retval == 0) { | ||
366 | /* timeout dropped to zero */ | ||
367 | switch (state) { | ||
368 | case INIT_SELECTING: | ||
369 | if (packet_num < client_config.retries) { | ||
370 | if (packet_num == 0) | ||
371 | xid = random_xid(); | ||
372 | |||
373 | /* send discover packet */ | ||
374 | send_discover(xid, requested_ip); /* broadcast */ | ||
375 | |||
376 | timeout = now + client_config.timeout; | ||
377 | packet_num++; | ||
378 | } else { | ||
379 | run_script(NULL, "leasefail"); | ||
380 | if (client_config.background_if_no_lease) { | ||
381 | LOG(LOG_INFO, "No lease, forking to background."); | ||
382 | client_background(); | ||
383 | } else if (client_config.abort_if_no_lease) { | ||
384 | LOG(LOG_INFO, "No lease, failing."); | ||
385 | return 1; | ||
386 | } | ||
387 | /* wait to try again */ | ||
388 | packet_num = 0; | ||
389 | timeout = now + 60; | ||
390 | } | ||
391 | break; | ||
392 | case RENEW_REQUESTED: | ||
393 | case REQUESTING: | ||
394 | if (packet_num < client_config.retries) { | ||
395 | /* send request packet */ | ||
396 | if (state == RENEW_REQUESTED) | ||
397 | send_renew(xid, server_addr, requested_ip); /* unicast */ | ||
398 | else send_selecting(xid, server_addr, requested_ip); /* broadcast */ | ||
399 | |||
400 | timeout = now + ((packet_num == 2) ? 10 : 2); | ||
401 | packet_num++; | ||
402 | } else { | ||
403 | /* timed out, go back to init state */ | ||
404 | if (state == RENEW_REQUESTED) run_script(NULL, "deconfig"); | ||
405 | state = INIT_SELECTING; | ||
406 | timeout = now; | ||
407 | packet_num = 0; | ||
408 | change_mode(LISTEN_RAW); | ||
409 | } | ||
410 | break; | ||
411 | case BOUND: | ||
412 | /* Lease is starting to run out, time to enter renewing state */ | ||
413 | state = RENEWING; | ||
414 | change_mode(LISTEN_KERNEL); | ||
415 | DEBUG(LOG_INFO, "Entering renew state"); | ||
416 | /* fall right through */ | ||
417 | case RENEWING: | ||
418 | /* Either set a new T1, or enter REBINDING state */ | ||
419 | if ((t2 - t1) <= (lease / 14400 + 1)) { | ||
420 | /* timed out, enter rebinding state */ | ||
421 | state = REBINDING; | ||
422 | timeout = now + (t2 - t1); | ||
423 | DEBUG(LOG_INFO, "Entering rebinding state"); | ||
424 | } else { | ||
425 | /* send a request packet */ | ||
426 | send_renew(xid, server_addr, requested_ip); /* unicast */ | ||
427 | |||
428 | t1 = (t2 - t1) / 2 + t1; | ||
429 | timeout = t1 + start; | ||
430 | } | ||
431 | break; | ||
432 | case REBINDING: | ||
433 | /* Either set a new T2, or enter INIT state */ | ||
434 | if ((lease - t2) <= (lease / 14400 + 1)) { | ||
435 | /* timed out, enter init state */ | ||
436 | state = INIT_SELECTING; | ||
437 | LOG(LOG_INFO, "Lease lost, entering init state"); | ||
438 | run_script(NULL, "deconfig"); | ||
439 | timeout = now; | ||
440 | packet_num = 0; | ||
441 | change_mode(LISTEN_RAW); | ||
442 | } else { | ||
443 | /* send a request packet */ | ||
444 | send_renew(xid, 0, requested_ip); /* broadcast */ | ||
445 | |||
446 | t2 = (lease - t2) / 2 + t2; | ||
447 | timeout = t2 + start; | ||
448 | } | ||
449 | break; | ||
450 | case RELEASED: | ||
451 | /* yah, I know, *you* say it would never happen */ | ||
452 | timeout = 0x7fffffff; | ||
453 | break; | ||
454 | } | ||
455 | } else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) { | ||
456 | /* a packet is ready, read it */ | ||
457 | |||
458 | if (listen_mode == LISTEN_KERNEL) | ||
459 | len = get_packet(&packet, fd); | ||
460 | else len = get_raw_packet(&packet, fd); | ||
461 | |||
462 | if (len == -1 && errno != EINTR) { | ||
463 | DEBUG(LOG_INFO, "error on read, %m, reopening socket"); | ||
464 | change_mode(listen_mode); /* just close and reopen */ | ||
465 | } | ||
466 | if (len < 0) continue; | ||
467 | |||
468 | if (packet.xid != xid) { | ||
469 | DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)", | ||
470 | (unsigned long) packet.xid, xid); | ||
471 | continue; | ||
472 | } | ||
473 | |||
474 | /* Ignore packets that aren't for us */ | ||
475 | if (memcmp(packet.chaddr, client_config.arp, 6)) { | ||
476 | DEBUG(LOG_INFO, "packet does not have our chaddr -- ignoring"); | ||
477 | continue; | ||
478 | } | ||
479 | |||
480 | if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { | ||
481 | DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring"); | ||
482 | continue; | ||
483 | } | ||
484 | |||
485 | switch (state) { | ||
486 | case INIT_SELECTING: | ||
487 | /* Must be a DHCPOFFER to one of our xid's */ | ||
488 | if (*message == DHCPOFFER) { | ||
489 | if ((temp = get_option(&packet, DHCP_SERVER_ID))) { | ||
490 | memcpy(&server_addr, temp, 4); | ||
491 | xid = packet.xid; | ||
492 | requested_ip = packet.yiaddr; | ||
493 | |||
494 | /* enter requesting state */ | ||
495 | state = REQUESTING; | ||
496 | timeout = now; | ||
497 | packet_num = 0; | ||
498 | } else { | ||
499 | DEBUG(LOG_ERR, "No server ID in message"); | ||
500 | } | ||
501 | } | ||
502 | break; | ||
503 | case RENEW_REQUESTED: | ||
504 | case REQUESTING: | ||
505 | case RENEWING: | ||
506 | case REBINDING: | ||
507 | if (*message == DHCPACK) { | ||
508 | if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) { | ||
509 | LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease"); | ||
510 | lease = 60 * 60; | ||
511 | } else { | ||
512 | memcpy(&lease, temp, 4); | ||
513 | lease = ntohl(lease); | ||
514 | } | ||
515 | |||
516 | /* enter bound state */ | ||
517 | t1 = lease / 2; | ||
518 | |||
519 | /* little fixed point for n * .875 */ | ||
520 | t2 = (lease * 0x7) >> 3; | ||
521 | temp_addr.s_addr = packet.yiaddr; | ||
522 | LOG(LOG_INFO, "Lease of %s obtained, lease time %ld", | ||
523 | inet_ntoa(temp_addr), lease); | ||
524 | start = now; | ||
525 | timeout = t1 + start; | ||
526 | requested_ip = packet.yiaddr; | ||
527 | run_script(&packet, | ||
528 | ((state == RENEWING || state == REBINDING) ? "renew" : "bound")); | ||
529 | |||
530 | state = BOUND; | ||
531 | change_mode(LISTEN_NONE); | ||
532 | if (client_config.quit_after_lease) | ||
533 | return 0; | ||
534 | if (!client_config.foreground) | ||
535 | client_background(); | ||
536 | |||
537 | } else if (*message == DHCPNAK) { | ||
538 | /* return to init state */ | ||
539 | LOG(LOG_INFO, "Received DHCP NAK"); | ||
540 | run_script(&packet, "nak"); | ||
541 | if (state != REQUESTING) | ||
542 | run_script(NULL, "deconfig"); | ||
543 | state = INIT_SELECTING; | ||
544 | timeout = now; | ||
545 | requested_ip = 0; | ||
546 | packet_num = 0; | ||
547 | change_mode(LISTEN_RAW); | ||
548 | sleep(3); /* avoid excessive network traffic */ | ||
549 | } | ||
550 | break; | ||
551 | /* case BOUND, RELEASED: - ignore all packets */ | ||
552 | } | ||
553 | } else if (retval > 0 && (sig = udhcp_sp_read(&rfds))) { | ||
554 | switch (sig) { | ||
555 | case SIGUSR1: | ||
556 | perform_renew(); | ||
557 | break; | ||
558 | case SIGUSR2: | ||
559 | perform_release(); | ||
560 | break; | ||
561 | case SIGTERM: | ||
562 | LOG(LOG_INFO, "Received SIGTERM"); | ||
563 | return 0; | ||
564 | } | ||
565 | } else if (retval == -1 && errno == EINTR) { | ||
566 | /* a signal was caught */ | ||
567 | } else { | ||
568 | /* An error occured */ | ||
569 | DEBUG(LOG_ERR, "Error on select"); | ||
570 | } | ||
571 | |||
572 | } | ||
573 | return 0; | ||
574 | } | ||
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h new file mode 100644 index 000000000..7c93f4232 --- /dev/null +++ b/networking/udhcp/dhcpc.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* dhcpc.h */ | ||
2 | #ifndef _DHCPC_H | ||
3 | #define _DHCPC_H | ||
4 | |||
5 | /* grab define DEFAULT_SCRIPT */ | ||
6 | #include "libbb_udhcp.h" | ||
7 | |||
8 | #define INIT_SELECTING 0 | ||
9 | #define REQUESTING 1 | ||
10 | #define BOUND 2 | ||
11 | #define RENEWING 3 | ||
12 | #define REBINDING 4 | ||
13 | #define INIT_REBOOT 5 | ||
14 | #define RENEW_REQUESTED 6 | ||
15 | #define RELEASED 7 | ||
16 | |||
17 | |||
18 | struct client_config_t { | ||
19 | char foreground; /* Do not fork */ | ||
20 | char quit_after_lease; /* Quit after obtaining lease */ | ||
21 | char abort_if_no_lease; /* Abort if no lease */ | ||
22 | char background_if_no_lease; /* Fork to background if no lease */ | ||
23 | char *interface; /* The name of the interface to use */ | ||
24 | char *pidfile; /* Optionally store the process ID */ | ||
25 | char *script; /* User script to run at dhcp events */ | ||
26 | uint8_t *clientid; /* Optional client id to use */ | ||
27 | uint8_t *vendorclass; /* Optional vendor class-id to use */ | ||
28 | uint8_t *hostname; /* Optional hostname to use */ | ||
29 | uint8_t *fqdn; /* Optional fully qualified domain name to use */ | ||
30 | int ifindex; /* Index number of the interface to use */ | ||
31 | int retries; /* Max number of request packets */ | ||
32 | int timeout; /* Number of seconds to try to get a lease */ | ||
33 | uint8_t arp[6]; /* Our arp address */ | ||
34 | }; | ||
35 | |||
36 | extern struct client_config_t client_config; | ||
37 | |||
38 | |||
39 | #endif | ||
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c new file mode 100644 index 000000000..0dfc0b559 --- /dev/null +++ b/networking/udhcp/dhcpd.c | |||
@@ -0,0 +1,273 @@ | |||
1 | /* dhcpd.c | ||
2 | * | ||
3 | * udhcp Server | ||
4 | * Copyright (C) 1999 Matthew Ramsay <matthewr@moreton.com.au> | ||
5 | * Chris Trew <ctrew@moreton.com.au> | ||
6 | * | ||
7 | * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <fcntl.h> | ||
25 | #include <string.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <sys/wait.h> | ||
28 | #include <arpa/inet.h> | ||
29 | #include <netdb.h> | ||
30 | #include <netinet/in.h> | ||
31 | #include <sys/socket.h> | ||
32 | #include <unistd.h> | ||
33 | #include <signal.h> | ||
34 | #include <errno.h> | ||
35 | #include <sys/ioctl.h> | ||
36 | #include <time.h> | ||
37 | #include <sys/time.h> | ||
38 | |||
39 | #include "dhcpd.h" | ||
40 | #include "arpping.h" | ||
41 | #include "socket.h" | ||
42 | #include "options.h" | ||
43 | #include "files.h" | ||
44 | #include "serverpacket.h" | ||
45 | #include "common.h" | ||
46 | #include "signalpipe.h" | ||
47 | #include "static_leases.h" | ||
48 | |||
49 | |||
50 | /* globals */ | ||
51 | struct dhcpOfferedAddr *leases; | ||
52 | struct server_config_t server_config; | ||
53 | |||
54 | |||
55 | #ifdef COMBINED_BINARY | ||
56 | int udhcpd_main(int argc, char *argv[]) | ||
57 | #else | ||
58 | int main(int argc, char *argv[]) | ||
59 | #endif | ||
60 | { | ||
61 | fd_set rfds; | ||
62 | struct timeval tv; | ||
63 | int server_socket = -1; | ||
64 | int bytes, retval; | ||
65 | struct dhcpMessage packet; | ||
66 | uint8_t *state; | ||
67 | uint8_t *server_id, *requested; | ||
68 | uint32_t server_id_align, requested_align; | ||
69 | unsigned long timeout_end; | ||
70 | struct option_set *option; | ||
71 | struct dhcpOfferedAddr *lease; | ||
72 | struct dhcpOfferedAddr static_lease; | ||
73 | int max_sock; | ||
74 | unsigned long num_ips; | ||
75 | |||
76 | uint32_t static_lease_ip; | ||
77 | |||
78 | memset(&server_config, 0, sizeof(struct server_config_t)); | ||
79 | read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]); | ||
80 | |||
81 | /* Start the log, sanitize fd's, and write a pid file */ | ||
82 | start_log_and_pid("udhcpd", server_config.pidfile); | ||
83 | |||
84 | if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) { | ||
85 | memcpy(&server_config.lease, option->data + 2, 4); | ||
86 | server_config.lease = ntohl(server_config.lease); | ||
87 | } | ||
88 | else server_config.lease = LEASE_TIME; | ||
89 | |||
90 | /* Sanity check */ | ||
91 | num_ips = ntohl(server_config.end) - ntohl(server_config.start) + 1; | ||
92 | if (server_config.max_leases > num_ips) { | ||
93 | LOG(LOG_ERR, "max_leases value (%lu) not sane, " | ||
94 | "setting to %lu instead", | ||
95 | server_config.max_leases, num_ips); | ||
96 | server_config.max_leases = num_ips; | ||
97 | } | ||
98 | |||
99 | leases = xcalloc(server_config.max_leases, sizeof(struct dhcpOfferedAddr)); | ||
100 | read_leases(server_config.lease_file); | ||
101 | |||
102 | if (read_interface(server_config.interface, &server_config.ifindex, | ||
103 | &server_config.server, server_config.arp) < 0) | ||
104 | return 1; | ||
105 | |||
106 | #ifndef UDHCP_DEBUG | ||
107 | background(server_config.pidfile); /* hold lock during fork. */ | ||
108 | #endif | ||
109 | |||
110 | /* Setup the signal pipe */ | ||
111 | udhcp_sp_setup(); | ||
112 | |||
113 | timeout_end = time(0) + server_config.auto_time; | ||
114 | while(1) { /* loop until universe collapses */ | ||
115 | |||
116 | if (server_socket < 0) | ||
117 | if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) { | ||
118 | LOG(LOG_ERR, "FATAL: couldn't create server socket, %m"); | ||
119 | return 2; | ||
120 | } | ||
121 | |||
122 | max_sock = udhcp_sp_fd_set(&rfds, server_socket); | ||
123 | if (server_config.auto_time) { | ||
124 | tv.tv_sec = timeout_end - time(0); | ||
125 | tv.tv_usec = 0; | ||
126 | } | ||
127 | if (!server_config.auto_time || tv.tv_sec > 0) { | ||
128 | retval = select(max_sock + 1, &rfds, NULL, NULL, | ||
129 | server_config.auto_time ? &tv : NULL); | ||
130 | } else retval = 0; /* If we already timed out, fall through */ | ||
131 | |||
132 | if (retval == 0) { | ||
133 | write_leases(); | ||
134 | timeout_end = time(0) + server_config.auto_time; | ||
135 | continue; | ||
136 | } else if (retval < 0 && errno != EINTR) { | ||
137 | DEBUG(LOG_INFO, "error on select"); | ||
138 | continue; | ||
139 | } | ||
140 | |||
141 | switch (udhcp_sp_read(&rfds)) { | ||
142 | case SIGUSR1: | ||
143 | LOG(LOG_INFO, "Received a SIGUSR1"); | ||
144 | write_leases(); | ||
145 | /* why not just reset the timeout, eh */ | ||
146 | timeout_end = time(0) + server_config.auto_time; | ||
147 | continue; | ||
148 | case SIGTERM: | ||
149 | LOG(LOG_INFO, "Received a SIGTERM"); | ||
150 | return 0; | ||
151 | case 0: break; /* no signal */ | ||
152 | default: continue; /* signal or error (probably EINTR) */ | ||
153 | } | ||
154 | |||
155 | if ((bytes = get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */ | ||
156 | if (bytes == -1 && errno != EINTR) { | ||
157 | DEBUG(LOG_INFO, "error on read, %m, reopening socket"); | ||
158 | close(server_socket); | ||
159 | server_socket = -1; | ||
160 | } | ||
161 | continue; | ||
162 | } | ||
163 | |||
164 | if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { | ||
165 | DEBUG(LOG_ERR, "couldn't get option from packet, ignoring"); | ||
166 | continue; | ||
167 | } | ||
168 | |||
169 | /* Look for a static lease */ | ||
170 | static_lease_ip = getIpByMac(server_config.static_leases, &packet.chaddr); | ||
171 | |||
172 | if(static_lease_ip) | ||
173 | { | ||
174 | printf("Found static lease: %x\n", static_lease_ip); | ||
175 | |||
176 | memcpy(&static_lease.chaddr, &packet.chaddr, 16); | ||
177 | static_lease.yiaddr = static_lease_ip; | ||
178 | static_lease.expires = 0; | ||
179 | |||
180 | lease = &static_lease; | ||
181 | |||
182 | } | ||
183 | else | ||
184 | { | ||
185 | lease = find_lease_by_chaddr(packet.chaddr); | ||
186 | } | ||
187 | |||
188 | switch (state[0]) { | ||
189 | case DHCPDISCOVER: | ||
190 | DEBUG(LOG_INFO,"received DISCOVER"); | ||
191 | |||
192 | if (sendOffer(&packet) < 0) { | ||
193 | LOG(LOG_ERR, "send OFFER failed"); | ||
194 | } | ||
195 | break; | ||
196 | case DHCPREQUEST: | ||
197 | DEBUG(LOG_INFO, "received REQUEST"); | ||
198 | |||
199 | requested = get_option(&packet, DHCP_REQUESTED_IP); | ||
200 | server_id = get_option(&packet, DHCP_SERVER_ID); | ||
201 | |||
202 | if (requested) memcpy(&requested_align, requested, 4); | ||
203 | if (server_id) memcpy(&server_id_align, server_id, 4); | ||
204 | |||
205 | if (lease) { | ||
206 | if (server_id) { | ||
207 | /* SELECTING State */ | ||
208 | DEBUG(LOG_INFO, "server_id = %08x", ntohl(server_id_align)); | ||
209 | if (server_id_align == server_config.server && requested && | ||
210 | requested_align == lease->yiaddr) { | ||
211 | sendACK(&packet, lease->yiaddr); | ||
212 | } | ||
213 | } else { | ||
214 | if (requested) { | ||
215 | /* INIT-REBOOT State */ | ||
216 | if (lease->yiaddr == requested_align) | ||
217 | sendACK(&packet, lease->yiaddr); | ||
218 | else sendNAK(&packet); | ||
219 | } else { | ||
220 | /* RENEWING or REBINDING State */ | ||
221 | if (lease->yiaddr == packet.ciaddr) | ||
222 | sendACK(&packet, lease->yiaddr); | ||
223 | else { | ||
224 | /* don't know what to do!!!! */ | ||
225 | sendNAK(&packet); | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | /* what to do if we have no record of the client */ | ||
231 | } else if (server_id) { | ||
232 | /* SELECTING State */ | ||
233 | |||
234 | } else if (requested) { | ||
235 | /* INIT-REBOOT State */ | ||
236 | if ((lease = find_lease_by_yiaddr(requested_align))) { | ||
237 | if (lease_expired(lease)) { | ||
238 | /* probably best if we drop this lease */ | ||
239 | memset(lease->chaddr, 0, 16); | ||
240 | /* make some contention for this address */ | ||
241 | } else sendNAK(&packet); | ||
242 | } else if (requested_align < server_config.start || | ||
243 | requested_align > server_config.end) { | ||
244 | sendNAK(&packet); | ||
245 | } /* else remain silent */ | ||
246 | |||
247 | } else { | ||
248 | /* RENEWING or REBINDING State */ | ||
249 | } | ||
250 | break; | ||
251 | case DHCPDECLINE: | ||
252 | DEBUG(LOG_INFO,"received DECLINE"); | ||
253 | if (lease) { | ||
254 | memset(lease->chaddr, 0, 16); | ||
255 | lease->expires = time(0) + server_config.decline_time; | ||
256 | } | ||
257 | break; | ||
258 | case DHCPRELEASE: | ||
259 | DEBUG(LOG_INFO,"received RELEASE"); | ||
260 | if (lease) lease->expires = time(0); | ||
261 | break; | ||
262 | case DHCPINFORM: | ||
263 | DEBUG(LOG_INFO,"received INFORM"); | ||
264 | send_inform(&packet); | ||
265 | break; | ||
266 | default: | ||
267 | LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h new file mode 100644 index 000000000..a060002cd --- /dev/null +++ b/networking/udhcp/dhcpd.h | |||
@@ -0,0 +1,141 @@ | |||
1 | /* dhcpd.h */ | ||
2 | #ifndef _DHCPD_H | ||
3 | #define _DHCPD_H | ||
4 | |||
5 | #include <netinet/ip.h> | ||
6 | #include <netinet/udp.h> | ||
7 | |||
8 | #include "libbb_udhcp.h" | ||
9 | #include "leases.h" | ||
10 | #include "version.h" | ||
11 | |||
12 | /************************************/ | ||
13 | /* Defaults _you_ may want to tweak */ | ||
14 | /************************************/ | ||
15 | |||
16 | /* the period of time the client is allowed to use that address */ | ||
17 | #define LEASE_TIME (60*60*24*10) /* 10 days of seconds */ | ||
18 | #define LEASES_FILE "/var/lib/misc/udhcpd.leases" | ||
19 | |||
20 | /* where to find the DHCP server configuration file */ | ||
21 | #define DHCPD_CONF_FILE "/etc/udhcpd.conf" | ||
22 | |||
23 | /*****************************************************************/ | ||
24 | /* Do not modify below here unless you know what you are doing!! */ | ||
25 | /*****************************************************************/ | ||
26 | |||
27 | /* DHCP protocol -- see RFC 2131 */ | ||
28 | #define SERVER_PORT 67 | ||
29 | #define CLIENT_PORT 68 | ||
30 | |||
31 | #define DHCP_MAGIC 0x63825363 | ||
32 | |||
33 | /* DHCP option codes (partial list) */ | ||
34 | #define DHCP_PADDING 0x00 | ||
35 | #define DHCP_SUBNET 0x01 | ||
36 | #define DHCP_TIME_OFFSET 0x02 | ||
37 | #define DHCP_ROUTER 0x03 | ||
38 | #define DHCP_TIME_SERVER 0x04 | ||
39 | #define DHCP_NAME_SERVER 0x05 | ||
40 | #define DHCP_DNS_SERVER 0x06 | ||
41 | #define DHCP_LOG_SERVER 0x07 | ||
42 | #define DHCP_COOKIE_SERVER 0x08 | ||
43 | #define DHCP_LPR_SERVER 0x09 | ||
44 | #define DHCP_HOST_NAME 0x0c | ||
45 | #define DHCP_BOOT_SIZE 0x0d | ||
46 | #define DHCP_DOMAIN_NAME 0x0f | ||
47 | #define DHCP_SWAP_SERVER 0x10 | ||
48 | #define DHCP_ROOT_PATH 0x11 | ||
49 | #define DHCP_IP_TTL 0x17 | ||
50 | #define DHCP_MTU 0x1a | ||
51 | #define DHCP_BROADCAST 0x1c | ||
52 | #define DHCP_NTP_SERVER 0x2a | ||
53 | #define DHCP_WINS_SERVER 0x2c | ||
54 | #define DHCP_REQUESTED_IP 0x32 | ||
55 | #define DHCP_LEASE_TIME 0x33 | ||
56 | #define DHCP_OPTION_OVER 0x34 | ||
57 | #define DHCP_MESSAGE_TYPE 0x35 | ||
58 | #define DHCP_SERVER_ID 0x36 | ||
59 | #define DHCP_PARAM_REQ 0x37 | ||
60 | #define DHCP_MESSAGE 0x38 | ||
61 | #define DHCP_MAX_SIZE 0x39 | ||
62 | #define DHCP_T1 0x3a | ||
63 | #define DHCP_T2 0x3b | ||
64 | #define DHCP_VENDOR 0x3c | ||
65 | #define DHCP_CLIENT_ID 0x3d | ||
66 | #define DHCP_FQDN 0x51 | ||
67 | |||
68 | #define DHCP_END 0xFF | ||
69 | |||
70 | |||
71 | #define BOOTREQUEST 1 | ||
72 | #define BOOTREPLY 2 | ||
73 | |||
74 | #define ETH_10MB 1 | ||
75 | #define ETH_10MB_LEN 6 | ||
76 | |||
77 | #define DHCPDISCOVER 1 | ||
78 | #define DHCPOFFER 2 | ||
79 | #define DHCPREQUEST 3 | ||
80 | #define DHCPDECLINE 4 | ||
81 | #define DHCPACK 5 | ||
82 | #define DHCPNAK 6 | ||
83 | #define DHCPRELEASE 7 | ||
84 | #define DHCPINFORM 8 | ||
85 | |||
86 | #define BROADCAST_FLAG 0x8000 | ||
87 | |||
88 | #define OPTION_FIELD 0 | ||
89 | #define FILE_FIELD 1 | ||
90 | #define SNAME_FIELD 2 | ||
91 | |||
92 | /* miscellaneous defines */ | ||
93 | #define MAC_BCAST_ADDR (uint8_t *) "\xff\xff\xff\xff\xff\xff" | ||
94 | #define OPT_CODE 0 | ||
95 | #define OPT_LEN 1 | ||
96 | #define OPT_DATA 2 | ||
97 | |||
98 | struct option_set { | ||
99 | uint8_t *data; | ||
100 | struct option_set *next; | ||
101 | }; | ||
102 | |||
103 | struct static_lease { | ||
104 | uint8_t *mac; | ||
105 | uint32_t *ip; | ||
106 | struct static_lease *next; | ||
107 | }; | ||
108 | |||
109 | struct server_config_t { | ||
110 | uint32_t server; /* Our IP, in network order */ | ||
111 | uint32_t start; /* Start address of leases, network order */ | ||
112 | uint32_t end; /* End of leases, network order */ | ||
113 | struct option_set *options; /* List of DHCP options loaded from the config file */ | ||
114 | char *interface; /* The name of the interface to use */ | ||
115 | int ifindex; /* Index number of the interface to use */ | ||
116 | uint8_t arp[6]; /* Our arp address */ | ||
117 | unsigned long lease; /* lease time in seconds (host order) */ | ||
118 | unsigned long max_leases; /* maximum number of leases (including reserved address) */ | ||
119 | char remaining; /* should the lease file be interpreted as lease time remaining, or | ||
120 | * as the time the lease expires */ | ||
121 | unsigned long auto_time; /* how long should udhcpd wait before writing a config file. | ||
122 | * if this is zero, it will only write one on SIGUSR1 */ | ||
123 | unsigned long decline_time; /* how long an address is reserved if a client returns a | ||
124 | * decline message */ | ||
125 | unsigned long conflict_time; /* how long an arp conflict offender is leased for */ | ||
126 | unsigned long offer_time; /* how long an offered address is reserved */ | ||
127 | unsigned long min_lease; /* minimum lease a client can request*/ | ||
128 | char *lease_file; | ||
129 | char *pidfile; | ||
130 | char *notify_file; /* What to run whenever leases are written */ | ||
131 | uint32_t siaddr; /* next server bootp option */ | ||
132 | char *sname; /* bootp server name */ | ||
133 | char *boot_file; /* bootp boot file option */ | ||
134 | struct static_lease *static_leases; /* List of ip/mac pairs to assign static leases */ | ||
135 | }; | ||
136 | |||
137 | extern struct server_config_t server_config; | ||
138 | extern struct dhcpOfferedAddr *leases; | ||
139 | |||
140 | |||
141 | #endif | ||
diff --git a/networking/udhcp/dumpleases.1 b/networking/udhcp/dumpleases.1 new file mode 100644 index 000000000..04a04da15 --- /dev/null +++ b/networking/udhcp/dumpleases.1 | |||
@@ -0,0 +1,30 @@ | |||
1 | .TH DUMPLEASES 1 2001-09-27 GNU/Linux "GNU/Linux Administrator's Manual" | ||
2 | .SH NAME | ||
3 | dumpleases \- display leases granted by udhcp server | ||
4 | .SH SYNOPSIS | ||
5 | .B dumpleases | ||
6 | .RI [ OPTION ]... | ||
7 | .SH DESCRIPTION | ||
8 | Display the DHCP leases granted by | ||
9 | .BR udhcpd (8). | ||
10 | .SH OPTIONS | ||
11 | .TP | ||
12 | .BR \-a ,\ \-\-absolute | ||
13 | Interpret lease times as expiration time. | ||
14 | .TP | ||
15 | .BI \-f\ FILE,\ \-\-file= FILE | ||
16 | Read lease information from | ||
17 | .IR FILE . | ||
18 | .TP | ||
19 | .BR \-h ,\ \-\-help | ||
20 | Display help. | ||
21 | .TP | ||
22 | .BR \-r ,\ \-\-remaining | ||
23 | Interpret lease times as remaining time. | ||
24 | .SH FILES | ||
25 | .TP | ||
26 | .I /var/lib/misc/udhcpd.leases | ||
27 | Lease information file. | ||
28 | .SH SEE ALSO | ||
29 | .BR udhcpd (8), | ||
30 | .BR udhcpd.conf (5). | ||
diff --git a/networking/udhcp/dumpleases.c b/networking/udhcp/dumpleases.c new file mode 100644 index 000000000..c0c58ee35 --- /dev/null +++ b/networking/udhcp/dumpleases.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | ||
4 | */ | ||
5 | #include <fcntl.h> | ||
6 | #include <string.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <stdio.h> | ||
9 | #include <sys/wait.h> | ||
10 | #include <arpa/inet.h> | ||
11 | #include <netdb.h> | ||
12 | #include <netinet/in.h> | ||
13 | #include <stdio.h> | ||
14 | #include <sys/socket.h> | ||
15 | #include <unistd.h> | ||
16 | #include <getopt.h> | ||
17 | #include <time.h> | ||
18 | |||
19 | #include "dhcpd.h" | ||
20 | #include "leases.h" | ||
21 | #include "libbb_udhcp.h" | ||
22 | |||
23 | #define REMAINING 0 | ||
24 | #define ABSOLUTE 1 | ||
25 | |||
26 | |||
27 | #ifndef IN_BUSYBOX | ||
28 | static void ATTRIBUTE_NORETURN show_usage(void) | ||
29 | { | ||
30 | printf( | ||
31 | "Usage: dumpleases -f <file> -[r|a]\n\n" | ||
32 | " -f, --file=FILENAME Leases file to load\n" | ||
33 | " -r, --remaining Interepret lease times as time remaing\n" | ||
34 | " -a, --absolute Interepret lease times as expire time\n"); | ||
35 | exit(0); | ||
36 | } | ||
37 | #else | ||
38 | #define show_usage bb_show_usage | ||
39 | #endif | ||
40 | |||
41 | |||
42 | #ifdef IN_BUSYBOX | ||
43 | int dumpleases_main(int argc, char *argv[]) | ||
44 | #else | ||
45 | int main(int argc, char *argv[]) | ||
46 | #endif | ||
47 | { | ||
48 | FILE *fp; | ||
49 | int i, c, mode = REMAINING; | ||
50 | long expires; | ||
51 | const char *file = LEASES_FILE; | ||
52 | struct dhcpOfferedAddr lease; | ||
53 | struct in_addr addr; | ||
54 | |||
55 | static const struct option options[] = { | ||
56 | {"absolute", 0, 0, 'a'}, | ||
57 | {"remaining", 0, 0, 'r'}, | ||
58 | {"file", 1, 0, 'f'}, | ||
59 | {0, 0, 0, 0} | ||
60 | }; | ||
61 | |||
62 | while (1) { | ||
63 | int option_index = 0; | ||
64 | c = getopt_long(argc, argv, "arf:", options, &option_index); | ||
65 | if (c == -1) break; | ||
66 | |||
67 | switch (c) { | ||
68 | case 'a': mode = ABSOLUTE; break; | ||
69 | case 'r': mode = REMAINING; break; | ||
70 | case 'f': | ||
71 | file = optarg; | ||
72 | break; | ||
73 | default: | ||
74 | show_usage(); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | fp = xfopen(file, "r"); | ||
79 | |||
80 | printf("Mac Address IP-Address Expires %s\n", mode == REMAINING ? "in" : "at"); | ||
81 | /* "00:00:00:00:00:00 255.255.255.255 Wed Jun 30 21:49:08 1993" */ | ||
82 | while (fread(&lease, sizeof(lease), 1, fp)) { | ||
83 | |||
84 | for (i = 0; i < 6; i++) { | ||
85 | printf("%02x", lease.chaddr[i]); | ||
86 | if (i != 5) printf(":"); | ||
87 | } | ||
88 | addr.s_addr = lease.yiaddr; | ||
89 | printf(" %-15s", inet_ntoa(addr)); | ||
90 | expires = ntohl(lease.expires); | ||
91 | printf(" "); | ||
92 | if (mode == REMAINING) { | ||
93 | if (!expires) printf("expired\n"); | ||
94 | else { | ||
95 | if (expires > 60*60*24) { | ||
96 | printf("%ld days, ", expires / (60*60*24)); | ||
97 | expires %= 60*60*24; | ||
98 | } | ||
99 | if (expires > 60*60) { | ||
100 | printf("%ld hours, ", expires / (60*60)); | ||
101 | expires %= 60*60; | ||
102 | } | ||
103 | if (expires > 60) { | ||
104 | printf("%ld minutes, ", expires / 60); | ||
105 | expires %= 60; | ||
106 | } | ||
107 | printf("%ld seconds\n", expires); | ||
108 | } | ||
109 | } else printf("%s", ctime(&expires)); | ||
110 | } | ||
111 | fclose(fp); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c new file mode 100644 index 000000000..fe853c7cc --- /dev/null +++ b/networking/udhcp/files.c | |||
@@ -0,0 +1,393 @@ | |||
1 | /* | ||
2 | * files.c -- DHCP server file manipulation * | ||
3 | * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
4 | */ | ||
5 | |||
6 | #include <sys/socket.h> | ||
7 | #include <arpa/inet.h> | ||
8 | #include <string.h> | ||
9 | #include <stdlib.h> | ||
10 | #include <time.h> | ||
11 | #include <ctype.h> | ||
12 | #include <netdb.h> | ||
13 | |||
14 | #include <netinet/ether.h> | ||
15 | #include "static_leases.h" | ||
16 | |||
17 | #include "dhcpd.h" | ||
18 | #include "options.h" | ||
19 | #include "files.h" | ||
20 | #include "common.h" | ||
21 | |||
22 | /* | ||
23 | * Domain names may have 254 chars, and string options can be 254 | ||
24 | * chars long. However, 80 bytes will be enough for most, and won't | ||
25 | * hog up memory. If you have a special application, change it | ||
26 | */ | ||
27 | #define READ_CONFIG_BUF_SIZE 80 | ||
28 | |||
29 | /* on these functions, make sure you datatype matches */ | ||
30 | static int read_ip(const char *line, void *arg) | ||
31 | { | ||
32 | struct in_addr *addr = arg; | ||
33 | struct hostent *host; | ||
34 | int retval = 1; | ||
35 | |||
36 | if (!inet_aton(line, addr)) { | ||
37 | if ((host = gethostbyname(line))) | ||
38 | addr->s_addr = *((unsigned long *) host->h_addr_list[0]); | ||
39 | else retval = 0; | ||
40 | } | ||
41 | return retval; | ||
42 | } | ||
43 | |||
44 | static int read_mac(const char *line, void *arg) | ||
45 | { | ||
46 | uint8_t *mac_bytes = arg; | ||
47 | struct ether_addr *temp_ether_addr; | ||
48 | int retval = 1; | ||
49 | |||
50 | temp_ether_addr = ether_aton(line); | ||
51 | |||
52 | if(temp_ether_addr == NULL) | ||
53 | retval = 0; | ||
54 | else | ||
55 | memcpy(mac_bytes, temp_ether_addr, 6); | ||
56 | |||
57 | return retval; | ||
58 | } | ||
59 | |||
60 | |||
61 | static int read_str(const char *line, void *arg) | ||
62 | { | ||
63 | char **dest = arg; | ||
64 | |||
65 | free(*dest); | ||
66 | *dest = strdup(line); | ||
67 | |||
68 | return 1; | ||
69 | } | ||
70 | |||
71 | |||
72 | static int read_u32(const char *line, void *arg) | ||
73 | { | ||
74 | uint32_t *dest = arg; | ||
75 | char *endptr; | ||
76 | *dest = strtoul(line, &endptr, 0); | ||
77 | return endptr[0] == '\0'; | ||
78 | } | ||
79 | |||
80 | |||
81 | static int read_yn(const char *line, void *arg) | ||
82 | { | ||
83 | char *dest = arg; | ||
84 | int retval = 1; | ||
85 | |||
86 | if (!strcasecmp("yes", line)) | ||
87 | *dest = 1; | ||
88 | else if (!strcasecmp("no", line)) | ||
89 | *dest = 0; | ||
90 | else retval = 0; | ||
91 | |||
92 | return retval; | ||
93 | } | ||
94 | |||
95 | |||
96 | /* find option 'code' in opt_list */ | ||
97 | struct option_set *find_option(struct option_set *opt_list, char code) | ||
98 | { | ||
99 | while (opt_list && opt_list->data[OPT_CODE] < code) | ||
100 | opt_list = opt_list->next; | ||
101 | |||
102 | if (opt_list && opt_list->data[OPT_CODE] == code) return opt_list; | ||
103 | else return NULL; | ||
104 | } | ||
105 | |||
106 | |||
107 | /* add an option to the opt_list */ | ||
108 | static void attach_option(struct option_set **opt_list, struct dhcp_option *option, char *buffer, int length) | ||
109 | { | ||
110 | struct option_set *existing, *new, **curr; | ||
111 | |||
112 | /* add it to an existing option */ | ||
113 | if ((existing = find_option(*opt_list, option->code))) { | ||
114 | DEBUG(LOG_INFO, "Attaching option %s to existing member of list", option->name); | ||
115 | if (option->flags & OPTION_LIST) { | ||
116 | if (existing->data[OPT_LEN] + length <= 255) { | ||
117 | existing->data = realloc(existing->data, | ||
118 | existing->data[OPT_LEN] + length + 2); | ||
119 | memcpy(existing->data + existing->data[OPT_LEN] + 2, buffer, length); | ||
120 | existing->data[OPT_LEN] += length; | ||
121 | } /* else, ignore the data, we could put this in a second option in the future */ | ||
122 | } /* else, ignore the new data */ | ||
123 | } else { | ||
124 | DEBUG(LOG_INFO, "Attaching option %s to list", option->name); | ||
125 | |||
126 | /* make a new option */ | ||
127 | new = xmalloc(sizeof(struct option_set)); | ||
128 | new->data = xmalloc(length + 2); | ||
129 | new->data[OPT_CODE] = option->code; | ||
130 | new->data[OPT_LEN] = length; | ||
131 | memcpy(new->data + 2, buffer, length); | ||
132 | |||
133 | curr = opt_list; | ||
134 | while (*curr && (*curr)->data[OPT_CODE] < option->code) | ||
135 | curr = &(*curr)->next; | ||
136 | |||
137 | new->next = *curr; | ||
138 | *curr = new; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | |||
143 | /* read a dhcp option and add it to opt_list */ | ||
144 | static int read_opt(const char *const_line, void *arg) | ||
145 | { | ||
146 | struct option_set **opt_list = arg; | ||
147 | char *opt, *val, *endptr; | ||
148 | struct dhcp_option *option; | ||
149 | int retval = 0, length; | ||
150 | char buffer[8]; | ||
151 | char *line; | ||
152 | uint16_t *result_u16 = (uint16_t *) buffer; | ||
153 | uint32_t *result_u32 = (uint32_t *) buffer; | ||
154 | |||
155 | /* Cheat, the only const line we'll actually get is "" */ | ||
156 | line = (char *) const_line; | ||
157 | if (!(opt = strtok(line, " \t="))) return 0; | ||
158 | |||
159 | for (option = dhcp_options; option->code; option++) | ||
160 | if (!strcasecmp(option->name, opt)) | ||
161 | break; | ||
162 | |||
163 | if (!option->code) return 0; | ||
164 | |||
165 | do { | ||
166 | if (!(val = strtok(NULL, ", \t"))) break; | ||
167 | length = option_lengths[option->flags & TYPE_MASK]; | ||
168 | retval = 0; | ||
169 | opt = buffer; /* new meaning for variable opt */ | ||
170 | switch (option->flags & TYPE_MASK) { | ||
171 | case OPTION_IP: | ||
172 | retval = read_ip(val, buffer); | ||
173 | break; | ||
174 | case OPTION_IP_PAIR: | ||
175 | retval = read_ip(val, buffer); | ||
176 | if (!(val = strtok(NULL, ", \t/-"))) retval = 0; | ||
177 | if (retval) retval = read_ip(val, buffer + 4); | ||
178 | break; | ||
179 | case OPTION_STRING: | ||
180 | length = strlen(val); | ||
181 | if (length > 0) { | ||
182 | if (length > 254) length = 254; | ||
183 | opt = val; | ||
184 | retval = 1; | ||
185 | } | ||
186 | break; | ||
187 | case OPTION_BOOLEAN: | ||
188 | retval = read_yn(val, buffer); | ||
189 | break; | ||
190 | case OPTION_U8: | ||
191 | buffer[0] = strtoul(val, &endptr, 0); | ||
192 | retval = (endptr[0] == '\0'); | ||
193 | break; | ||
194 | case OPTION_U16: | ||
195 | *result_u16 = htons(strtoul(val, &endptr, 0)); | ||
196 | retval = (endptr[0] == '\0'); | ||
197 | break; | ||
198 | case OPTION_S16: | ||
199 | *result_u16 = htons(strtol(val, &endptr, 0)); | ||
200 | retval = (endptr[0] == '\0'); | ||
201 | break; | ||
202 | case OPTION_U32: | ||
203 | *result_u32 = htonl(strtoul(val, &endptr, 0)); | ||
204 | retval = (endptr[0] == '\0'); | ||
205 | break; | ||
206 | case OPTION_S32: | ||
207 | *result_u32 = htonl(strtol(val, &endptr, 0)); | ||
208 | retval = (endptr[0] == '\0'); | ||
209 | break; | ||
210 | default: | ||
211 | break; | ||
212 | } | ||
213 | if (retval) | ||
214 | attach_option(opt_list, option, opt, length); | ||
215 | } while (retval && option->flags & OPTION_LIST); | ||
216 | return retval; | ||
217 | } | ||
218 | |||
219 | static int read_staticlease(const char *const_line, void *arg) | ||
220 | { | ||
221 | |||
222 | char *line; | ||
223 | char *mac_string; | ||
224 | char *ip_string; | ||
225 | uint8_t *mac_bytes; | ||
226 | uint32_t *ip; | ||
227 | |||
228 | |||
229 | /* Allocate memory for addresses */ | ||
230 | mac_bytes = xmalloc(sizeof(unsigned char) * 8); | ||
231 | ip = xmalloc(sizeof(uint32_t)); | ||
232 | |||
233 | /* Read mac */ | ||
234 | line = (char *) const_line; | ||
235 | mac_string = strtok(line, " \t"); | ||
236 | read_mac(mac_string, mac_bytes); | ||
237 | |||
238 | /* Read ip */ | ||
239 | ip_string = strtok(NULL, " \t"); | ||
240 | read_ip(ip_string, ip); | ||
241 | |||
242 | addStaticLease(arg, mac_bytes, ip); | ||
243 | |||
244 | #ifdef UDHCP_DEBUG | ||
245 | printStaticLeases(arg); | ||
246 | #endif | ||
247 | |||
248 | return 1; | ||
249 | |||
250 | } | ||
251 | |||
252 | |||
253 | static const struct config_keyword keywords[] = { | ||
254 | /* keyword handler variable address default */ | ||
255 | {"start", read_ip, &(server_config.start), "192.168.0.20"}, | ||
256 | {"end", read_ip, &(server_config.end), "192.168.0.254"}, | ||
257 | {"interface", read_str, &(server_config.interface), "eth0"}, | ||
258 | {"option", read_opt, &(server_config.options), ""}, | ||
259 | {"opt", read_opt, &(server_config.options), ""}, | ||
260 | {"max_leases", read_u32, &(server_config.max_leases), "254"}, | ||
261 | {"remaining", read_yn, &(server_config.remaining), "yes"}, | ||
262 | {"auto_time", read_u32, &(server_config.auto_time), "7200"}, | ||
263 | {"decline_time",read_u32, &(server_config.decline_time),"3600"}, | ||
264 | {"conflict_time",read_u32,&(server_config.conflict_time),"3600"}, | ||
265 | {"offer_time", read_u32, &(server_config.offer_time), "60"}, | ||
266 | {"min_lease", read_u32, &(server_config.min_lease), "60"}, | ||
267 | {"lease_file", read_str, &(server_config.lease_file), LEASES_FILE}, | ||
268 | {"pidfile", read_str, &(server_config.pidfile), "/var/run/udhcpd.pid"}, | ||
269 | {"notify_file", read_str, &(server_config.notify_file), ""}, | ||
270 | {"siaddr", read_ip, &(server_config.siaddr), "0.0.0.0"}, | ||
271 | {"sname", read_str, &(server_config.sname), ""}, | ||
272 | {"boot_file", read_str, &(server_config.boot_file), ""}, | ||
273 | {"static_lease",read_staticlease, &(server_config.static_leases), ""}, | ||
274 | /*ADDME: static lease */ | ||
275 | {"", NULL, NULL, ""} | ||
276 | }; | ||
277 | |||
278 | |||
279 | int read_config(const char *file) | ||
280 | { | ||
281 | FILE *in; | ||
282 | char buffer[READ_CONFIG_BUF_SIZE], *token, *line; | ||
283 | #ifdef UDHCP_DEBUG | ||
284 | char orig[READ_CONFIG_BUF_SIZE]; | ||
285 | #endif | ||
286 | int i, lm = 0; | ||
287 | |||
288 | for (i = 0; keywords[i].keyword[0]; i++) | ||
289 | if (keywords[i].def[0]) | ||
290 | keywords[i].handler(keywords[i].def, keywords[i].var); | ||
291 | |||
292 | if (!(in = fopen(file, "r"))) { | ||
293 | LOG(LOG_ERR, "unable to open config file: %s", file); | ||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | while (fgets(buffer, READ_CONFIG_BUF_SIZE, in)) { | ||
298 | lm++; | ||
299 | if (strchr(buffer, '\n')) *(strchr(buffer, '\n')) = '\0'; | ||
300 | #ifdef UDHCP_DEBUG | ||
301 | strcpy(orig, buffer); | ||
302 | #endif | ||
303 | if (strchr(buffer, '#')) *(strchr(buffer, '#')) = '\0'; | ||
304 | |||
305 | if (!(token = strtok(buffer, " \t"))) continue; | ||
306 | if (!(line = strtok(NULL, ""))) continue; | ||
307 | |||
308 | /* eat leading whitespace */ | ||
309 | line = line + strspn(line, " \t="); | ||
310 | /* eat trailing whitespace */ | ||
311 | for (i = strlen(line); i > 0 && isspace(line[i - 1]); i--); | ||
312 | line[i] = '\0'; | ||
313 | |||
314 | for (i = 0; keywords[i].keyword[0]; i++) | ||
315 | if (!strcasecmp(token, keywords[i].keyword)) | ||
316 | if (!keywords[i].handler(line, keywords[i].var)) { | ||
317 | LOG(LOG_ERR, "Failure parsing line %d of %s", lm, file); | ||
318 | DEBUG(LOG_ERR, "unable to parse '%s'", orig); | ||
319 | /* reset back to the default value */ | ||
320 | keywords[i].handler(keywords[i].def, keywords[i].var); | ||
321 | } | ||
322 | } | ||
323 | fclose(in); | ||
324 | return 1; | ||
325 | } | ||
326 | |||
327 | |||
328 | void write_leases(void) | ||
329 | { | ||
330 | FILE *fp; | ||
331 | unsigned int i; | ||
332 | char buf[255]; | ||
333 | time_t curr = time(0); | ||
334 | unsigned long tmp_time; | ||
335 | |||
336 | if (!(fp = fopen(server_config.lease_file, "w"))) { | ||
337 | LOG(LOG_ERR, "Unable to open %s for writing", server_config.lease_file); | ||
338 | return; | ||
339 | } | ||
340 | |||
341 | for (i = 0; i < server_config.max_leases; i++) { | ||
342 | if (leases[i].yiaddr != 0) { | ||
343 | |||
344 | /* screw with the time in the struct, for easier writing */ | ||
345 | tmp_time = leases[i].expires; | ||
346 | |||
347 | if (server_config.remaining) { | ||
348 | if (lease_expired(&(leases[i]))) | ||
349 | leases[i].expires = 0; | ||
350 | else leases[i].expires -= curr; | ||
351 | } /* else stick with the time we got */ | ||
352 | leases[i].expires = htonl(leases[i].expires); | ||
353 | fwrite(&leases[i], sizeof(struct dhcpOfferedAddr), 1, fp); | ||
354 | |||
355 | /* Then restore it when done. */ | ||
356 | leases[i].expires = tmp_time; | ||
357 | } | ||
358 | } | ||
359 | fclose(fp); | ||
360 | |||
361 | if (server_config.notify_file) { | ||
362 | sprintf(buf, "%s %s", server_config.notify_file, server_config.lease_file); | ||
363 | system(buf); | ||
364 | } | ||
365 | } | ||
366 | |||
367 | |||
368 | void read_leases(const char *file) | ||
369 | { | ||
370 | FILE *fp; | ||
371 | unsigned int i = 0; | ||
372 | struct dhcpOfferedAddr lease; | ||
373 | |||
374 | if (!(fp = fopen(file, "r"))) { | ||
375 | LOG(LOG_ERR, "Unable to open %s for reading", file); | ||
376 | return; | ||
377 | } | ||
378 | |||
379 | while (i < server_config.max_leases && (fread(&lease, sizeof lease, 1, fp) == 1)) { | ||
380 | /* ADDME: is it a static lease */ | ||
381 | if (lease.yiaddr >= server_config.start && lease.yiaddr <= server_config.end) { | ||
382 | lease.expires = ntohl(lease.expires); | ||
383 | if (!server_config.remaining) lease.expires -= time(0); | ||
384 | if (!(add_lease(lease.chaddr, lease.yiaddr, lease.expires))) { | ||
385 | LOG(LOG_WARNING, "Too many leases while loading %s\n", file); | ||
386 | break; | ||
387 | } | ||
388 | i++; | ||
389 | } | ||
390 | } | ||
391 | DEBUG(LOG_INFO, "Read %d leases", i); | ||
392 | fclose(fp); | ||
393 | } | ||
diff --git a/networking/udhcp/files.h b/networking/udhcp/files.h new file mode 100644 index 000000000..03acee2fc --- /dev/null +++ b/networking/udhcp/files.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* files.h */ | ||
2 | #ifndef _FILES_H | ||
3 | #define _FILES_H | ||
4 | |||
5 | struct config_keyword { | ||
6 | const char *keyword; | ||
7 | int (* const handler)(const char *line, void *var); | ||
8 | void *var; | ||
9 | const char *def; | ||
10 | }; | ||
11 | |||
12 | |||
13 | int read_config(const char *file); | ||
14 | void write_leases(void); | ||
15 | void read_leases(const char *file); | ||
16 | |||
17 | struct option_set *find_option(struct option_set *opt_list, char code); | ||
18 | |||
19 | #endif | ||
diff --git a/networking/udhcp/frontend.c b/networking/udhcp/frontend.c new file mode 100644 index 000000000..fa77ab977 --- /dev/null +++ b/networking/udhcp/frontend.c | |||
@@ -0,0 +1,16 @@ | |||
1 | #include <string.h> | ||
2 | |||
3 | extern int udhcpd_main(int argc, char *argv[]); | ||
4 | extern int udhcpc_main(int argc, char *argv[]); | ||
5 | |||
6 | int main(int argc, char *argv[]) | ||
7 | { | ||
8 | int ret = 0; | ||
9 | char *base = strrchr(argv[0], '/'); | ||
10 | |||
11 | if (strstr(base ? (base + 1) : argv[0], "dhcpd")) | ||
12 | ret = udhcpd_main(argc, argv); | ||
13 | else ret = udhcpc_main(argc, argv); | ||
14 | |||
15 | return ret; | ||
16 | } | ||
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c new file mode 100644 index 000000000..bb08c3adb --- /dev/null +++ b/networking/udhcp/leases.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * leases.c -- tools to manage DHCP leases | ||
3 | * Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
4 | */ | ||
5 | |||
6 | #include <time.h> | ||
7 | #include <string.h> | ||
8 | #include <sys/socket.h> | ||
9 | #include <netinet/in.h> | ||
10 | #include <arpa/inet.h> | ||
11 | |||
12 | #include "dhcpd.h" | ||
13 | #include "files.h" | ||
14 | #include "options.h" | ||
15 | #include "leases.h" | ||
16 | #include "arpping.h" | ||
17 | #include "common.h" | ||
18 | |||
19 | #include "static_leases.h" | ||
20 | |||
21 | |||
22 | uint8_t blank_chaddr[] = {[0 ... 15] = 0}; | ||
23 | |||
24 | /* clear every lease out that chaddr OR yiaddr matches and is nonzero */ | ||
25 | void clear_lease(uint8_t *chaddr, uint32_t yiaddr) | ||
26 | { | ||
27 | unsigned int i, j; | ||
28 | |||
29 | for (j = 0; j < 16 && !chaddr[j]; j++); | ||
30 | |||
31 | for (i = 0; i < server_config.max_leases; i++) | ||
32 | if ((j != 16 && !memcmp(leases[i].chaddr, chaddr, 16)) || | ||
33 | (yiaddr && leases[i].yiaddr == yiaddr)) { | ||
34 | memset(&(leases[i]), 0, sizeof(struct dhcpOfferedAddr)); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | |||
39 | /* add a lease into the table, clearing out any old ones */ | ||
40 | struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease) | ||
41 | { | ||
42 | struct dhcpOfferedAddr *oldest; | ||
43 | |||
44 | /* clean out any old ones */ | ||
45 | clear_lease(chaddr, yiaddr); | ||
46 | |||
47 | oldest = oldest_expired_lease(); | ||
48 | |||
49 | if (oldest) { | ||
50 | memcpy(oldest->chaddr, chaddr, 16); | ||
51 | oldest->yiaddr = yiaddr; | ||
52 | oldest->expires = time(0) + lease; | ||
53 | } | ||
54 | |||
55 | return oldest; | ||
56 | } | ||
57 | |||
58 | |||
59 | /* true if a lease has expired */ | ||
60 | int lease_expired(struct dhcpOfferedAddr *lease) | ||
61 | { | ||
62 | return (lease->expires < (unsigned long) time(0)); | ||
63 | } | ||
64 | |||
65 | |||
66 | /* Find the oldest expired lease, NULL if there are no expired leases */ | ||
67 | struct dhcpOfferedAddr *oldest_expired_lease(void) | ||
68 | { | ||
69 | struct dhcpOfferedAddr *oldest = NULL; | ||
70 | unsigned long oldest_lease = time(0); | ||
71 | unsigned int i; | ||
72 | |||
73 | |||
74 | for (i = 0; i < server_config.max_leases; i++) | ||
75 | if (oldest_lease > leases[i].expires) { | ||
76 | oldest_lease = leases[i].expires; | ||
77 | oldest = &(leases[i]); | ||
78 | } | ||
79 | return oldest; | ||
80 | |||
81 | } | ||
82 | |||
83 | |||
84 | /* Find the first lease that matches chaddr, NULL if no match */ | ||
85 | struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr) | ||
86 | { | ||
87 | unsigned int i; | ||
88 | |||
89 | for (i = 0; i < server_config.max_leases; i++) | ||
90 | if (!memcmp(leases[i].chaddr, chaddr, 16)) return &(leases[i]); | ||
91 | |||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | |||
96 | /* Find the first lease that matches yiaddr, NULL is no match */ | ||
97 | struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr) | ||
98 | { | ||
99 | unsigned int i; | ||
100 | |||
101 | for (i = 0; i < server_config.max_leases; i++) | ||
102 | if (leases[i].yiaddr == yiaddr) return &(leases[i]); | ||
103 | |||
104 | return NULL; | ||
105 | } | ||
106 | |||
107 | |||
108 | /* check is an IP is taken, if it is, add it to the lease table */ | ||
109 | static int check_ip(uint32_t addr) | ||
110 | { | ||
111 | struct in_addr temp; | ||
112 | |||
113 | if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) { | ||
114 | temp.s_addr = addr; | ||
115 | LOG(LOG_INFO, "%s belongs to someone, reserving it for %ld seconds", | ||
116 | inet_ntoa(temp), server_config.conflict_time); | ||
117 | add_lease(blank_chaddr, addr, server_config.conflict_time); | ||
118 | return 1; | ||
119 | } else return 0; | ||
120 | } | ||
121 | |||
122 | |||
123 | /* find an assignable address, it check_expired is true, we check all the expired leases as well. | ||
124 | * Maybe this should try expired leases by age... */ | ||
125 | uint32_t find_address(int check_expired) | ||
126 | { | ||
127 | uint32_t addr, ret; | ||
128 | struct dhcpOfferedAddr *lease = NULL; | ||
129 | |||
130 | addr = ntohl(server_config.start); /* addr is in host order here */ | ||
131 | for (;addr <= ntohl(server_config.end); addr++) { | ||
132 | |||
133 | /* ie, 192.168.55.0 */ | ||
134 | if (!(addr & 0xFF)) continue; | ||
135 | |||
136 | /* ie, 192.168.55.255 */ | ||
137 | if ((addr & 0xFF) == 0xFF) continue; | ||
138 | |||
139 | /* Only do if it isn't an assigned as a static lease */ | ||
140 | if(!reservedIp(server_config.static_leases, htonl(addr))) | ||
141 | { | ||
142 | |||
143 | /* lease is not taken */ | ||
144 | ret = htonl(addr); | ||
145 | if ((!(lease = find_lease_by_yiaddr(ret)) || | ||
146 | |||
147 | /* or it expired and we are checking for expired leases */ | ||
148 | (check_expired && lease_expired(lease))) && | ||
149 | |||
150 | /* and it isn't on the network */ | ||
151 | !check_ip(ret)) { | ||
152 | return ret; | ||
153 | break; | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | return 0; | ||
158 | } | ||
diff --git a/networking/udhcp/leases.h b/networking/udhcp/leases.h new file mode 100644 index 000000000..b13fa72d3 --- /dev/null +++ b/networking/udhcp/leases.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* leases.h */ | ||
2 | #ifndef _LEASES_H | ||
3 | #define _LEASES_H | ||
4 | |||
5 | |||
6 | struct dhcpOfferedAddr { | ||
7 | uint8_t chaddr[16]; | ||
8 | uint32_t yiaddr; /* network order */ | ||
9 | uint32_t expires; /* host order */ | ||
10 | }; | ||
11 | |||
12 | extern uint8_t blank_chaddr[]; | ||
13 | |||
14 | void clear_lease(uint8_t *chaddr, uint32_t yiaddr); | ||
15 | struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease); | ||
16 | int lease_expired(struct dhcpOfferedAddr *lease); | ||
17 | struct dhcpOfferedAddr *oldest_expired_lease(void); | ||
18 | struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr); | ||
19 | struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr); | ||
20 | uint32_t find_address(int check_expired); | ||
21 | |||
22 | |||
23 | #endif | ||
diff --git a/networking/udhcp/libbb_udhcp.h b/networking/udhcp/libbb_udhcp.h new file mode 100644 index 000000000..cce826786 --- /dev/null +++ b/networking/udhcp/libbb_udhcp.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /* libbb_udhcp.h - busybox compatibility wrapper */ | ||
2 | |||
3 | /* bit of a hack, do this no matter what the order of the includes. | ||
4 | * (for busybox) */ | ||
5 | |||
6 | #ifndef _LIBBB_UDHCP_H | ||
7 | #define _LIBBB_UDHCP_H | ||
8 | |||
9 | #ifdef CONFIG_INSTALL_NO_USR | ||
10 | # define DEFAULT_SCRIPT "/share/udhcpc/default.script" | ||
11 | #else | ||
12 | # define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script" | ||
13 | #endif | ||
14 | |||
15 | #ifdef IN_BUSYBOX | ||
16 | #include "busybox.h" | ||
17 | |||
18 | #ifdef CONFIG_FEATURE_UDHCP_SYSLOG | ||
19 | #define UDHCP_SYSLOG | ||
20 | #endif | ||
21 | |||
22 | #ifdef CONFIG_FEATURE_UDHCP_DEBUG | ||
23 | #define UDHCP_DEBUG | ||
24 | #endif | ||
25 | |||
26 | #define COMBINED_BINARY | ||
27 | #include "version.h" | ||
28 | |||
29 | #define xfopen bb_xfopen | ||
30 | |||
31 | /* make safe the exported namespace */ | ||
32 | /* from common.h */ | ||
33 | #define background udhcp_background | ||
34 | #define start_log_and_pid udhcp_start_log_and_pid | ||
35 | /* from script.h */ | ||
36 | #define run_script udhcp_run_script | ||
37 | /* from packet.h */ | ||
38 | #define init_header udhcp_init_header | ||
39 | #define get_packet udhcp_get_packet | ||
40 | #define checksum udhcp_checksum | ||
41 | #define raw_packet udhcp_raw_packet | ||
42 | #define kernel_packet udhcp_kernel_packet | ||
43 | /* from pidfile.h */ | ||
44 | #define pidfile_acquire udhcp_pidfile_acquire | ||
45 | #define pidfile_write_release udhcp_pidfile_write_release | ||
46 | /* from options.h */ | ||
47 | #define get_option udhcp_get_option | ||
48 | #define end_option udhcp_end_option | ||
49 | #define add_option_string udhcp_add_option_string | ||
50 | #define add_simple_option udhcp_add_simple_option | ||
51 | #define option_lengths udhcp_option_lengths | ||
52 | /* from socket.h */ | ||
53 | #define listen_socket udhcp_listen_socket | ||
54 | #define read_interface udhcp_read_interface | ||
55 | /* from dhcpc.h */ | ||
56 | #define client_config udhcp_client_config | ||
57 | /* from dhcpd.h */ | ||
58 | #define server_config udhcp_server_config | ||
59 | |||
60 | #else /* ! IN_BUSYBOX */ | ||
61 | |||
62 | #include <stdlib.h> | ||
63 | #include <stdio.h> | ||
64 | #include <sys/sysinfo.h> | ||
65 | |||
66 | #ifndef ATTRIBUTE_NORETURN | ||
67 | #define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) | ||
68 | #endif /* ATTRIBUTE_NORETURN */ | ||
69 | |||
70 | #ifndef ATTRIBUTE_PACKED | ||
71 | #define ATTRIBUTE_PACKED __attribute__ ((__packed__)) | ||
72 | #endif /* ATTRIBUTE_PACKED */ | ||
73 | |||
74 | #define TRUE 1 | ||
75 | #define FALSE 0 | ||
76 | |||
77 | #define xmalloc malloc | ||
78 | #define xcalloc calloc | ||
79 | |||
80 | static inline FILE *xfopen(const char *file, const char *mode) | ||
81 | { | ||
82 | FILE *fp; | ||
83 | if (!(fp = fopen(file, mode))) { | ||
84 | perror("could not open input file"); | ||
85 | exit(0); | ||
86 | } | ||
87 | return fp; | ||
88 | } | ||
89 | |||
90 | #endif /* IN_BUSYBOX */ | ||
91 | |||
92 | #endif /* _LIBBB_UDHCP_H */ | ||
diff --git a/networking/udhcp/options.c b/networking/udhcp/options.c new file mode 100644 index 000000000..d394b4c39 --- /dev/null +++ b/networking/udhcp/options.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * options.c -- DHCP server option packet tools | ||
3 | * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
4 | */ | ||
5 | |||
6 | #include <stdlib.h> | ||
7 | #include <string.h> | ||
8 | |||
9 | #include "common.h" | ||
10 | #include "dhcpd.h" | ||
11 | #include "options.h" | ||
12 | #include "files.h" | ||
13 | |||
14 | |||
15 | /* supported options are easily added here */ | ||
16 | struct dhcp_option dhcp_options[] = { | ||
17 | /* name[10] flags code */ | ||
18 | {"subnet", OPTION_IP | OPTION_REQ, 0x01}, | ||
19 | {"timezone", OPTION_S32, 0x02}, | ||
20 | {"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03}, | ||
21 | {"timesvr", OPTION_IP | OPTION_LIST, 0x04}, | ||
22 | {"namesvr", OPTION_IP | OPTION_LIST, 0x05}, | ||
23 | {"dns", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06}, | ||
24 | {"logsvr", OPTION_IP | OPTION_LIST, 0x07}, | ||
25 | {"cookiesvr", OPTION_IP | OPTION_LIST, 0x08}, | ||
26 | {"lprsvr", OPTION_IP | OPTION_LIST, 0x09}, | ||
27 | {"hostname", OPTION_STRING | OPTION_REQ, 0x0c}, | ||
28 | {"bootsize", OPTION_U16, 0x0d}, | ||
29 | {"domain", OPTION_STRING | OPTION_REQ, 0x0f}, | ||
30 | {"swapsvr", OPTION_IP, 0x10}, | ||
31 | {"rootpath", OPTION_STRING, 0x11}, | ||
32 | {"ipttl", OPTION_U8, 0x17}, | ||
33 | {"mtu", OPTION_U16, 0x1a}, | ||
34 | {"broadcast", OPTION_IP | OPTION_REQ, 0x1c}, | ||
35 | {"nisdomain", OPTION_STRING | OPTION_REQ, 0x28}, | ||
36 | {"nissrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x29}, | ||
37 | {"ntpsrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a}, | ||
38 | {"wins", OPTION_IP | OPTION_LIST, 0x2c}, | ||
39 | {"requestip", OPTION_IP, 0x32}, | ||
40 | {"lease", OPTION_U32, 0x33}, | ||
41 | {"dhcptype", OPTION_U8, 0x35}, | ||
42 | {"serverid", OPTION_IP, 0x36}, | ||
43 | {"message", OPTION_STRING, 0x38}, | ||
44 | {"tftp", OPTION_STRING, 0x42}, | ||
45 | {"bootfile", OPTION_STRING, 0x43}, | ||
46 | {"", 0x00, 0x00} | ||
47 | }; | ||
48 | |||
49 | /* Lengths of the different option types */ | ||
50 | int option_lengths[] = { | ||
51 | [OPTION_IP] = 4, | ||
52 | [OPTION_IP_PAIR] = 8, | ||
53 | [OPTION_BOOLEAN] = 1, | ||
54 | [OPTION_STRING] = 1, | ||
55 | [OPTION_U8] = 1, | ||
56 | [OPTION_U16] = 2, | ||
57 | [OPTION_S16] = 2, | ||
58 | [OPTION_U32] = 4, | ||
59 | [OPTION_S32] = 4 | ||
60 | }; | ||
61 | |||
62 | |||
63 | /* get an option with bounds checking (warning, not aligned). */ | ||
64 | uint8_t *get_option(struct dhcpMessage *packet, int code) | ||
65 | { | ||
66 | int i, length; | ||
67 | uint8_t *optionptr; | ||
68 | int over = 0, done = 0, curr = OPTION_FIELD; | ||
69 | |||
70 | optionptr = packet->options; | ||
71 | i = 0; | ||
72 | length = 308; | ||
73 | while (!done) { | ||
74 | if (i >= length) { | ||
75 | LOG(LOG_WARNING, "bogus packet, option fields too long."); | ||
76 | return NULL; | ||
77 | } | ||
78 | if (optionptr[i + OPT_CODE] == code) { | ||
79 | if (i + 1 + optionptr[i + OPT_LEN] >= length) { | ||
80 | LOG(LOG_WARNING, "bogus packet, option fields too long."); | ||
81 | return NULL; | ||
82 | } | ||
83 | return optionptr + i + 2; | ||
84 | } | ||
85 | switch (optionptr[i + OPT_CODE]) { | ||
86 | case DHCP_PADDING: | ||
87 | i++; | ||
88 | break; | ||
89 | case DHCP_OPTION_OVER: | ||
90 | if (i + 1 + optionptr[i + OPT_LEN] >= length) { | ||
91 | LOG(LOG_WARNING, "bogus packet, option fields too long."); | ||
92 | return NULL; | ||
93 | } | ||
94 | over = optionptr[i + 3]; | ||
95 | i += optionptr[OPT_LEN] + 2; | ||
96 | break; | ||
97 | case DHCP_END: | ||
98 | if (curr == OPTION_FIELD && over & FILE_FIELD) { | ||
99 | optionptr = packet->file; | ||
100 | i = 0; | ||
101 | length = 128; | ||
102 | curr = FILE_FIELD; | ||
103 | } else if (curr == FILE_FIELD && over & SNAME_FIELD) { | ||
104 | optionptr = packet->sname; | ||
105 | i = 0; | ||
106 | length = 64; | ||
107 | curr = SNAME_FIELD; | ||
108 | } else done = 1; | ||
109 | break; | ||
110 | default: | ||
111 | i += optionptr[OPT_LEN + i] + 2; | ||
112 | } | ||
113 | } | ||
114 | return NULL; | ||
115 | } | ||
116 | |||
117 | |||
118 | /* return the position of the 'end' option (no bounds checking) */ | ||
119 | int end_option(uint8_t *optionptr) | ||
120 | { | ||
121 | int i = 0; | ||
122 | |||
123 | while (optionptr[i] != DHCP_END) { | ||
124 | if (optionptr[i] == DHCP_PADDING) i++; | ||
125 | else i += optionptr[i + OPT_LEN] + 2; | ||
126 | } | ||
127 | return i; | ||
128 | } | ||
129 | |||
130 | |||
131 | /* add an option string to the options (an option string contains an option code, | ||
132 | * length, then data) */ | ||
133 | int add_option_string(uint8_t *optionptr, uint8_t *string) | ||
134 | { | ||
135 | int end = end_option(optionptr); | ||
136 | |||
137 | /* end position + string length + option code/length + end option */ | ||
138 | if (end + string[OPT_LEN] + 2 + 1 >= 308) { | ||
139 | LOG(LOG_ERR, "Option 0x%02x did not fit into the packet!", string[OPT_CODE]); | ||
140 | return 0; | ||
141 | } | ||
142 | DEBUG(LOG_INFO, "adding option 0x%02x", string[OPT_CODE]); | ||
143 | memcpy(optionptr + end, string, string[OPT_LEN] + 2); | ||
144 | optionptr[end + string[OPT_LEN] + 2] = DHCP_END; | ||
145 | return string[OPT_LEN] + 2; | ||
146 | } | ||
147 | |||
148 | |||
149 | /* add a one to four byte option to a packet */ | ||
150 | int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) | ||
151 | { | ||
152 | struct dhcp_option *dh; | ||
153 | |||
154 | for (dh=dhcp_options; dh->code; dh++) { | ||
155 | if (dh->code == code) { | ||
156 | uint8_t option[6], len; | ||
157 | |||
158 | option[OPT_CODE] = code; | ||
159 | len = option_lengths[dh->flags & TYPE_MASK]; | ||
160 | option[OPT_LEN] = len; | ||
161 | if (__BYTE_ORDER == __BIG_ENDIAN) | ||
162 | data <<= 8 * (4 - len); | ||
163 | /* This memcpy is for broken processors which can't | ||
164 | * handle a simple unaligned 32-bit assignment */ | ||
165 | memcpy(&option[OPT_DATA], &data, 4); | ||
166 | return add_option_string(optionptr, option); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | DEBUG(LOG_ERR, "Could not add option 0x%02x", code); | ||
171 | return 0; | ||
172 | } | ||
diff --git a/networking/udhcp/options.h b/networking/udhcp/options.h new file mode 100644 index 000000000..4948bac00 --- /dev/null +++ b/networking/udhcp/options.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* options.h */ | ||
2 | #ifndef _OPTIONS_H | ||
3 | #define _OPTIONS_H | ||
4 | |||
5 | #include "packet.h" | ||
6 | |||
7 | #define TYPE_MASK 0x0F | ||
8 | |||
9 | enum { | ||
10 | OPTION_IP=1, | ||
11 | OPTION_IP_PAIR, | ||
12 | OPTION_STRING, | ||
13 | OPTION_BOOLEAN, | ||
14 | OPTION_U8, | ||
15 | OPTION_U16, | ||
16 | OPTION_S16, | ||
17 | OPTION_U32, | ||
18 | OPTION_S32 | ||
19 | }; | ||
20 | |||
21 | #define OPTION_REQ 0x10 /* have the client request this option */ | ||
22 | #define OPTION_LIST 0x20 /* There can be a list of 1 or more of these */ | ||
23 | |||
24 | struct dhcp_option { | ||
25 | char name[10]; | ||
26 | char flags; | ||
27 | uint8_t code; | ||
28 | }; | ||
29 | |||
30 | extern struct dhcp_option dhcp_options[]; | ||
31 | extern int option_lengths[]; | ||
32 | |||
33 | uint8_t *get_option(struct dhcpMessage *packet, int code); | ||
34 | int end_option(uint8_t *optionptr); | ||
35 | int add_option_string(uint8_t *optionptr, uint8_t *string); | ||
36 | int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data); | ||
37 | |||
38 | #endif | ||
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c new file mode 100644 index 000000000..ae06d53cc --- /dev/null +++ b/networking/udhcp/packet.c | |||
@@ -0,0 +1,207 @@ | |||
1 | #include <unistd.h> | ||
2 | #include <string.h> | ||
3 | #include <netinet/in.h> | ||
4 | #include <sys/types.h> | ||
5 | #include <sys/socket.h> | ||
6 | #include <features.h> | ||
7 | #if (__GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || defined _NEWLIB_VERSION | ||
8 | #include <netpacket/packet.h> | ||
9 | #include <net/ethernet.h> | ||
10 | #else | ||
11 | #include <asm/types.h> | ||
12 | #include <linux/if_packet.h> | ||
13 | #include <linux/if_ether.h> | ||
14 | #endif | ||
15 | #include <errno.h> | ||
16 | |||
17 | #include "common.h" | ||
18 | #include "packet.h" | ||
19 | #include "dhcpd.h" | ||
20 | #include "options.h" | ||
21 | |||
22 | |||
23 | void init_header(struct dhcpMessage *packet, char type) | ||
24 | { | ||
25 | memset(packet, 0, sizeof(struct dhcpMessage)); | ||
26 | switch (type) { | ||
27 | case DHCPDISCOVER: | ||
28 | case DHCPREQUEST: | ||
29 | case DHCPRELEASE: | ||
30 | case DHCPINFORM: | ||
31 | packet->op = BOOTREQUEST; | ||
32 | break; | ||
33 | case DHCPOFFER: | ||
34 | case DHCPACK: | ||
35 | case DHCPNAK: | ||
36 | packet->op = BOOTREPLY; | ||
37 | } | ||
38 | packet->htype = ETH_10MB; | ||
39 | packet->hlen = ETH_10MB_LEN; | ||
40 | packet->cookie = htonl(DHCP_MAGIC); | ||
41 | packet->options[0] = DHCP_END; | ||
42 | add_simple_option(packet->options, DHCP_MESSAGE_TYPE, type); | ||
43 | } | ||
44 | |||
45 | |||
46 | /* read a packet from socket fd, return -1 on read error, -2 on packet error */ | ||
47 | int get_packet(struct dhcpMessage *packet, int fd) | ||
48 | { | ||
49 | static const char broken_vendors[][8] = { | ||
50 | "MSFT 98", | ||
51 | "" | ||
52 | }; | ||
53 | int bytes; | ||
54 | int i; | ||
55 | char unsigned *vendor; | ||
56 | |||
57 | memset(packet, 0, sizeof(struct dhcpMessage)); | ||
58 | bytes = read(fd, packet, sizeof(struct dhcpMessage)); | ||
59 | if (bytes < 0) { | ||
60 | DEBUG(LOG_INFO, "couldn't read on listening socket, ignoring"); | ||
61 | return -1; | ||
62 | } | ||
63 | |||
64 | if (ntohl(packet->cookie) != DHCP_MAGIC) { | ||
65 | LOG(LOG_ERR, "received bogus message, ignoring"); | ||
66 | return -2; | ||
67 | } | ||
68 | DEBUG(LOG_INFO, "Received a packet"); | ||
69 | |||
70 | if (packet->op == BOOTREQUEST && (vendor = get_option(packet, DHCP_VENDOR))) { | ||
71 | for (i = 0; broken_vendors[i][0]; i++) { | ||
72 | if (vendor[OPT_LEN - 2] == (uint8_t) strlen(broken_vendors[i]) && | ||
73 | !strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - 2])) { | ||
74 | DEBUG(LOG_INFO, "broken client (%s), forcing broadcast", | ||
75 | broken_vendors[i]); | ||
76 | packet->flags |= htons(BROADCAST_FLAG); | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | |||
81 | return bytes; | ||
82 | } | ||
83 | |||
84 | |||
85 | uint16_t checksum(void *addr, int count) | ||
86 | { | ||
87 | /* Compute Internet Checksum for "count" bytes | ||
88 | * beginning at location "addr". | ||
89 | */ | ||
90 | register int32_t sum = 0; | ||
91 | uint16_t *source = (uint16_t *) addr; | ||
92 | |||
93 | while (count > 1) { | ||
94 | /* This is the inner loop */ | ||
95 | sum += *source++; | ||
96 | count -= 2; | ||
97 | } | ||
98 | |||
99 | /* Add left-over byte, if any */ | ||
100 | if (count > 0) { | ||
101 | /* Make sure that the left-over byte is added correctly both | ||
102 | * with little and big endian hosts */ | ||
103 | uint16_t tmp = 0; | ||
104 | *(uint8_t *) (&tmp) = * (uint8_t *) source; | ||
105 | sum += tmp; | ||
106 | } | ||
107 | /* Fold 32-bit sum to 16 bits */ | ||
108 | while (sum >> 16) | ||
109 | sum = (sum & 0xffff) + (sum >> 16); | ||
110 | |||
111 | return ~sum; | ||
112 | } | ||
113 | |||
114 | |||
115 | /* Construct a ip/udp header for a packet, and specify the source and dest hardware address */ | ||
116 | int raw_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port, | ||
117 | uint32_t dest_ip, int dest_port, uint8_t *dest_arp, int ifindex) | ||
118 | { | ||
119 | int fd; | ||
120 | int result; | ||
121 | struct sockaddr_ll dest; | ||
122 | struct udp_dhcp_packet packet; | ||
123 | |||
124 | if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { | ||
125 | DEBUG(LOG_ERR, "socket call failed: %m"); | ||
126 | return -1; | ||
127 | } | ||
128 | |||
129 | memset(&dest, 0, sizeof(dest)); | ||
130 | memset(&packet, 0, sizeof(packet)); | ||
131 | |||
132 | dest.sll_family = AF_PACKET; | ||
133 | dest.sll_protocol = htons(ETH_P_IP); | ||
134 | dest.sll_ifindex = ifindex; | ||
135 | dest.sll_halen = 6; | ||
136 | memcpy(dest.sll_addr, dest_arp, 6); | ||
137 | if (bind(fd, (struct sockaddr *)&dest, sizeof(struct sockaddr_ll)) < 0) { | ||
138 | DEBUG(LOG_ERR, "bind call failed: %m"); | ||
139 | close(fd); | ||
140 | return -1; | ||
141 | } | ||
142 | |||
143 | packet.ip.protocol = IPPROTO_UDP; | ||
144 | packet.ip.saddr = source_ip; | ||
145 | packet.ip.daddr = dest_ip; | ||
146 | packet.udp.source = htons(source_port); | ||
147 | packet.udp.dest = htons(dest_port); | ||
148 | packet.udp.len = htons(sizeof(packet.udp) + sizeof(struct dhcpMessage)); /* cheat on the psuedo-header */ | ||
149 | packet.ip.tot_len = packet.udp.len; | ||
150 | memcpy(&(packet.data), payload, sizeof(struct dhcpMessage)); | ||
151 | packet.udp.check = checksum(&packet, sizeof(struct udp_dhcp_packet)); | ||
152 | |||
153 | packet.ip.tot_len = htons(sizeof(struct udp_dhcp_packet)); | ||
154 | packet.ip.ihl = sizeof(packet.ip) >> 2; | ||
155 | packet.ip.version = IPVERSION; | ||
156 | packet.ip.ttl = IPDEFTTL; | ||
157 | packet.ip.check = checksum(&(packet.ip), sizeof(packet.ip)); | ||
158 | |||
159 | result = sendto(fd, &packet, sizeof(struct udp_dhcp_packet), 0, (struct sockaddr *) &dest, sizeof(dest)); | ||
160 | if (result <= 0) { | ||
161 | DEBUG(LOG_ERR, "write on socket failed: %m"); | ||
162 | } | ||
163 | close(fd); | ||
164 | return result; | ||
165 | } | ||
166 | |||
167 | |||
168 | /* Let the kernel do all the work for packet generation */ | ||
169 | int kernel_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port, | ||
170 | uint32_t dest_ip, int dest_port) | ||
171 | { | ||
172 | int n = 1; | ||
173 | int fd, result; | ||
174 | struct sockaddr_in client; | ||
175 | |||
176 | if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) | ||
177 | return -1; | ||
178 | |||
179 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) { | ||
180 | close(fd); | ||
181 | return -1; | ||
182 | } | ||
183 | |||
184 | memset(&client, 0, sizeof(client)); | ||
185 | client.sin_family = AF_INET; | ||
186 | client.sin_port = htons(source_port); | ||
187 | client.sin_addr.s_addr = source_ip; | ||
188 | |||
189 | if (bind(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1) { | ||
190 | close(fd); | ||
191 | return -1; | ||
192 | } | ||
193 | |||
194 | memset(&client, 0, sizeof(client)); | ||
195 | client.sin_family = AF_INET; | ||
196 | client.sin_port = htons(dest_port); | ||
197 | client.sin_addr.s_addr = dest_ip; | ||
198 | |||
199 | if (connect(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1) { | ||
200 | close(fd); | ||
201 | return -1; | ||
202 | } | ||
203 | |||
204 | result = write(fd, payload, sizeof(struct dhcpMessage)); | ||
205 | close(fd); | ||
206 | return result; | ||
207 | } | ||
diff --git a/networking/udhcp/packet.h b/networking/udhcp/packet.h new file mode 100644 index 000000000..f5859e824 --- /dev/null +++ b/networking/udhcp/packet.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifndef _PACKET_H | ||
2 | #define _PACKET_H | ||
3 | |||
4 | #include <netinet/udp.h> | ||
5 | #include <netinet/ip.h> | ||
6 | |||
7 | struct dhcpMessage { | ||
8 | uint8_t op; | ||
9 | uint8_t htype; | ||
10 | uint8_t hlen; | ||
11 | uint8_t hops; | ||
12 | uint32_t xid; | ||
13 | uint16_t secs; | ||
14 | uint16_t flags; | ||
15 | uint32_t ciaddr; | ||
16 | uint32_t yiaddr; | ||
17 | uint32_t siaddr; | ||
18 | uint32_t giaddr; | ||
19 | uint8_t chaddr[16]; | ||
20 | uint8_t sname[64]; | ||
21 | uint8_t file[128]; | ||
22 | uint32_t cookie; | ||
23 | uint8_t options[308]; /* 312 - cookie */ | ||
24 | }; | ||
25 | |||
26 | struct udp_dhcp_packet { | ||
27 | struct iphdr ip; | ||
28 | struct udphdr udp; | ||
29 | struct dhcpMessage data; | ||
30 | }; | ||
31 | |||
32 | void init_header(struct dhcpMessage *packet, char type); | ||
33 | int get_packet(struct dhcpMessage *packet, int fd); | ||
34 | uint16_t checksum(void *addr, int count); | ||
35 | int raw_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port, | ||
36 | uint32_t dest_ip, int dest_port, uint8_t *dest_arp, int ifindex); | ||
37 | int kernel_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port, | ||
38 | uint32_t dest_ip, int dest_port); | ||
39 | |||
40 | |||
41 | #endif | ||
diff --git a/networking/udhcp/pidfile.c b/networking/udhcp/pidfile.c new file mode 100644 index 000000000..7a956fb47 --- /dev/null +++ b/networking/udhcp/pidfile.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* pidfile.c | ||
2 | * | ||
3 | * Functions to assist in the writing and removing of pidfiles. | ||
4 | * | ||
5 | * Russ Dill <Russ.Dill@asu.edu> September 2001 | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <sys/types.h> | ||
23 | #include <sys/stat.h> | ||
24 | #include <fcntl.h> | ||
25 | #include <unistd.h> | ||
26 | #include <stdio.h> | ||
27 | #include <stdlib.h> | ||
28 | |||
29 | #include "common.h" | ||
30 | #include "pidfile.h" | ||
31 | |||
32 | static char *saved_pidfile; | ||
33 | |||
34 | static void pidfile_delete(void) | ||
35 | { | ||
36 | if (saved_pidfile) unlink(saved_pidfile); | ||
37 | } | ||
38 | |||
39 | |||
40 | int pidfile_acquire(const char *pidfile) | ||
41 | { | ||
42 | int pid_fd; | ||
43 | if (!pidfile) return -1; | ||
44 | |||
45 | pid_fd = open(pidfile, O_CREAT | O_WRONLY, 0644); | ||
46 | if (pid_fd < 0) { | ||
47 | LOG(LOG_ERR, "Unable to open pidfile %s: %m\n", pidfile); | ||
48 | } else { | ||
49 | lockf(pid_fd, F_LOCK, 0); | ||
50 | if (!saved_pidfile) | ||
51 | atexit(pidfile_delete); | ||
52 | saved_pidfile = (char *) pidfile; | ||
53 | } | ||
54 | |||
55 | return pid_fd; | ||
56 | } | ||
57 | |||
58 | |||
59 | void pidfile_write_release(int pid_fd) | ||
60 | { | ||
61 | FILE *out; | ||
62 | |||
63 | if (pid_fd < 0) return; | ||
64 | |||
65 | if ((out = fdopen(pid_fd, "w")) != NULL) { | ||
66 | fprintf(out, "%d\n", getpid()); | ||
67 | fclose(out); | ||
68 | } | ||
69 | lockf(pid_fd, F_UNLCK, 0); | ||
70 | close(pid_fd); | ||
71 | } | ||
72 | |||
73 | |||
74 | |||
75 | |||
diff --git a/networking/udhcp/pidfile.h b/networking/udhcp/pidfile.h new file mode 100644 index 000000000..ea97d1de5 --- /dev/null +++ b/networking/udhcp/pidfile.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* pidfile.h | ||
2 | * | ||
3 | * Functions to assist in the writing and removing of pidfiles. | ||
4 | * | ||
5 | * Russ Dill <Russ.Dill@asu.edu> September 2001 | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | |||
23 | int pidfile_acquire(const char *pidfile); | ||
24 | void pidfile_write_release(int pid_fd); | ||
25 | |||
diff --git a/networking/udhcp/samples/README b/networking/udhcp/samples/README new file mode 100644 index 000000000..51721ea3c --- /dev/null +++ b/networking/udhcp/samples/README | |||
@@ -0,0 +1,11 @@ | |||
1 | The files in this dir are: | ||
2 | |||
3 | udhcpd.conf: A sample udhpcd configuration file. | ||
4 | |||
5 | sample.script | ||
6 | sample.nak | ||
7 | sample.deconfig | ||
8 | sample.bound | ||
9 | sample.renew : sample scripts for the udhcpc client. | ||
10 | |||
11 | simple.script : a simple sample script for the client. | ||
diff --git a/networking/udhcp/samples/sample.bound b/networking/udhcp/samples/sample.bound new file mode 100755 index 000000000..200352672 --- /dev/null +++ b/networking/udhcp/samples/sample.bound | |||
@@ -0,0 +1,30 @@ | |||
1 | #!/bin/sh | ||
2 | # Sample udhcpc renew script | ||
3 | |||
4 | RESOLV_CONF="/etc/udhcpc/resolv.conf" | ||
5 | |||
6 | [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" | ||
7 | [ -n "$subnet" ] && NETMASK="netmask $subnet" | ||
8 | |||
9 | /sbin/ifconfig $interface $ip $BROADCAST $NETMASK | ||
10 | |||
11 | if [ -n "$router" ] | ||
12 | then | ||
13 | echo "deleting routers" | ||
14 | while /sbin/route del default gw 0.0.0.0 dev $interface | ||
15 | do : | ||
16 | done | ||
17 | |||
18 | for i in $router | ||
19 | do | ||
20 | /sbin/route add default gw $i dev $interface | ||
21 | done | ||
22 | fi | ||
23 | |||
24 | echo -n > $RESOLV_CONF | ||
25 | [ -n "$domain" ] && echo domain $domain >> $RESOLV_CONF | ||
26 | for i in $dns | ||
27 | do | ||
28 | echo adding dns $i | ||
29 | echo nameserver $i >> $RESOLV_CONF | ||
30 | done \ No newline at end of file | ||
diff --git a/networking/udhcp/samples/sample.deconfig b/networking/udhcp/samples/sample.deconfig new file mode 100755 index 000000000..b221bcf12 --- /dev/null +++ b/networking/udhcp/samples/sample.deconfig | |||
@@ -0,0 +1,4 @@ | |||
1 | #!/bin/sh | ||
2 | # Sample udhcpc deconfig script | ||
3 | |||
4 | /sbin/ifconfig $interface 0.0.0.0 | ||
diff --git a/networking/udhcp/samples/sample.nak b/networking/udhcp/samples/sample.nak new file mode 100755 index 000000000..f4d08e669 --- /dev/null +++ b/networking/udhcp/samples/sample.nak | |||
@@ -0,0 +1,4 @@ | |||
1 | #!/bin/sh | ||
2 | # Sample udhcpc nak script | ||
3 | |||
4 | echo Received a NAK: $message | ||
diff --git a/networking/udhcp/samples/sample.renew b/networking/udhcp/samples/sample.renew new file mode 100755 index 000000000..c953e9758 --- /dev/null +++ b/networking/udhcp/samples/sample.renew | |||
@@ -0,0 +1,30 @@ | |||
1 | #!/bin/sh | ||
2 | # Sample udhcpc bound script | ||
3 | |||
4 | RESOLV_CONF="/etc/udhcpc/resolv.conf" | ||
5 | |||
6 | [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" | ||
7 | [ -n "$subnet" ] && NETMASK="netmask $subnet" | ||
8 | |||
9 | /sbin/ifconfig $interface $ip $BROADCAST $NETMASK | ||
10 | |||
11 | if [ -n "$router" ] | ||
12 | then | ||
13 | echo "deleting routers" | ||
14 | while /sbin/route del default gw 0.0.0.0 dev $interface | ||
15 | do : | ||
16 | done | ||
17 | |||
18 | for i in $router | ||
19 | do | ||
20 | /sbin/route add default gw $i dev $interface | ||
21 | done | ||
22 | fi | ||
23 | |||
24 | echo -n > $RESOLV_CONF | ||
25 | [ -n "$domain" ] && echo domain $domain >> $RESOLV_CONF | ||
26 | for i in $dns | ||
27 | do | ||
28 | echo adding dns $i | ||
29 | echo nameserver $i >> $RESOLV_CONF | ||
30 | done \ No newline at end of file | ||
diff --git a/networking/udhcp/samples/sample.script b/networking/udhcp/samples/sample.script new file mode 100644 index 000000000..9b717ac3c --- /dev/null +++ b/networking/udhcp/samples/sample.script | |||
@@ -0,0 +1,7 @@ | |||
1 | #!/bin/sh | ||
2 | # Currently, we only dispatch according to command. However, a more | ||
3 | # elaborate system might dispatch by command and interface or do some | ||
4 | # common initialization first, especially if more dhcp event notifications | ||
5 | # are added. | ||
6 | |||
7 | exec /usr/share/udhcpc/sample.$1 | ||
diff --git a/networking/udhcp/samples/simple.script b/networking/udhcp/samples/simple.script new file mode 100644 index 000000000..a52a7f812 --- /dev/null +++ b/networking/udhcp/samples/simple.script | |||
@@ -0,0 +1,39 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | # udhcpc script edited by Tim Riker <Tim@Rikers.org> | ||
4 | |||
5 | [ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1 | ||
6 | |||
7 | RESOLV_CONF="/etc/resolv.conf" | ||
8 | [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" | ||
9 | [ -n "$subnet" ] && NETMASK="netmask $subnet" | ||
10 | |||
11 | case "$1" in | ||
12 | deconfig) | ||
13 | /sbin/ifconfig $interface 0.0.0.0 | ||
14 | ;; | ||
15 | |||
16 | renew|bound) | ||
17 | /sbin/ifconfig $interface $ip $BROADCAST $NETMASK | ||
18 | |||
19 | if [ -n "$router" ] ; then | ||
20 | echo "deleting routers" | ||
21 | while route del default gw 0.0.0.0 dev $interface ; do | ||
22 | : | ||
23 | done | ||
24 | |||
25 | for i in $router ; do | ||
26 | route add default gw $i dev $interface | ||
27 | done | ||
28 | fi | ||
29 | |||
30 | echo -n > $RESOLV_CONF | ||
31 | [ -n "$domain" ] && echo search $domain >> $RESOLV_CONF | ||
32 | for i in $dns ; do | ||
33 | echo adding dns $i | ||
34 | echo nameserver $i >> $RESOLV_CONF | ||
35 | done | ||
36 | ;; | ||
37 | esac | ||
38 | |||
39 | exit 0 | ||
diff --git a/networking/udhcp/samples/udhcpd.conf b/networking/udhcp/samples/udhcpd.conf new file mode 100644 index 000000000..00105b3e5 --- /dev/null +++ b/networking/udhcp/samples/udhcpd.conf | |||
@@ -0,0 +1,116 @@ | |||
1 | # Sample udhcpd configuration file (/etc/udhcpd.conf) | ||
2 | |||
3 | # The start and end of the IP lease block | ||
4 | |||
5 | start 192.168.0.20 #default: 192.168.0.20 | ||
6 | end 192.168.0.254 #default: 192.168.0.254 | ||
7 | |||
8 | |||
9 | # The interface that udhcpd will use | ||
10 | |||
11 | interface eth0 #default: eth0 | ||
12 | |||
13 | |||
14 | # The maximim number of leases (includes addressesd reserved | ||
15 | # by OFFER's, DECLINE's, and ARP conficts | ||
16 | |||
17 | #max_leases 254 #default: 254 | ||
18 | |||
19 | |||
20 | # If remaining is true (default), udhcpd will store the time | ||
21 | # remaining for each lease in the udhcpd leases file. This is | ||
22 | # for embedded systems that cannot keep time between reboots. | ||
23 | # If you set remaining to no, the absolute time that the lease | ||
24 | # expires at will be stored in the dhcpd.leases file. | ||
25 | |||
26 | #remaining yes #default: yes | ||
27 | |||
28 | |||
29 | # The time period at which udhcpd will write out a dhcpd.leases | ||
30 | # file. If this is 0, udhcpd will never automatically write a | ||
31 | # lease file. (specified in seconds) | ||
32 | |||
33 | #auto_time 7200 #default: 7200 (2 hours) | ||
34 | |||
35 | |||
36 | # The amount of time that an IP will be reserved (leased) for if a | ||
37 | # DHCP decline message is received (seconds). | ||
38 | |||
39 | #decline_time 3600 #default: 3600 (1 hour) | ||
40 | |||
41 | |||
42 | # The amount of time that an IP will be reserved (leased) for if an | ||
43 | # ARP conflct occurs. (seconds | ||
44 | |||
45 | #conflict_time 3600 #default: 3600 (1 hour) | ||
46 | |||
47 | |||
48 | # How long an offered address is reserved (leased) in seconds | ||
49 | |||
50 | #offer_time 60 #default: 60 (1 minute) | ||
51 | |||
52 | # If a lease to be given is below this value, the full lease time is | ||
53 | # instead used (seconds). | ||
54 | |||
55 | #min_lease 60 #defult: 60 | ||
56 | |||
57 | |||
58 | # The location of the leases file | ||
59 | |||
60 | #lease_file /var/lib/misc/udhcpd.leases #defualt: /var/lib/misc/udhcpd.leases | ||
61 | |||
62 | # The location of the pid file | ||
63 | #pidfile /var/run/udhcpd.pid #default: /var/run/udhcpd.pid | ||
64 | |||
65 | # Everytime udhcpd writes a leases file, the below script will be called. | ||
66 | # Useful for writing the lease file to flash every few hours. | ||
67 | |||
68 | #notify_file #default: (no script) | ||
69 | |||
70 | #notify_file dumpleases # <--- usefull for debugging | ||
71 | |||
72 | # The following are bootp specific options, setable by udhcpd. | ||
73 | |||
74 | #siaddr 192.168.0.22 #default: 0.0.0.0 | ||
75 | |||
76 | #sname zorak #default: (none) | ||
77 | |||
78 | #boot_file /var/nfs_root #default: (none) | ||
79 | |||
80 | # The remainer of options are DHCP options and can be specifed with the | ||
81 | # keyword 'opt' or 'option'. If an option can take multiple items, such | ||
82 | # as the dns option, they can be listed on the same line, or multiple | ||
83 | # lines. The only option with a default is 'lease'. | ||
84 | |||
85 | #Examles | ||
86 | opt dns 192.168.10.2 192.168.10.10 | ||
87 | option subnet 255.255.255.0 | ||
88 | opt router 192.168.10.2 | ||
89 | opt wins 192.168.10.10 | ||
90 | option dns 129.219.13.81 # appened to above DNS servers for a total of 3 | ||
91 | option domain local | ||
92 | option lease 864000 # 10 days of seconds | ||
93 | |||
94 | |||
95 | # Currently supported options, for more info, see options.c | ||
96 | #opt subnet | ||
97 | #opt timezone | ||
98 | #opt router | ||
99 | #opt timesvr | ||
100 | #opt namesvr | ||
101 | #opt dns | ||
102 | #opt logsvr | ||
103 | #opt cookiesvr | ||
104 | #opt lprsvr | ||
105 | #opt bootsize | ||
106 | #opt domain | ||
107 | #opt swapsvr | ||
108 | #opt rootpath | ||
109 | #opt ipttl | ||
110 | #opt mtu | ||
111 | #opt broadcast | ||
112 | #opt wins | ||
113 | #opt lease | ||
114 | #opt ntpsrv | ||
115 | #opt tftp | ||
116 | #opt bootfile | ||
diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c new file mode 100644 index 000000000..b6b0e0d59 --- /dev/null +++ b/networking/udhcp/script.c | |||
@@ -0,0 +1,234 @@ | |||
1 | /* script.c | ||
2 | * | ||
3 | * Functions to call the DHCP client notification scripts | ||
4 | * | ||
5 | * Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <string.h> | ||
23 | #include <unistd.h> | ||
24 | #include <stdio.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <sys/socket.h> | ||
27 | #include <netinet/in.h> | ||
28 | #include <arpa/inet.h> | ||
29 | #include <sys/types.h> | ||
30 | #include <sys/wait.h> | ||
31 | |||
32 | #include "common.h" | ||
33 | #include "options.h" | ||
34 | #include "dhcpd.h" | ||
35 | #include "dhcpc.h" | ||
36 | #include "script.h" | ||
37 | |||
38 | /* get a rough idea of how long an option will be (rounding up...) */ | ||
39 | static const int max_option_length[] = { | ||
40 | [OPTION_IP] = sizeof("255.255.255.255 "), | ||
41 | [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, | ||
42 | [OPTION_STRING] = 1, | ||
43 | [OPTION_BOOLEAN] = sizeof("yes "), | ||
44 | [OPTION_U8] = sizeof("255 "), | ||
45 | [OPTION_U16] = sizeof("65535 "), | ||
46 | [OPTION_S16] = sizeof("-32768 "), | ||
47 | [OPTION_U32] = sizeof("4294967295 "), | ||
48 | [OPTION_S32] = sizeof("-2147483684 "), | ||
49 | }; | ||
50 | |||
51 | |||
52 | static inline int upper_length(int length, int opt_index) | ||
53 | { | ||
54 | return max_option_length[opt_index] * | ||
55 | (length / option_lengths[opt_index]); | ||
56 | } | ||
57 | |||
58 | |||
59 | static int sprintip(char *dest, char *pre, uint8_t *ip) | ||
60 | { | ||
61 | return sprintf(dest, "%s%d.%d.%d.%d", pre, ip[0], ip[1], ip[2], ip[3]); | ||
62 | } | ||
63 | |||
64 | |||
65 | /* really simple implementation, just count the bits */ | ||
66 | static int mton(struct in_addr *mask) | ||
67 | { | ||
68 | int i; | ||
69 | unsigned long bits = ntohl(mask->s_addr); | ||
70 | /* too bad one can't check the carry bit, etc in c bit | ||
71 | * shifting */ | ||
72 | for (i = 0; i < 32 && !((bits >> i) & 1); i++); | ||
73 | return 32 - i; | ||
74 | } | ||
75 | |||
76 | |||
77 | /* Fill dest with the text of option 'option'. */ | ||
78 | static void fill_options(char *dest, uint8_t *option, struct dhcp_option *type_p) | ||
79 | { | ||
80 | int type, optlen; | ||
81 | uint16_t val_u16; | ||
82 | int16_t val_s16; | ||
83 | uint32_t val_u32; | ||
84 | int32_t val_s32; | ||
85 | int len = option[OPT_LEN - 2]; | ||
86 | |||
87 | dest += sprintf(dest, "%s=", type_p->name); | ||
88 | |||
89 | type = type_p->flags & TYPE_MASK; | ||
90 | optlen = option_lengths[type]; | ||
91 | for(;;) { | ||
92 | switch (type) { | ||
93 | case OPTION_IP_PAIR: | ||
94 | dest += sprintip(dest, "", option); | ||
95 | *(dest++) = '/'; | ||
96 | option += 4; | ||
97 | optlen = 4; | ||
98 | case OPTION_IP: /* Works regardless of host byte order. */ | ||
99 | dest += sprintip(dest, "", option); | ||
100 | break; | ||
101 | case OPTION_BOOLEAN: | ||
102 | dest += sprintf(dest, *option ? "yes" : "no"); | ||
103 | break; | ||
104 | case OPTION_U8: | ||
105 | dest += sprintf(dest, "%u", *option); | ||
106 | break; | ||
107 | case OPTION_U16: | ||
108 | memcpy(&val_u16, option, 2); | ||
109 | dest += sprintf(dest, "%u", ntohs(val_u16)); | ||
110 | break; | ||
111 | case OPTION_S16: | ||
112 | memcpy(&val_s16, option, 2); | ||
113 | dest += sprintf(dest, "%d", ntohs(val_s16)); | ||
114 | break; | ||
115 | case OPTION_U32: | ||
116 | memcpy(&val_u32, option, 4); | ||
117 | dest += sprintf(dest, "%lu", (unsigned long) ntohl(val_u32)); | ||
118 | break; | ||
119 | case OPTION_S32: | ||
120 | memcpy(&val_s32, option, 4); | ||
121 | dest += sprintf(dest, "%ld", (long) ntohl(val_s32)); | ||
122 | break; | ||
123 | case OPTION_STRING: | ||
124 | memcpy(dest, option, len); | ||
125 | dest[len] = '\0'; | ||
126 | return; /* Short circuit this case */ | ||
127 | } | ||
128 | option += optlen; | ||
129 | len -= optlen; | ||
130 | if (len <= 0) break; | ||
131 | dest += sprintf(dest, " "); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | |||
136 | /* put all the parameters into an environment */ | ||
137 | static char **fill_envp(struct dhcpMessage *packet) | ||
138 | { | ||
139 | int num_options = 0; | ||
140 | int i, j; | ||
141 | char **envp; | ||
142 | uint8_t *temp; | ||
143 | struct in_addr subnet; | ||
144 | char over = 0; | ||
145 | |||
146 | if (packet == NULL) | ||
147 | num_options = 0; | ||
148 | else { | ||
149 | for (i = 0; dhcp_options[i].code; i++) | ||
150 | if (get_option(packet, dhcp_options[i].code)) { | ||
151 | num_options++; | ||
152 | if (dhcp_options[i].code == DHCP_SUBNET) | ||
153 | num_options++; /* for mton */ | ||
154 | } | ||
155 | if (packet->siaddr) num_options++; | ||
156 | if ((temp = get_option(packet, DHCP_OPTION_OVER))) | ||
157 | over = *temp; | ||
158 | if (!(over & FILE_FIELD) && packet->file[0]) num_options++; | ||
159 | if (!(over & SNAME_FIELD) && packet->sname[0]) num_options++; | ||
160 | } | ||
161 | |||
162 | envp = xcalloc(sizeof(char *), num_options + 5); | ||
163 | j = 0; | ||
164 | asprintf(&envp[j++], "interface=%s", client_config.interface); | ||
165 | asprintf(&envp[j++], "%s=%s", "PATH", | ||
166 | getenv("PATH") ? : "/bin:/usr/bin:/sbin:/usr/sbin"); | ||
167 | asprintf(&envp[j++], "%s=%s", "HOME", getenv("HOME") ? : "/"); | ||
168 | |||
169 | if (packet == NULL) return envp; | ||
170 | |||
171 | envp[j] = xmalloc(sizeof("ip=255.255.255.255")); | ||
172 | sprintip(envp[j++], "ip=", (uint8_t *) &packet->yiaddr); | ||
173 | |||
174 | |||
175 | for (i = 0; dhcp_options[i].code; i++) { | ||
176 | if (!(temp = get_option(packet, dhcp_options[i].code))) | ||
177 | continue; | ||
178 | envp[j] = xmalloc(upper_length(temp[OPT_LEN - 2], | ||
179 | dhcp_options[i].flags & TYPE_MASK) + strlen(dhcp_options[i].name) + 2); | ||
180 | fill_options(envp[j++], temp, &dhcp_options[i]); | ||
181 | |||
182 | /* Fill in a subnet bits option for things like /24 */ | ||
183 | if (dhcp_options[i].code == DHCP_SUBNET) { | ||
184 | memcpy(&subnet, temp, 4); | ||
185 | asprintf(&envp[j++], "mask=%d", mton(&subnet)); | ||
186 | } | ||
187 | } | ||
188 | if (packet->siaddr) { | ||
189 | envp[j] = xmalloc(sizeof("siaddr=255.255.255.255")); | ||
190 | sprintip(envp[j++], "siaddr=", (uint8_t *) &packet->siaddr); | ||
191 | } | ||
192 | if (!(over & FILE_FIELD) && packet->file[0]) { | ||
193 | /* watch out for invalid packets */ | ||
194 | packet->file[sizeof(packet->file) - 1] = '\0'; | ||
195 | asprintf(&envp[j++], "boot_file=%s", packet->file); | ||
196 | } | ||
197 | if (!(over & SNAME_FIELD) && packet->sname[0]) { | ||
198 | /* watch out for invalid packets */ | ||
199 | packet->sname[sizeof(packet->sname) - 1] = '\0'; | ||
200 | asprintf(&envp[j++], "sname=%s", packet->sname); | ||
201 | } | ||
202 | return envp; | ||
203 | } | ||
204 | |||
205 | |||
206 | /* Call a script with a par file and env vars */ | ||
207 | void run_script(struct dhcpMessage *packet, const char *name) | ||
208 | { | ||
209 | int pid; | ||
210 | char **envp, **curr; | ||
211 | |||
212 | if (client_config.script == NULL) | ||
213 | return; | ||
214 | |||
215 | DEBUG(LOG_INFO, "vforking and execle'ing %s", client_config.script); | ||
216 | |||
217 | envp = fill_envp(packet); | ||
218 | /* call script */ | ||
219 | pid = vfork(); | ||
220 | if (pid) { | ||
221 | waitpid(pid, NULL, 0); | ||
222 | for (curr = envp; *curr; curr++) free(*curr); | ||
223 | free(envp); | ||
224 | return; | ||
225 | } else if (pid == 0) { | ||
226 | /* close fd's? */ | ||
227 | |||
228 | /* exec script */ | ||
229 | execle(client_config.script, client_config.script, | ||
230 | name, NULL, envp); | ||
231 | LOG(LOG_ERR, "script %s failed: %m", client_config.script); | ||
232 | exit(1); | ||
233 | } | ||
234 | } | ||
diff --git a/networking/udhcp/script.h b/networking/udhcp/script.h new file mode 100644 index 000000000..71003311c --- /dev/null +++ b/networking/udhcp/script.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _SCRIPT_H | ||
2 | #define _SCRIPT_H | ||
3 | |||
4 | extern void run_script(struct dhcpMessage *packet, const char *name); | ||
5 | |||
6 | #endif | ||
diff --git a/networking/udhcp/serverpacket.c b/networking/udhcp/serverpacket.c new file mode 100644 index 000000000..fe880b4a0 --- /dev/null +++ b/networking/udhcp/serverpacket.c | |||
@@ -0,0 +1,275 @@ | |||
1 | /* serverpacket.c | ||
2 | * | ||
3 | * Construct and send DHCP server packets | ||
4 | * | ||
5 | * Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <sys/socket.h> | ||
23 | #include <netinet/in.h> | ||
24 | #include <arpa/inet.h> | ||
25 | #include <string.h> | ||
26 | #include <time.h> | ||
27 | |||
28 | #include "common.h" | ||
29 | #include "serverpacket.h" | ||
30 | #include "dhcpd.h" | ||
31 | #include "options.h" | ||
32 | #include "static_leases.h" | ||
33 | |||
34 | /* send a packet to giaddr using the kernel ip stack */ | ||
35 | static int send_packet_to_relay(struct dhcpMessage *payload) | ||
36 | { | ||
37 | DEBUG(LOG_INFO, "Forwarding packet to relay"); | ||
38 | |||
39 | return kernel_packet(payload, server_config.server, SERVER_PORT, | ||
40 | payload->giaddr, SERVER_PORT); | ||
41 | } | ||
42 | |||
43 | |||
44 | /* send a packet to a specific arp address and ip address by creating our own ip packet */ | ||
45 | static int send_packet_to_client(struct dhcpMessage *payload, int force_broadcast) | ||
46 | { | ||
47 | uint8_t *chaddr; | ||
48 | uint32_t ciaddr; | ||
49 | |||
50 | if (force_broadcast) { | ||
51 | DEBUG(LOG_INFO, "broadcasting packet to client (NAK)"); | ||
52 | ciaddr = INADDR_BROADCAST; | ||
53 | chaddr = MAC_BCAST_ADDR; | ||
54 | } else if (payload->ciaddr) { | ||
55 | DEBUG(LOG_INFO, "unicasting packet to client ciaddr"); | ||
56 | ciaddr = payload->ciaddr; | ||
57 | chaddr = payload->chaddr; | ||
58 | } else if (ntohs(payload->flags) & BROADCAST_FLAG) { | ||
59 | DEBUG(LOG_INFO, "broadcasting packet to client (requested)"); | ||
60 | ciaddr = INADDR_BROADCAST; | ||
61 | chaddr = MAC_BCAST_ADDR; | ||
62 | } else { | ||
63 | DEBUG(LOG_INFO, "unicasting packet to client yiaddr"); | ||
64 | ciaddr = payload->yiaddr; | ||
65 | chaddr = payload->chaddr; | ||
66 | } | ||
67 | return raw_packet(payload, server_config.server, SERVER_PORT, | ||
68 | ciaddr, CLIENT_PORT, chaddr, server_config.ifindex); | ||
69 | } | ||
70 | |||
71 | |||
72 | /* send a dhcp packet, if force broadcast is set, the packet will be broadcast to the client */ | ||
73 | static int send_packet(struct dhcpMessage *payload, int force_broadcast) | ||
74 | { | ||
75 | int ret; | ||
76 | |||
77 | if (payload->giaddr) | ||
78 | ret = send_packet_to_relay(payload); | ||
79 | else ret = send_packet_to_client(payload, force_broadcast); | ||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | |||
84 | static void init_packet(struct dhcpMessage *packet, struct dhcpMessage *oldpacket, char type) | ||
85 | { | ||
86 | init_header(packet, type); | ||
87 | packet->xid = oldpacket->xid; | ||
88 | memcpy(packet->chaddr, oldpacket->chaddr, 16); | ||
89 | packet->flags = oldpacket->flags; | ||
90 | packet->giaddr = oldpacket->giaddr; | ||
91 | packet->ciaddr = oldpacket->ciaddr; | ||
92 | add_simple_option(packet->options, DHCP_SERVER_ID, server_config.server); | ||
93 | } | ||
94 | |||
95 | |||
96 | /* add in the bootp options */ | ||
97 | static void add_bootp_options(struct dhcpMessage *packet) | ||
98 | { | ||
99 | packet->siaddr = server_config.siaddr; | ||
100 | if (server_config.sname) | ||
101 | strncpy((char*)packet->sname, server_config.sname, sizeof(packet->sname) - 1); | ||
102 | if (server_config.boot_file) | ||
103 | strncpy((char*)packet->file, server_config.boot_file, sizeof(packet->file) - 1); | ||
104 | } | ||
105 | |||
106 | |||
107 | /* send a DHCP OFFER to a DHCP DISCOVER */ | ||
108 | int sendOffer(struct dhcpMessage *oldpacket) | ||
109 | { | ||
110 | struct dhcpMessage packet; | ||
111 | struct dhcpOfferedAddr *lease = NULL; | ||
112 | uint32_t req_align, lease_time_align = server_config.lease; | ||
113 | uint8_t *req, *lease_time; | ||
114 | struct option_set *curr; | ||
115 | struct in_addr addr; | ||
116 | |||
117 | uint32_t static_lease_ip; | ||
118 | |||
119 | init_packet(&packet, oldpacket, DHCPOFFER); | ||
120 | |||
121 | static_lease_ip = getIpByMac(server_config.static_leases, oldpacket->chaddr); | ||
122 | |||
123 | /* ADDME: if static, short circuit */ | ||
124 | if(!static_lease_ip) | ||
125 | { | ||
126 | /* the client is in our lease/offered table */ | ||
127 | if ((lease = find_lease_by_chaddr(oldpacket->chaddr))) { | ||
128 | if (!lease_expired(lease)) | ||
129 | lease_time_align = lease->expires - time(0); | ||
130 | packet.yiaddr = lease->yiaddr; | ||
131 | |||
132 | /* Or the client has a requested ip */ | ||
133 | } else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP)) && | ||
134 | |||
135 | /* Don't look here (ugly hackish thing to do) */ | ||
136 | memcpy(&req_align, req, 4) && | ||
137 | |||
138 | /* and the ip is in the lease range */ | ||
139 | ntohl(req_align) >= ntohl(server_config.start) && | ||
140 | ntohl(req_align) <= ntohl(server_config.end) && | ||
141 | |||
142 | !static_lease_ip && /* Check that its not a static lease */ | ||
143 | /* and is not already taken/offered */ | ||
144 | ((!(lease = find_lease_by_yiaddr(req_align)) || | ||
145 | |||
146 | /* or its taken, but expired */ /* ADDME: or maybe in here */ | ||
147 | lease_expired(lease)))) { | ||
148 | packet.yiaddr = req_align; /* FIXME: oh my, is there a host using this IP? */ | ||
149 | |||
150 | /* otherwise, find a free IP */ | ||
151 | } else { | ||
152 | /* Is it a static lease? (No, because find_address skips static lease) */ | ||
153 | packet.yiaddr = find_address(0); | ||
154 | |||
155 | /* try for an expired lease */ | ||
156 | if (!packet.yiaddr) packet.yiaddr = find_address(1); | ||
157 | } | ||
158 | |||
159 | if(!packet.yiaddr) { | ||
160 | LOG(LOG_WARNING, "no IP addresses to give -- OFFER abandoned"); | ||
161 | return -1; | ||
162 | } | ||
163 | |||
164 | if (!add_lease(packet.chaddr, packet.yiaddr, server_config.offer_time)) { | ||
165 | LOG(LOG_WARNING, "lease pool is full -- OFFER abandoned"); | ||
166 | return -1; | ||
167 | } | ||
168 | |||
169 | if ((lease_time = get_option(oldpacket, DHCP_LEASE_TIME))) { | ||
170 | memcpy(&lease_time_align, lease_time, 4); | ||
171 | lease_time_align = ntohl(lease_time_align); | ||
172 | if (lease_time_align > server_config.lease) | ||
173 | lease_time_align = server_config.lease; | ||
174 | } | ||
175 | |||
176 | /* Make sure we aren't just using the lease time from the previous offer */ | ||
177 | if (lease_time_align < server_config.min_lease) | ||
178 | lease_time_align = server_config.lease; | ||
179 | } | ||
180 | /* ADDME: end of short circuit */ | ||
181 | else | ||
182 | { | ||
183 | /* It is a static lease... use it */ | ||
184 | packet.yiaddr = static_lease_ip; | ||
185 | } | ||
186 | |||
187 | add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_align)); | ||
188 | |||
189 | curr = server_config.options; | ||
190 | while (curr) { | ||
191 | if (curr->data[OPT_CODE] != DHCP_LEASE_TIME) | ||
192 | add_option_string(packet.options, curr->data); | ||
193 | curr = curr->next; | ||
194 | } | ||
195 | |||
196 | add_bootp_options(&packet); | ||
197 | |||
198 | addr.s_addr = packet.yiaddr; | ||
199 | LOG(LOG_INFO, "sending OFFER of %s", inet_ntoa(addr)); | ||
200 | return send_packet(&packet, 0); | ||
201 | } | ||
202 | |||
203 | |||
204 | int sendNAK(struct dhcpMessage *oldpacket) | ||
205 | { | ||
206 | struct dhcpMessage packet; | ||
207 | |||
208 | init_packet(&packet, oldpacket, DHCPNAK); | ||
209 | |||
210 | DEBUG(LOG_INFO, "sending NAK"); | ||
211 | return send_packet(&packet, 1); | ||
212 | } | ||
213 | |||
214 | |||
215 | int sendACK(struct dhcpMessage *oldpacket, uint32_t yiaddr) | ||
216 | { | ||
217 | struct dhcpMessage packet; | ||
218 | struct option_set *curr; | ||
219 | uint8_t *lease_time; | ||
220 | uint32_t lease_time_align = server_config.lease; | ||
221 | struct in_addr addr; | ||
222 | |||
223 | init_packet(&packet, oldpacket, DHCPACK); | ||
224 | packet.yiaddr = yiaddr; | ||
225 | |||
226 | if ((lease_time = get_option(oldpacket, DHCP_LEASE_TIME))) { | ||
227 | memcpy(&lease_time_align, lease_time, 4); | ||
228 | lease_time_align = ntohl(lease_time_align); | ||
229 | if (lease_time_align > server_config.lease) | ||
230 | lease_time_align = server_config.lease; | ||
231 | else if (lease_time_align < server_config.min_lease) | ||
232 | lease_time_align = server_config.lease; | ||
233 | } | ||
234 | |||
235 | add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_align)); | ||
236 | |||
237 | curr = server_config.options; | ||
238 | while (curr) { | ||
239 | if (curr->data[OPT_CODE] != DHCP_LEASE_TIME) | ||
240 | add_option_string(packet.options, curr->data); | ||
241 | curr = curr->next; | ||
242 | } | ||
243 | |||
244 | add_bootp_options(&packet); | ||
245 | |||
246 | addr.s_addr = packet.yiaddr; | ||
247 | LOG(LOG_INFO, "sending ACK to %s", inet_ntoa(addr)); | ||
248 | |||
249 | if (send_packet(&packet, 0) < 0) | ||
250 | return -1; | ||
251 | |||
252 | add_lease(packet.chaddr, packet.yiaddr, lease_time_align); | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | |||
258 | int send_inform(struct dhcpMessage *oldpacket) | ||
259 | { | ||
260 | struct dhcpMessage packet; | ||
261 | struct option_set *curr; | ||
262 | |||
263 | init_packet(&packet, oldpacket, DHCPACK); | ||
264 | |||
265 | curr = server_config.options; | ||
266 | while (curr) { | ||
267 | if (curr->data[OPT_CODE] != DHCP_LEASE_TIME) | ||
268 | add_option_string(packet.options, curr->data); | ||
269 | curr = curr->next; | ||
270 | } | ||
271 | |||
272 | add_bootp_options(&packet); | ||
273 | |||
274 | return send_packet(&packet, 0); | ||
275 | } | ||
diff --git a/networking/udhcp/serverpacket.h b/networking/udhcp/serverpacket.h new file mode 100644 index 000000000..902492895 --- /dev/null +++ b/networking/udhcp/serverpacket.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _SERVERPACKET_H | ||
2 | #define _SERVERPACKET_H | ||
3 | |||
4 | #include "packet.h" | ||
5 | |||
6 | int sendOffer(struct dhcpMessage *oldpacket); | ||
7 | int sendNAK(struct dhcpMessage *oldpacket); | ||
8 | int sendACK(struct dhcpMessage *oldpacket, uint32_t yiaddr); | ||
9 | int send_inform(struct dhcpMessage *oldpacket); | ||
10 | |||
11 | |||
12 | #endif | ||
diff --git a/networking/udhcp/signalpipe.c b/networking/udhcp/signalpipe.c new file mode 100644 index 000000000..e973ff6b2 --- /dev/null +++ b/networking/udhcp/signalpipe.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* signalpipe.c | ||
2 | * | ||
3 | * Signal pipe infrastructure. A reliable way of delivering signals. | ||
4 | * | ||
5 | * Russ Dill <Russ.Dill@asu.edu> December 2003 | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <unistd.h> | ||
23 | #include <fcntl.h> | ||
24 | #include <signal.h> | ||
25 | #include <sys/types.h> | ||
26 | #include <sys/socket.h> | ||
27 | #include <sys/select.h> | ||
28 | |||
29 | |||
30 | #include "signalpipe.h" | ||
31 | #include "common.h" | ||
32 | |||
33 | static int signal_pipe[2]; | ||
34 | |||
35 | static void signal_handler(int sig) | ||
36 | { | ||
37 | if (send(signal_pipe[1], &sig, sizeof(sig), MSG_DONTWAIT) < 0) | ||
38 | DEBUG(LOG_ERR, "Could not send signal: %m"); | ||
39 | } | ||
40 | |||
41 | |||
42 | /* Call this before doing anything else. Sets up the socket pair | ||
43 | * and installs the signal handler */ | ||
44 | void udhcp_sp_setup(void) | ||
45 | { | ||
46 | socketpair(AF_UNIX, SOCK_STREAM, 0, signal_pipe); | ||
47 | fcntl(signal_pipe[0], F_SETFD, FD_CLOEXEC); | ||
48 | fcntl(signal_pipe[1], F_SETFD, FD_CLOEXEC); | ||
49 | signal(SIGUSR1, signal_handler); | ||
50 | signal(SIGUSR2, signal_handler); | ||
51 | signal(SIGTERM, signal_handler); | ||
52 | } | ||
53 | |||
54 | |||
55 | /* Quick little function to setup the rfds. Will return the | ||
56 | * max_fd for use with select. Limited in that you can only pass | ||
57 | * one extra fd */ | ||
58 | int udhcp_sp_fd_set(fd_set *rfds, int extra_fd) | ||
59 | { | ||
60 | FD_ZERO(rfds); | ||
61 | FD_SET(signal_pipe[0], rfds); | ||
62 | if (extra_fd >= 0) { | ||
63 | fcntl(extra_fd, F_SETFD, FD_CLOEXEC); | ||
64 | FD_SET(extra_fd, rfds); | ||
65 | } | ||
66 | return signal_pipe[0] > extra_fd ? signal_pipe[0] : extra_fd; | ||
67 | } | ||
68 | |||
69 | |||
70 | /* Read a signal from the signal pipe. Returns 0 if there is | ||
71 | * no signal, -1 on error (and sets errno appropriately), and | ||
72 | * your signal on success */ | ||
73 | int udhcp_sp_read(fd_set *rfds) | ||
74 | { | ||
75 | int sig; | ||
76 | |||
77 | if (!FD_ISSET(signal_pipe[0], rfds)) | ||
78 | return 0; | ||
79 | |||
80 | if (read(signal_pipe[0], &sig, sizeof(sig)) < 0) | ||
81 | return -1; | ||
82 | |||
83 | return sig; | ||
84 | } | ||
diff --git a/networking/udhcp/signalpipe.h b/networking/udhcp/signalpipe.h new file mode 100644 index 000000000..70c1e5715 --- /dev/null +++ b/networking/udhcp/signalpipe.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* signalpipe.h | ||
2 | * | ||
3 | * Russ Dill <Russ.Dill@asu.edu> December 2003 | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | void udhcp_sp_setup(void); | ||
21 | int udhcp_sp_fd_set(fd_set *rfds, int extra_fd); | ||
22 | int udhcp_sp_read(fd_set *rfds); | ||
diff --git a/networking/udhcp/socket.c b/networking/udhcp/socket.c new file mode 100644 index 000000000..6417267ec --- /dev/null +++ b/networking/udhcp/socket.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * socket.c -- DHCP server client/server socket creation | ||
3 | * | ||
4 | * udhcp client/server | ||
5 | * Copyright (C) 1999 Matthew Ramsay <matthewr@moreton.com.au> | ||
6 | * Chris Trew <ctrew@moreton.com.au> | ||
7 | * | ||
8 | * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | #include <sys/types.h> | ||
26 | #include <sys/socket.h> | ||
27 | #include <sys/ioctl.h> | ||
28 | #include <netinet/in.h> | ||
29 | #include <unistd.h> | ||
30 | #include <string.h> | ||
31 | #include <arpa/inet.h> | ||
32 | #include <net/if.h> | ||
33 | #include <errno.h> | ||
34 | #include <features.h> | ||
35 | #if (__GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || defined _NEWLIB_VERSION | ||
36 | #include <netpacket/packet.h> | ||
37 | #include <net/ethernet.h> | ||
38 | #else | ||
39 | #include <asm/types.h> | ||
40 | #include <linux/if_packet.h> | ||
41 | #include <linux/if_ether.h> | ||
42 | #endif | ||
43 | |||
44 | #include "common.h" | ||
45 | #include "socket.h" | ||
46 | |||
47 | int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp) | ||
48 | { | ||
49 | int fd; | ||
50 | struct ifreq ifr; | ||
51 | struct sockaddr_in *our_ip; | ||
52 | |||
53 | memset(&ifr, 0, sizeof(struct ifreq)); | ||
54 | if((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) { | ||
55 | ifr.ifr_addr.sa_family = AF_INET; | ||
56 | strcpy(ifr.ifr_name, interface); | ||
57 | |||
58 | if (addr) { | ||
59 | if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { | ||
60 | our_ip = (struct sockaddr_in *) &ifr.ifr_addr; | ||
61 | *addr = our_ip->sin_addr.s_addr; | ||
62 | DEBUG(LOG_INFO, "%s (our ip) = %s", ifr.ifr_name, inet_ntoa(our_ip->sin_addr)); | ||
63 | } else { | ||
64 | LOG(LOG_ERR, "SIOCGIFADDR failed, is the interface up and configured?: %m"); | ||
65 | close(fd); | ||
66 | return -1; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) { | ||
71 | DEBUG(LOG_INFO, "adapter index %d", ifr.ifr_ifindex); | ||
72 | *ifindex = ifr.ifr_ifindex; | ||
73 | } else { | ||
74 | LOG(LOG_ERR, "SIOCGIFINDEX failed!: %m"); | ||
75 | close(fd); | ||
76 | return -1; | ||
77 | } | ||
78 | if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) { | ||
79 | memcpy(arp, ifr.ifr_hwaddr.sa_data, 6); | ||
80 | DEBUG(LOG_INFO, "adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x", | ||
81 | arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]); | ||
82 | } else { | ||
83 | LOG(LOG_ERR, "SIOCGIFHWADDR failed!: %m"); | ||
84 | close(fd); | ||
85 | return -1; | ||
86 | } | ||
87 | } else { | ||
88 | LOG(LOG_ERR, "socket failed!: %m"); | ||
89 | return -1; | ||
90 | } | ||
91 | close(fd); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | |||
96 | int listen_socket(uint32_t ip, int port, char *inf) | ||
97 | { | ||
98 | struct ifreq interface; | ||
99 | int fd; | ||
100 | struct sockaddr_in addr; | ||
101 | int n = 1; | ||
102 | |||
103 | DEBUG(LOG_INFO, "Opening listen socket on 0x%08x:%d %s", ip, port, inf); | ||
104 | if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { | ||
105 | DEBUG(LOG_ERR, "socket call failed: %m"); | ||
106 | return -1; | ||
107 | } | ||
108 | |||
109 | memset(&addr, 0, sizeof(addr)); | ||
110 | addr.sin_family = AF_INET; | ||
111 | addr.sin_port = htons(port); | ||
112 | addr.sin_addr.s_addr = ip; | ||
113 | |||
114 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) { | ||
115 | close(fd); | ||
116 | return -1; | ||
117 | } | ||
118 | if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &n, sizeof(n)) == -1) { | ||
119 | close(fd); | ||
120 | return -1; | ||
121 | } | ||
122 | |||
123 | strncpy(interface.ifr_name, inf, IFNAMSIZ); | ||
124 | if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,(char *)&interface, sizeof(interface)) < 0) { | ||
125 | close(fd); | ||
126 | return -1; | ||
127 | } | ||
128 | |||
129 | if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) { | ||
130 | close(fd); | ||
131 | return -1; | ||
132 | } | ||
133 | |||
134 | return fd; | ||
135 | } | ||
diff --git a/networking/udhcp/socket.h b/networking/udhcp/socket.h new file mode 100644 index 000000000..66179d4f5 --- /dev/null +++ b/networking/udhcp/socket.h | |||
@@ -0,0 +1,8 @@ | |||
1 | /* socket.h */ | ||
2 | #ifndef _SOCKET_H | ||
3 | #define _SOCKET_H | ||
4 | |||
5 | int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp); | ||
6 | int listen_socket(uint32_t ip, int port, char *inf); | ||
7 | |||
8 | #endif | ||
diff --git a/networking/udhcp/static_leases.c b/networking/udhcp/static_leases.c new file mode 100644 index 000000000..1124d39de --- /dev/null +++ b/networking/udhcp/static_leases.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | * static_leases.c -- Couple of functions to assist with storing and | ||
3 | * retrieving data for static leases | ||
4 | * | ||
5 | * Wade Berrier <wberrier@myrealbox.com> September 2004 | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | |||
10 | #include <stdlib.h> | ||
11 | #include <stdio.h> | ||
12 | #include <string.h> | ||
13 | |||
14 | #include "static_leases.h" | ||
15 | #include "dhcpd.h" | ||
16 | |||
17 | /* Takes the address of the pointer to the static_leases linked list, | ||
18 | * Address to a 6 byte mac address | ||
19 | * Address to a 4 byte ip address */ | ||
20 | int addStaticLease(struct static_lease **lease_struct, uint8_t *mac, uint32_t *ip) | ||
21 | { | ||
22 | |||
23 | struct static_lease *cur; | ||
24 | struct static_lease *new_static_lease; | ||
25 | |||
26 | /* Build new node */ | ||
27 | new_static_lease = xmalloc(sizeof(struct static_lease)); | ||
28 | new_static_lease->mac = mac; | ||
29 | new_static_lease->ip = ip; | ||
30 | new_static_lease->next = NULL; | ||
31 | |||
32 | /* If it's the first node to be added... */ | ||
33 | if(*lease_struct == NULL) | ||
34 | { | ||
35 | *lease_struct = new_static_lease; | ||
36 | } | ||
37 | else | ||
38 | { | ||
39 | cur = *lease_struct; | ||
40 | while(cur->next != NULL) | ||
41 | { | ||
42 | cur = cur->next; | ||
43 | } | ||
44 | |||
45 | cur->next = new_static_lease; | ||
46 | } | ||
47 | |||
48 | return 1; | ||
49 | |||
50 | } | ||
51 | |||
52 | /* Check to see if a mac has an associated static lease */ | ||
53 | uint32_t getIpByMac(struct static_lease *lease_struct, void *arg) | ||
54 | { | ||
55 | uint32_t return_ip; | ||
56 | struct static_lease *cur = lease_struct; | ||
57 | uint8_t *mac = arg; | ||
58 | |||
59 | return_ip = 0; | ||
60 | |||
61 | while(cur != NULL) | ||
62 | { | ||
63 | /* If the client has the correct mac */ | ||
64 | if(memcmp(cur->mac, mac, 6) == 0) | ||
65 | { | ||
66 | return_ip = *(cur->ip); | ||
67 | } | ||
68 | |||
69 | cur = cur->next; | ||
70 | } | ||
71 | |||
72 | return return_ip; | ||
73 | |||
74 | } | ||
75 | |||
76 | /* Check to see if an ip is reserved as a static ip */ | ||
77 | uint32_t reservedIp(struct static_lease *lease_struct, uint32_t ip) | ||
78 | { | ||
79 | struct static_lease *cur = lease_struct; | ||
80 | |||
81 | uint32_t return_val = 0; | ||
82 | |||
83 | while(cur != NULL) | ||
84 | { | ||
85 | /* If the client has the correct ip */ | ||
86 | if(*cur->ip == ip) | ||
87 | return_val = 1; | ||
88 | |||
89 | cur = cur->next; | ||
90 | } | ||
91 | |||
92 | return return_val; | ||
93 | |||
94 | } | ||
95 | |||
96 | #ifdef UDHCP_DEBUG | ||
97 | /* Print out static leases just to check what's going on */ | ||
98 | /* Takes the address of the pointer to the static_leases linked list */ | ||
99 | void printStaticLeases(struct static_lease **arg) | ||
100 | { | ||
101 | /* Get a pointer to the linked list */ | ||
102 | struct static_lease *cur = *arg; | ||
103 | |||
104 | while(cur != NULL) | ||
105 | { | ||
106 | /* printf("PrintStaticLeases: Lease mac Address: %x\n", cur->mac); */ | ||
107 | printf("PrintStaticLeases: Lease mac Value: %x\n", *(cur->mac)); | ||
108 | /* printf("PrintStaticLeases: Lease ip Address: %x\n", cur->ip); */ | ||
109 | printf("PrintStaticLeases: Lease ip Value: %x\n", *(cur->ip)); | ||
110 | |||
111 | cur = cur->next; | ||
112 | } | ||
113 | |||
114 | |||
115 | } | ||
116 | #endif | ||
117 | |||
118 | |||
119 | |||
diff --git a/networking/udhcp/static_leases.h b/networking/udhcp/static_leases.h new file mode 100644 index 000000000..d06520b23 --- /dev/null +++ b/networking/udhcp/static_leases.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* static_leases.h */ | ||
2 | #ifndef _STATIC_LEASES_H | ||
3 | #define _STATIC_LEASES_H | ||
4 | |||
5 | #include "dhcpd.h" | ||
6 | |||
7 | /* Config file will pass static lease info to this function which will add it | ||
8 | * to a data structure that can be searched later */ | ||
9 | int addStaticLease(struct static_lease **lease_struct, uint8_t *mac, uint32_t *ip); | ||
10 | |||
11 | /* Check to see if a mac has an associated static lease */ | ||
12 | uint32_t getIpByMac(struct static_lease *lease_struct, void *arg); | ||
13 | |||
14 | /* Check to see if an ip is reserved as a static ip */ | ||
15 | uint32_t reservedIp(struct static_lease *lease_struct, uint32_t ip); | ||
16 | |||
17 | #ifdef UDHCP_DEBUG | ||
18 | /* Print out static leases just to check what's going on */ | ||
19 | void printStaticLeases(struct static_lease **lease_struct); | ||
20 | #endif | ||
21 | |||
22 | #endif | ||
23 | |||
24 | |||
25 | |||
diff --git a/networking/udhcp/udhcpc.8 b/networking/udhcp/udhcpc.8 new file mode 100644 index 000000000..752a736c0 --- /dev/null +++ b/networking/udhcp/udhcpc.8 | |||
@@ -0,0 +1,208 @@ | |||
1 | .TH UDHCPC 8 2001-09-26 GNU/Linux "GNU/Linux Administrator's Manual" | ||
2 | .SH NAME | ||
3 | udhcpc \- very small DHCP client | ||
4 | .SH SYNOPSIS | ||
5 | .B udhcpc | ||
6 | .RI [ OPTION ]... | ||
7 | .SH DESCRIPTION | ||
8 | The udhcp client negotiates a lease with the DHCP server and | ||
9 | executes a script when it is obtained or lost. | ||
10 | .SH OPTIONS | ||
11 | .TP | ||
12 | .BI \-c\ CLIENTID ,\ \-\-clientid= CLIENTID | ||
13 | Send the client identifier | ||
14 | .IR CLIENTID . | ||
15 | .TP | ||
16 | .BR -f ,\ \-\-foreground | ||
17 | Do not fork after obtaining a lease. | ||
18 | .TP | ||
19 | .BI \-H\ HOSTNAME ,\ \-\-hostname= HOSTNAME | ||
20 | Send the client hostname | ||
21 | .IR HOSTNAME . | ||
22 | .TP | ||
23 | .BI \-h\ HOSTNAME | ||
24 | Alias for -H | ||
25 | .IR HOSTNAME . | ||
26 | .TP | ||
27 | .BI \-i\ INTERFACE ,\ \-\-interface= INTERFACE | ||
28 | Configure | ||
29 | .IR INTERFACE . | ||
30 | .TP | ||
31 | .BR -n ,\ \-\-now | ||
32 | Exit with failure if a lease cannot be obtained. | ||
33 | .TP | ||
34 | .BI \-p\ FILE ,\ \-\-pidfile= FILE | ||
35 | Write the process ID of the daemon to | ||
36 | .IR FILE . | ||
37 | .TP | ||
38 | .BR -q ,\ \-\-quit | ||
39 | Exit after obtaining a lease. | ||
40 | .TP | ||
41 | .BI \-r\ ADDRESS ,\ \-\-request= ADDRESS | ||
42 | Request IP address | ||
43 | .IR ADDRESS . | ||
44 | .TP | ||
45 | .BI \-s\ FILE ,\ \-\-script= FILE | ||
46 | Use script | ||
47 | .IR FILE . | ||
48 | .TP | ||
49 | .BR -v ,\ \-\-version | ||
50 | Display version. | ||
51 | .SH USAGE | ||
52 | When an event occurs, | ||
53 | .B udhcpc | ||
54 | executes a script. There are four possible arguments to this | ||
55 | script: | ||
56 | .TP | ||
57 | .B deconfig | ||
58 | .B deconfig | ||
59 | is used when | ||
60 | .B udhcpc | ||
61 | starts, and when a lease is lost. The script should put the | ||
62 | interface in an up, but deconfigured, state. | ||
63 | .TP | ||
64 | .B bound | ||
65 | .B bound | ||
66 | is used when | ||
67 | .B udhcpc | ||
68 | moves from an unbound to a bound state. The script should | ||
69 | configure the interface and set any other relevant parameters | ||
70 | (e.g., default gateway, dns server, etc.). | ||
71 | .TP | ||
72 | .B renew | ||
73 | .B renew | ||
74 | is used when | ||
75 | .B udhcpc | ||
76 | when a lease is renewed. The interface is already | ||
77 | configured, so the IP address will not change. Other parameters | ||
78 | (e.g., default gateway, subnet mask, dns server) may. | ||
79 | .TP | ||
80 | .B nak | ||
81 | .B nak | ||
82 | is used when | ||
83 | .B udhcpc | ||
84 | receieves a NAK packet from the server. The | ||
85 | enviromental variable | ||
86 | .B $message | ||
87 | will contain the reason for the | ||
88 | NAK message if the server included one. Processing this message | ||
89 | is optional, as the script will also be called with deconfig if | ||
90 | need be. | ||
91 | .PP | ||
92 | Parameters are passed to the script via the following environment | ||
93 | variables: | ||
94 | .TP | ||
95 | .B HOME | ||
96 | The inherited HOME, or "/" if it is unset. | ||
97 | .TP | ||
98 | .B PATH | ||
99 | The inherited PATH, or "/bin:/usr/bin:/sbin:/usr/sbin" if it is | ||
100 | unset. | ||
101 | .TP | ||
102 | .B interface | ||
103 | The interface. | ||
104 | .TP | ||
105 | .B ip | ||
106 | The client IP address. | ||
107 | .TP | ||
108 | .B siaddr | ||
109 | The BOOTP next server option. | ||
110 | .TP | ||
111 | .B sname | ||
112 | The BOOTP server name option. | ||
113 | .TP | ||
114 | .B boot_file | ||
115 | The BOOTP boot file option. | ||
116 | .TP | ||
117 | .B subnet | ||
118 | The subnet mask. | ||
119 | .TP | ||
120 | .B timezone | ||
121 | The timezone offset from UTC in seconds. | ||
122 | .TP | ||
123 | .B router | ||
124 | The list of routers. | ||
125 | .TP | ||
126 | .B timesvr | ||
127 | The list of time servers. | ||
128 | .TP | ||
129 | .B namesvr | ||
130 | The list of IEN 116 name servers. | ||
131 | .TP | ||
132 | .B dns | ||
133 | The list of DNS servers. | ||
134 | .TP | ||
135 | .B logsvr | ||
136 | The list of MIT-LCS UDP log servers. | ||
137 | .TP | ||
138 | .B cookiesvr | ||
139 | The list of RFC 865 cookie servers. | ||
140 | .TP | ||
141 | .B lprsvr | ||
142 | The list of LPR servers. | ||
143 | .TP | ||
144 | .B hostname | ||
145 | The host name. | ||
146 | .TP | ||
147 | .B bootsize | ||
148 | The length in 512-octet blocks of the bootfile. | ||
149 | .TP | ||
150 | .B domain | ||
151 | The domain name of the network. | ||
152 | .TP | ||
153 | .B swapsvr | ||
154 | The client's swap server. | ||
155 | .TP | ||
156 | .B rootpath | ||
157 | The path of the client's root dist. | ||
158 | .TP | ||
159 | .B ipttl | ||
160 | The TTL. | ||
161 | .TP | ||
162 | .B mtu | ||
163 | The MTU. | ||
164 | .TP | ||
165 | .B broadcast | ||
166 | The broadcast address. | ||
167 | .TP | ||
168 | .B ntpsrv | ||
169 | The list of NTP servers. | ||
170 | .TP | ||
171 | .B wins | ||
172 | The list of WINS servers. | ||
173 | .TP | ||
174 | .B lease | ||
175 | The lease time in seconds. | ||
176 | .TP | ||
177 | .B dhcptype | ||
178 | The DHCP message type (safely ignored). | ||
179 | .TP | ||
180 | .B serverid | ||
181 | The server IP address. | ||
182 | .TP | ||
183 | .B message | ||
184 | Reason for a DHCPNAK. | ||
185 | .TP | ||
186 | .B tftp | ||
187 | The TFTP server name. | ||
188 | .TP | ||
189 | .B bootfile | ||
190 | The bootfile name. | ||
191 | .SH FILES | ||
192 | .TP | ||
193 | .I /usr/share/udhcpc/default.script | ||
194 | Script run when leases are obtained or lost. | ||
195 | .SH NOTES | ||
196 | .B udhcpc | ||
197 | responds to the following signals: | ||
198 | .TP | ||
199 | .B SIGUSR1 | ||
200 | This signal causes | ||
201 | .B udhcpc | ||
202 | to renew the current lease or, if it does not have one, obtain a | ||
203 | new lease. | ||
204 | .TP | ||
205 | .B SIGUSR2 | ||
206 | This signal caused | ||
207 | .B udhcpc | ||
208 | to release the current lease. | ||
diff --git a/networking/udhcp/udhcpd.8 b/networking/udhcp/udhcpd.8 new file mode 100644 index 000000000..be8fac888 --- /dev/null +++ b/networking/udhcp/udhcpd.8 | |||
@@ -0,0 +1,17 @@ | |||
1 | .TH UDHCPD 8 2001-09-27 GNU/Linux "GNU/Linux Administrator's Manual" | ||
2 | .SH NAME | ||
3 | udhcpd \- very small DHCP server | ||
4 | .SH SYNOPSIS | ||
5 | .B udhcpd | ||
6 | .SH DESCRIPTION | ||
7 | The udhcp server negotiates leases with DHCP clients. | ||
8 | .SH FILES | ||
9 | .TP | ||
10 | .I /etc/udhcpd.conf | ||
11 | Configuration file. | ||
12 | .TP | ||
13 | .I /var/lib/misc/udhcpd.leases | ||
14 | Lease information file. | ||
15 | .SH SEE ALSO | ||
16 | .BR dumpleases (1), | ||
17 | .BR udhcpd.conf (8). | ||
diff --git a/networking/udhcp/udhcpd.conf.5 b/networking/udhcp/udhcpd.conf.5 new file mode 100644 index 000000000..b86a9f51f --- /dev/null +++ b/networking/udhcp/udhcpd.conf.5 | |||
@@ -0,0 +1,164 @@ | |||
1 | .TH UDHCPD.CONF 5 2001-09-26 GNU/Linux "GNU/Linux Administrator's Manual" | ||
2 | .SH NAME | ||
3 | udhcpd.conf \- udhcp server configuration file | ||
4 | .SH DESCRIPTION | ||
5 | The file | ||
6 | .I /etc/udhcpd.conf | ||
7 | contains configuration information specific to the udhcp server. | ||
8 | It should contain one configuration keyword per line, followed by | ||
9 | appropriate configuration information. | ||
10 | .SH OPTIONS | ||
11 | .TP | ||
12 | .BI start\ ADDRESS | ||
13 | The starting address of the IP lease block is | ||
14 | .IR ADDRESS . | ||
15 | The default is | ||
16 | .BR 192.168.0.20 . | ||
17 | .TP | ||
18 | .BI end\ ADDRESS | ||
19 | The ending address of the IP lease block is | ||
20 | .IR ADDRESS . | ||
21 | The default is | ||
22 | .BR 192.168.0.254 . | ||
23 | .TP | ||
24 | .BI interface\ INTERFACE | ||
25 | The udhcp server should listen on | ||
26 | .IR INTERFACE . | ||
27 | The default is | ||
28 | .BR eth0 . | ||
29 | .TP | ||
30 | .BI max_leases\ LEASES | ||
31 | Offer at most | ||
32 | .I LEASES | ||
33 | leases (including those reserved by OFFERs, DECLINEs, and ARP | ||
34 | conflicts). The default is | ||
35 | .BR 254 . | ||
36 | .TP | ||
37 | .BI remaining\ REMAINING | ||
38 | If | ||
39 | .I REMAINING | ||
40 | is | ||
41 | .BR yes , | ||
42 | store the time remaining for each lease. If it is | ||
43 | .BR no , | ||
44 | store the expiration time for each lease. The default is | ||
45 | .BR yes . | ||
46 | .TP | ||
47 | .BI auto_time\ SECONDS | ||
48 | Write the lease information to a file every | ||
49 | .I SECONDS | ||
50 | seconds. The default is | ||
51 | .BR 7200 . | ||
52 | .TP | ||
53 | .BI decline_time\ SECONDS | ||
54 | Reserve an IP for | ||
55 | .I SECONDS | ||
56 | seconds if a DHCP decline message is received. The default is | ||
57 | .BR 3600 . | ||
58 | .TP | ||
59 | .BI conflict_time\ SECONDS | ||
60 | Reserve an IP for | ||
61 | .I SECONDS | ||
62 | seconds if an ARP conflict occurs. The default is | ||
63 | .BR 3600 . | ||
64 | .TP | ||
65 | .BI offer_time\ SECONDS | ||
66 | Reserve an IP for | ||
67 | .I SECONDS | ||
68 | seconds if it is offered. The default is | ||
69 | .BR 60 . | ||
70 | .TP | ||
71 | .BI min_lease\ SECONDS | ||
72 | Reserve an IP for the full lease time if the lease to be given is less than | ||
73 | .I SECONDS | ||
74 | seconds. The default is | ||
75 | .BR 60 . | ||
76 | .TP | ||
77 | .BI lease_file\ FILE | ||
78 | Write the lease information to | ||
79 | .IR FILE . | ||
80 | The default is | ||
81 | .BR /var/lib/misc/udhcpd.leases . | ||
82 | .TP | ||
83 | .BI pidfile\ FILE | ||
84 | Write the process ID to | ||
85 | .IR FILE . | ||
86 | The default is | ||
87 | .BR /var/run/udhcpd.pid . | ||
88 | .TP | ||
89 | .BI notify_file\ FILE | ||
90 | Execute | ||
91 | .I FILE | ||
92 | after the lease information is written. By default, no file is executed. | ||
93 | .TP | ||
94 | .BI siaddr\ ADDRESS | ||
95 | BOOTP specific option. The default is | ||
96 | .BR 0.0.0.0 . | ||
97 | .TP | ||
98 | .BI sname\ NAME | ||
99 | BOOTP specific option. There is no default. | ||
100 | .TP | ||
101 | .BI boot_file\ FILE | ||
102 | BOOTP specific option. There is no default. | ||
103 | .TP | ||
104 | .BI option\ OPTION | ||
105 | DHCP specific option. | ||
106 | .RS | ||
107 | .TP | ||
108 | .BI subnet\ ADDRESS | ||
109 | .TP | ||
110 | .BI timezone\ OFFSET | ||
111 | .TP | ||
112 | .BI router\ ADDRESS... | ||
113 | .TP | ||
114 | .BI timesvr\ ADDRESS... | ||
115 | .TP | ||
116 | .BI namesvr\ ADDRESS... | ||
117 | .TP | ||
118 | .BI dns\ ADDRESS... | ||
119 | .TP | ||
120 | .BI logsvr\ ADDRESS... | ||
121 | .TP | ||
122 | .BI cookiesvr\ ADDRESS... | ||
123 | .TP | ||
124 | .BI lprsvr\ ADDRESS... | ||
125 | .TP | ||
126 | .BI hostname\ HOSTNAME | ||
127 | .TP | ||
128 | .BI bootsize\ SIZE | ||
129 | .TP | ||
130 | .BI domain\ DOMAIN | ||
131 | .TP | ||
132 | .BI swapsvr\ ADDRESS | ||
133 | .TP | ||
134 | .BI rootpath\ PATH | ||
135 | .TP | ||
136 | .BI ipttl\ TTL | ||
137 | .TP | ||
138 | .BI mtu\ MTU | ||
139 | .TP | ||
140 | .BI broadcast\ ADDRESS | ||
141 | .TP | ||
142 | .BI ntpsrv\ ADDRESS... | ||
143 | .TP | ||
144 | .BI wins\ ADDRESS... | ||
145 | .TP | ||
146 | .BI requestip\ ADDRESS | ||
147 | .TP | ||
148 | .BI lease\ SECONDS | ||
149 | .TP | ||
150 | .BI dhcptype\ TYPE | ||
151 | .TP | ||
152 | .BI serverid\ ADDRESS | ||
153 | .TP | ||
154 | .BI tftp\ FILE | ||
155 | .TP | ||
156 | .BI bootfile\ FILE | ||
157 | The default for | ||
158 | .B lease | ||
159 | is | ||
160 | .BR 864000 . | ||
161 | There are no defaults for the other options. | ||
162 | .RE | ||
163 | .SH SEE ALSO | ||
164 | .BR udhcpd (8). | ||
diff --git a/networking/udhcp/version.h b/networking/udhcp/version.h new file mode 100644 index 000000000..3862539f5 --- /dev/null +++ b/networking/udhcp/version.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _UDHCP_VERSION_H | ||
2 | #define _UDHCP_VERSION_H | ||
3 | |||
4 | #define VERSION "0.9.9-pre" | ||
5 | |||
6 | #endif | ||