Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / network / stacks / AROSTCP / dhcp / client / dhclient.c
blob2014bc9392f04798d9a4b8fc554e78d4c182bc9d
1 /* dhclient.c
3 DHCP Client. */
5 /*
6 * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
27 * This code is based on the original client state machine that was
28 * written by Elliot Poger. The code has been extensively hacked on
29 * by Ted Lemon since then, so any mistakes you find are probably his
30 * fault and not Elliot's.
33 #ifndef lint
34 static char ocopyright[] =
35 "$Id$ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
36 #endif /* not lint */
38 #include "dhcpd.h"
39 #include "version.h"
41 #ifdef AMIGA
42 #include <proto/dos.h>
43 #include <proto/exec.h>
44 #endif
46 #ifdef __AROS__
47 int h_errno = 0;
48 struct Library *MiamiBase = NULL;
49 struct Library *SocketBase = NULL;
51 static void __close_bsdsocket()
53 if (MiamiBase)
55 CloseLibrary(MiamiBase);
56 MiamiBase = NULL;
58 if (SocketBase)
60 CloseLibrary(SocketBase);
61 SocketBase = NULL;
65 void openlog(const char *ident, int logstat, int logfac)
67 log_debug("openlog %s %d %d\n", ident, logstat, logfac);
70 int setlogmask(int pmask)
72 log_debug("setlogmask %d\n", pmask);
73 return -1;
75 #endif
77 TIME default_lease_time = 43200; /* 12 hours... */
78 TIME max_lease_time = 86400; /* 24 hours... */
80 const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
81 const char *path_dhclient_db = _PATH_DHCLIENT_DB;
82 const char *path_dhclient_pid = _PATH_DHCLIENT_PID;
83 static char path_dhclient_script_array [] = _PATH_DHCLIENT_SCRIPT;
84 char *path_dhclient_script = path_dhclient_script_array;
86 int dhcp_max_agent_option_packet_length = 0;
88 int interfaces_requested = 0;
90 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
91 struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
92 struct in_addr inaddr_any;
93 struct sockaddr_in sockaddr_broadcast;
94 struct in_addr giaddr;
96 /* ASSERT_STATE() does nothing now; it used to be
97 assert (state_is == state_shouldbe). */
98 #define ASSERT_STATE(state_is, state_shouldbe) {}
100 static char copyright[] = "Copyright 2004-2005 Internet Systems Consortium.";
101 static char arr [] = "All rights reserved.";
102 static char message [] = "Internet Systems Consortium DHCP Client";
103 static char url [] = "For info, please visit http://www.isc.org/products/DHCP";
105 u_int16_t local_port=0;
106 u_int16_t remote_port=0;
107 int no_daemon=0;
108 struct string_list *client_env=NULL;
109 int client_env_count=0;
110 int onetry=0;
111 int quiet=0;
112 int nowait=0;
114 static void usage PROTO ((void));
116 void do_release(struct client_state *);
118 #define ia2ulong(x) (*(u_long *)(x.iabuf))
119 void interface_preinit (struct client_state *);
120 int interface_medium (struct client_state *, char *);
121 int interface_bind (struct client_state *);
122 /*void interface_expire (struct client_state *);
123 void interface_fail (struct client_state *);
124 void interface_release (struct client_state *);*/
125 #define interface_expire interface_stop
126 #define interface_fail interface_stop
127 #define interface_release interface_stop
128 void interface_stop (struct client_state *);
129 int interface_timeout (struct client_state *);
131 int main (argc, argv, envp)
132 int argc;
133 char **argv, **envp;
135 int i;
136 struct servent *ent;
137 struct interface_info *ip;
138 struct client_state *client;
139 unsigned seed;
140 char *server = (char *)0;
141 char *relay = (char *)0;
142 isc_result_t status;
143 int release_mode = 0;
144 omapi_object_t *listener;
145 isc_result_t result;
146 int persist = 0;
147 int omapi_port;
148 int no_dhclient_conf = 0;
149 int no_dhclient_db = 0;
150 int no_dhclient_pid = 0;
151 int no_dhclient_script = 0;
152 char *s;
154 /* Make sure we have stdin, stdout and stderr. */
155 #ifdef AMIGA
156 struct Process *me;
158 me = (struct Process *)FindTask(NULL);
159 if (!me->pr_COS)
160 log_perror = 0;
161 #else
162 i = open ("/dev/null", O_RDWR);
163 if (i == 0)
164 i = open ("/dev/null", O_RDWR);
165 if (i == 1) {
166 i = open ("/dev/null", O_RDWR);
167 log_perror = 0; /* No sense logging to /dev/null. */
168 } else if (i != -1)
169 close (i);
170 #endif
172 #ifdef __AROS__
173 if (!(SocketBase = OpenLibrary("bsdsocket.library", 4)))
175 fprintf(stderr, "No TCP/IP Stack running!\n");
176 return RETURN_FAIL;
178 if (!(MiamiBase = OpenLibrary("miami.library", 0)))
180 fprintf(stderr, "No miami avalailable !\n");
181 return RETURN_FAIL;
183 atexit(__close_bsdsocket);
185 static TEXT dh_conf[256];
186 static TEXT dh_db[256];
187 LONG len;
189 dh_conf[0] = dh_db[0] = '\0';
191 if ((len = GetVar("AROSTCP/Config", dh_conf, 256, 0)) > 0)
193 sprintf(dh_db, "%s/dhclient.lease", dh_conf);
194 strcpy(dh_conf + len, "/dhclient.conf");
196 path_dhclient_conf = dh_conf;
197 path_dhclient_db = dh_db;
200 #endif
202 #ifdef SYSLOG_4_2
203 openlog ("dhclient", LOG_NDELAY);
204 log_priority = LOG_DAEMON;
205 #else
206 openlog ("dhclient", LOG_NDELAY, LOG_DAEMON);
207 #endif
209 #if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__))
210 setlogmask (LOG_UPTO (LOG_INFO));
211 #endif
213 #if defined (DEBUG)
214 log_debug("conf: %s", path_dhclient_conf);
215 log_debug("db: %s", path_dhclient_db);
216 #endif
218 /* Set up the OMAPI. */
219 status = omapi_init ();
220 if (status != ISC_R_SUCCESS)
221 log_fatal ("Can't initialize OMAPI: %s",
222 isc_result_totext (status));
224 /* Set up the OMAPI wrappers for various server database internal
225 objects. */
226 dhcp_common_objects_setup ();
228 dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
229 dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
230 dhcp_interface_startup_hook = dhclient_interface_startup_hook;
232 for (i = 1; i < argc; i++) {
233 if (!strcmp (argv [i], "-r")) {
234 release_mode = 1;
235 no_daemon = 1;
236 } else if (!strcmp (argv [i], "-p")) {
237 if (++i == argc)
238 usage ();
239 local_port = htons (atoi (argv [i]));
240 log_debug ("binding to user-specified port %d",
241 ntohs (local_port));
242 } else if (!strcmp (argv [i], "-d")) {
243 no_daemon = 1;
244 } else if (!strcmp (argv [i], "-pf")) {
245 if (++i == argc)
246 usage ();
247 path_dhclient_pid = argv [i];
248 no_dhclient_pid = 1;
249 } else if (!strcmp (argv [i], "-cf")) {
250 if (++i == argc)
251 usage ();
252 path_dhclient_conf = argv [i];
253 no_dhclient_conf = 1;
254 } else if (!strcmp (argv [i], "-lf")) {
255 if (++i == argc)
256 usage ();
257 path_dhclient_db = argv [i];
258 no_dhclient_db = 1;
259 } else if (!strcmp (argv [i], "-sf")) {
260 if (++i == argc)
261 usage ();
262 path_dhclient_script = argv [i];
263 no_dhclient_script = 1;
264 } else if (!strcmp (argv [i], "-1")) {
265 onetry = 1;
266 } else if (!strcmp (argv [i], "-q")) {
267 quiet = 1;
268 quiet_interface_discovery = 1;
269 } else if (!strcmp (argv [i], "-s")) {
270 if (++i == argc)
271 usage ();
272 server = argv [i];
273 } else if (!strcmp (argv [i], "-g")) {
274 if (++i == argc)
275 usage ();
276 relay = argv [i];
277 } else if (!strcmp (argv [i], "-nw")) {
278 nowait = 1;
279 } else if (!strcmp (argv [i], "-n")) {
280 /* do not start up any interfaces */
281 interfaces_requested = 1;
282 } else if (!strcmp (argv [i], "-w")) {
283 /* do not exit if there are no broadcast interfaces. */
284 persist = 1;
285 } else if (!strcmp (argv [i], "-e")) {
286 struct string_list *tmp;
287 if (++i == argc)
288 usage ();
289 tmp = dmalloc (strlen (argv [i]) + sizeof *tmp, MDL);
290 if (!tmp)
291 log_fatal ("No memory for %s", argv [i]);
292 strcpy (tmp -> string, argv [i]);
293 tmp -> next = client_env;
294 client_env = tmp;
295 client_env_count++;
296 } else if (!strcmp (argv [i], "--version")) {
297 log_info ("isc-dhclient-%s", DHCP_VERSION);
298 exit (0);
299 } else if (argv [i][0] == '-') {
300 usage ();
301 } else {
302 struct interface_info *tmp = (struct interface_info *)0;
303 status = interface_allocate (&tmp, MDL);
304 if (status != ISC_R_SUCCESS)
305 log_fatal ("Can't record interface %s:%s",
306 argv [i], isc_result_totext (status));
307 if (strlen (argv [i]) > sizeof tmp -> name)
308 log_fatal ("%s: interface name too long (max %ld)",
309 argv [i], (long)strlen (argv [i]));
310 strcpy (tmp -> name, argv [i]);
311 if (interfaces) {
312 interface_reference (&tmp -> next,
313 interfaces, MDL);
314 interface_dereference (&interfaces, MDL);
316 interface_reference (&interfaces, tmp, MDL);
317 tmp -> flags = INTERFACE_REQUESTED;
318 interfaces_requested = 1;
322 if (!no_dhclient_conf && (s = getenv ("PATH_DHCLIENT_CONF"))) {
323 path_dhclient_conf = s;
325 if (!no_dhclient_db && (s = getenv ("PATH_DHCLIENT_DB"))) {
326 path_dhclient_db = s;
328 if (!no_dhclient_pid && (s = getenv ("PATH_DHCLIENT_PID"))) {
329 path_dhclient_pid = s;
331 if (!no_dhclient_script && (s = getenv ("PATH_DHCLIENT_SCRIPT"))) {
332 path_dhclient_script = s;
335 /* first kill of any currently running client */
336 if (release_mode) {
337 FILE *pidfd;
338 pid_t oldpid;
339 long temp;
340 int e;
342 oldpid = 0;
343 if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) {
344 e = fscanf(pidfd, "%ld\n", &temp);
345 oldpid = (pid_t)temp;
347 if (e != 0 && e != EOF) {
348 if (oldpid) {
349 if (kill(oldpid, SIGTERM) == 0)
350 unlink(path_dhclient_pid);
353 fclose(pidfd);
357 if (!quiet) {
358 log_info ("%s %s", message, DHCP_VERSION);
359 log_info (copyright);
360 log_info (arr);
361 log_info (url);
362 log_info ("%s", "");
363 } else
364 log_perror = 0;
366 /* If we're given a relay agent address to insert, for testing
367 purposes, figure out what it is. */
368 if (relay) {
369 if (!inet_aton (relay, &giaddr)) {
370 struct hostent *he;
371 he = gethostbyname (relay);
372 if (he) {
373 memcpy (&giaddr, he -> h_addr_list [0],
374 sizeof giaddr);
375 } else {
376 log_fatal ("%s: no such host", relay);
381 /* Default to the DHCP/BOOTP port. */
382 if (!local_port) {
383 /* If we're faking a relay agent, and we're not using loopback,
384 use the server port, not the client port. */
385 if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
386 local_port = htons(67);
387 } else {
388 ent = getservbyname ("dhcpc", "udp");
389 if (!ent)
390 local_port = htons (68);
391 else
392 local_port = ent -> s_port;
393 #ifndef __CYGWIN32__
394 #ifndef __AROS__
395 endservent ();
396 #endif
397 #endif
401 /* If we're faking a relay agent, and we're not using loopback,
402 we're using the server port, not the client port. */
403 if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
404 remote_port = local_port;
405 } else
406 remote_port = htons (ntohs (local_port) - 1); /* XXX */
408 /* Get the current time... */
409 GET_TIME (&cur_time);
411 sockaddr_broadcast.sin_family = AF_INET;
412 sockaddr_broadcast.sin_port = remote_port;
413 if (server) {
414 if (!inet_aton (server, &sockaddr_broadcast.sin_addr)) {
415 struct hostent *he;
416 he = gethostbyname (server);
417 if (he) {
418 memcpy (&sockaddr_broadcast.sin_addr,
419 he -> h_addr_list [0],
420 sizeof sockaddr_broadcast.sin_addr);
421 } else
422 sockaddr_broadcast.sin_addr.s_addr =
423 INADDR_BROADCAST;
425 } else {
426 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
429 inaddr_any.s_addr = INADDR_ANY;
431 /* Discover all the network interfaces. */
432 discover_interfaces (DISCOVER_UNCONFIGURED);
434 /* Parse the dhclient.conf file. */
435 read_client_conf ();
437 /* Parse the lease database. */
438 read_client_leases ();
440 /* Rewrite the lease database... */
441 rewrite_client_leases ();
443 /* XXX */
444 /* config_counter(&snd_counter, &rcv_counter); */
446 /* If no broadcast interfaces were discovered, call the script
447 and tell it so. */
448 if (!interfaces) {
449 #ifndef BUILTIN_IFCONFIG
450 /* Call dhclient-script with the NBI flag, in case somebody
451 cares. */
452 script_init ((struct client_state *)0, "NBI",
453 (struct string_list *)0);
454 script_go ((struct client_state *)0);
455 #endif
456 /* If we haven't been asked to persist, waiting for new
457 interfaces, then just exit. */
458 if (!persist) {
459 /* Nothing more to do. */
460 log_info ("No broadcast interfaces found - exiting.");
461 exit (0);
463 } else if (!release_mode) {
464 /* Call the script with the list of interfaces. */
465 for (ip = interfaces; ip; ip = ip -> next) {
466 /* If interfaces were specified, don't configure
467 interfaces that weren't specified! */
468 if (interfaces_requested &&
469 ((ip -> flags & (INTERFACE_REQUESTED |
470 INTERFACE_AUTOMATIC)) !=
471 INTERFACE_REQUESTED))
472 continue;
473 #ifdef BUILTIN_IFCONFIG
474 interface_preinit (ip->client);
475 #else
476 script_init (ip -> client,
477 "PREINIT", (struct string_list *)0);
478 if (ip -> client -> alias)
479 script_write_params (ip -> client, "alias_",
480 ip -> client -> alias);
481 script_go (ip -> client);
482 #endif
486 /* At this point, all the interfaces that the script thinks
487 are relevant should be running, so now we once again call
488 discover_interfaces(), and this time ask it to actually set
489 up the interfaces. */
490 discover_interfaces (interfaces_requested
491 ? DISCOVER_REQUESTED
492 : DISCOVER_RUNNING);
494 /* Make up a seed for the random number generator from current
495 time plus the sum of the last four bytes of each
496 interface's hardware address interpreted as an integer.
497 Not much entropy, but we're booting, so we're not likely to
498 find anything better. */
499 seed = 0;
500 for (ip = interfaces; ip; ip = ip -> next) {
501 int junk;
502 memcpy (&junk,
503 &ip -> hw_address.hbuf [ip -> hw_address.hlen -
504 sizeof seed], sizeof seed);
505 seed += junk;
507 srandom (seed + cur_time);
509 /* Start a configuration state machine for each interface. */
510 for (ip = interfaces; ip; ip = ip -> next) {
511 ip -> flags |= INTERFACE_RUNNING;
512 for (client = ip -> client; client; client = client -> next) {
513 if (release_mode)
514 do_release (client);
515 else {
516 client -> state = S_INIT;
517 /* Set up a timeout to start the initialization
518 process. */
519 add_timeout (cur_time + random () % 5,
520 state_reboot, client, 0, 0);
525 if (release_mode)
526 return 0;
528 /* Start up a listener for the object management API protocol. */
529 if (top_level_config.omapi_port != -1) {
530 listener = (omapi_object_t *)0;
531 result = omapi_generic_new (&listener, MDL);
532 if (result != ISC_R_SUCCESS)
533 log_fatal ("Can't allocate new generic object: %s\n",
534 isc_result_totext (result));
535 result = omapi_protocol_listen (listener,
536 (unsigned)
537 top_level_config.omapi_port,
539 if (result != ISC_R_SUCCESS)
540 log_fatal ("Can't start OMAPI protocol: %s",
541 isc_result_totext (result));
544 /* Set up the bootp packet handler... */
545 bootp_packet_handler = do_packet;
547 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
548 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
549 dmalloc_cutoff_generation = dmalloc_generation;
550 dmalloc_longterm = dmalloc_outstanding;
551 dmalloc_outstanding = 0;
552 #endif
554 /* If we're not supposed to wait before getting the address,
555 don't. */
556 if (nowait)
557 go_daemon ();
559 /* If we're not going to daemonize, write the pid file
560 now. */
561 if (no_daemon || nowait)
562 write_client_pid_file ();
564 /* Start dispatching packets and timeouts... */
565 dispatch ();
567 /*NOTREACHED*/
568 return 0;
571 static void usage ()
573 log_info ("%s %s", message, DHCP_VERSION);
574 log_info (copyright);
575 log_info (arr);
576 log_info (url);
578 log_error ("Usage: dhclient [-1dqr] [-nw] [-p <port>] %s",
579 "[-s server]");
580 log_error (" [-cf config-file] [-lf lease-file]%s",
581 "[-pf pid-file] [-e VAR=val]");
582 log_fatal (" [-sf script-file] [interface]");
585 isc_result_t find_class (struct class **c,
586 const char *s, const char *file, int line)
588 return 0;
591 int check_collection (packet, lease, collection)
592 struct packet *packet;
593 struct lease *lease;
594 struct collection *collection;
596 return 0;
599 void classify (packet, class)
600 struct packet *packet;
601 struct class *class;
605 int unbill_class (lease, class)
606 struct lease *lease;
607 struct class *class;
609 return 0;
612 int find_subnet (struct subnet **sp,
613 struct iaddr addr, const char *file, int line)
615 return 0;
618 /* Individual States:
620 * Each routine is called from the dhclient_state_machine() in one of
621 * these conditions:
622 * -> entering INIT state
623 * -> recvpacket_flag == 0: timeout in this state
624 * -> otherwise: received a packet in this state
626 * Return conditions as handled by dhclient_state_machine():
627 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
628 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
629 * Returns 0: finish the nap which was interrupted for no good reason.
631 * Several per-interface variables are used to keep track of the process:
632 * active_lease: the lease that is being used on the interface
633 * (null pointer if not configured yet).
634 * offered_leases: leases corresponding to DHCPOFFER messages that have
635 * been sent to us by DHCP servers.
636 * acked_leases: leases corresponding to DHCPACK messages that have been
637 * sent to us by DHCP servers.
638 * sendpacket: DHCP packet we're trying to send.
639 * destination: IP address to send sendpacket to
640 * In addition, there are several relevant per-lease variables.
641 * T1_expiry, T2_expiry, lease_expiry: lease milestones
642 * In the active lease, these control the process of renewing the lease;
643 * In leases on the acked_leases list, this simply determines when we
644 * can no longer legitimately use the lease.
647 void state_reboot (cpp)
648 void *cpp;
650 struct client_state *client = cpp;
652 /* If we don't remember an active lease, go straight to INIT. */
653 if (!client -> active ||
654 client -> active -> is_bootp ||
655 client -> active -> expiry <= cur_time) {
656 state_init (client);
657 return;
660 /* We are in the rebooting state. */
661 client -> state = S_REBOOTING;
663 /* make_request doesn't initialize xid because it normally comes
664 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
665 so pick an xid now. */
666 client -> xid = random ();
668 /* Make a DHCPREQUEST packet, and set appropriate per-interface
669 flags. */
670 make_request (client, client -> active);
671 client -> destination = iaddr_broadcast;
672 client -> first_sending = cur_time;
673 client -> interval = client -> config -> initial_interval;
675 /* Zap the medium list... */
676 client -> medium = (struct string_list *)0;
678 /* Send out the first DHCPREQUEST packet. */
679 send_request (client);
682 /* Called when a lease has completely expired and we've been unable to
683 renew it. */
685 void state_init (cpp)
686 void *cpp;
688 struct client_state *client = cpp;
690 ASSERT_STATE(state, S_INIT);
692 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
693 flags. */
694 make_discover (client, client -> active);
695 client -> xid = client -> packet.xid;
696 client -> destination = iaddr_broadcast;
697 client -> state = S_SELECTING;
698 client -> first_sending = cur_time;
699 client -> interval = client -> config -> initial_interval;
701 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
702 to go out. */
703 send_discover (client);
706 /* state_selecting is called when one or more DHCPOFFER packets have been
707 received and a configurable period of time has passed. */
709 void state_selecting (cpp)
710 void *cpp;
712 struct client_state *client = cpp;
713 struct client_lease *lp, *next, *picked;
716 ASSERT_STATE(state, S_SELECTING);
718 /* Cancel state_selecting and send_discover timeouts, since either
719 one could have got us here. */
720 cancel_timeout (state_selecting, client);
721 cancel_timeout (send_discover, client);
723 /* We have received one or more DHCPOFFER packets. Currently,
724 the only criterion by which we judge leases is whether or
725 not we get a response when we arp for them. */
726 picked = (struct client_lease *)0;
727 for (lp = client -> offered_leases; lp; lp = next) {
728 next = lp -> next;
730 /* Check to see if we got an ARPREPLY for the address
731 in this particular lease. */
732 if (!picked) {
733 picked = lp;
734 picked -> next = (struct client_lease *)0;
735 } else {
736 freeit:
737 destroy_client_lease (lp);
740 client -> offered_leases = (struct client_lease *)0;
742 /* If we just tossed all the leases we were offered, go back
743 to square one. */
744 if (!picked) {
745 client -> state = S_INIT;
746 state_init (client);
747 return;
750 /* If it was a BOOTREPLY, we can just take the address right now. */
751 if (picked -> is_bootp) {
752 client -> new = picked;
754 /* Make up some lease expiry times
755 XXX these should be configurable. */
756 client -> new -> expiry = cur_time + 12000;
757 client -> new -> renewal += cur_time + 8000;
758 client -> new -> rebind += cur_time + 10000;
760 client -> state = S_REQUESTING;
762 /* Bind to the address we received. */
763 bind_lease (client);
764 return;
767 /* Go to the REQUESTING state. */
768 client -> destination = iaddr_broadcast;
769 client -> state = S_REQUESTING;
770 client -> first_sending = cur_time;
771 client -> interval = client -> config -> initial_interval;
773 /* Make a DHCPREQUEST packet from the lease we picked. */
774 make_request (client, picked);
775 client -> xid = client -> packet.xid;
777 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
778 destroy_client_lease (picked);
780 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
781 send_request (client);
784 /* state_requesting is called when we receive a DHCPACK message after
785 having sent out one or more DHCPREQUEST packets. */
787 void dhcpack (packet)
788 struct packet *packet;
790 struct interface_info *ip = packet -> interface;
791 struct client_state *client;
792 struct client_lease *lease;
793 struct option_cache *oc;
794 struct data_string ds;
795 int i;
797 /* If we're not receptive to an offer right now, or if the offer
798 has an unrecognizable transaction id, then just drop it. */
799 for (client = ip -> client; client; client = client -> next) {
800 if (client -> xid == packet -> raw -> xid)
801 break;
803 if (!client ||
804 (packet -> interface -> hw_address.hlen - 1 !=
805 packet -> raw -> hlen) ||
806 (memcmp (&packet -> interface -> hw_address.hbuf [1],
807 packet -> raw -> chaddr, packet -> raw -> hlen))) {
808 #if defined (DEBUG)
809 log_debug ("DHCPACK in wrong transaction.");
810 #endif
811 return;
814 if (client -> state != S_REBOOTING &&
815 client -> state != S_REQUESTING &&
816 client -> state != S_RENEWING &&
817 client -> state != S_REBINDING) {
818 #if defined (DEBUG)
819 log_debug ("DHCPACK in wrong state.");
820 #endif
821 return;
824 log_info ("DHCPACK from %s", piaddr (packet -> client_addr));
826 lease = packet_to_lease (packet, client);
827 if (!lease) {
828 log_info ("packet_to_lease failed.");
829 return;
832 client -> new = lease;
834 /* Stop resending DHCPREQUEST. */
835 cancel_timeout (send_request, client);
837 /* Figure out the lease time. */
838 oc = lookup_option (&dhcp_universe, client -> new -> options,
839 DHO_DHCP_LEASE_TIME);
840 memset (&ds, 0, sizeof ds);
841 if (oc &&
842 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
843 packet -> options, client -> new -> options,
844 &global_scope, oc, MDL)) {
845 if (ds.len > 3)
846 client -> new -> expiry = getULong (ds.data);
847 else
848 client -> new -> expiry = 0;
849 data_string_forget (&ds, MDL);
850 } else
851 client -> new -> expiry = 0;
853 if (!client -> new -> expiry) {
854 log_error ("no expiry time on offered lease.");
855 /* XXX this is going to be bad - if this _does_
856 XXX happen, we should probably dynamically
857 XXX disqualify the DHCP server that gave us the
858 XXX bad packet from future selections and
859 XXX then go back into the init state. */
860 state_init (client);
861 return;
864 /* A number that looks negative here is really just very large,
865 because the lease expiry offset is unsigned. */
866 if (client -> new -> expiry < 0)
867 client -> new -> expiry = TIME_MAX;
868 /* Take the server-provided renewal time if there is one. */
869 oc = lookup_option (&dhcp_universe, client -> new -> options,
870 DHO_DHCP_RENEWAL_TIME);
871 if (oc &&
872 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
873 packet -> options, client -> new -> options,
874 &global_scope, oc, MDL)) {
875 if (ds.len > 3)
876 client -> new -> renewal = getULong (ds.data);
877 else
878 client -> new -> renewal = 0;
879 data_string_forget (&ds, MDL);
880 } else
881 client -> new -> renewal = 0;
883 /* If it wasn't specified by the server, calculate it. */
884 if (!client -> new -> renewal)
885 client -> new -> renewal = client -> new -> expiry / 2 + 1;
887 if (client -> new -> renewal <= 0)
888 client -> new -> renewal = TIME_MAX;
890 /* Now introduce some randomness to the renewal time: */
891 if (client -> new -> renewal <= TIME_MAX / 3 - 3)
892 client -> new -> renewal =
893 (((client -> new -> renewal + 3) * 3 / 4) +
894 (random () % /* XXX NUMS */
895 ((client -> new -> renewal + 3) / 4)));
897 /* Same deal with the rebind time. */
898 oc = lookup_option (&dhcp_universe, client -> new -> options,
899 DHO_DHCP_REBINDING_TIME);
900 if (oc &&
901 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
902 packet -> options, client -> new -> options,
903 &global_scope, oc, MDL)) {
904 if (ds.len > 3)
905 client -> new -> rebind = getULong (ds.data);
906 else
907 client -> new -> rebind = 0;
908 data_string_forget (&ds, MDL);
909 } else
910 client -> new -> rebind = 0;
912 if (client -> new -> rebind <= 0) {
913 if (client -> new -> expiry <= TIME_MAX / 7)
914 client -> new -> rebind =
915 client -> new -> expiry * 7 / 8;
916 else
917 client -> new -> rebind =
918 client -> new -> expiry / 8 * 7;
921 /* Make sure our randomness didn't run the renewal time past the
922 rebind time. */
923 if (client -> new -> renewal > client -> new -> rebind) {
924 if (client -> new -> rebind <= TIME_MAX / 3)
925 client -> new -> renewal =
926 client -> new -> rebind * 3 / 4;
927 else
928 client -> new -> renewal =
929 client -> new -> rebind / 4 * 3;
932 client -> new -> expiry += cur_time;
933 /* Lease lengths can never be negative. */
934 if (client -> new -> expiry < cur_time)
935 client -> new -> expiry = TIME_MAX;
936 client -> new -> renewal += cur_time;
937 if (client -> new -> renewal < cur_time)
938 client -> new -> renewal = TIME_MAX;
939 client -> new -> rebind += cur_time;
940 if (client -> new -> rebind < cur_time)
941 client -> new -> rebind = TIME_MAX;
943 bind_lease (client);
946 void bind_lease (client)
947 struct client_state *client;
949 struct interface_info *ip = client -> interface;
951 /* Remember the medium. */
952 client -> new -> medium = client -> medium;
954 #ifdef BUILTIN_IFCONFIG
955 if (interface_bind (client)) {
956 #else
957 /* Run the client script with the new parameters. */
958 script_init (client, (client -> state == S_REQUESTING
959 ? "BOUND"
960 : (client -> state == S_RENEWING
961 ? "RENEW"
962 : (client -> state == S_REBOOTING
963 ? "REBOOT" : "REBIND"))),
964 client -> new -> medium);
965 if (client -> active && client -> state != S_REBOOTING)
966 script_write_params (client, "old_", client -> active);
967 script_write_params (client, "new_", client -> new);
968 if (client -> alias)
969 script_write_params (client, "alias_", client -> alias);
971 /* If the BOUND/RENEW code detects another machine using the
972 offered address, it exits nonzero. We need to send a
973 DHCPDECLINE and toss the lease. */
974 if (script_go (client)) {
975 #endif
976 make_decline (client, client -> new);
977 send_decline (client);
978 destroy_client_lease (client -> new);
979 client -> new = (struct client_lease *)0;
980 state_init (client);
981 return;
984 /* Write out the new lease. */
985 write_client_lease (client, client -> new, 0, 0);
987 /* Replace the old active lease with the new one. */
988 if (client -> active)
989 destroy_client_lease (client -> active);
990 client -> active = client -> new;
991 client -> new = (struct client_lease *)0;
993 /* Set up a timeout to start the renewal process. */
994 add_timeout (client -> active -> renewal,
995 state_bound, client, 0, 0);
997 log_info ("bound to %s -- renewal in %ld seconds.",
998 piaddr (client -> active -> address),
999 (long)(client -> active -> renewal - cur_time));
1000 client -> state = S_BOUND;
1001 reinitialize_interfaces ();
1002 go_daemon ();
1003 if (client -> config -> do_forward_update) {
1004 client -> dns_update_timeout = 1;
1005 add_timeout (cur_time + 1, client_dns_update_timeout,
1006 client, 0, 0);
1010 /* state_bound is called when we've successfully bound to a particular
1011 lease, but the renewal time on that lease has expired. We are
1012 expected to unicast a DHCPREQUEST to the server that gave us our
1013 original lease. */
1015 void state_bound (cpp)
1016 void *cpp;
1018 struct client_state *client = cpp;
1019 int i;
1020 struct option_cache *oc;
1021 struct data_string ds;
1023 ASSERT_STATE(state, S_BOUND);
1025 /* T1 has expired. */
1026 make_request (client, client -> active);
1027 client -> xid = client -> packet.xid;
1029 memset (&ds, 0, sizeof ds);
1030 oc = lookup_option (&dhcp_universe, client -> active -> options,
1031 DHO_DHCP_SERVER_IDENTIFIER);
1032 if (oc &&
1033 evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
1034 client, (struct option_state *)0,
1035 client -> active -> options,
1036 &global_scope, oc, MDL)) {
1037 if (ds.len > 3) {
1038 memcpy (client -> destination.iabuf, ds.data, 4);
1039 client -> destination.len = 4;
1040 } else
1041 client -> destination = iaddr_broadcast;
1043 data_string_forget (&ds, MDL);
1044 } else
1045 client -> destination = iaddr_broadcast;
1047 client -> first_sending = cur_time;
1048 client -> interval = client -> config -> initial_interval;
1049 client -> state = S_RENEWING;
1051 /* Send the first packet immediately. */
1052 send_request (client);
1055 /* state_stop is called when we've been told to shut down. We unconfigure
1056 the interfaces, and then stop operating until told otherwise. */
1058 void state_stop (cpp)
1059 void *cpp;
1061 struct client_state *client = cpp;
1062 int i;
1064 /* Cancel all timeouts. */
1065 cancel_timeout (state_selecting, client);
1066 cancel_timeout (send_discover, client);
1067 cancel_timeout (send_request, client);
1068 cancel_timeout (state_bound, client);
1070 /* If we have an address, unconfigure it. */
1071 if (client -> active) {
1072 #ifdef BUILTIN_IFCONFIG
1073 interface_stop (client);
1074 #else
1075 script_init (client, "STOP", client -> active -> medium);
1076 script_write_params (client, "old_", client -> active);
1077 if (client -> alias)
1078 script_write_params (client, "alias_",
1079 client -> alias);
1080 script_go (client);
1081 #endif
1085 int commit_leases ()
1087 return 0;
1090 int write_lease (lease)
1091 struct lease *lease;
1093 return 0;
1096 int write_host (host)
1097 struct host_decl *host;
1099 return 0;
1102 void db_startup (testp)
1103 int testp;
1107 void bootp (packet)
1108 struct packet *packet;
1110 struct iaddrlist *ap;
1112 if (packet -> raw -> op != BOOTREPLY)
1113 return;
1115 /* If there's a reject list, make sure this packet's sender isn't
1116 on it. */
1117 for (ap = packet -> interface -> client -> config -> reject_list;
1118 ap; ap = ap -> next) {
1119 if (addr_eq (packet -> client_addr, ap -> addr)) {
1120 log_info ("BOOTREPLY from %s rejected.",
1121 piaddr (ap -> addr));
1122 return;
1126 dhcpoffer (packet);
1130 void dhcp (packet)
1131 struct packet *packet;
1133 struct iaddrlist *ap;
1134 void (*handler) PROTO ((struct packet *));
1135 const char *type;
1137 switch (packet -> packet_type) {
1138 case DHCPOFFER:
1139 handler = dhcpoffer;
1140 type = "DHCPOFFER";
1141 break;
1143 case DHCPNAK:
1144 handler = dhcpnak;
1145 type = "DHCPNACK";
1146 break;
1148 case DHCPACK:
1149 handler = dhcpack;
1150 type = "DHCPACK";
1151 break;
1153 default:
1154 return;
1157 /* If there's a reject list, make sure this packet's sender isn't
1158 on it. */
1159 for (ap = packet -> interface -> client -> config -> reject_list;
1160 ap; ap = ap -> next) {
1161 if (addr_eq (packet -> client_addr, ap -> addr)) {
1162 log_info ("%s from %s rejected.",
1163 type, piaddr (ap -> addr));
1164 return;
1167 (*handler) (packet);
1170 void dhcpoffer (packet)
1171 struct packet *packet;
1173 struct interface_info *ip = packet -> interface;
1174 struct client_state *client;
1175 struct client_lease *lease, *lp;
1176 int i;
1177 int stop_selecting;
1178 const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
1179 struct iaddrlist *ap;
1180 struct option_cache *oc;
1181 char obuf [1024];
1183 #ifdef DEBUG_PACKET
1184 dump_packet (packet);
1185 #endif
1187 /* Find a client state that matches the xid... */
1188 for (client = ip -> client; client; client = client -> next)
1189 if (client -> xid == packet -> raw -> xid)
1190 break;
1192 /* If we're not receptive to an offer right now, or if the offer
1193 has an unrecognizable transaction id, then just drop it. */
1194 if (!client ||
1195 client -> state != S_SELECTING ||
1196 (packet -> interface -> hw_address.hlen - 1 !=
1197 packet -> raw -> hlen) ||
1198 (memcmp (&packet -> interface -> hw_address.hbuf [1],
1199 packet -> raw -> chaddr, packet -> raw -> hlen))) {
1200 #if defined (DEBUG)
1201 log_debug ("%s in wrong transaction.", name);
1202 #endif
1203 return;
1206 sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
1209 /* If this lease doesn't supply the minimum required parameters,
1210 blow it off. */
1211 if (client -> config -> required_options) {
1212 for (i = 0; client -> config -> required_options [i]; i++) {
1213 if (!lookup_option
1214 (&dhcp_universe, packet -> options,
1215 client -> config -> required_options [i])) {
1216 log_info ("%s: no %s option.",
1217 obuf, (dhcp_universe.options
1218 [client -> config -> required_options [i]]
1219 -> name));
1220 return;
1225 /* If we've already seen this lease, don't record it again. */
1226 for (lease = client -> offered_leases; lease; lease = lease -> next) {
1227 if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
1228 !memcmp (lease -> address.iabuf,
1229 &packet -> raw -> yiaddr, lease -> address.len)) {
1230 log_debug ("%s: already seen.", obuf);
1231 return;
1235 lease = packet_to_lease (packet, client);
1236 if (!lease) {
1237 log_info ("%s: packet_to_lease failed.", obuf);
1238 return;
1241 /* If this lease was acquired through a BOOTREPLY, record that
1242 fact. */
1243 if (!packet -> options_valid || !packet -> packet_type)
1244 lease -> is_bootp = 1;
1246 /* Record the medium under which this lease was offered. */
1247 lease -> medium = client -> medium;
1249 /* Figure out when we're supposed to stop selecting. */
1250 stop_selecting = (client -> first_sending +
1251 client -> config -> select_interval);
1253 /* If this is the lease we asked for, put it at the head of the
1254 list, and don't mess with the arp request timeout. */
1255 if (lease -> address.len == client -> requested_address.len &&
1256 !memcmp (lease -> address.iabuf,
1257 client -> requested_address.iabuf,
1258 client -> requested_address.len)) {
1259 lease -> next = client -> offered_leases;
1260 client -> offered_leases = lease;
1261 } else {
1262 /* Put the lease at the end of the list. */
1263 lease -> next = (struct client_lease *)0;
1264 if (!client -> offered_leases)
1265 client -> offered_leases = lease;
1266 else {
1267 for (lp = client -> offered_leases; lp -> next;
1268 lp = lp -> next)
1270 lp -> next = lease;
1274 /* If the selecting interval has expired, go immediately to
1275 state_selecting(). Otherwise, time out into
1276 state_selecting at the select interval. */
1277 if (stop_selecting <= 0)
1278 state_selecting (client);
1279 else {
1280 add_timeout (stop_selecting, state_selecting, client, 0, 0);
1281 cancel_timeout (send_discover, client);
1283 log_info ("%s", obuf);
1286 /* Allocate a client_lease structure and initialize it from the parameters
1287 in the specified packet. */
1289 struct client_lease *packet_to_lease (packet, client)
1290 struct packet *packet;
1291 struct client_state *client;
1293 struct client_lease *lease;
1294 unsigned i;
1295 struct option_cache *oc;
1296 struct data_string data;
1298 lease = (struct client_lease *)new_client_lease (MDL);
1300 if (!lease) {
1301 log_error ("packet_to_lease: no memory to record lease.\n");
1302 return (struct client_lease *)0;
1305 memset (lease, 0, sizeof *lease);
1307 /* Copy the lease options. */
1308 option_state_reference (&lease -> options, packet -> options, MDL);
1310 lease -> address.len = sizeof (packet -> raw -> yiaddr);
1311 memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
1312 lease -> address.len);
1314 memset (&data, 0, sizeof data);
1316 if (client -> config -> vendor_space_name) {
1317 i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
1319 /* See if there was a vendor encapsulation option. */
1320 oc = lookup_option (&dhcp_universe, lease -> options, i);
1321 if (oc &&
1322 client -> config -> vendor_space_name &&
1323 evaluate_option_cache (&data, packet,
1324 (struct lease *)0, client,
1325 packet -> options, lease -> options,
1326 &global_scope, oc, MDL)) {
1327 if (data.len) {
1328 parse_encapsulated_suboptions
1329 (packet -> options, &dhcp_options [i],
1330 data.data, data.len, &dhcp_universe,
1331 client -> config -> vendor_space_name
1334 data_string_forget (&data, MDL);
1336 } else
1337 i = 0;
1339 /* Figure out the overload flag. */
1340 oc = lookup_option (&dhcp_universe, lease -> options,
1341 DHO_DHCP_OPTION_OVERLOAD);
1342 if (oc &&
1343 evaluate_option_cache (&data, packet, (struct lease *)0, client,
1344 packet -> options, lease -> options,
1345 &global_scope, oc, MDL)) {
1346 if (data.len > 0)
1347 i = data.data [0];
1348 else
1349 i = 0;
1350 data_string_forget (&data, MDL);
1351 } else
1352 i = 0;
1354 /* If the server name was filled out, copy it. */
1355 if (!(i & 2) && packet -> raw -> sname [0]) {
1356 unsigned len;
1357 /* Don't count on the NUL terminator. */
1358 for (len = 0; len < 64; len++)
1359 if (!packet -> raw -> sname [len])
1360 break;
1361 lease -> server_name = dmalloc (len + 1, MDL);
1362 if (!lease -> server_name) {
1363 log_error ("dhcpoffer: no memory for server name.\n");
1364 destroy_client_lease (lease);
1365 return (struct client_lease *)0;
1366 } else {
1367 memcpy (lease -> server_name,
1368 packet -> raw -> sname, len);
1369 lease -> server_name [len] = 0;
1373 /* Ditto for the filename. */
1374 if (!(i & 1) && packet -> raw -> file [0]) {
1375 unsigned len;
1376 /* Don't count on the NUL terminator. */
1377 for (len = 0; len < 64; len++)
1378 if (!packet -> raw -> file [len])
1379 break;
1380 lease -> filename = dmalloc (len + 1, MDL);
1381 if (!lease -> filename) {
1382 log_error ("dhcpoffer: no memory for filename.\n");
1383 destroy_client_lease (lease);
1384 return (struct client_lease *)0;
1385 } else {
1386 memcpy (lease -> filename,
1387 packet -> raw -> file, len);
1388 lease -> filename [len] = 0;
1392 execute_statements_in_scope ((struct binding_value **)0,
1393 (struct packet *)packet,
1394 (struct lease *)0, client,
1395 lease -> options, lease -> options,
1396 &global_scope,
1397 client -> config -> on_receipt,
1398 (struct group *)0);
1400 return lease;
1403 void dhcpnak (packet)
1404 struct packet *packet;
1406 struct interface_info *ip = packet -> interface;
1407 struct client_state *client;
1409 /* Find a client state that matches the xid... */
1410 for (client = ip -> client; client; client = client -> next)
1411 if (client -> xid == packet -> raw -> xid)
1412 break;
1414 /* If we're not receptive to an offer right now, or if the offer
1415 has an unrecognizable transaction id, then just drop it. */
1416 if (!client ||
1417 (packet -> interface -> hw_address.hlen - 1 !=
1418 packet -> raw -> hlen) ||
1419 (memcmp (&packet -> interface -> hw_address.hbuf [1],
1420 packet -> raw -> chaddr, packet -> raw -> hlen))) {
1421 #if defined (DEBUG)
1422 log_debug ("DHCPNAK in wrong transaction.");
1423 #endif
1424 return;
1427 if (client -> state != S_REBOOTING &&
1428 client -> state != S_REQUESTING &&
1429 client -> state != S_RENEWING &&
1430 client -> state != S_REBINDING) {
1431 #if defined (DEBUG)
1432 log_debug ("DHCPNAK in wrong state.");
1433 #endif
1434 return;
1437 log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
1439 if (!client -> active) {
1440 #if defined (DEBUG)
1441 log_info ("DHCPNAK with no active lease.\n");
1442 #endif
1443 return;
1446 destroy_client_lease (client -> active);
1447 client -> active = (struct client_lease *)0;
1449 /* Stop sending DHCPREQUEST packets... */
1450 cancel_timeout (send_request, client);
1452 client -> state = S_INIT;
1453 state_init (client);
1456 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1457 one after the right interval has expired. If we don't get an offer by
1458 the time we reach the panic interval, call the panic function. */
1460 void send_discover (cpp)
1461 void *cpp;
1463 struct client_state *client = cpp;
1465 int result;
1466 int interval;
1467 int increase = 1;
1469 /* Figure out how long it's been since we started transmitting. */
1470 interval = cur_time - client -> first_sending;
1472 /* If we're past the panic timeout, call the script and tell it
1473 we haven't found anything for this interface yet. */
1474 if (interval > client -> config -> timeout) {
1475 state_panic (client);
1476 return;
1479 /* If we're selecting media, try the whole list before doing
1480 the exponential backoff, but if we've already received an
1481 offer, stop looping, because we obviously have it right. */
1482 if (!client -> offered_leases &&
1483 client -> config -> media) {
1484 int fail = 0;
1485 again:
1486 if (client -> medium) {
1487 client -> medium = client -> medium -> next;
1488 increase = 0;
1490 if (!client -> medium) {
1491 if (fail)
1492 log_fatal ("No valid media types for %s!",
1493 client -> interface -> name);
1494 client -> medium =
1495 client -> config -> media;
1496 increase = 1;
1499 log_info ("Trying medium \"%s\" %d",
1500 client -> medium -> string, increase);
1501 #ifdef BUILTIN_IFCONFIG
1502 if (interface_medium (client, client -> medium -> string)) {
1503 #else
1504 script_init (client, "MEDIUM", client -> medium);
1505 if (script_go (client)) {
1506 #endif
1507 fail = 1;
1508 goto again;
1512 /* If we're supposed to increase the interval, do so. If it's
1513 currently zero (i.e., we haven't sent any packets yet), set
1514 it to initial_interval; otherwise, add to it a random number
1515 between zero and two times itself. On average, this means
1516 that it will double with every transmission. */
1517 if (increase) {
1518 if (!client -> interval)
1519 client -> interval =
1520 client -> config -> initial_interval;
1521 else
1522 client -> interval += ((random () >> 2) %
1523 (2 * client -> interval));
1525 /* Don't backoff past cutoff. */
1526 if (client -> interval >
1527 client -> config -> backoff_cutoff)
1528 client -> interval =
1529 ((client -> config -> backoff_cutoff / 2)
1530 + ((random () >> 2) %
1531 client -> config -> backoff_cutoff));
1532 } else if (!client -> interval)
1533 client -> interval = client -> config -> initial_interval;
1535 /* If the backoff would take us to the panic timeout, just use that
1536 as the interval. */
1537 if (cur_time + client -> interval >
1538 client -> first_sending + client -> config -> timeout)
1539 client -> interval =
1540 (client -> first_sending +
1541 client -> config -> timeout) - cur_time + 1;
1543 /* Record the number of seconds since we started sending. */
1544 if (interval < 65536)
1545 client -> packet.secs = htons (interval);
1546 else
1547 client -> packet.secs = htons (65535);
1548 client -> secs = client -> packet.secs;
1550 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
1551 client -> name ? client -> name : client -> interface -> name,
1552 inet_ntoa (sockaddr_broadcast.sin_addr),
1553 ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
1555 /* Send out a packet. */
1556 result = send_packet (client -> interface, (struct packet *)0,
1557 &client -> packet,
1558 client -> packet_length,
1559 inaddr_any, &sockaddr_broadcast,
1560 (struct hardware *)0);
1562 add_timeout (cur_time + client -> interval,
1563 send_discover, client, 0, 0);
1566 /* state_panic gets called if we haven't received any offers in a preset
1567 amount of time. When this happens, we try to use existing leases that
1568 haven't yet expired, and failing that, we call the client script and
1569 hope it can do something. */
1571 void state_panic (cpp)
1572 void *cpp;
1574 struct client_state *client = cpp;
1575 struct client_lease *loop;
1576 struct client_lease *lp;
1578 loop = lp = client -> active;
1580 log_info ("No DHCPOFFERS received.");
1582 /* We may not have an active lease, but we may have some
1583 predefined leases that we can try. */
1584 if (!client -> active && client -> leases)
1585 goto activate_next;
1587 /* Run through the list of leases and see if one can be used. */
1588 while (client -> active) {
1589 if (client -> active -> expiry > cur_time) {
1590 log_info ("Trying recorded lease %s",
1591 piaddr (client -> active -> address));
1592 #ifdef BUILTIN_IFCONFIG
1593 if (interface_timeout (client)) {
1594 #else
1595 /* Run the client script with the existing
1596 parameters. */
1597 script_init (client, "TIMEOUT",
1598 client -> active -> medium);
1599 script_write_params (client, "new_", client -> active);
1600 if (client -> alias)
1601 script_write_params (client, "alias_",
1602 client -> alias);
1604 /* If the old lease is still good and doesn't
1605 yet need renewal, go into BOUND state and
1606 timeout at the renewal time. */
1607 if (!script_go (client)) {
1608 #endif
1609 if (cur_time < client -> active -> renewal) {
1610 client -> state = S_BOUND;
1611 log_info ("bound: renewal in %ld %s.",
1612 (long)(client -> active -> renewal -
1613 cur_time), "seconds");
1614 add_timeout (client -> active -> renewal,
1615 state_bound, client, 0, 0);
1616 } else {
1617 client -> state = S_BOUND;
1618 log_info ("bound: immediate renewal.");
1619 state_bound (client);
1621 reinitialize_interfaces ();
1622 go_daemon ();
1623 return;
1627 /* If there are no other leases, give up. */
1628 if (!client -> leases) {
1629 client -> leases = client -> active;
1630 client -> active = (struct client_lease *)0;
1631 break;
1634 activate_next:
1635 /* Otherwise, put the active lease at the end of the
1636 lease list, and try another lease.. */
1637 for (lp = client -> leases; lp -> next; lp = lp -> next)
1639 lp -> next = client -> active;
1640 if (lp -> next) {
1641 lp -> next -> next = (struct client_lease *)0;
1643 client -> active = client -> leases;
1644 client -> leases = client -> leases -> next;
1646 /* If we already tried this lease, we've exhausted the
1647 set of leases, so we might as well give up for
1648 now. */
1649 if (client -> active == loop)
1650 break;
1651 else if (!loop)
1652 loop = client -> active;
1655 /* No leases were available, or what was available didn't work, so
1656 tell the shell script that we failed to allocate an address,
1657 and try again later. */
1658 if (onetry) {
1659 if (!quiet)
1660 log_info ("Unable to obtain a lease on first try.%s",
1661 " Exiting.");
1662 exit (2);
1665 log_info ("No working leases in persistent database - sleeping.");
1666 #ifdef BUILTIN_IFCONFIG
1667 interface_fail (client);
1668 #else
1669 script_init (client, "FAIL", (struct string_list *)0);
1670 if (client -> alias)
1671 script_write_params (client, "alias_", client -> alias);
1672 script_go (client);
1673 #endif
1674 client -> state = S_INIT;
1675 add_timeout (cur_time +
1676 ((client -> config -> retry_interval + 1) / 2 +
1677 (random () % client -> config -> retry_interval)),
1678 state_init, client, 0, 0);
1679 go_daemon ();
1682 void send_request (cpp)
1683 void *cpp;
1685 struct client_state *client = cpp;
1687 int result;
1688 int interval;
1689 struct sockaddr_in destination;
1690 struct in_addr from;
1692 /* Figure out how long it's been since we started transmitting. */
1693 interval = cur_time - client -> first_sending;
1695 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1696 past the reboot timeout, go to INIT and see if we can
1697 DISCOVER an address... */
1698 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1699 means either that we're on a network with no DHCP server,
1700 or that our server is down. In the latter case, assuming
1701 that there is a backup DHCP server, DHCPDISCOVER will get
1702 us a new address, but we could also have successfully
1703 reused our old address. In the former case, we're hosed
1704 anyway. This is not a win-prone situation. */
1705 if ((client -> state == S_REBOOTING ||
1706 client -> state == S_REQUESTING) &&
1707 interval > client -> config -> reboot_timeout) {
1708 cancel:
1709 client -> state = S_INIT;
1710 cancel_timeout (send_request, client);
1711 state_init (client);
1712 return;
1715 /* If we're in the reboot state, make sure the media is set up
1716 correctly. */
1717 if (client -> state == S_REBOOTING &&
1718 !client -> medium &&
1719 client -> active -> medium ) {
1720 #ifdef BUILTIN_IFCONFIG
1721 if (interface_medium (client, client -> active -> medium -> string))
1722 #else
1723 script_init (client, "MEDIUM", client -> active -> medium);
1725 /* If the medium we chose won't fly, go to INIT state. */
1726 if (script_go (client))
1727 #endif
1728 goto cancel;
1730 /* Record the medium. */
1731 client -> medium = client -> active -> medium;
1734 /* If the lease has expired, relinquish the address and go back
1735 to the INIT state. */
1736 if (client -> state != S_REQUESTING &&
1737 cur_time > client -> active -> expiry) {
1738 #ifdef BUILTIN_IFCONFIG
1739 interface_expire (client);
1740 interface_preinit (client);
1741 #else
1742 /* Run the client script with the new parameters. */
1743 script_init (client, "EXPIRE", (struct string_list *)0);
1744 script_write_params (client, "old_", client -> active);
1745 if (client -> alias)
1746 script_write_params (client, "alias_",
1747 client -> alias);
1748 script_go (client);
1750 /* Now do a preinit on the interface so that we can
1751 discover a new address. */
1752 script_init (client, "PREINIT", (struct string_list *)0);
1753 if (client -> alias)
1754 script_write_params (client, "alias_",
1755 client -> alias);
1756 script_go (client);
1757 #endif
1759 client -> state = S_INIT;
1760 state_init (client);
1761 return;
1764 /* Do the exponential backoff... */
1765 if (!client -> interval)
1766 client -> interval = client -> config -> initial_interval;
1767 else {
1768 client -> interval += ((random () >> 2) %
1769 (2 * client -> interval));
1772 /* Don't backoff past cutoff. */
1773 if (client -> interval >
1774 client -> config -> backoff_cutoff)
1775 client -> interval =
1776 ((client -> config -> backoff_cutoff / 2)
1777 + ((random () >> 2) %
1778 client -> config -> backoff_cutoff));
1780 /* If the backoff would take us to the expiry time, just set the
1781 timeout to the expiry time. */
1782 if (client -> state != S_REQUESTING &&
1783 cur_time + client -> interval > client -> active -> expiry)
1784 client -> interval =
1785 client -> active -> expiry - cur_time + 1;
1787 /* If the lease T2 time has elapsed, or if we're not yet bound,
1788 broadcast the DHCPREQUEST rather than unicasting. */
1789 if (client -> state == S_REQUESTING ||
1790 client -> state == S_REBOOTING ||
1791 cur_time > client -> active -> rebind)
1792 destination.sin_addr = sockaddr_broadcast.sin_addr;
1793 else
1794 memcpy (&destination.sin_addr.s_addr,
1795 client -> destination.iabuf,
1796 sizeof destination.sin_addr.s_addr);
1797 destination.sin_port = remote_port;
1798 destination.sin_family = AF_INET;
1799 #ifdef HAVE_SA_LEN
1800 destination.sin_len = sizeof destination;
1801 #endif
1803 if (client -> state == S_RENEWING ||
1804 client -> state == S_REBINDING)
1805 memcpy (&from, client -> active -> address.iabuf,
1806 sizeof from);
1807 else
1808 from.s_addr = INADDR_ANY;
1810 /* Record the number of seconds since we started sending. */
1811 if (client -> state == S_REQUESTING)
1812 client -> packet.secs = client -> secs;
1813 else {
1814 if (interval < 65536)
1815 client -> packet.secs = htons (interval);
1816 else
1817 client -> packet.secs = htons (65535);
1820 log_info ("DHCPREQUEST on %s to %s port %d",
1821 client -> name ? client -> name : client -> interface -> name,
1822 inet_ntoa (destination.sin_addr),
1823 ntohs (destination.sin_port));
1825 if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
1826 fallback_interface)
1827 result = send_packet (fallback_interface,
1828 (struct packet *)0,
1829 &client -> packet,
1830 client -> packet_length,
1831 from, &destination,
1832 (struct hardware *)0);
1833 else
1834 /* Send out a packet. */
1835 result = send_packet (client -> interface, (struct packet *)0,
1836 &client -> packet,
1837 client -> packet_length,
1838 from, &destination,
1839 (struct hardware *)0);
1841 add_timeout (cur_time + client -> interval,
1842 send_request, client, 0, 0);
1845 void send_decline (cpp)
1846 void *cpp;
1848 struct client_state *client = cpp;
1850 int result;
1852 log_info ("DHCPDECLINE on %s to %s port %d",
1853 client -> name ? client -> name : client -> interface -> name,
1854 inet_ntoa (sockaddr_broadcast.sin_addr),
1855 ntohs (sockaddr_broadcast.sin_port));
1857 /* Send out a packet. */
1858 result = send_packet (client -> interface, (struct packet *)0,
1859 &client -> packet,
1860 client -> packet_length,
1861 inaddr_any, &sockaddr_broadcast,
1862 (struct hardware *)0);
1865 void send_release (cpp)
1866 void *cpp;
1868 struct client_state *client = cpp;
1870 int result;
1871 struct sockaddr_in destination;
1872 struct in_addr from;
1874 memcpy (&from, client -> active -> address.iabuf,
1875 sizeof from);
1876 memcpy (&destination.sin_addr.s_addr,
1877 client -> destination.iabuf,
1878 sizeof destination.sin_addr.s_addr);
1879 destination.sin_port = remote_port;
1880 destination.sin_family = AF_INET;
1881 #ifdef HAVE_SA_LEN
1882 destination.sin_len = sizeof destination;
1883 #endif
1885 /* Set the lease to end now, so that we don't accidentally
1886 reuse it if we restart before the old expiry time. */
1887 client -> active -> expiry =
1888 client -> active -> renewal =
1889 client -> active -> rebind = cur_time;
1890 if (!write_client_lease (client, client -> active, 1, 1)) {
1891 log_error ("Can't release lease: lease write failed.");
1892 return;
1895 log_info ("DHCPRELEASE on %s to %s port %d",
1896 client -> name ? client -> name : client -> interface -> name,
1897 inet_ntoa (destination.sin_addr),
1898 ntohs (destination.sin_port));
1900 if (fallback_interface)
1901 result = send_packet (fallback_interface,
1902 (struct packet *)0,
1903 &client -> packet,
1904 client -> packet_length,
1905 from, &destination,
1906 (struct hardware *)0);
1907 else
1908 /* Send out a packet. */
1909 result = send_packet (client -> interface, (struct packet *)0,
1910 &client -> packet,
1911 client -> packet_length,
1912 from, &destination,
1913 (struct hardware *)0);
1916 void make_client_options (client, lease, type, sid, rip, prl, op)
1917 struct client_state *client;
1918 struct client_lease *lease;
1919 u_int8_t *type;
1920 struct option_cache *sid;
1921 struct iaddr *rip;
1922 u_int32_t *prl;
1923 struct option_state **op;
1925 unsigned i;
1926 struct option_cache *oc;
1927 struct buffer *bp = (struct buffer *)0;
1929 /* If there are any leftover options, get rid of them. */
1930 if (*op)
1931 option_state_dereference (op, MDL);
1933 /* Allocate space for options. */
1934 option_state_allocate (op, MDL);
1936 /* Send the server identifier if provided. */
1937 if (sid)
1938 save_option (&dhcp_universe, *op, sid);
1940 oc = (struct option_cache *)0;
1942 /* Send the requested address if provided. */
1943 if (rip) {
1944 client -> requested_address = *rip;
1945 if (!(make_const_option_cache
1946 (&oc, (struct buffer **)0, rip -> iabuf, rip -> len,
1947 &dhcp_options [DHO_DHCP_REQUESTED_ADDRESS], MDL)))
1948 log_error ("can't make requested address cache.");
1949 else {
1950 save_option (&dhcp_universe, *op, oc);
1951 option_cache_dereference (&oc, MDL);
1953 } else {
1954 client -> requested_address.len = 0;
1957 if (!(make_const_option_cache
1958 (&oc, (struct buffer **)0,
1959 type, 1, &dhcp_options [DHO_DHCP_MESSAGE_TYPE], MDL)))
1960 log_error ("can't make message type.");
1961 else {
1962 save_option (&dhcp_universe, *op, oc);
1963 option_cache_dereference (&oc, MDL);
1966 if (prl) {
1967 /* Figure out how many parameters were requested. */
1968 for (i = 0; prl [i]; i++)
1970 if (!buffer_allocate (&bp, i, MDL))
1971 log_error ("can't make parameter list buffer.");
1972 else {
1973 for (i = 0; prl [i]; i++)
1974 bp -> data [i] = prl [i];
1975 if (!(make_const_option_cache
1976 (&oc, &bp, (u_int8_t *)0, i,
1977 &dhcp_options [DHO_DHCP_PARAMETER_REQUEST_LIST],
1978 MDL)))
1979 log_error ("can't make option cache");
1980 else {
1981 save_option (&dhcp_universe, *op, oc);
1982 option_cache_dereference (&oc, MDL);
1987 /* Run statements that need to be run on transmission. */
1988 if (client -> config -> on_transmission)
1989 execute_statements_in_scope
1990 ((struct binding_value **)0,
1991 (struct packet *)0, (struct lease *)0, client,
1992 (lease ? lease -> options : (struct option_state *)0),
1993 *op, &global_scope,
1994 client -> config -> on_transmission,
1995 (struct group *)0);
1998 void make_discover (client, lease)
1999 struct client_state *client;
2000 struct client_lease *lease;
2002 unsigned char discover = DHCPDISCOVER;
2003 int i;
2004 struct option_state *options = (struct option_state *)0;
2006 memset (&client -> packet, 0, sizeof (client -> packet));
2008 make_client_options (client,
2009 lease, &discover, (struct option_cache *)0,
2010 lease ? &lease -> address : (struct iaddr *)0,
2011 client -> config -> requested_options,
2012 &options);
2014 /* Set up the option buffer... */
2015 client -> packet_length =
2016 cons_options ((struct packet *)0, &client -> packet,
2017 (struct lease *)0, client,
2018 /* maximum packet size */1500,
2019 (struct option_state *)0,
2020 options,
2021 /* scope */ &global_scope,
2022 /* overload */ 0,
2023 /* terminate */0,
2024 /* bootpp */0,
2025 (struct data_string *)0,
2026 client -> config -> vendor_space_name);
2028 option_state_dereference (&options, MDL);
2029 if (client -> packet_length < BOOTP_MIN_LEN)
2030 client -> packet_length = BOOTP_MIN_LEN;
2032 client -> packet.op = BOOTREQUEST;
2033 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2034 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2035 client -> packet.hops = 0;
2036 client -> packet.xid = random ();
2037 client -> packet.secs = 0; /* filled in by send_discover. */
2039 if (can_receive_unicast_unconfigured (client -> interface))
2040 client -> packet.flags = 0;
2041 else
2042 client -> packet.flags = htons (BOOTP_BROADCAST);
2044 memset (&(client -> packet.ciaddr),
2045 0, sizeof client -> packet.ciaddr);
2046 memset (&(client -> packet.yiaddr),
2047 0, sizeof client -> packet.yiaddr);
2048 memset (&(client -> packet.siaddr),
2049 0, sizeof client -> packet.siaddr);
2050 client -> packet.giaddr = giaddr;
2051 if (client -> interface -> hw_address.hlen > 0)
2052 memcpy (client -> packet.chaddr,
2053 &client -> interface -> hw_address.hbuf [1],
2054 (unsigned)(client -> interface -> hw_address.hlen - 1));
2056 #ifdef DEBUG_PACKET
2057 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2058 #endif
2062 void make_request (client, lease)
2063 struct client_state *client;
2064 struct client_lease *lease;
2066 unsigned char request = DHCPREQUEST;
2067 int i, j;
2068 unsigned char *tmp, *digest;
2069 unsigned char *old_digest_loc;
2070 struct option_cache *oc;
2072 memset (&client -> packet, 0, sizeof (client -> packet));
2074 if (client -> state == S_REQUESTING)
2075 oc = lookup_option (&dhcp_universe, lease -> options,
2076 DHO_DHCP_SERVER_IDENTIFIER);
2077 else
2078 oc = (struct option_cache *)0;
2080 if (client -> sent_options)
2081 option_state_dereference (&client -> sent_options, MDL);
2083 make_client_options (client, lease, &request, oc,
2084 ((client -> state == S_REQUESTING ||
2085 client -> state == S_REBOOTING)
2086 ? &lease -> address
2087 : (struct iaddr *)0),
2088 client -> config -> requested_options,
2089 &client -> sent_options);
2091 /* Set up the option buffer... */
2092 client -> packet_length =
2093 cons_options ((struct packet *)0, &client -> packet,
2094 (struct lease *)0, client,
2095 /* maximum packet size */1500,
2096 (struct option_state *)0,
2097 client -> sent_options,
2098 /* scope */ &global_scope,
2099 /* overload */ 0,
2100 /* terminate */0,
2101 /* bootpp */0,
2102 (struct data_string *)0,
2103 client -> config -> vendor_space_name);
2105 if (client -> packet_length < BOOTP_MIN_LEN)
2106 client -> packet_length = BOOTP_MIN_LEN;
2108 client -> packet.op = BOOTREQUEST;
2109 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2110 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2111 client -> packet.hops = 0;
2112 client -> packet.xid = client -> xid;
2113 client -> packet.secs = 0; /* Filled in by send_request. */
2115 /* If we own the address we're requesting, put it in ciaddr;
2116 otherwise set ciaddr to zero. */
2117 if (client -> state == S_BOUND ||
2118 client -> state == S_RENEWING ||
2119 client -> state == S_REBINDING) {
2120 memcpy (&client -> packet.ciaddr,
2121 lease -> address.iabuf, lease -> address.len);
2122 client -> packet.flags = 0;
2123 } else {
2124 memset (&client -> packet.ciaddr, 0,
2125 sizeof client -> packet.ciaddr);
2126 if (can_receive_unicast_unconfigured (client -> interface))
2127 client -> packet.flags = 0;
2128 else
2129 client -> packet.flags = htons (BOOTP_BROADCAST);
2132 memset (&client -> packet.yiaddr, 0,
2133 sizeof client -> packet.yiaddr);
2134 memset (&client -> packet.siaddr, 0,
2135 sizeof client -> packet.siaddr);
2136 if (client -> state != S_BOUND &&
2137 client -> state != S_RENEWING)
2138 client -> packet.giaddr = giaddr;
2139 else
2140 memset (&client -> packet.giaddr, 0,
2141 sizeof client -> packet.giaddr);
2142 if (client -> interface -> hw_address.hlen > 0)
2143 memcpy (client -> packet.chaddr,
2144 &client -> interface -> hw_address.hbuf [1],
2145 (unsigned)(client -> interface -> hw_address.hlen - 1));
2147 #ifdef DEBUG_PACKET
2148 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2149 #endif
2152 void make_decline (client, lease)
2153 struct client_state *client;
2154 struct client_lease *lease;
2156 unsigned char decline = DHCPDECLINE;
2157 int i;
2158 struct option_cache *oc;
2160 struct option_state *options = (struct option_state *)0;
2162 oc = lookup_option (&dhcp_universe, lease -> options,
2163 DHO_DHCP_SERVER_IDENTIFIER);
2164 make_client_options (client, lease, &decline, oc,
2165 &lease -> address, (u_int32_t *)0, &options);
2167 /* Set up the option buffer... */
2168 memset (&client -> packet, 0, sizeof (client -> packet));
2169 client -> packet_length =
2170 cons_options ((struct packet *)0, &client -> packet,
2171 (struct lease *)0, client, 0,
2172 (struct option_state *)0, options,
2173 &global_scope, 0, 0, 0, (struct data_string *)0,
2174 client -> config -> vendor_space_name);
2175 option_state_dereference (&options, MDL);
2176 if (client -> packet_length < BOOTP_MIN_LEN)
2177 client -> packet_length = BOOTP_MIN_LEN;
2178 option_state_dereference (&options, MDL);
2180 client -> packet.op = BOOTREQUEST;
2181 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2182 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2183 client -> packet.hops = 0;
2184 client -> packet.xid = client -> xid;
2185 client -> packet.secs = 0; /* Filled in by send_request. */
2186 if (can_receive_unicast_unconfigured (client -> interface))
2187 client -> packet.flags = 0;
2188 else
2189 client -> packet.flags = htons (BOOTP_BROADCAST);
2191 /* ciaddr must always be zero. */
2192 memset (&client -> packet.ciaddr, 0,
2193 sizeof client -> packet.ciaddr);
2194 memset (&client -> packet.yiaddr, 0,
2195 sizeof client -> packet.yiaddr);
2196 memset (&client -> packet.siaddr, 0,
2197 sizeof client -> packet.siaddr);
2198 client -> packet.giaddr = giaddr;
2199 memcpy (client -> packet.chaddr,
2200 &client -> interface -> hw_address.hbuf [1],
2201 client -> interface -> hw_address.hlen);
2203 #ifdef DEBUG_PACKET
2204 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2205 #endif
2208 void make_release (client, lease)
2209 struct client_state *client;
2210 struct client_lease *lease;
2212 unsigned char request = DHCPRELEASE;
2213 int i;
2214 struct option_cache *oc;
2216 struct option_state *options = (struct option_state *)0;
2218 memset (&client -> packet, 0, sizeof (client -> packet));
2220 oc = lookup_option (&dhcp_universe, lease -> options,
2221 DHO_DHCP_SERVER_IDENTIFIER);
2222 make_client_options (client, lease, &request, oc,
2223 (struct iaddr *)0, (u_int32_t *)0,
2224 &options);
2226 /* Set up the option buffer... */
2227 client -> packet_length =
2228 cons_options ((struct packet *)0, &client -> packet,
2229 (struct lease *)0, client,
2230 /* maximum packet size */1500,
2231 (struct option_state *)0,
2232 options,
2233 /* scope */ &global_scope,
2234 /* overload */ 0,
2235 /* terminate */0,
2236 /* bootpp */0,
2237 (struct data_string *)0,
2238 client -> config -> vendor_space_name);
2240 if (client -> packet_length < BOOTP_MIN_LEN)
2241 client -> packet_length = BOOTP_MIN_LEN;
2242 option_state_dereference (&options, MDL);
2244 client -> packet.op = BOOTREQUEST;
2245 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2246 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2247 client -> packet.hops = 0;
2248 client -> packet.xid = random ();
2249 client -> packet.secs = 0;
2250 client -> packet.flags = 0;
2251 memcpy (&client -> packet.ciaddr,
2252 lease -> address.iabuf, lease -> address.len);
2253 memset (&client -> packet.yiaddr, 0,
2254 sizeof client -> packet.yiaddr);
2255 memset (&client -> packet.siaddr, 0,
2256 sizeof client -> packet.siaddr);
2257 client -> packet.giaddr = giaddr;
2258 memcpy (client -> packet.chaddr,
2259 &client -> interface -> hw_address.hbuf [1],
2260 client -> interface -> hw_address.hlen);
2262 #ifdef DEBUG_PACKET
2263 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2264 #endif
2267 void destroy_client_lease (lease)
2268 struct client_lease *lease;
2270 int i;
2272 if (lease -> server_name)
2273 dfree (lease -> server_name, MDL);
2274 if (lease -> filename)
2275 dfree (lease -> filename, MDL);
2276 option_state_dereference (&lease -> options, MDL);
2277 free_client_lease (lease, MDL);
2280 FILE *leaseFile;
2282 void rewrite_client_leases ()
2284 struct interface_info *ip;
2285 struct client_state *client;
2286 struct client_lease *lp;
2288 if (leaseFile)
2289 fclose (leaseFile);
2290 leaseFile = fopen (path_dhclient_db, "w");
2291 if (!leaseFile) {
2292 log_error ("can't create %s: %m", path_dhclient_db);
2293 return;
2296 /* Write out all the leases attached to configured interfaces that
2297 we know about. */
2298 for (ip = interfaces; ip; ip = ip -> next) {
2299 for (client = ip -> client; client; client = client -> next) {
2300 for (lp = client -> leases; lp; lp = lp -> next) {
2301 write_client_lease (client, lp, 1, 0);
2303 if (client -> active)
2304 write_client_lease (client,
2305 client -> active, 1, 0);
2309 /* Write out any leases that are attached to interfaces that aren't
2310 currently configured. */
2311 for (ip = dummy_interfaces; ip; ip = ip -> next) {
2312 for (client = ip -> client; client; client = client -> next) {
2313 for (lp = client -> leases; lp; lp = lp -> next) {
2314 write_client_lease (client, lp, 1, 0);
2316 if (client -> active)
2317 write_client_lease (client,
2318 client -> active, 1, 0);
2321 fflush (leaseFile);
2324 void write_lease_option (struct option_cache *oc,
2325 struct packet *packet, struct lease *lease,
2326 struct client_state *client_state,
2327 struct option_state *in_options,
2328 struct option_state *cfg_options,
2329 struct binding_scope **scope,
2330 struct universe *u, void *stuff)
2332 const char *name, *dot;
2333 struct data_string ds;
2334 int status;
2335 struct client_state *client;
2337 memset (&ds, 0, sizeof ds);
2339 if (u != &dhcp_universe) {
2340 name = u -> name;
2341 dot = ".";
2342 } else {
2343 name = "";
2344 dot = "";
2346 if (evaluate_option_cache (&ds, packet, lease, client_state,
2347 in_options, cfg_options, scope, oc, MDL)) {
2348 fprintf (leaseFile,
2349 " option %s%s%s %s;\n",
2350 name, dot, oc -> option -> name,
2351 pretty_print_option (oc -> option,
2352 ds.data, ds.len, 1, 1));
2353 data_string_forget (&ds, MDL);
2357 int write_client_lease (client, lease, rewrite, makesure)
2358 struct client_state *client;
2359 struct client_lease *lease;
2360 int rewrite;
2361 int makesure;
2363 int i;
2364 struct tm *t;
2365 static int leases_written;
2366 struct option_cache *oc;
2367 struct data_string ds;
2368 pair *hash;
2369 int errors = 0;
2370 char *s;
2372 if (!rewrite) {
2373 if (leases_written++ > 20) {
2374 rewrite_client_leases ();
2375 leases_written = 0;
2379 /* If the lease came from the config file, we don't need to stash
2380 a copy in the lease database. */
2381 if (lease -> is_static)
2382 return 1;
2384 if (!leaseFile) { /* XXX */
2385 leaseFile = fopen (path_dhclient_db, "w");
2386 if (!leaseFile) {
2387 log_error ("can't create %s: %m", path_dhclient_db);
2388 return 0;
2392 errno = 0;
2393 fprintf (leaseFile, "lease {\n");
2394 if (lease -> is_bootp) {
2395 fprintf (leaseFile, " bootp;\n");
2396 if (errno) {
2397 ++errors;
2398 errno = 0;
2401 fprintf (leaseFile, " interface \"%s\";\n",
2402 client -> interface -> name);
2403 if (errno) {
2404 ++errors;
2405 errno = 0;
2407 if (client -> name) {
2408 fprintf (leaseFile, " name \"%s\";\n", client -> name);
2409 if (errno) {
2410 ++errors;
2411 errno = 0;
2414 fprintf (leaseFile, " fixed-address %s;\n",
2415 piaddr (lease -> address));
2416 if (errno) {
2417 ++errors;
2418 errno = 0;
2420 if (lease -> filename) {
2421 s = quotify_string (lease -> filename, MDL);
2422 if (s) {
2423 fprintf (leaseFile, " filename \"%s\";\n", s);
2424 if (errno) {
2425 ++errors;
2426 errno = 0;
2428 dfree (s, MDL);
2429 } else
2430 errors++;
2433 if (lease -> server_name) {
2434 s = quotify_string (lease -> filename, MDL);
2435 if (s) {
2436 fprintf (leaseFile, " server-name \"%s\";\n", s);
2437 if (errno) {
2438 ++errors;
2439 errno = 0;
2441 dfree (s, MDL);
2442 } else
2443 ++errors;
2445 if (lease -> medium) {
2446 s = quotify_string (lease -> medium -> string, MDL);
2447 if (s) {
2448 fprintf (leaseFile, " medium \"%s\";\n", s);
2449 if (errno) {
2450 ++errors;
2451 errno = 0;
2453 dfree (s, MDL);
2454 } else
2455 errors++;
2457 if (errno != 0) {
2458 errors++;
2459 errno = 0;
2462 memset (&ds, 0, sizeof ds);
2464 for (i = 0; i < lease -> options -> universe_count; i++) {
2465 option_space_foreach ((struct packet *)0, (struct lease *)0,
2466 client, (struct option_state *)0,
2467 lease -> options, &global_scope,
2468 universes [i],
2469 client, write_lease_option);
2472 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
2473 somebody invents a time machine, I think we can safely disregard
2474 it. */
2475 t = gmtime (&lease -> renewal);
2476 fprintf (leaseFile,
2477 " renew %d %d/%d/%d %02d:%02d:%02d;\n",
2478 t -> tm_wday, t -> tm_year + 1900,
2479 t -> tm_mon + 1, t -> tm_mday,
2480 t -> tm_hour, t -> tm_min, t -> tm_sec);
2481 if (errno != 0) {
2482 errors++;
2483 errno = 0;
2485 t = gmtime (&lease -> rebind);
2486 fprintf (leaseFile,
2487 " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
2488 t -> tm_wday, t -> tm_year + 1900,
2489 t -> tm_mon + 1, t -> tm_mday,
2490 t -> tm_hour, t -> tm_min, t -> tm_sec);
2491 if (errno != 0) {
2492 errors++;
2493 errno = 0;
2495 t = gmtime (&lease -> expiry);
2496 fprintf (leaseFile,
2497 " expire %d %d/%d/%d %02d:%02d:%02d;\n",
2498 t -> tm_wday, t -> tm_year + 1900,
2499 t -> tm_mon + 1, t -> tm_mday,
2500 t -> tm_hour, t -> tm_min, t -> tm_sec);
2501 if (errno != 0) {
2502 errors++;
2503 errno = 0;
2505 fprintf (leaseFile, "}\n");
2506 if (errno != 0) {
2507 errors++;
2508 errno = 0;
2510 fflush (leaseFile);
2511 if (errno != 0) {
2512 errors++;
2513 errno = 0;
2515 #ifndef FSYNC_MISSING
2516 if (!errors && makesure) {
2517 if (fsync (fileno (leaseFile)) < 0) {
2518 log_info ("write_client_lease: %m");
2519 return 0;
2522 #endif
2523 return errors ? 0 : 1;
2526 #ifdef BUILTIN_IFCONFIG
2527 #ifndef SOCKET_IS_NOT_A_FILE
2528 #define IoctlSocket ioctl
2529 #define CloseSocket close
2530 #endif
2532 void inline setaddr (struct sockaddr_in *sa, u_long addr, u_short af)
2534 sa->sin_len = sizeof (struct sockaddr_in);
2535 sa->sin_family = af;
2536 sa->sin_addr.s_addr = addr;
2539 void ifconfig (char *name, u_long addr, u_long mask, u_long bcast)
2541 int s;
2542 struct ifaliasreq req;
2544 s = socket (AF_INET, SOCK_DGRAM, 0);
2545 if (s < 0) {
2546 log_error ("Can't create configuration socket: %m");
2547 return;
2549 memset (&req, 0, sizeof (req));
2550 strncpy (req.ifra_name, name, sizeof (req.ifra_name));
2551 IoctlSocket (s, SIOCDIFADDR, (char *)&req);
2552 setaddr ((struct sockaddr_in *)&req.ifra_addr, addr, AF_INET);
2553 setaddr ((struct sockaddr_in *)&req.ifra_mask, mask, AF_UNSPEC);
2554 if (bcast)
2555 setaddr ((struct sockaddr_in *)&req.ifra_broadaddr, bcast, AF_INET);
2556 if (IoctlSocket (s, SIOCAIFADDR, (char *)&req) < 0)
2557 log_error ("Can't set interface configuration: %m");
2558 CloseSocket (s);
2561 void ifdeconfig (char *name)
2563 int s;
2564 struct ifaliasreq req;
2566 s = socket (AF_INET, SOCK_DGRAM, 0);
2567 if (s < 0) {
2568 log_error ("Can't create configuration socket: %m");
2569 return;
2571 memset (&req, 0, sizeof (req));
2572 strncpy (req.ifra_name, name, sizeof (req.ifra_name));
2573 IoctlSocket (s, SIOCDIFADDR, (char *)&req);
2574 CloseSocket (s);
2577 void addroute (u_long dest, u_long gate, short flags)
2579 int s;
2580 struct ortentry route;
2582 s = socket (AF_INET, SOCK_RAW, 0);
2583 if (s < 0) {
2584 log_error ("Can't create route socket: %m");
2585 return;
2587 memset (&route, 0, sizeof (route));
2588 setaddr ((struct sockaddr_in *)&route.rt_dst, dest, AF_INET);
2589 setaddr ((struct sockaddr_in *)&route.rt_gateway, gate, AF_INET);
2590 route.rt_flags = flags;
2591 IoctlSocket (s, SIOCADDRT, (char *)&route);
2592 CloseSocket (s);
2595 void delroute (u_long dest)
2597 int s;
2598 struct ortentry route;
2600 s = socket (AF_INET, SOCK_RAW, 0);
2601 if (s < 0) {
2602 log_error ("Can't create route socket: %m");
2603 return;
2605 memset (&route, 0, sizeof (route));
2606 setaddr ((struct sockaddr_in *)&route.rt_dst, dest, AF_INET);
2607 IoctlSocket (s, SIOCDELRT, (char *)&route);
2608 CloseSocket (s);
2611 void interface_preinit (struct client_state *client)
2613 log_debug ("PREINIT %s", client->interface->name);
2614 if (client -> alias) {
2615 log_debug ("Alias IP: %s", piaddr (client->alias->address));
2616 /* TODO: remove alias and its routes */
2618 /* TODO: clear ARP cache and remove old interface's routes (ifdown ???) */
2619 ifconfig (client->interface->name, INADDR_ANY, INADDR_ANY, INADDR_BROADCAST);
2620 addroute (INADDR_BROADCAST, INADDR_ANY, RTF_UP|RTF_HOST);
2623 int interface_medium (struct client_state *client, char *medium)
2625 log_debug ("MEDIUM %s %s", client->interface->name, medium);
2626 /* TODO */
2627 return 0;
2630 void client_option_dump (struct option_cache *oc,
2631 struct packet *packet, struct lease *lease,
2632 struct client_state *client_state,
2633 struct option_state *in_options,
2634 struct option_state *cfg_options,
2635 struct binding_scope **scope,
2636 struct universe *u, void *stuff)
2638 struct data_string data;
2639 memset (&data, 0, sizeof data);
2641 if (evaluate_option_cache (&data, packet, lease, client_state,
2642 in_options, cfg_options, scope, oc, MDL)) {
2643 if (data.len) {
2644 char name [256];
2645 if (dhcp_option_ev_name (name, sizeof name,
2646 oc -> option)) {
2647 log_debug ("%s: %s", name,
2648 (pretty_print_option
2649 (oc -> option,
2650 data.data, data.len,
2651 0, 0)));
2652 data_string_forget (&data, MDL);
2658 void dump_params (struct client_state *client, struct client_lease *lease)
2660 int i;
2662 log_debug ("ip_address: %s", piaddr (lease -> address));
2664 if (lease -> filename)
2665 log_debug ("filename: %s", lease -> filename);
2667 if (lease -> server_name)
2668 log_debug ("server_name: %s", lease -> server_name);
2670 for (i = 0; i < lease -> options -> universe_count; i++) {
2671 option_space_foreach ((struct packet *)0, (struct lease *)0,
2672 client, (struct option_state *)0,
2673 lease -> options, &global_scope,
2674 universes [i],
2675 0, client_option_dump);
2677 log_debug ("expiry: %d", (int)(lease -> expiry));
2680 int data_cmp (struct data_string *d1, struct data_string *d2)
2682 if (d1->len != d2->len)
2683 return 1;
2684 else {
2685 if (d1->len)
2686 return memcmp (d1->data, d2->data, d1->len);
2687 else
2688 return 0;
2692 int interface_bind (struct client_state *client)
2694 struct data_string data = {0};
2695 struct option_cache *oc;
2696 int i;
2697 u_long old_netmask = INADDR_ANY;
2698 u_long old_broadcast = INADDR_ANY;
2699 struct data_string old_gateways_data = {0};
2700 struct data_string old_hostname_data = {0};
2701 struct data_string old_dns_data = {0};
2702 struct data_string old_domain_data = {0};
2703 u_long new_netmask = INADDR_ANY;
2704 u_long new_broadcast = INADDR_ANY;
2705 struct data_string new_gateways_data = {0};
2706 struct data_string new_hostname_data = {0};
2707 struct data_string new_dns_data = {0};
2708 struct data_string new_domain_data = {0};
2709 short new_ifconfig = 1;
2710 short new_gateways = 1;
2711 short new_hostname = 1;
2712 short new_routes = 1;
2713 short new_dns = 1;
2714 short new_domain = 1;
2716 log_debug ("%s %s", (client -> state == S_REQUESTING
2717 ? "BOUND"
2718 : (client -> state == S_RENEWING
2719 ? "RENEW"
2720 : (client -> state == S_REBOOTING
2721 ? "REBOOT"
2722 : (client -> state == S_REBINDING
2723 ? "REBIND" : "BAD STATE")))), client->interface->name);
2724 if (client -> alias) {
2725 log_debug ("Alias parameters:");
2726 dump_params (client, client -> alias);
2727 /* TODO: process alias */
2730 /* Parse new options */
2731 oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_SUBNET_MASK);
2732 if (oc && evaluate_option_cache (&data, (struct packet *)0,
2733 (struct lease *)0, client,
2734 (struct option_state *)0,
2735 client -> new -> options,
2736 &global_scope, oc, MDL)) {
2737 memcpy (&new_netmask, data.data, 4);
2738 data_string_forget (&data, MDL);
2740 oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_BROADCAST_ADDRESS);
2741 if (oc && evaluate_option_cache (&data, (struct packet *)0,
2742 (struct lease *)0, client,
2743 (struct option_state *)0,
2744 client -> new -> options,
2745 &global_scope, oc, MDL)) {
2746 memcpy (&new_broadcast, data.data, 4);
2747 data_string_forget (&data, MDL);
2749 oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_ROUTERS);
2750 if (oc)
2751 evaluate_option_cache (&new_gateways_data, (struct packet *)0,
2752 (struct lease *)0, client,
2753 (struct option_state *)0,
2754 client -> new -> options,
2755 &global_scope, oc, MDL);
2756 oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_HOST_NAME);
2757 if (oc)
2758 evaluate_option_cache (&new_hostname_data, (struct packet *)0,
2759 (struct lease *)0, client,
2760 (struct option_state *)0,
2761 client -> new -> options,
2762 &global_scope, oc, MDL);
2763 oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_DOMAIN_NAME_SERVERS);
2764 if (oc)
2765 evaluate_option_cache (&new_dns_data, (struct packet *)0,
2766 (struct lease *)0, client,
2767 (struct option_state *)0,
2768 client -> new -> options,
2769 &global_scope, oc, MDL);
2770 oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_DOMAIN_NAME);
2771 if (oc)
2772 evaluate_option_cache (&new_domain_data, (struct packet *)0,
2773 (struct lease *)0, client,
2774 (struct option_state *)0,
2775 client -> new -> options,
2776 &global_scope, oc, MDL);
2777 /* Perform actions depending on our state */
2778 switch (client->state) {
2779 case S_RENEWING:
2780 new_ifconfig = 0;
2781 case S_REBINDING:
2782 if (client -> active) {
2783 log_debug ("Old parameters:");
2784 dump_params (client, client -> active);
2785 } else
2786 log_fatal ("Inconsistent state: old parameters not specified");
2787 if (new_ifconfig) {
2788 oc = lookup_option (&dhcp_universe, client -> active -> options, DHO_SUBNET_MASK);
2789 if (oc && evaluate_option_cache (&data, (struct packet *)0,
2790 (struct lease *)0, client,
2791 (struct option_state *)0,
2792 client -> active -> options,
2793 &global_scope, oc, MDL)) {
2794 memcpy (&old_netmask, data.data, 4);
2795 data_string_forget (&data, MDL);
2797 oc = lookup_option (&dhcp_universe, client -> active -> options, DHO_BROADCAST_ADDRESS);
2798 if (oc && evaluate_option_cache (&data, (struct packet *)0,
2799 (struct lease *)0, client,
2800 (struct option_state *)0,
2801 client -> active -> options,
2802 &global_scope, oc, MDL)) {
2803 memcpy (&old_broadcast, data.data, 4);
2804 data_string_forget (&data, MDL);
2806 if ((addr_eq(client->active->address, client->new->address)) &&
2807 (old_netmask == new_netmask) && (old_broadcast == new_broadcast))
2808 new_ifconfig = 0;
2810 oc = lookup_option (&dhcp_universe, client -> active -> options, DHO_ROUTERS);
2811 if (oc && evaluate_option_cache (&old_gateways_data, (struct packet *)0,
2812 (struct lease *)0, client,
2813 (struct option_state *)0,
2814 client -> active -> options,
2815 &global_scope, oc, MDL)) {
2816 if (!(data_cmp (&new_gateways_data, &old_gateways_data)))
2817 new_gateways = 0;
2818 data_string_forget (&old_gateways_data, MDL);
2820 oc = lookup_option (&dhcp_universe, client -> active -> options, DHO_HOST_NAME);
2821 if (oc && evaluate_option_cache (&old_hostname_data, (struct packet *)0,
2822 (struct lease *)0, client,
2823 (struct option_state *)0,
2824 client -> active -> options,
2825 &global_scope, oc, MDL)) {
2826 if (!(data_cmp (&new_hostname_data, &old_hostname_data)))
2827 new_hostname = 0;
2828 data_string_forget (&old_hostname_data, MDL);
2830 oc = lookup_option (&dhcp_universe, client -> active -> options, DHO_DOMAIN_NAME_SERVERS);
2831 if (oc && evaluate_option_cache (&old_dns_data, (struct packet *)0,
2832 (struct lease *)0, client,
2833 (struct option_state *)0,
2834 client -> active -> options,
2835 &global_scope, oc, MDL)) {
2836 if (!(data_cmp (&new_dns_data, &old_dns_data)))
2837 new_dns = 0;
2838 data_string_forget (&old_dns_data, MDL);
2840 oc = lookup_option (&dhcp_universe, client -> active -> options, DHO_DOMAIN_NAME);
2841 if (oc && evaluate_option_cache (&old_domain_data, (struct packet *)0,
2842 (struct lease *)0, client,
2843 (struct option_state *)0,
2844 client -> active -> options,
2845 &global_scope, oc, MDL)) {
2846 if (!(data_cmp (&new_domain_data, &old_domain_data)))
2847 new_domain = 0;
2848 data_string_forget (&old_domain_data, MDL);
2850 case S_REBOOTING:
2851 case S_REQUESTING:
2852 log_debug ("New parameters:");
2853 dump_params (client, client -> new);
2854 if (new_ifconfig) {
2855 delroute (INADDR_BROADCAST);
2856 ifconfig (client->interface->name, ia2ulong(client->new->address), new_netmask, new_broadcast);
2858 if (new_gateways) {
2859 delroute (INADDR_ANY);
2860 if (new_gateways_data.data)
2861 addroute (INADDR_ANY, htonl(getULong(new_gateways_data.data)), RTF_UP | RTF_GATEWAY);
2862 /* TODO: process all gateways not only first one */
2864 if (new_hostname && new_hostname_data.data) {
2865 log_debug ("New hostname: %s", new_hostname_data.data);
2866 sethostname (new_hostname_data.data, new_hostname_data.len);
2868 /* if (new_routes) {
2869 ***TODO*** add new static routes
2871 if (new_dns) {
2872 ClearDynNameServ();
2873 if (new_dns_data.data) {
2874 struct sockaddr_in ns_addr;
2875 unsigned char *errstr;
2876 u_long *addrs = (u_long *)new_dns_data.data;
2877 int len = new_dns_data.len/4;
2878 ns_addr.sin_len = sizeof(ns_addr);
2879 ns_addr.sin_family = AF_INET;
2880 for (i=0; i<len; i++) {
2881 log_debug ("New DNS server: %s", Inet_NtoA(addrs[i]));
2882 ns_addr.sin_addr.s_addr = addrs[i];
2883 AddDynNameServ((struct sockaddr *)&ns_addr);
2886 EndDynNameServ();
2888 if (new_domain) {
2889 ClearDynDomain();
2890 if (new_domain_data.data) {
2891 log_debug ("New domain name: %s", new_domain_data.data);
2892 AddDynDomain((unsigned char *)new_domain_data.data);
2894 EndDynDomain();
2896 /* TODO: do something with other options (place to some file ?) */
2897 data_string_forget (&new_gateways_data, MDL);
2898 data_string_forget (&new_hostname_data, MDL);
2899 data_string_forget (&new_dns_data, MDL);
2900 data_string_forget (&new_domain_data, MDL);
2901 break;
2902 default:
2903 log_debug ("Inconsistent state: %d", client->state);
2905 return 0;
2908 void interface_expire (struct client_state *client)
2910 log_debug ("EXPIRE %s", client->interface->name);
2911 *** TODO ***
2914 void interface_fail (struct client_state *client)
2916 log_debug ("FAIL %s", client->interface->name);
2917 *** TODO ***
2920 void interface_release (struct client_state *client)
2922 log_debug ("RELEASE %s", client->interface->name);
2923 *** TODO ***
2926 void interface_stop (struct client_state *client)
2928 unsigned char *errstr;
2930 log_debug ("STOP %s", client->interface->name);
2931 ifdeconfig (client->interface->name);
2932 delroute (INADDR_ANY);
2933 ClearDynNameServ();
2934 EndDynNameServ();
2935 ClearDynDomain();
2936 EndDynDomain();
2939 int interface_timeout (struct client_state *client)
2941 log_debug ("TIMEOUT %s", client->interface->name);
2942 /* TODO */
2943 return 1;
2946 #else
2948 /* Variables holding name of script and file pointer for writing to
2949 script. Needless to say, this is not reentrant - only one script
2950 can be invoked at a time. */
2951 char scriptName [256];
2952 FILE *scriptFile;
2954 void script_init (client, reason, medium)
2955 struct client_state *client;
2956 const char *reason;
2957 struct string_list *medium;
2959 struct string_list *sl, *next;
2961 if (client) {
2962 for (sl = client -> env; sl; sl = next) {
2963 next = sl -> next;
2964 dfree (sl, MDL);
2966 client -> env = (struct string_list *)0;
2967 client -> envc = 0;
2969 if (client -> interface) {
2970 client_envadd (client, "", "interface", "%s",
2971 client -> interface -> name);
2973 if (client -> name)
2974 client_envadd (client,
2975 "", "client", "%s", client -> name);
2976 if (medium)
2977 client_envadd (client,
2978 "", "medium", "%s", medium -> string);
2980 client_envadd (client, "", "reason", "%s", reason);
2981 client_envadd (client, "", "pid", "%ld", (long int)getpid ());
2985 struct envadd_state {
2986 struct client_state *client;
2987 const char *prefix;
2990 void client_option_envadd (struct option_cache *oc,
2991 struct packet *packet, struct lease *lease,
2992 struct client_state *client_state,
2993 struct option_state *in_options,
2994 struct option_state *cfg_options,
2995 struct binding_scope **scope,
2996 struct universe *u, void *stuff)
2998 struct envadd_state *es = stuff;
2999 struct data_string data;
3000 memset (&data, 0, sizeof data);
3002 if (evaluate_option_cache (&data, packet, lease, client_state,
3003 in_options, cfg_options, scope, oc, MDL)) {
3004 if (data.len) {
3005 char name [256];
3006 if (dhcp_option_ev_name (name, sizeof name,
3007 oc -> option)) {
3008 client_envadd (es -> client, es -> prefix,
3009 name, "%s",
3010 (pretty_print_option
3011 (oc -> option,
3012 data.data, data.len,
3013 0, 0)));
3014 data_string_forget (&data, MDL);
3020 void script_write_params (client, prefix, lease)
3021 struct client_state *client;
3022 const char *prefix;
3023 struct client_lease *lease;
3025 int i;
3026 struct data_string data;
3027 struct option_cache *oc;
3028 pair *hash;
3029 char *s, *t;
3030 struct envadd_state es;
3032 es.client = client;
3033 es.prefix = prefix;
3035 client_envadd (client,
3036 prefix, "ip_address", "%s", piaddr (lease -> address));
3038 /* For the benefit of Linux (and operating systems which may
3039 have similar needs), compute the network address based on
3040 the supplied ip address and netmask, if provided. Also
3041 compute the broadcast address (the host address all ones
3042 broadcast address, not the host address all zeroes
3043 broadcast address). */
3045 memset (&data, 0, sizeof data);
3046 oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
3047 if (oc && evaluate_option_cache (&data, (struct packet *)0,
3048 (struct lease *)0, client,
3049 (struct option_state *)0,
3050 lease -> options,
3051 &global_scope, oc, MDL)) {
3052 if (data.len > 3) {
3053 struct iaddr netmask, subnet, broadcast;
3055 memcpy (netmask.iabuf, data.data, data.len);
3056 netmask.len = data.len;
3057 data_string_forget (&data, MDL);
3059 subnet = subnet_number (lease -> address, netmask);
3060 if (subnet.len) {
3061 client_envadd (client, prefix, "network_number",
3062 "%s", piaddr (subnet));
3064 oc = lookup_option (&dhcp_universe,
3065 lease -> options,
3066 DHO_BROADCAST_ADDRESS);
3067 if (!oc ||
3068 !(evaluate_option_cache
3069 (&data, (struct packet *)0,
3070 (struct lease *)0, client,
3071 (struct option_state *)0,
3072 lease -> options,
3073 &global_scope, oc, MDL))) {
3074 broadcast = broadcast_addr (subnet, netmask);
3075 if (broadcast.len) {
3076 client_envadd (client,
3077 prefix, "broadcast_address",
3078 "%s", piaddr (broadcast));
3083 data_string_forget (&data, MDL);
3086 if (lease -> filename)
3087 client_envadd (client,
3088 prefix, "filename", "%s", lease -> filename);
3089 if (lease -> server_name)
3090 client_envadd (client, prefix, "server_name",
3091 "%s", lease -> server_name);
3093 for (i = 0; i < lease -> options -> universe_count; i++) {
3094 option_space_foreach ((struct packet *)0, (struct lease *)0,
3095 client, (struct option_state *)0,
3096 lease -> options, &global_scope,
3097 universes [i],
3098 &es, client_option_envadd);
3100 client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry));
3103 int script_go (client)
3104 struct client_state *client;
3106 int rval;
3107 char *scriptName;
3108 char *argv [2];
3109 char **envp;
3110 char *epp [3];
3111 char reason [] = "REASON=NBI";
3112 static char client_path [] = CLIENT_PATH;
3113 int i;
3114 struct string_list *sp, *next;
3115 int pid, wpid, wstatus;
3117 if (client)
3118 scriptName = client -> config -> script_name;
3119 else
3120 scriptName = top_level_config.script_name;
3122 envp = dmalloc (((client ? client -> envc : 2) +
3123 client_env_count + 2) * sizeof (char *), MDL);
3124 if (!envp) {
3125 log_error ("No memory for client script environment.");
3126 return 0;
3128 i = 0;
3129 /* Copy out the environment specified on the command line,
3130 if any. */
3131 for (sp = client_env; sp; sp = sp -> next) {
3132 envp [i++] = sp -> string;
3134 /* Copy out the environment specified by dhclient. */
3135 if (client) {
3136 for (sp = client -> env; sp; sp = sp -> next) {
3137 envp [i++] = sp -> string;
3139 } else {
3140 envp [i++] = reason;
3142 /* Set $PATH. */
3143 envp [i++] = client_path;
3144 envp [i] = (char *)0;
3146 argv [0] = scriptName;
3147 argv [1] = (char *)0;
3149 pid = fork ();
3150 if (pid < 0) {
3151 log_error ("fork: %m");
3152 wstatus = 0;
3153 } else if (pid) {
3154 do {
3155 wpid = wait (&wstatus);
3156 } while (wpid != pid && wpid > 0);
3157 if (wpid < 0) {
3158 log_error ("wait: %m");
3159 wstatus = 0;
3161 } else {
3162 execve (scriptName, argv, envp);
3163 log_error ("execve (%s, ...): %m", scriptName);
3164 exit (0);
3167 if (client) {
3168 for (sp = client -> env; sp; sp = next) {
3169 next = sp -> next;
3170 dfree (sp, MDL);
3172 client -> env = (struct string_list *)0;
3173 client -> envc = 0;
3175 dfree (envp, MDL);
3176 GET_TIME (&cur_time);
3177 return (WIFEXITED (wstatus) ?
3178 WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
3181 void client_envadd (struct client_state *client,
3182 const char *prefix, const char *name, const char *fmt, ...)
3184 char spbuf [1024];
3185 char *s;
3186 unsigned len, i;
3187 struct string_list *val;
3188 va_list list;
3190 va_start (list, fmt);
3191 len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
3192 va_end (list);
3194 val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
3195 len + sizeof *val, MDL);
3196 if (!val)
3197 return;
3198 s = val -> string;
3199 strcpy (s, prefix);
3200 strcat (s, name);
3201 s += strlen (s);
3202 *s++ = '=';
3203 if (len >= sizeof spbuf) {
3204 va_start (list, fmt);
3205 vsnprintf (s, len + 1, fmt, list);
3206 va_end (list);
3207 } else
3208 strcpy (s, spbuf);
3209 val -> next = client -> env;
3210 client -> env = val;
3211 client -> envc++;
3213 #endif
3215 int dhcp_option_ev_name (buf, buflen, option)
3216 char *buf;
3217 size_t buflen;
3218 struct option *option;
3220 int i, j;
3221 const char *s;
3223 j = 0;
3224 if (option -> universe != &dhcp_universe) {
3225 s = option -> universe -> name;
3226 i = 0;
3227 } else {
3228 s = option -> name;
3229 i = 1;
3232 do {
3233 while (*s) {
3234 if (j + 1 == buflen)
3235 return 0;
3236 if (*s == '-')
3237 buf [j++] = '_';
3238 else
3239 buf [j++] = *s;
3240 ++s;
3242 if (!i) {
3243 s = option -> name;
3244 if (j + 1 == buflen)
3245 return 0;
3246 buf [j++] = '_';
3248 ++i;
3249 } while (i != 2);
3251 buf [j] = 0;
3252 return 1;
3255 void go_daemon ()
3257 #ifndef FORK_MISSING
3258 static int state = 0;
3259 int pid;
3260 int i;
3262 /* Don't become a daemon if the user requested otherwise. */
3263 if (no_daemon) {
3264 write_client_pid_file ();
3265 return;
3268 /* Only do it once. */
3269 if (state)
3270 return;
3271 state = 1;
3273 /* Stop logging to stderr... */
3274 log_perror = 0;
3276 /* Become a daemon... */
3277 if ((pid = fork ()) < 0)
3278 log_fatal ("Can't fork daemon: %m");
3279 else if (pid)
3280 exit (0);
3281 /* Become session leader and get pid... */
3282 pid = setsid ();
3284 /* Close standard I/O descriptors. */
3285 close(0);
3286 close(1);
3287 close(2);
3289 /* Reopen them on /dev/null. */
3290 i = open ("/dev/null", O_RDWR);
3291 if (i == 0)
3292 i = open ("/dev/null", O_RDWR);
3293 if (i == 1) {
3294 i = open ("/dev/null", O_RDWR);
3295 log_perror = 0; /* No sense logging to /dev/null. */
3296 } else if (i != -1)
3297 close (i);
3298 #endif
3299 write_client_pid_file ();
3302 void write_client_pid_file ()
3304 FILE *pf;
3305 int pfdesc;
3307 pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
3309 if (pfdesc < 0) {
3310 log_error ("Can't create %s: %m", path_dhclient_pid);
3311 return;
3314 pf = fdopen (pfdesc, "w");
3315 if (!pf)
3316 log_error ("Can't fdopen %s: %m", path_dhclient_pid);
3317 else {
3318 fprintf (pf, "%ld\n", (long)getpid ());
3319 fclose (pf);
3323 void client_location_changed ()
3325 struct interface_info *ip;
3326 struct client_state *client;
3328 for (ip = interfaces; ip; ip = ip -> next) {
3329 for (client = ip -> client; client; client = client -> next) {
3330 switch (client -> state) {
3331 case S_SELECTING:
3332 cancel_timeout (send_discover, client);
3333 break;
3335 case S_BOUND:
3336 cancel_timeout (state_bound, client);
3337 break;
3339 case S_REBOOTING:
3340 case S_REQUESTING:
3341 case S_RENEWING:
3342 cancel_timeout (send_request, client);
3343 break;
3345 case S_INIT:
3346 case S_REBINDING:
3347 case S_STOPPED:
3348 break;
3350 client -> state = S_INIT;
3351 state_reboot (client);
3356 void do_release(client)
3357 struct client_state *client;
3359 struct data_string ds;
3360 struct option_cache *oc;
3362 /* Pick a random xid. */
3363 client -> xid = random ();
3365 /* is there even a lease to release? */
3366 if (client -> active) {
3367 /* Make a DHCPRELEASE packet, and set appropriate per-interface
3368 flags. */
3369 make_release (client, client -> active);
3371 memset (&ds, 0, sizeof ds);
3372 oc = lookup_option (&dhcp_universe,
3373 client -> active -> options,
3374 DHO_DHCP_SERVER_IDENTIFIER);
3375 if (oc &&
3376 evaluate_option_cache (&ds, (struct packet *)0,
3377 (struct lease *)0, client,
3378 (struct option_state *)0,
3379 client -> active -> options,
3380 &global_scope, oc, MDL)) {
3381 if (ds.len > 3) {
3382 memcpy (client -> destination.iabuf,
3383 ds.data, 4);
3384 client -> destination.len = 4;
3385 } else
3386 client -> destination = iaddr_broadcast;
3388 data_string_forget (&ds, MDL);
3389 } else
3390 client -> destination = iaddr_broadcast;
3391 client -> first_sending = cur_time;
3392 client -> interval = client -> config -> initial_interval;
3394 /* Zap the medium list... */
3395 client -> medium = (struct string_list *)0;
3397 /* Send out the first and only DHCPRELEASE packet. */
3398 send_release (client);
3400 #ifdef BUILTIN_IFCONFIG
3401 interface_release (client);
3402 #else
3403 /* Do the client script RELEASE operation. */
3404 script_init (client,
3405 "RELEASE", (struct string_list *)0);
3406 if (client -> alias)
3407 script_write_params (client, "alias_",
3408 client -> alias);
3409 script_write_params (client, "old_", client -> active);
3410 script_go (client);
3411 #endif
3414 /* Cancel any timeouts. */
3415 cancel_timeout (state_bound, client);
3416 cancel_timeout (send_discover, client);
3417 cancel_timeout (state_init, client);
3418 cancel_timeout (send_request, client);
3419 cancel_timeout (state_reboot, client);
3420 client -> state = S_STOPPED;
3423 int dhclient_interface_shutdown_hook (struct interface_info *interface)
3425 do_release (interface -> client);
3427 return 1;
3430 int dhclient_interface_discovery_hook (struct interface_info *tmp)
3432 struct interface_info *last, *ip;
3433 /* See if we can find the client from dummy_interfaces */
3434 last = 0;
3435 for (ip = dummy_interfaces; ip; ip = ip -> next) {
3436 if (!strcmp (ip -> name, tmp -> name)) {
3437 /* Remove from dummy_interfaces */
3438 if (last) {
3439 ip = (struct interface_info *)0;
3440 interface_reference (&ip, last -> next, MDL);
3441 interface_dereference (&last -> next, MDL);
3442 if (ip -> next) {
3443 interface_reference (&last -> next,
3444 ip -> next, MDL);
3445 interface_dereference (&ip -> next,
3446 MDL);
3448 } else {
3449 ip = (struct interface_info *)0;
3450 interface_reference (&ip,
3451 dummy_interfaces, MDL);
3452 interface_dereference (&dummy_interfaces, MDL);
3453 if (ip -> next) {
3454 interface_reference (&dummy_interfaces,
3455 ip -> next, MDL);
3456 interface_dereference (&ip -> next,
3457 MDL);
3460 /* Copy "client" to tmp */
3461 if (ip -> client) {
3462 tmp -> client = ip -> client;
3463 tmp -> client -> interface = tmp;
3465 interface_dereference (&ip, MDL);
3466 break;
3468 last = ip;
3470 return 1;
3473 isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
3475 struct interface_info *ip;
3476 struct client_state *client;
3478 /* This code needs some rethinking. It doesn't test against
3479 a signal name, and it just kind of bulls into doing something
3480 that may or may not be appropriate. */
3482 if (interfaces) {
3483 interface_reference (&interface -> next, interfaces, MDL);
3484 interface_dereference (&interfaces, MDL);
3486 interface_reference (&interfaces, interface, MDL);
3488 discover_interfaces (DISCOVER_UNCONFIGURED);
3490 for (ip = interfaces; ip; ip = ip -> next) {
3491 /* If interfaces were specified, don't configure
3492 interfaces that weren't specified! */
3493 if (ip -> flags & INTERFACE_RUNNING ||
3494 (ip -> flags & (INTERFACE_REQUESTED |
3495 INTERFACE_AUTOMATIC)) !=
3496 INTERFACE_REQUESTED)
3497 continue;
3498 #ifdef BUILTIN_IFCONFIG
3499 interface_preinit (ip -> client);
3500 #else
3501 script_init (ip -> client,
3502 "PREINIT", (struct string_list *)0);
3503 if (ip -> client -> alias)
3504 script_write_params (ip -> client, "alias_",
3505 ip -> client -> alias);
3506 script_go (ip -> client);
3507 #endif
3510 discover_interfaces (interfaces_requested
3511 ? DISCOVER_REQUESTED
3512 : DISCOVER_RUNNING);
3514 for (ip = interfaces; ip; ip = ip -> next) {
3515 if (ip -> flags & INTERFACE_RUNNING)
3516 continue;
3517 ip -> flags |= INTERFACE_RUNNING;
3518 for (client = ip -> client; client; client = client -> next) {
3519 client -> state = S_INIT;
3520 /* Set up a timeout to start the initialization
3521 process. */
3522 add_timeout (cur_time + random () % 5,
3523 state_reboot, client, 0, 0);
3526 return ISC_R_SUCCESS;
3529 /* The client should never receive a relay agent information option,
3530 so if it does, log it and discard it. */
3532 int parse_agent_information_option (packet, len, data)
3533 struct packet *packet;
3534 int len;
3535 u_int8_t *data;
3537 return 1;
3540 /* The client never sends relay agent information options. */
3542 unsigned cons_agent_information_options (cfg_options, outpacket,
3543 agentix, length)
3544 struct option_state *cfg_options;
3545 struct dhcp_packet *outpacket;
3546 unsigned agentix;
3547 unsigned length;
3549 return length;
3552 static void shutdown_exit (void *foo)
3554 exit (0);
3557 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
3558 control_object_state_t newstate)
3560 struct interface_info *ip;
3561 struct client_state *client;
3563 /* Do the right thing for each interface. */
3564 for (ip = interfaces; ip; ip = ip -> next) {
3565 for (client = ip -> client; client; client = client -> next) {
3566 switch (newstate) {
3567 case server_startup:
3568 return ISC_R_SUCCESS;
3570 case server_running:
3571 return ISC_R_SUCCESS;
3573 case server_shutdown:
3574 if (client -> active &&
3575 client -> active -> expiry > cur_time) {
3576 if (client -> config -> do_forward_update)
3577 client_dns_update (client, 0, 0);
3578 do_release (client);
3580 break;
3582 case server_hibernate:
3583 state_stop (client);
3584 break;
3586 case server_awaken:
3587 state_reboot (client);
3588 break;
3592 if (newstate == server_shutdown)
3593 add_timeout (cur_time + 1, shutdown_exit, 0, 0, 0);
3594 return ISC_R_SUCCESS;
3597 /* Called after a timeout if the DNS update failed on the previous try.
3598 Retries the update, and if it times out, schedules a retry after
3599 ten times as long of a wait. */
3601 void client_dns_update_timeout (void *cp)
3603 struct client_state *client = cp;
3604 isc_result_t status;
3606 if (client -> active) {
3607 status = client_dns_update (client, 1,
3608 (client -> active -> renewal -
3609 cur_time));
3610 if (status == ISC_R_TIMEDOUT) {
3611 client -> dns_update_timeout *= 10;
3612 add_timeout (cur_time + client -> dns_update_timeout,
3613 client_dns_update_timeout, client, 0, 0);
3618 /* See if we should do a DNS update, and if so, do it. */
3620 isc_result_t client_dns_update (struct client_state *client, int addp, int ttl)
3622 struct data_string ddns_fqdn, ddns_fwd_name,
3623 ddns_dhcid, client_identifier;
3624 struct option_cache *oc;
3625 int ignorep;
3626 int result;
3627 isc_result_t rcode;
3629 /* If we didn't send an FQDN option, we certainly aren't going to
3630 be doing an update. */
3631 if (!client -> sent_options)
3632 return ISC_R_SUCCESS;
3634 /* If we don't have a lease, we can't do an update. */
3635 if (!client -> active)
3636 return ISC_R_SUCCESS;
3638 /* If we set the no client update flag, don't do the update. */
3639 if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
3640 FQDN_NO_CLIENT_UPDATE)) &&
3641 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
3642 (struct lease *)0, client,
3643 client -> sent_options,
3644 (struct option_state *)0,
3645 &global_scope, oc, MDL))
3646 return ISC_R_SUCCESS;
3648 /* If we set the "server, please update" flag, or didn't set it
3649 to false, don't do the update. */
3650 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
3651 FQDN_SERVER_UPDATE)) ||
3652 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
3653 (struct lease *)0, client,
3654 client -> sent_options,
3655 (struct option_state *)0,
3656 &global_scope, oc, MDL))
3657 return ISC_R_SUCCESS;
3659 /* If no FQDN option was supplied, don't do the update. */
3660 memset (&ddns_fwd_name, 0, sizeof ddns_fwd_name);
3661 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
3662 FQDN_FQDN)) ||
3663 !evaluate_option_cache (&ddns_fwd_name, (struct packet *)0,
3664 (struct lease *)0, client,
3665 client -> sent_options,
3666 (struct option_state *)0,
3667 &global_scope, oc, MDL))
3668 return ISC_R_SUCCESS;
3670 /* Make a dhcid string out of either the client identifier,
3671 if we are sending one, or the interface's MAC address,
3672 otherwise. */
3673 memset (&ddns_dhcid, 0, sizeof ddns_dhcid);
3675 memset (&client_identifier, 0, sizeof client_identifier);
3676 if ((oc = lookup_option (&dhcp_universe, client -> sent_options,
3677 DHO_DHCP_CLIENT_IDENTIFIER)) &&
3678 evaluate_option_cache (&client_identifier, (struct packet *)0,
3679 (struct lease *)0, client,
3680 client -> sent_options,
3681 (struct option_state *)0,
3682 &global_scope, oc, MDL)) {
3683 result = get_dhcid (&ddns_dhcid,
3684 DHO_DHCP_CLIENT_IDENTIFIER,
3685 client_identifier.data,
3686 client_identifier.len);
3687 data_string_forget (&client_identifier, MDL);
3688 } else
3689 result = get_dhcid (&ddns_dhcid, 0,
3690 client -> interface -> hw_address.hbuf,
3691 client -> interface -> hw_address.hlen);
3692 if (!result) {
3693 data_string_forget (&ddns_fwd_name, MDL);
3694 return ISC_R_SUCCESS;
3697 /* Start the resolver, if necessary. */
3698 if (!resolver_inited) {
3699 minires_ninit (&resolver_state);
3700 resolver_inited = 1;
3701 resolver_state.retrans = 1;
3702 resolver_state.retry = 1;
3706 * Perform updates.
3708 if (ddns_fwd_name.len && ddns_dhcid.len) {
3709 if (addp)
3710 rcode = ddns_update_a (&ddns_fwd_name,
3711 client -> active -> address,
3712 &ddns_dhcid, ttl,
3714 else
3715 rcode = ddns_remove_a (&ddns_fwd_name,
3716 client -> active -> address,
3717 &ddns_dhcid);
3718 } else
3719 rcode = ISC_R_FAILURE;
3721 data_string_forget (&ddns_fwd_name, MDL);
3722 data_string_forget (&ddns_dhcid, MDL);
3723 return rcode;