6 * Copyright (c) 1995, 1996, 1997, 1998, 1999
7 * The Internet Software Consortium. All rights reserved.
9 * Redistribution and use of this source file, source files derived in whole
10 * or in part from this source file, and binary files derived in whole or in
11 * part from this source file, with or without modification, are permitted
12 * provided that the following conditions are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * This copyright notice must appear directly below any initial commentary
17 * describing the file, and may not be preceded by any other copyright
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of The Internet Software Consortium (hereafter
23 * referred to as "the ISC") nor the names of its contributors may be
24 * used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 * 4. This software is a part of the ISC DHCP Distribution. Redistributions
27 * of this source file or binary files derived from this source file
28 * MUST include all documentation accompanying the ISC release from
29 * which such redistributions are derived of this source file, specifically
30 * the following files (listed relative to the top of the ISC DHCP
31 * distribution directory tree):
34 * common/dhcp-contrib.5
35 * common/dhcp-options.5
38 * server/dhcpd.leases.5
40 * client/dhclient.conf.5
41 * client/dhclient-script.8
42 * client/dhclient.leases.5
45 * Absence of these files from a distribution you receive does not excuse
46 * you from this requirement - if the distribution you receive does not
47 * contain these files, you must get them from the ISC and include them
48 * in any redistribution of this source file or any derivative work based
49 * wholly or in part on this source file. It is permissible in a binary
50 * redistribution derived from this source file to include formatted
51 * versions of the manual pages mentioned above, and also to add to or
52 * correct the manual pages and README file mentioned above so long as the
53 * sections labeled CONTRIBUTIONS in these documents are unchanged except
54 * with respect to formatting, so long as the order in which the
55 * CONTRIBUTIONS section appears in these documents is not changed, and
56 * so long as the dhcp-contrib.5 manual page is unchanged except with
57 * respect to formatting. It is also permissible to redistribute this
58 * source file, source files derived wholly or in part from this source
59 * file, and binaries derived wholly or in part from this source file
60 * accompanied by the aforementioned manual pages translated into another
61 * language. In this case, the CONTRIBUTIONS section and the
62 * dhcp-contrib.5 section may either be left in their original language
63 * or translated into the new language with such care and diligence as
64 * is required to preserve the original meaning.
65 * 5. If, in addition to the documentation mentioned in section 4, this
66 * source file, a source file derived wholly or in part from this source
67 * file, or a binary file derived wholly or in part from this source file
68 * is redistributed with additional printed or electronic documentation,
69 * then that documentation must refer to the dhcp-contrib.5 manual page
70 * in as conspicuous a way as the aforementioned documentation refers to
71 * it, and the dhcp-contrib.5 manual page must be converted into the same
72 * format and be made easily accessible to any recipient of such
75 * THIS SOFTWARE IS PROVIDED BY THE ISC AND CONTRIBUTORS ``AS IS'' AND ANY
76 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
77 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
78 * DISCLAIMED. IN NO EVENT SHALL THE ISC OR CONTRIBUTORS BE LIABLE FOR ANY
79 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
80 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
81 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
82 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
83 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
84 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
87 * This software has been written for the ISC by Ted Lemon <mellon@isc.org>
88 * in cooperation with Vixie Enterprises and Internet Engines, Inc. To
89 * learn more about the ISC, see ``http://www.vix.com/isc''. Development
90 * of this software is funded through contributions and support contracts.
91 * Please see the dhcp-contrib manual page that accompanies this file for
92 * information on how you can contribute.
96 static char ocopyright
[] =
97 "$Id: dhcpd.c,v 1.58 1999/03/16 00:56:36 mellon Exp $ Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.";
100 static char copyright
[] =
101 "Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.";
102 static char arr
[] = "All rights reserved.";
103 static char message
[] = "Internet Software Consortium DHCP Server V3.0-alpha 980315";
104 static char contrib
[] = "\nPlease contribute if you find this software useful.";
105 static char url
[] = "For info, please visit http://www.isc.org/dhcp-contrib.html\n";
109 static void usage
PROTO ((void));
112 struct group root_group
;
114 struct iaddr server_identifier
;
115 int server_identifier_matched
;
117 u_int16_t local_port
;
118 u_int16_t remote_port
;
127 char *path_dhcpd_conf
= _PATH_DHCPD_CONF
;
128 char *path_dhcpd_db
= _PATH_DHCPD_DB
;
129 char *path_dhcpd_pid
= _PATH_DHCPD_PID
;
131 int dhcp_max_agent_option_packet_length
= DHCP_MTU_MAX
;
133 int main (argc
, argv
, envp
)
142 int pidfilewritten
= 0;
149 /* Initially, log errors to stderr as well as to syslogd. */
151 openlog ("dhcpd", LOG_NDELAY
);
152 log_priority
= DHCPD_LOG_FACILITY
;
154 openlog ("dhcpd", LOG_NDELAY
, DHCPD_LOG_FACILITY
);
159 #ifndef __CYGWIN32__ /* XXX */
160 setlogmask (LOG_UPTO (LOG_INFO
));
165 for (i
= 1; i
< argc
; i
++) {
166 if (!strcmp (argv
[i
], "-p")) {
169 for (s
= argv
[i
]; *s
; s
++)
171 log_fatal ("%s: not a valid UDP port",
173 status
= atoi (argv
[i
]);
174 if (status
< 1 || status
> 65535)
175 log_fatal ("%s: not a valid UDP port",
177 local_port
= htons (status
);
178 log_debug ("binding to user-specified port %d",
180 } else if (!strcmp (argv
[i
], "-f")) {
184 } else if (!strcmp (argv
[i
], "-d")) {
189 } else if (!strcmp (argv
[i
], "-cf")) {
192 path_dhcpd_conf
= argv
[i
];
193 } else if (!strcmp (argv
[i
], "-lf")) {
196 path_dhcpd_db
= argv
[i
];
197 } else if (!strcmp (argv
[i
], "-pf")) {
200 path_dhcpd_pid
= argv
[i
];
201 } else if (!strcmp (argv
[i
], "-t")) {
202 /* test configurations only */
208 } else if (!strcmp (argv
[i
], "-q")) {
210 quiet_interface_discovery
= 1;
211 } else if (argv
[i
][0] == '-') {
214 struct interface_info
*tmp
=
215 ((struct interface_info
*)
216 dmalloc (sizeof *tmp
, "get_interface_list"));
218 log_fatal ("Insufficient memory to %s %s",
219 "record interface", argv
[i
]);
220 memset (tmp
, 0, sizeof *tmp
);
221 strcpy (tmp
-> name
, argv
[i
]);
222 tmp
-> next
= interfaces
;
223 tmp
-> flags
= INTERFACE_REQUESTED
;
230 log_info (copyright
);
236 /* Default to the DHCP/BOOTP port. */
239 ent
= getservbyname ("dhcp", "udp");
241 local_port
= htons (67);
243 local_port
= ent
-> s_port
;
244 #ifndef __CYGWIN32__ /* XXX */
249 remote_port
= htons (ntohs (local_port
) + 1);
251 /* Get the current time... */
252 GET_TIME (&cur_time
);
254 /* Initialize DNS support... */
259 /* Start the interactive client listener. */
262 /* Set up the client classification system. */
263 classification_setup ();
265 /* Read the dhcpd.conf file... */
267 log_fatal ("Configuration file errors encountered -- exiting");
269 /* test option should cause an early exit */
273 /* Start up the database... */
276 /* Discover all the network interfaces and initialize them. */
277 discover_interfaces (DISCOVER_SERVER
);
279 /* Initialize icmp support... */
280 icmp_startup (1, lease_pinged
);
284 /* First part of becoming a daemon... */
285 if ((pid
= fork ()) < 0)
286 log_fatal ("Can't fork daemon: %m");
291 /* Read previous pid file. */
292 if ((i
= open (path_dhcpd_pid
, O_RDONLY
)) >= 0) {
293 status
= read (i
, pbuf
, (sizeof pbuf
) - 1);
298 /* If the previous server process is not still running,
299 write a new pid file immediately. */
300 if (pid
&& (pid
== getpid() || kill (pid
, 0) < 0)) {
301 unlink (path_dhcpd_pid
);
302 if ((i
= open (path_dhcpd_pid
,
303 O_WRONLY
| O_CREAT
, 0640)) >= 0) {
304 sprintf (pbuf
, "%d\n", (int)getpid ());
305 write (i
, pbuf
, strlen (pbuf
));
310 log_fatal ("There's already a DHCP server running.\n");
313 /* If we were requested to log to stdout on the command line,
314 keep doing so; otherwise, stop. */
315 if (log_perror
== -1)
321 /* Become session leader and get pid... */
328 /* If we didn't write the pid file earlier because we found a
329 process running the logged pid, but we made it to here,
330 meaning nothing is listening on the bootp port, then write
331 the pid file out - what's in it now is bogus anyway. */
332 if (!pidfilewritten
) {
333 unlink (path_dhcpd_pid
);
334 if ((i
= open (path_dhcpd_pid
,
335 O_WRONLY
| O_CREAT
, 0640)) >= 0) {
336 sprintf (pbuf
, "%d\n", (int)getpid ());
337 write (i
, pbuf
, strlen (pbuf
));
344 /* Set up the bootp packet handler... */
345 bootp_packet_handler
= do_packet
;
347 /* Receive packets and dispatch them... */
354 /* Print usage message. */
359 log_info (copyright
);
362 log_fatal ("Usage: dhcpd [-p <UDP port #>] [-d] [-f] [-cf config-file]%s",
363 "\n [-lf lease-file] [if0 [...ifN]]");
370 void lease_pinged (from
, packet
, length
)
377 /* Don't try to look up a pinged lease if we aren't trying to
378 ping one - otherwise somebody could easily make us churn by
379 just forging repeated ICMP EchoReply packets for us to look
381 if (!outstanding_pings
)
384 lp
= find_lease_by_ip_addr (from
);
387 log_info ("unexpected ICMP Echo Reply from %s", piaddr (from
));
392 log_error ("ICMP Echo Reply for %s arrived late or is spurious.\n",
397 if (lp
-> ends
> cur_time
) {
398 log_error ("ICMP Echo reply arrived while lease %s was valid.\n",
402 /* At this point it looks like we pinged a lease and got a
403 response, which shouldn't have happened. */
404 data_string_forget (&lp
-> state
-> parameter_request_list
,
406 free_lease_state (lp
-> state
, "lease_pinged");
407 lp
-> state
= (struct lease_state
*)0;
409 abandon_lease (lp
, "pinged before offer");
410 cancel_timeout (lease_ping_timeout
, lp
);
414 void lease_ping_timeout (vlp
)
417 struct lease
*lp
= vlp
;