aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2006-05-08 03:20:50 +0000
committerMike Frysinger <vapier@gentoo.org>2006-05-08 03:20:50 +0000
commit7031f62d9b750568b5e98bdb8c59c3c1a72e073d (patch)
treeb8d037a539281e7f7592e3045fa59e445495f603
parent15fe2e11d7886d04450cabc8b40f0d396b6b6d85 (diff)
downloadbusybox-w32-7031f62d9b750568b5e98bdb8c59c3c1a72e073d.tar.gz
busybox-w32-7031f62d9b750568b5e98bdb8c59c3c1a72e073d.tar.bz2
busybox-w32-7031f62d9b750568b5e98bdb8c59c3c1a72e073d.zip
add back in udhcp support
-rw-r--r--include/applets.h3
-rw-r--r--networking/udhcp/AUTHORS13
-rw-r--r--networking/udhcp/COPYING339
-rw-r--r--networking/udhcp/ChangeLog260
-rw-r--r--networking/udhcp/Config.in62
-rw-r--r--networking/udhcp/Makefile5
-rw-r--r--networking/udhcp/Makefile.busybox36
-rw-r--r--networking/udhcp/Makefile.in53
-rw-r--r--networking/udhcp/Makefile.udhcp110
-rw-r--r--networking/udhcp/README53
-rw-r--r--networking/udhcp/README.dumpleases17
-rw-r--r--networking/udhcp/README.udhcpc144
-rw-r--r--networking/udhcp/README.udhcpd59
-rw-r--r--networking/udhcp/TODO16
-rw-r--r--networking/udhcp/arpping.c106
-rw-r--r--networking/udhcp/arpping.h35
-rw-r--r--networking/udhcp/clientpacket.c245
-rw-r--r--networking/udhcp/clientpacket.h14
-rw-r--r--networking/udhcp/clientsocket.c62
-rw-r--r--networking/udhcp/clientsocket.h7
-rw-r--r--networking/udhcp/common.c135
-rw-r--r--networking/udhcp/common.h55
-rw-r--r--networking/udhcp/dhcpc.c574
-rw-r--r--networking/udhcp/dhcpc.h39
-rw-r--r--networking/udhcp/dhcpd.c273
-rw-r--r--networking/udhcp/dhcpd.h141
-rw-r--r--networking/udhcp/dumpleases.130
-rw-r--r--networking/udhcp/dumpleases.c114
-rw-r--r--networking/udhcp/files.c393
-rw-r--r--networking/udhcp/files.h19
-rw-r--r--networking/udhcp/frontend.c16
-rw-r--r--networking/udhcp/leases.c158
-rw-r--r--networking/udhcp/leases.h23
-rw-r--r--networking/udhcp/libbb_udhcp.h92
-rw-r--r--networking/udhcp/options.c172
-rw-r--r--networking/udhcp/options.h38
-rw-r--r--networking/udhcp/packet.c207
-rw-r--r--networking/udhcp/packet.h41
-rw-r--r--networking/udhcp/pidfile.c75
-rw-r--r--networking/udhcp/pidfile.h25
-rw-r--r--networking/udhcp/samples/README11
-rwxr-xr-xnetworking/udhcp/samples/sample.bound30
-rwxr-xr-xnetworking/udhcp/samples/sample.deconfig4
-rwxr-xr-xnetworking/udhcp/samples/sample.nak4
-rwxr-xr-xnetworking/udhcp/samples/sample.renew30
-rw-r--r--networking/udhcp/samples/sample.script7
-rw-r--r--networking/udhcp/samples/simple.script39
-rw-r--r--networking/udhcp/samples/udhcpd.conf116
-rw-r--r--networking/udhcp/script.c234
-rw-r--r--networking/udhcp/script.h6
-rw-r--r--networking/udhcp/serverpacket.c275
-rw-r--r--networking/udhcp/serverpacket.h12
-rw-r--r--networking/udhcp/signalpipe.c84
-rw-r--r--networking/udhcp/signalpipe.h22
-rw-r--r--networking/udhcp/socket.c135
-rw-r--r--networking/udhcp/socket.h8
-rw-r--r--networking/udhcp/static_leases.c119
-rw-r--r--networking/udhcp/static_leases.h25
-rw-r--r--networking/udhcp/udhcpc.8208
-rw-r--r--networking/udhcp/udhcpd.817
-rw-r--r--networking/udhcp/udhcpd.conf.5164
-rw-r--r--networking/udhcp/version.h6
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))
95USE_DPKG_DEB(APPLET_ODDNAME(dpkg-deb, dpkg_deb, _BB_DIR_USR_BIN, _BB_SUID_NEVER, dpkg_deb)) 95USE_DPKG_DEB(APPLET_ODDNAME(dpkg-deb, dpkg_deb, _BB_DIR_USR_BIN, _BB_SUID_NEVER, dpkg_deb))
96USE_DU(APPLET(du, du, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 96USE_DU(APPLET(du, du, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
97USE_DUMPKMAP(APPLET(dumpkmap, dumpkmap, _BB_DIR_BIN, _BB_SUID_NEVER)) 97USE_DUMPKMAP(APPLET(dumpkmap, dumpkmap, _BB_DIR_BIN, _BB_SUID_NEVER))
98USE_DUMPLEASES(APPLET(dumpleases, dumpleases, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
98USE_E2FSCK(APPLET(e2fsck, e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER)) 99USE_E2FSCK(APPLET(e2fsck, e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER))
99USE_E2LABEL(APPLET_NOUSAGE(e2label, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER)) 100USE_E2LABEL(APPLET_NOUSAGE(e2label, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER))
100USE_ECHO(APPLET(echo, echo, _BB_DIR_BIN, _BB_SUID_NEVER)) 101USE_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))
273USE_TRUE(APPLET(true, true, _BB_DIR_BIN, _BB_SUID_NEVER)) 274USE_TRUE(APPLET(true, true, _BB_DIR_BIN, _BB_SUID_NEVER))
274USE_TTY(APPLET(tty, tty, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 275USE_TTY(APPLET(tty, tty, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
275USE_TUNE2FS(APPLET(tune2fs, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER)) 276USE_TUNE2FS(APPLET(tune2fs, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER))
277USE_UDHCPC(APPLET(udhcpc, udhcpc, _BB_DIR_SBIN, _BB_SUID_NEVER))
278USE_UDHCPD(APPLET(udhcpd, udhcpd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
276USE_UMOUNT(APPLET(umount, umount, _BB_DIR_BIN, _BB_SUID_NEVER)) 279USE_UMOUNT(APPLET(umount, umount, _BB_DIR_BIN, _BB_SUID_NEVER))
277USE_UNAME(APPLET(uname, uname, _BB_DIR_BIN, _BB_SUID_NEVER)) 280USE_UNAME(APPLET(uname, uname, _BB_DIR_BIN, _BB_SUID_NEVER))
278USE_UNCOMPRESS(APPLET(uncompress, uncompress, _BB_DIR_BIN, _BB_SUID_NEVER)) 281USE_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 @@
1udhcp server/client package
2-----------------------
3
4Russ Dill <Russ.Dill@asu.edu>
5Matthew Ramsay <matthewr@moreton.com.au>
6Chris Trew <christ@moreton.com.au>
7
8Other Credits:
9--------------
10Moreton Bay (http://www.moretonbay.com/)
11Vladimir 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
12freedom to share and change it. By contrast, the GNU General Public
13License is intended to guarantee your freedom to share and change free
14software--to make sure the software is free for all its users. This
15General Public License applies to most of the Free Software
16Foundation's software and to any other program whose authors commit to
17using it. (Some other Free Software Foundation software is covered by
18the GNU Library General Public License instead.) You can apply it to
19your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22price. Our General Public Licenses are designed to make sure that you
23have the freedom to distribute copies of free software (and charge for
24this service if you wish), that you receive source code or can get it
25if you want it, that you can change the software or use pieces of it
26in 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
29anyone to deny you these rights or to ask you to surrender the rights.
30These restrictions translate to certain responsibilities for you if you
31distribute copies of the software, or if you modify it.
32
33 For example, if you distribute copies of such a program, whether
34gratis or for a fee, you must give the recipients all the rights that
35you have. You must make sure that they, too, receive or can get the
36source code. And you must show them these terms so they know their
37rights.
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,
41distribute and/or modify the software.
42
43 Also, for each author's protection and ours, we want to make certain
44that everyone understands that there is no warranty for this free
45software. If the software is modified by someone else and passed on, we
46want its recipients to know that what they have is not the original, so
47that any problems introduced by others will not reflect on the original
48authors' reputations.
49
50 Finally, any free program is threatened constantly by software
51patents. We wish to avoid the danger that redistributors of a free
52program will individually obtain patent licenses, in effect making the
53program proprietary. To prevent this, we have made it clear that any
54patent must be licensed for everyone's free use or not licensed at all.
55
56 The precise terms and conditions for copying, distribution and
57modification 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
63a notice placed by the copyright holder saying it may be distributed
64under the terms of this General Public License. The "Program", below,
65refers to any such program or work, and a "work based on the Program"
66means either the Program or any derivative work under copyright law:
67that is to say, a work containing the Program or a portion of it,
68either verbatim or with modifications and/or translated into another
69language. (Hereinafter, translation is included without limitation in
70the term "modification".) Each licensee is addressed as "you".
71
72Activities other than copying, distribution and modification are not
73covered by this License; they are outside its scope. The act of
74running the Program is not restricted, and the output from the Program
75is covered only if its contents constitute a work based on the
76Program (independent of having been made by running the Program).
77Whether that is true depends on what the Program does.
78
79 1. You may copy and distribute verbatim copies of the Program's
80source code as you receive it, in any medium, provided that you
81conspicuously and appropriately publish on each copy an appropriate
82copyright notice and disclaimer of warranty; keep intact all the
83notices that refer to this License and to the absence of any warranty;
84and give any other recipients of the Program a copy of this License
85along with the Program.
86
87You may charge a fee for the physical act of transferring a copy, and
88you 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
91of it, thus forming a work based on the Program, and copy and
92distribute such modifications or work under the terms of Section 1
93above, 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
114These requirements apply to the modified work as a whole. If
115identifiable sections of that work are not derived from the Program,
116and can be reasonably considered independent and separate works in
117themselves, then this License, and its terms, do not apply to those
118sections when you distribute them as separate works. But when you
119distribute the same sections as part of a whole which is a work based
120on the Program, the distribution of the whole must be on the terms of
121this License, whose permissions for other licensees extend to the
122entire whole, and thus to each and every part regardless of who wrote it.
123
124Thus, it is not the intent of this section to claim rights or contest
125your rights to work written entirely by you; rather, the intent is to
126exercise the right to control the distribution of derivative or
127collective works based on the Program.
128
129In addition, mere aggregation of another work not based on the Program
130with the Program (or with a work based on the Program) on a volume of
131a storage or distribution medium does not bring the other work under
132the scope of this License.
133
134 3. You may copy and distribute the Program (or a work based on it,
135under Section 2) in object code or executable form under the terms of
136Sections 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
155The source code for a work means the preferred form of the work for
156making modifications to it. For an executable work, complete source
157code means all the source code for all modules it contains, plus any
158associated interface definition files, plus the scripts used to
159control compilation and installation of the executable. However, as a
160special exception, the source code distributed need not include
161anything that is normally distributed (in either source or binary
162form) with the major components (compiler, kernel, and so on) of the
163operating system on which the executable runs, unless that component
164itself accompanies the executable.
165
166If distribution of executable or object code is made by offering
167access to copy from a designated place, then offering equivalent
168access to copy the source code from the same place counts as
169distribution of the source code, even though third parties are not
170compelled to copy the source along with the object code.
171
172 4. You may not copy, modify, sublicense, or distribute the Program
173except as expressly provided under this License. Any attempt
174otherwise to copy, modify, sublicense or distribute the Program is
175void, and will automatically terminate your rights under this License.
176However, parties who have received copies, or rights, from you under
177this License will not have their licenses terminated so long as such
178parties remain in full compliance.
179
180 5. You are not required to accept this License, since you have not
181signed it. However, nothing else grants you permission to modify or
182distribute the Program or its derivative works. These actions are
183prohibited by law if you do not accept this License. Therefore, by
184modifying or distributing the Program (or any work based on the
185Program), you indicate your acceptance of this License to do so, and
186all its terms and conditions for copying, distributing or modifying
187the Program or works based on it.
188
189 6. Each time you redistribute the Program (or any work based on the
190Program), the recipient automatically receives a license from the
191original licensor to copy, distribute or modify the Program subject to
192these terms and conditions. You may not impose any further
193restrictions on the recipients' exercise of the rights granted herein.
194You are not responsible for enforcing compliance by third parties to
195this License.
196
197 7. If, as a consequence of a court judgment or allegation of patent
198infringement or for any other reason (not limited to patent issues),
199conditions are imposed on you (whether by court order, agreement or
200otherwise) that contradict the conditions of this License, they do not
201excuse you from the conditions of this License. If you cannot
202distribute so as to satisfy simultaneously your obligations under this
203License and any other pertinent obligations, then as a consequence you
204may not distribute the Program at all. For example, if a patent
205license would not permit royalty-free redistribution of the Program by
206all those who receive copies directly or indirectly through you, then
207the only way you could satisfy both it and this License would be to
208refrain entirely from distribution of the Program.
209
210If any portion of this section is held invalid or unenforceable under
211any particular circumstance, the balance of the section is intended to
212apply and the section as a whole is intended to apply in other
213circumstances.
214
215It is not the purpose of this section to induce you to infringe any
216patents or other property right claims or to contest validity of any
217such claims; this section has the sole purpose of protecting the
218integrity of the free software distribution system, which is
219implemented by public license practices. Many people have made
220generous contributions to the wide range of software distributed
221through that system in reliance on consistent application of that
222system; it is up to the author/donor to decide if he or she is willing
223to distribute software through any other system and a licensee cannot
224impose that choice.
225
226This section is intended to make thoroughly clear what is believed to
227be a consequence of the rest of this License.
228
229 8. If the distribution and/or use of the Program is restricted in
230certain countries either by patents or by copyrighted interfaces, the
231original copyright holder who places the Program under this License
232may add an explicit geographical distribution limitation excluding
233those countries, so that distribution is permitted only in or among
234countries not thus excluded. In such case, this License incorporates
235the limitation as if written in the body of this License.
236
237 9. The Free Software Foundation may publish revised and/or new versions
238of the General Public License from time to time. Such new versions will
239be similar in spirit to the present version, but may differ in detail to
240address new problems or concerns.
241
242Each version is given a distinguishing version number. If the Program
243specifies a version number of this License which applies to it and "any
244later version", you have the option of following the terms and conditions
245either of that version or of any later version published by the Free
246Software Foundation. If the Program does not specify a version number of
247this License, you may choose any version ever published by the Free Software
248Foundation.
249
250 10. If you wish to incorporate parts of the Program into other free
251programs whose distribution conditions are different, write to the author
252to ask for permission. For software which is copyrighted by the Free
253Software Foundation, write to the Free Software Foundation; we sometimes
254make exceptions for this. Our decision will be guided by the two goals
255of preserving the free status of all derivatives of our free software and
256of 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
261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268REPAIR OR CORRECTION.
269
270 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278POSSIBILITY 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
285possible use to the public, the best way to achieve this is to make it
286free 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
289to attach them to the start of each source file to most effectively
290convey the exclusion of warranty; and each file should have at least
291the "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
310Also add information on how to contact you by electronic and paper mail.
311
312If the program is interactive, make it output a short notice like this
313when 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
320The hypothetical commands `show w' and `show c' should show the appropriate
321parts of the General Public License. Of course, the commands you use may
322be called something other than `show w' and `show c'; they could even be
323mouse-clicks or menu items--whatever suits your program.
324
325You should also get your employer (if you work as a programmer) or your
326school, if any, to sign a "copyright disclaimer" for the program, if
327necessary. 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
335This General Public License does not permit incorporating your program into
336proprietary programs. If your program is a subroutine library, you may
337consider it more useful to permit linking proprietary applications with the
338library. If this is what you want to do, use the GNU Library General
339Public 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 @@
10.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
120.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
450.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
720.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
790.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
850.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
930.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
1010.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
1090.9.1 (010806)
110+ Added udhcpc client
111+ reorganized functions/files
112+ listening socket now only binds to one interface
113
1140.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
1280.8.29 (000323)
129+ stable(?) release
130
131
1320.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
1380.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
1430.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
1480.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
1530.8.23 (000117)
154+ NETtel specific fix for ignoring dhcp requests on 2nd interface
155
1560.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
1610.8.21 (000113)
162+ now sends the correct server ip instead of hardcoded value
163+ minor debugging fixes for critical messages
164
1650.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
1730.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
1770.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
1830.8.17 (991212)
184
185- has problems clearing out the offered array
186
1870.8.16 (991203)
188+ Non blocking error is changes to informational as it is not really
189 an error
190
1910.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
1950.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
2000.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
2060.8.12 (991111)
207+ debugging was real bad.. cleaned up a bit.. needs overhaul
208
209
2100.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
2220.8.10 (991105)
223+ \n bug in arpping
224+ minor debugging changes (removed printfs etc)
225+ started browseiplist (not finished)
226
2270.8.9 (19991105)
228+ fixed options array size bug (options were cut off)
229
2300.8.8 (19991105)
231+ ignores requests from dhcpcd on the same machine
232
2330.8.7 (19991104)
234+ don't die if we can't bind to search for existing DHCP server
235+ slightly more verbose syslogging
236
2370.8.6 (19991103)
238+ added makeiplist (not finished -- core dumps)
239+ minor debug changes
240
2410.8.5 (19991029)
242+ exits if another DHCP server is already on the network
243+ added Linux Makefile
244
2450.8.4 (19991026)
246+ minor bug fix in findaddr preventing an addr being found
247
2480.8.3 (19991025)
249+ fixed up debugging
250+ minor hwaddr issues
251
2520.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
6menu "udhcp Server/Client"
7
8config 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
17config 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
29config 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
40config 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
50config 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
61endmenu
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 @@
1ifneq ($(wildcard ../../networking/Config.in),)
2include Makefile.busybox
3else
4include Makefile.udhcp
5endif
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
20ifndef top_srcdir
21top_srcdir=../..
22endif
23ifndef top_builddir
24top_builddir=../..
25endif
26srcdir=$(top_srcdir)/networking/udhcp
27UDHCP_DIR:=./
28include $(top_builddir)/Rules.mak
29include $(top_builddir)/.config
30include Makefile.in
31all: $(libraries-y)
32-include $(top_builddir)/.depend
33
34clean:
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
8UDHCP_AR:=udhcp.a
9ifndef $(UDHCP_DIR)
10UDHCP_DIR:=$(top_builddir)/networking/udhcp/
11endif
12srcdir=$(top_srcdir)/networking/udhcp
13
14#ok, so I forgot how to do an or, but this is a quick and dirty hack
15ifeq ($(strip $(CONFIG_UDHCPC)),y)
16CONFIG_UDHCP_SHARED=y
17else
18ifeq ($(strip $(CONFIG_UDHCPD)),y)
19CONFIG_UDHCP_SHARED=y
20else
21CONFIG_UDHCP_SHARED=n
22endif
23endif
24
25UDHCP-y:=
26UDHCP-$(CONFIG_UDHCP_SHARED) += common.c options.c packet.c pidfile.c \
27 signalpipe.c socket.c
28UDHCP-$(CONFIG_UDHCPC) += dhcpc.c clientpacket.c clientsocket.c \
29 script.c
30UDHCP-$(CONFIG_UDHCPD) += dhcpd.c arpping.c files.c leases.c \
31 serverpacket.c static_leases.c
32UDHCP-$(CONFIG_DUMPLEASES) += dumpleases.c
33UDHCP_OBJS:=$(patsubst %.c,$(UDHCP_DIR)%.o, $(UDHCP-y))
34
35ifneq ($(strip $(UDHCP-y)),)
36libraries-y+=$(UDHCP_DIR)$(UDHCP_AR)
37endif
38
39UDHCP-y:=$(patsubst %,$(srcdir)/%,$(UDHCP-y))
40UDHCP-a:=$(wildcard $(srcdir)/*.c)
41APPLET_SRC-y+=$(UDHCP-y)
42APPLET_SRC-a+=$(UDHCP-a)
43
44UDHCP_INCLUDES:=$(srcdir)
45
46APPLETS_DEFINE-y+=-DIN_BUSYBOX -I$(UDHCP_INCLUDES)
47APPLETS_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
3DESTDIR =
4prefix = /usr
5SBINDIR = /sbin
6USRSBINDIR = $(DESTDIR)$(prefix)/sbin
7USRBINDIR = $(DESTDIR)$(prefix)/bin
8USRSHAREDIR = $(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
28CC = $(CROSS_COMPILE)gcc
29LD = $(CROSS_COMPILE)gcc
30INSTALL = install
31
32OBJS_SHARED = common.o options.o packet.o pidfile.o signalpipe.o socket.o
33DHCPD_OBJS = dhcpd.o arpping.o files.o leases.o serverpacket.o static_leases.o
34DHCPC_OBJS = dhcpc.o clientpacket.o clientsocket.o script.o
35
36ifdef COMBINED_BINARY
37EXEC1 = udhcpd
38OBJS1 = $(DHCPD_OBJS) $(DHCPC_OBJS) $(OBJS_SHARED) frontend.o
39CFLAGS += -DCOMBINED_BINARY
40else
41EXEC1 = udhcpd
42OBJS1 = $(DHCPD_OBJS) $(OBJS_SHARED)
43
44EXEC2 = udhcpc
45OBJS2 = $(DHCPC_OBJS) $(OBJS_SHARED)
46endif
47
48EXEC3 = dumpleases
49OBJS3 = dumpleases.o
50
51BOOT_PROGRAM = udhcpc
52DAEMON = udhcpd
53COMMAND = dumpleases
54
55ifdef UDHCP_SYSLOG
56CFLAGS += -DUDHCP_SYSLOG
57endif
58
59CFLAGS += -W -Wall -Wstrict-prototypes -D_GNU_SOURCE
60
61ifdef UDHCP_DEBUG
62CFLAGS += -g -DUDHCP_DEBUG
63STRIP=true
64else
65CFLAGS += -Os -fomit-frame-pointer
66STRIP=$(CROSS_COMPILE)strip
67endif
68
69all: $(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
88install: all
89 mkdir -p $(USRSBINDIR) $(USRBINDIR)
90 $(INSTALL) -m 755 $(DAEMON) $(USRSBINDIR)
91 $(INSTALL) -m 755 $(COMMAND) $(USRBINDIR)
92ifdef COMBINED_BINARY
93 ln -sf $(DAEMON) $(USRSBINDIR)/$(BOOT_PROGRAM)
94else
95 $(INSTALL) -m 755 $(BOOT_PROGRAM) $(USRSBINDIR)
96endif
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
109clean:
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 @@
1udhcp server/client package readme
2-------------------------
3
4The udhcp server/client package is primarily geared towards embedded
5systems. It does however, strive to be fully functional, and RFC
6compliant.
7
8
9compile time options
10-------------------
11
12The 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
24dhcpd.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
33options.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
43busybox drop-in
44--------------
45udhcp is now a drop-in component for busybox (http://busybox.net).
46To update busybox to the latest revision, simply do a:
47
48cp *.[ch] README AUTHORS COPYING ChangeLog TODO \
49 <busybox_source>/networking/udhcp
50
51The only two files udhcp does not provide are config.in and
52Makefile.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 @@
1udhcp lease dump (dumpleases)
2----------------------------
3
4dumpleases displays the leases written out by the udhcpd server. Lease
5times are stored in the file by time remaining in lease (for systems
6without clock that works when there is no power), or by the absolute
7time that it expires in seconds from epoch. dumpleases accepts the
8following 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
15Note that if udhcpd has not written a leases file recently, the output
16of 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 @@
1udhcp client (udhcpc)
2--------------------
3
4The udhcp client negotiates a lease with the DHCP server and notifies
5a set of scripts when a leases is obtained or lost.
6
7
8command line options
9-------------------
10
11The 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
33If the requested IP address cannot be obtained, the client accepts the
34address that the server offers.
35
36
37udhcp client scripts
38-------------------
39
40When an event occurs, udhcpc calls the action script. udhcpc never does
41any configuration of the network interface itself, but instead relies on
42a set of scripts. The script by default is
43/usr/share/udhcpc/default.script but this can be changed via the command
44line 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
68The 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
105additional options are easily added in options.c.
106
107
108note on udhcpc's random seed
109---------------------------
110
111udhcpc will seed its random number generator (used for generating xid's)
112by reading /dev/urandom. If you have a lot of embedded systems on the same
113network, with no entropy, you can either seed /dev/urandom by a method of
114your own, or doing the following on startup:
115
116ifconfig eth0 > /dev/urandom
117
118in order to seed /dev/urandom with some data (mac address) unique to your
119system. If reading /dev/urandom fails, udhcpc will fall back to its old
120behavior of seeding with time(0).
121
122
123signals accepted by udhcpc
124-------------------------
125
126udhcpc also responds to SIGUSR1 and SIGUSR2. SIGUSR1 will force a renew state,
127and SIGUSR2 will force a release of the current lease, and cause udhcpc to
128go into an inactive state (until it is killed, or receives a SIGUSR1). You do
129not need to sleep between sending signals, as signals received are processed
130sequencially in the order they are received.
131
132
133compile time options
134-------------------
135
136options.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 @@
1udhcp server (udhcpd)
2--------------------
3
4The only command line argument to udhcpd is an optional specifed
5config file. If no config file is specified, udhcpd uses the default
6config file, /etc/udhcpd.conf. Ex:
7
8udhcpd /etc/udhcpd.eth1.conf
9
10The udhcp server employs a number of simple config files:
11
12udhcpd.leases
13------------
14
15The udhcpd.leases behavior is designed for an embedded system. The
16file is written either every auto_time seconds, or when a SIGUSR1
17is received (the auto_time timer restarts if a SIGUSR1 is received).
18If you send a SIGTERM to udhcpd directly after a SIGUSR1, udhcpd will
19finish writing the leases file and wait for the aftermentioned script
20to be executed and finish before quiting, so you do not need to sleep
21between sending signals. When the file is written, a script can be
22optionally called to commit the file to flash. Lease times are stored
23in the file by time remaining in lease (for systems without clock
24that works when there is no power), or by the absolute time that it
25expires in seconds from epoch. In the remaining format, expired leases
26are stored as zero. The file is of the format:
27
2816 byte MAC
294 byte ip address
30u32 expire time
3116 byte MAC
324 byte ip address
33u32 expire time
34.
35etc.
36
37example: hexdump udhcpd.leases
38
390000000 1000 c95a 27d9 0000 0000 0000 0000 0000
400000010 a8c0 150a 0d00 2d29 5000 23fc 8566 0000
410000020 0000 0000 0000 0000 a8c0 140a 0d00 4e29
420000030
43
44
45udhcpd.conf
46----------
47
48The format is fairly simple, there is a sample file with all the
49available options and comments describing them in samples/udhcpd.conf
50
51compile time options
52-------------------
53
54dhcpd.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 @@
1TODO
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 */
32int 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
13struct 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 */
33int 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 */
49unsigned 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 */
70static 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. */
85static 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 */
101int 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 */
118int 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 */
138int 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 */
158int 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 */
175int 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
6unsigned long random_xid(void);
7int send_discover(unsigned long xid, unsigned long requested);
8int send_selecting(unsigned long xid, unsigned long server, unsigned long requested);
9int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr);
10int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr);
11int send_release(unsigned long server, unsigned long ciaddr);
12int 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
41int 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
5int 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
27static int daemonized;
28
29long 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 */
42static 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
51void 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
72void 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
90static 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
101void 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
116void 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
29enum 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
42long uptime(void);
43void background(const char *pidfile);
44void start_log_and_pid(const char *client_server, const char *pidfile);
45void 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
35static int state;
36static unsigned long requested_ip; /* = 0 */
37static unsigned long server_addr;
38static unsigned long timeout;
39static int packet_num; /* = 0 */
40static int fd = -1;
41
42#define LISTEN_NONE 0
43#define LISTEN_KERNEL 1
44#define LISTEN_RAW 2
45static int listen_mode;
46
47struct 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
67static 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
97extern void show_usage(void) ATTRIBUTE_NORETURN;
98#endif
99
100
101/* just a little helper */
102static 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 */
113static 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 */
143static 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
166static 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
175int udhcpc_main(int argc, char *argv[])
176#else
177int 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
18struct 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
36extern 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 */
51struct dhcpOfferedAddr *leases;
52struct server_config_t server_config;
53
54
55#ifdef COMBINED_BINARY
56int udhcpd_main(int argc, char *argv[])
57#else
58int 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
98struct option_set {
99 uint8_t *data;
100 struct option_set *next;
101};
102
103struct static_lease {
104 uint8_t *mac;
105 uint32_t *ip;
106 struct static_lease *next;
107};
108
109struct 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
137extern struct server_config_t server_config;
138extern 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
3dumpleases \- display leases granted by udhcp server
4.SH SYNOPSIS
5.B dumpleases
6.RI [ OPTION ]...
7.SH DESCRIPTION
8Display the DHCP leases granted by
9.BR udhcpd (8).
10.SH OPTIONS
11.TP
12.BR \-a ,\ \-\-absolute
13Interpret lease times as expiration time.
14.TP
15.BI \-f\ FILE,\ \-\-file= FILE
16Read lease information from
17.IR FILE .
18.TP
19.BR \-h ,\ \-\-help
20Display help.
21.TP
22.BR \-r ,\ \-\-remaining
23Interpret lease times as remaining time.
24.SH FILES
25.TP
26.I /var/lib/misc/udhcpd.leases
27Lease 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
28static 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
43int dumpleases_main(int argc, char *argv[])
44#else
45int 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 */
30static 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
44static 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
61static 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
72static 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
81static 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 */
97struct 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 */
108static 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 */
144static 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
219static 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
253static 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
279int 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
328void 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
368void 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
5struct 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
13int read_config(const char *file);
14void write_leases(void);
15void read_leases(const char *file);
16
17struct 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
3extern int udhcpd_main(int argc, char *argv[]);
4extern int udhcpc_main(int argc, char *argv[]);
5
6int 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
22uint8_t blank_chaddr[] = {[0 ... 15] = 0};
23
24/* clear every lease out that chaddr OR yiaddr matches and is nonzero */
25void 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 */
40struct 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 */
60int 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 */
67struct 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 */
85struct 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 */
97struct 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 */
109static 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... */
125uint32_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
6struct dhcpOfferedAddr {
7 uint8_t chaddr[16];
8 uint32_t yiaddr; /* network order */
9 uint32_t expires; /* host order */
10};
11
12extern uint8_t blank_chaddr[];
13
14void clear_lease(uint8_t *chaddr, uint32_t yiaddr);
15struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease);
16int lease_expired(struct dhcpOfferedAddr *lease);
17struct dhcpOfferedAddr *oldest_expired_lease(void);
18struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr);
19struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr);
20uint32_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
80static 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 */
16struct 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 */
50int 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). */
64uint8_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) */
119int 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) */
133int 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 */
150int 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
9enum {
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
24struct dhcp_option {
25 char name[10];
26 char flags;
27 uint8_t code;
28};
29
30extern struct dhcp_option dhcp_options[];
31extern int option_lengths[];
32
33uint8_t *get_option(struct dhcpMessage *packet, int code);
34int end_option(uint8_t *optionptr);
35int add_option_string(uint8_t *optionptr, uint8_t *string);
36int 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
23void 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 */
47int 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
85uint16_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 */
116int 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 */
169int 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
7struct 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
26struct udp_dhcp_packet {
27 struct iphdr ip;
28 struct udphdr udp;
29 struct dhcpMessage data;
30};
31
32void init_header(struct dhcpMessage *packet, char type);
33int get_packet(struct dhcpMessage *packet, int fd);
34uint16_t checksum(void *addr, int count);
35int 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);
37int 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
32static char *saved_pidfile;
33
34static void pidfile_delete(void)
35{
36 if (saved_pidfile) unlink(saved_pidfile);
37}
38
39
40int 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
59void 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
23int pidfile_acquire(const char *pidfile);
24void 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 @@
1The 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
4RESOLV_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
11if [ -n "$router" ]
12then
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
22fi
23
24echo -n > $RESOLV_CONF
25[ -n "$domain" ] && echo domain $domain >> $RESOLV_CONF
26for i in $dns
27do
28 echo adding dns $i
29 echo nameserver $i >> $RESOLV_CONF
30done \ 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
4echo 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
4RESOLV_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
11if [ -n "$router" ]
12then
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
22fi
23
24echo -n > $RESOLV_CONF
25[ -n "$domain" ] && echo domain $domain >> $RESOLV_CONF
26for i in $dns
27do
28 echo adding dns $i
29 echo nameserver $i >> $RESOLV_CONF
30done \ 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
7exec /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
7RESOLV_CONF="/etc/resolv.conf"
8[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
9[ -n "$subnet" ] && NETMASK="netmask $subnet"
10
11case "$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 ;;
37esac
38
39exit 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
5start 192.168.0.20 #default: 192.168.0.20
6end 192.168.0.254 #default: 192.168.0.254
7
8
9# The interface that udhcpd will use
10
11interface 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
86opt dns 192.168.10.2 192.168.10.10
87option subnet 255.255.255.0
88opt router 192.168.10.2
89opt wins 192.168.10.10
90option dns 129.219.13.81 # appened to above DNS servers for a total of 3
91option domain local
92option 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...) */
39static 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
52static 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
59static 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 */
66static 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'. */
78static 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 */
137static 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 */
207void 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
4extern 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 */
35static 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 */
45static 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 */
73static 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
84static 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 */
97static 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 */
108int 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
204int 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
215int 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
258int 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
6int sendOffer(struct dhcpMessage *oldpacket);
7int sendNAK(struct dhcpMessage *oldpacket);
8int sendACK(struct dhcpMessage *oldpacket, uint32_t yiaddr);
9int 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
33static int signal_pipe[2];
34
35static 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 */
44void 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 */
58int 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 */
73int 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
20void udhcp_sp_setup(void);
21int udhcp_sp_fd_set(fd_set *rfds, int extra_fd);
22int 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
47int 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
96int 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
5int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp);
6int 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 */
20int 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 */
53uint32_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 */
77uint32_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 */
99void 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 */
9int 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 */
12uint32_t getIpByMac(struct static_lease *lease_struct, void *arg);
13
14/* Check to see if an ip is reserved as a static ip */
15uint32_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 */
19void 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
3udhcpc \- very small DHCP client
4.SH SYNOPSIS
5.B udhcpc
6.RI [ OPTION ]...
7.SH DESCRIPTION
8The udhcp client negotiates a lease with the DHCP server and
9executes a script when it is obtained or lost.
10.SH OPTIONS
11.TP
12.BI \-c\ CLIENTID ,\ \-\-clientid= CLIENTID
13Send the client identifier
14.IR CLIENTID .
15.TP
16.BR -f ,\ \-\-foreground
17Do not fork after obtaining a lease.
18.TP
19.BI \-H\ HOSTNAME ,\ \-\-hostname= HOSTNAME
20Send the client hostname
21.IR HOSTNAME .
22.TP
23.BI \-h\ HOSTNAME
24Alias for -H
25.IR HOSTNAME .
26.TP
27.BI \-i\ INTERFACE ,\ \-\-interface= INTERFACE
28Configure
29.IR INTERFACE .
30.TP
31.BR -n ,\ \-\-now
32Exit with failure if a lease cannot be obtained.
33.TP
34.BI \-p\ FILE ,\ \-\-pidfile= FILE
35Write the process ID of the daemon to
36.IR FILE .
37.TP
38.BR -q ,\ \-\-quit
39Exit after obtaining a lease.
40.TP
41.BI \-r\ ADDRESS ,\ \-\-request= ADDRESS
42Request IP address
43.IR ADDRESS .
44.TP
45.BI \-s\ FILE ,\ \-\-script= FILE
46Use script
47.IR FILE .
48.TP
49.BR -v ,\ \-\-version
50Display version.
51.SH USAGE
52When an event occurs,
53.B udhcpc
54executes a script. There are four possible arguments to this
55script:
56.TP
57.B deconfig
58.B deconfig
59is used when
60.B udhcpc
61starts, and when a lease is lost. The script should put the
62interface in an up, but deconfigured, state.
63.TP
64.B bound
65.B bound
66is used when
67.B udhcpc
68moves from an unbound to a bound state. The script should
69configure the interface and set any other relevant parameters
70(e.g., default gateway, dns server, etc.).
71.TP
72.B renew
73.B renew
74is used when
75.B udhcpc
76when a lease is renewed. The interface is already
77configured, 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
82is used when
83.B udhcpc
84receieves a NAK packet from the server. The
85enviromental variable
86.B $message
87will contain the reason for the
88NAK message if the server included one. Processing this message
89is optional, as the script will also be called with deconfig if
90need be.
91.PP
92Parameters are passed to the script via the following environment
93variables:
94.TP
95.B HOME
96The inherited HOME, or "/" if it is unset.
97.TP
98.B PATH
99The inherited PATH, or "/bin:/usr/bin:/sbin:/usr/sbin" if it is
100unset.
101.TP
102.B interface
103The interface.
104.TP
105.B ip
106The client IP address.
107.TP
108.B siaddr
109The BOOTP next server option.
110.TP
111.B sname
112The BOOTP server name option.
113.TP
114.B boot_file
115The BOOTP boot file option.
116.TP
117.B subnet
118The subnet mask.
119.TP
120.B timezone
121The timezone offset from UTC in seconds.
122.TP
123.B router
124The list of routers.
125.TP
126.B timesvr
127The list of time servers.
128.TP
129.B namesvr
130The list of IEN 116 name servers.
131.TP
132.B dns
133The list of DNS servers.
134.TP
135.B logsvr
136The list of MIT-LCS UDP log servers.
137.TP
138.B cookiesvr
139The list of RFC 865 cookie servers.
140.TP
141.B lprsvr
142The list of LPR servers.
143.TP
144.B hostname
145The host name.
146.TP
147.B bootsize
148The length in 512-octet blocks of the bootfile.
149.TP
150.B domain
151The domain name of the network.
152.TP
153.B swapsvr
154The client's swap server.
155.TP
156.B rootpath
157The path of the client's root dist.
158.TP
159.B ipttl
160The TTL.
161.TP
162.B mtu
163The MTU.
164.TP
165.B broadcast
166The broadcast address.
167.TP
168.B ntpsrv
169The list of NTP servers.
170.TP
171.B wins
172The list of WINS servers.
173.TP
174.B lease
175The lease time in seconds.
176.TP
177.B dhcptype
178The DHCP message type (safely ignored).
179.TP
180.B serverid
181The server IP address.
182.TP
183.B message
184Reason for a DHCPNAK.
185.TP
186.B tftp
187The TFTP server name.
188.TP
189.B bootfile
190The bootfile name.
191.SH FILES
192.TP
193.I /usr/share/udhcpc/default.script
194Script run when leases are obtained or lost.
195.SH NOTES
196.B udhcpc
197responds to the following signals:
198.TP
199.B SIGUSR1
200This signal causes
201.B udhcpc
202to renew the current lease or, if it does not have one, obtain a
203new lease.
204.TP
205.B SIGUSR2
206This signal caused
207.B udhcpc
208to 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
3udhcpd \- very small DHCP server
4.SH SYNOPSIS
5.B udhcpd
6.SH DESCRIPTION
7The udhcp server negotiates leases with DHCP clients.
8.SH FILES
9.TP
10.I /etc/udhcpd.conf
11Configuration file.
12.TP
13.I /var/lib/misc/udhcpd.leases
14Lease 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
3udhcpd.conf \- udhcp server configuration file
4.SH DESCRIPTION
5The file
6.I /etc/udhcpd.conf
7contains configuration information specific to the udhcp server.
8It should contain one configuration keyword per line, followed by
9appropriate configuration information.
10.SH OPTIONS
11.TP
12.BI start\ ADDRESS
13The starting address of the IP lease block is
14.IR ADDRESS .
15The default is
16.BR 192.168.0.20 .
17.TP
18.BI end\ ADDRESS
19The ending address of the IP lease block is
20.IR ADDRESS .
21The default is
22.BR 192.168.0.254 .
23.TP
24.BI interface\ INTERFACE
25The udhcp server should listen on
26.IR INTERFACE .
27The default is
28.BR eth0 .
29.TP
30.BI max_leases\ LEASES
31Offer at most
32.I LEASES
33leases (including those reserved by OFFERs, DECLINEs, and ARP
34conflicts). The default is
35.BR 254 .
36.TP
37.BI remaining\ REMAINING
38If
39.I REMAINING
40is
41.BR yes ,
42store the time remaining for each lease. If it is
43.BR no ,
44store the expiration time for each lease. The default is
45.BR yes .
46.TP
47.BI auto_time\ SECONDS
48Write the lease information to a file every
49.I SECONDS
50seconds. The default is
51.BR 7200 .
52.TP
53.BI decline_time\ SECONDS
54Reserve an IP for
55.I SECONDS
56seconds if a DHCP decline message is received. The default is
57.BR 3600 .
58.TP
59.BI conflict_time\ SECONDS
60Reserve an IP for
61.I SECONDS
62seconds if an ARP conflict occurs. The default is
63.BR 3600 .
64.TP
65.BI offer_time\ SECONDS
66Reserve an IP for
67.I SECONDS
68seconds if it is offered. The default is
69.BR 60 .
70.TP
71.BI min_lease\ SECONDS
72Reserve an IP for the full lease time if the lease to be given is less than
73.I SECONDS
74seconds. The default is
75.BR 60 .
76.TP
77.BI lease_file\ FILE
78Write the lease information to
79.IR FILE .
80The default is
81.BR /var/lib/misc/udhcpd.leases .
82.TP
83.BI pidfile\ FILE
84Write the process ID to
85.IR FILE .
86The default is
87.BR /var/run/udhcpd.pid .
88.TP
89.BI notify_file\ FILE
90Execute
91.I FILE
92after the lease information is written. By default, no file is executed.
93.TP
94.BI siaddr\ ADDRESS
95BOOTP specific option. The default is
96.BR 0.0.0.0 .
97.TP
98.BI sname\ NAME
99BOOTP specific option. There is no default.
100.TP
101.BI boot_file\ FILE
102BOOTP specific option. There is no default.
103.TP
104.BI option\ OPTION
105DHCP 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
157The default for
158.B lease
159is
160.BR 864000 .
161There 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