Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / dhcp / client / dhclient.c
blob0fbd63daf54f0fb5d5e7404054bbabc76bbff216
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: dhclient.c,v 1.20 2009/06/23 19:50:50 christos Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
36 #endif /* not lint */
38 #include "dhcpd.h"
39 #include "version.h"
41 TIME default_lease_time = 43200; /* 12 hours... */
42 TIME max_lease_time = 86400; /* 24 hours... */
44 const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
45 const char *path_dhclient_db = _PATH_DHCLIENT_DB;
46 const char *path_dhclient_pid = _PATH_DHCLIENT_PID;
47 static char path_dhclient_script_array [] = _PATH_DHCLIENT_SCRIPT;
48 char *path_dhclient_script = path_dhclient_script_array;
50 int dhcp_max_agent_option_packet_length = 0;
52 int interfaces_requested = 0;
54 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
55 struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
56 struct in_addr inaddr_any;
57 struct sockaddr_in sockaddr_broadcast;
58 struct in_addr giaddr;
60 /* ASSERT_STATE() does nothing now; it used to be
61 assert (state_is == state_shouldbe). */
62 #define ASSERT_STATE(state_is, state_shouldbe) {}
64 static char copyright[] = "Copyright 2004-2005 Internet Systems Consortium.";
65 static char arr [] = "All rights reserved.";
66 static char message [] = "Internet Systems Consortium DHCP Client";
67 static char url [] = "For info, please visit http://www.isc.org/products/DHCP";
69 u_int16_t local_port=0;
70 u_int16_t remote_port=0;
71 int no_daemon=0;
72 struct string_list *client_env=NULL;
73 int client_env_count=0;
74 int onetry=0;
75 int fixed = 0;
76 int quiet=0;
77 int nowait=0;
79 static void usage PROTO ((void));
80 static void limit_interval PROTO((struct client_state *));
82 void do_release(struct client_state *);
84 #if !defined (SMALL)
85 static isc_result_t
86 verify_addr (omapi_object_t *l, omapi_addr_t *addr)
88 return ISC_R_SUCCESS;
91 static isc_result_t
92 verify_auth (omapi_object_t *p, omapi_auth_key_t *a)
94 if (a != top_level_config.omapi_key)
95 return ISC_R_INVALIDKEY;
96 return ISC_R_SUCCESS;
98 #endif
100 int main (argc, argv, envp)
101 int argc;
102 char **argv, **envp;
104 int i;
105 struct servent *ent;
106 struct interface_info *ip;
107 struct client_state *client;
108 unsigned seed;
109 char *server = (char *)0;
110 char *relay = (char *)0;
111 isc_result_t status;
112 int release_mode = 0;
113 omapi_object_t *listener;
114 isc_result_t result;
115 int persist = 0;
116 int no_dhclient_conf = 0;
117 int no_dhclient_db = 0;
118 int no_dhclient_pid = 0;
119 int no_dhclient_script = 0;
120 char *s;
121 FILE *pidfd;
122 long pidfd_pid;
123 int e;
125 /* Make sure we have stdin, stdout and stderr. */
126 i = open ("/dev/null", O_RDWR);
127 if (i == 0)
128 i = open ("/dev/null", O_RDWR);
129 if (i == 1) {
130 i = open ("/dev/null", O_RDWR);
131 log_perror = 0; /* No sense logging to /dev/null. */
132 } else if (i != -1)
133 close (i);
135 #ifdef SYSLOG_4_2
136 openlog ("dhclient", LOG_NDELAY);
137 log_priority = LOG_DAEMON;
138 #else
139 openlog ("dhclient", LOG_NDELAY, LOG_DAEMON);
140 #endif
142 #if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__))
143 setlogmask (LOG_UPTO (LOG_INFO));
144 #endif
146 /* Set up the OMAPI. */
147 status = omapi_init ();
148 if (status != ISC_R_SUCCESS)
149 log_fatal ("Can't initialize OMAPI: %s",
150 isc_result_totext (status));
152 /* Set up the OMAPI wrappers for various server database internal
153 objects. */
154 dhcp_common_objects_setup ();
156 dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
157 dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
158 dhcp_interface_startup_hook = dhclient_interface_startup_hook;
160 for (i = 1; i < argc; i++) {
161 if (!strcmp (argv [i], "-r")) {
162 release_mode = 1;
163 no_daemon = 1;
164 } else if (!strcmp (argv [i], "-p")) {
165 if (++i == argc)
166 usage ();
167 local_port = htons (atoi (argv [i]));
168 log_debug ("binding to user-specified port %d",
169 ntohs (local_port));
170 } else if (!strcmp (argv [i], "-d")) {
171 no_daemon = 1;
172 } else if (!strcmp (argv [i], "-pf")) {
173 if (++i == argc)
174 usage ();
175 path_dhclient_pid = argv [i];
176 no_dhclient_pid = 1;
177 } else if (!strcmp (argv [i], "-cf")) {
178 if (++i == argc)
179 usage ();
180 path_dhclient_conf = argv [i];
181 no_dhclient_conf = 1;
182 } else if (!strcmp (argv [i], "-lf")) {
183 if (++i == argc)
184 usage ();
185 path_dhclient_db = argv [i];
186 no_dhclient_db = 1;
187 } else if (!strcmp (argv [i], "-sf")) {
188 if (++i == argc)
189 usage ();
190 path_dhclient_script = argv [i];
191 no_dhclient_script = 1;
192 } else if (!strcmp (argv [i], "-o")) {
193 fixed = 1;
194 } else if (!strcmp (argv [i], "-1")) {
195 onetry = 1;
196 } else if (!strcmp (argv [i], "-q")) {
197 quiet = 1;
198 quiet_interface_discovery = 1;
199 } else if (!strcmp (argv [i], "-s")) {
200 if (++i == argc)
201 usage ();
202 server = argv [i];
203 } else if (!strcmp (argv [i], "-g")) {
204 if (++i == argc)
205 usage ();
206 relay = argv [i];
207 } else if (!strcmp (argv [i], "-nw")) {
208 nowait = 1;
209 } else if (!strcmp (argv [i], "-n")) {
210 /* do not start up any interfaces */
211 interfaces_requested = 1;
212 } else if (!strcmp (argv [i], "-w")) {
213 /* do not exit if there are no broadcast interfaces. */
214 persist = 1;
215 } else if (!strcmp (argv [i], "-e")) {
216 struct string_list *tmp;
217 if (++i == argc)
218 usage ();
219 tmp = dmalloc (strlen (argv [i]) + sizeof *tmp, MDL);
220 if (!tmp)
221 log_fatal ("No memory for %s", argv [i]);
222 strcpy (tmp -> string, argv [i]);
223 tmp -> next = client_env;
224 client_env = tmp;
225 client_env_count++;
226 } else if (!strcmp (argv [i], "--version")) {
227 log_info ("isc-dhclient-%s", DHCP_VERSION);
228 exit (0);
229 } else if (argv [i][0] == '-') {
230 usage ();
231 } else {
232 struct interface_info *tmp = (struct interface_info *)0;
233 status = interface_allocate (&tmp, MDL);
234 if (status != ISC_R_SUCCESS)
235 log_fatal ("Can't record interface %s:%s",
236 argv [i], isc_result_totext (status));
237 if (strlen (argv [i]) > sizeof tmp -> name)
238 log_fatal ("%s: interface name too long (max %lu)",
239 argv [i],
240 (unsigned long)sizeof tmp -> name);
241 strcpy (tmp -> name, argv [i]);
242 if (interfaces) {
243 interface_reference (&tmp -> next,
244 interfaces, MDL);
245 interface_dereference (&interfaces, MDL);
247 interface_reference (&interfaces, tmp, MDL);
248 tmp -> flags = INTERFACE_REQUESTED;
249 interfaces_requested = 1;
253 if (!no_dhclient_conf && (s = getenv ("PATH_DHCLIENT_CONF"))) {
254 path_dhclient_conf = s;
256 if (!no_dhclient_db && (s = getenv ("PATH_DHCLIENT_DB"))) {
257 path_dhclient_db = s;
259 if (!no_dhclient_pid && (s = getenv ("PATH_DHCLIENT_PID"))) {
260 path_dhclient_pid = s;
262 if (!no_dhclient_script && (s = getenv ("PATH_DHCLIENT_SCRIPT"))) {
263 path_dhclient_script = s;
266 if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) {
267 e = fscanf(pidfd, "%ld\n", &pidfd_pid);
268 fclose(pidfd);
270 if (e != 0 && e != EOF && pidfd_pid) {
271 if (release_mode) {
272 if (kill((pid_t)pidfd_pid, SIGTERM) == 0)
273 unlink(path_dhclient_pid);
274 } else if (kill((pid_t)pidfd_pid, 0) == 0)
275 log_fatal("dhclient[%li] is already running",
276 pidfd_pid);
280 /* This isn't the final pid, but it may be needed so that
281 * /etc/rc.d/dhclient can kill the client before it's done with
282 * initially configuring an interface.
284 write_client_pid_file();
286 if (!quiet) {
287 log_info ("%s %s", message, DHCP_VERSION);
288 log_info (copyright);
289 log_info (arr);
290 log_info (url);
291 log_info ("%s", "");
292 } else
293 log_perror = 0;
295 /* If we're given a relay agent address to insert, for testing
296 purposes, figure out what it is. */
297 if (relay) {
298 if (!inet_aton (relay, &giaddr)) {
299 struct hostent *he;
300 he = gethostbyname (relay);
301 if (he) {
302 memcpy (&giaddr, he -> h_addr_list [0],
303 sizeof giaddr);
304 } else {
305 log_fatal ("%s: no such host", relay);
310 /* Default to the DHCP/BOOTP port. */
311 if (!local_port) {
312 /* If we're faking a relay agent, and we're not using loopback,
313 use the server port, not the client port. */
314 if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
315 local_port = htons(67);
316 } else {
317 ent = getservbyname ("dhcpc", "udp");
318 if (!ent)
319 local_port = htons (68);
320 else
321 local_port = ent -> s_port;
322 #ifndef __CYGWIN32__
323 endservent ();
324 #endif
328 /* If we're faking a relay agent, and we're not using loopback,
329 we're using the server port, not the client port. */
330 if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
331 remote_port = local_port;
332 } else
333 remote_port = htons (ntohs (local_port) - 1); /* XXX */
335 /* Get the current time... */
336 GET_TIME (&cur_time);
338 memset(&sockaddr_broadcast, 0, sizeof(sockaddr_broadcast));
339 sockaddr_broadcast.sin_family = AF_INET;
340 sockaddr_broadcast.sin_port = remote_port;
341 if (server) {
342 if (!inet_aton (server, &sockaddr_broadcast.sin_addr)) {
343 struct hostent *he;
344 he = gethostbyname (server);
345 if (he) {
346 memcpy (&sockaddr_broadcast.sin_addr,
347 he -> h_addr_list [0],
348 sizeof sockaddr_broadcast.sin_addr);
349 } else
350 sockaddr_broadcast.sin_addr.s_addr =
351 INADDR_BROADCAST;
353 } else {
354 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
357 inaddr_any.s_addr = INADDR_ANY;
359 /* Discover all the network interfaces. */
360 discover_interfaces (DISCOVER_UNCONFIGURED);
362 /* Parse the dhclient.conf file. */
363 read_client_conf ();
365 /* Parse the lease database. */
366 read_client_leases ();
368 /* Rewrite the lease database... */
369 rewrite_client_leases ();
371 /* XXX */
372 /* config_counter(&snd_counter, &rcv_counter); */
374 /* If no broadcast interfaces were discovered, call the script
375 and tell it so. */
376 if (!interfaces) {
377 /* Call dhclient-script with the NBI flag, in case somebody
378 cares. */
379 script_init ((struct client_state *)0, "NBI",
380 (struct string_list *)0);
381 script_go ((struct client_state *)0);
383 /* If we haven't been asked to persist, waiting for new
384 interfaces, then just exit. */
385 if (!persist) {
386 /* Nothing more to do. */
387 log_info ("No broadcast interfaces found - exiting.");
388 exit (0);
390 } else if (!release_mode) {
391 /* Call the script with the list of interfaces. */
392 for (ip = interfaces; ip; ip = ip -> next) {
393 /* If interfaces were specified, don't configure
394 interfaces that weren't specified! */
395 if (interfaces_requested &&
396 ((ip -> flags & (INTERFACE_REQUESTED |
397 INTERFACE_AUTOMATIC)) !=
398 INTERFACE_REQUESTED))
399 continue;
400 script_init (ip -> client,
401 "PREINIT", (struct string_list *)0);
402 if (ip -> client -> alias)
403 script_write_params (ip -> client, "alias_",
404 ip -> client -> alias);
405 script_go (ip -> client);
409 /* At this point, all the interfaces that the script thinks
410 are relevant should be running, so now we once again call
411 discover_interfaces(), and this time ask it to actually set
412 up the interfaces. */
413 discover_interfaces (interfaces_requested
414 ? DISCOVER_REQUESTED
415 : DISCOVER_RUNNING);
417 /* Make up a seed for the random number generator from current
418 time plus the sum of the last four bytes of each
419 interface's hardware address interpreted as an integer.
420 Not much entropy, but we're booting, so we're not likely to
421 find anything better. */
422 seed = 0;
423 for (ip = interfaces; ip; ip = ip -> next) {
424 int junk;
425 memcpy (&junk,
426 &ip -> hw_address.hbuf [ip -> hw_address.hlen -
427 sizeof seed], sizeof seed);
428 seed += junk;
430 srandom (seed + cur_time);
432 /* Start a configuration state machine for each interface. */
433 for (ip = interfaces; ip; ip = ip -> next) {
434 ip -> flags |= INTERFACE_RUNNING;
435 for (client = ip -> client; client; client = client -> next) {
436 if (release_mode)
437 do_release (client);
438 else {
439 client -> state = S_INIT;
440 /* Set up a timeout to start the initialization
441 process. */
442 add_timeout (cur_time + random () % 5,
443 state_reboot, client, 0, 0);
448 if (release_mode)
449 return 0;
451 #if !defined (SMALL)
452 /* Start up a listener for the object management API protocol. */
453 if (top_level_config.omapi_port != -1) {
454 listener = (omapi_object_t *)0;
455 result = omapi_generic_new (&listener, MDL);
456 if (result != ISC_R_SUCCESS)
457 log_fatal ("Can't allocate new generic object: %s\n",
458 isc_result_totext (result));
459 result = (omapi_protocol_listen
460 (listener,
461 (unsigned)top_level_config.omapi_port, 1));
462 if (result == ISC_R_SUCCESS && top_level_config.omapi_key)
463 result = (omapi_protocol_configure_security
464 (listener, verify_addr, verify_auth));
465 if (result != ISC_R_SUCCESS)
466 log_fatal ("Can't start OMAPI protocol: %s",
467 isc_result_totext (result));
469 #endif
471 /* Set up the bootp packet handler... */
472 bootp_packet_handler = do_packet;
474 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
475 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
476 dmalloc_cutoff_generation = dmalloc_generation;
477 dmalloc_longterm = dmalloc_outstanding;
478 dmalloc_outstanding = 0;
479 #endif
481 /* If we're not supposed to wait before getting the address,
482 don't. */
483 if (nowait)
484 go_daemon ();
486 /* If we're not going to daemonize, write the pid file
487 now. */
488 if (no_daemon || nowait)
489 write_client_pid_file ();
491 /* Start dispatching packets and timeouts... */
492 dispatch ();
494 /*NOTREACHED*/
495 return 0;
498 static void usage ()
500 log_info ("%s %s", message, DHCP_VERSION);
501 log_info (copyright);
502 log_info (arr);
503 log_info (url);
505 log_error ("Usage: dhclient [-1dqr] [-nw] [-p <port>] %s",
506 "[-s server]");
507 log_error (" [-cf config-file] [-lf lease-file]%s",
508 "[-pf pid-file] [-e VAR=val]");
509 log_fatal (" [-sf script-file] [interface]");
512 isc_result_t find_class (struct class **c,
513 const char *s, const char *file, int line)
515 return 0;
518 int check_collection (packet, lease, collection)
519 struct packet *packet;
520 struct lease *lease;
521 struct collection *collection;
523 return 0;
526 void classify (packet, class)
527 struct packet *packet;
528 struct class *class;
532 int unbill_class (lease, class)
533 struct lease *lease;
534 struct class *class;
536 return 0;
539 int find_subnet (struct subnet **sp,
540 struct iaddr addr, const char *file, int line)
542 return 0;
545 /* Individual States:
547 * Each routine is called from the dhclient_state_machine() in one of
548 * these conditions:
549 * -> entering INIT state
550 * -> recvpacket_flag == 0: timeout in this state
551 * -> otherwise: received a packet in this state
553 * Return conditions as handled by dhclient_state_machine():
554 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
555 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
556 * Returns 0: finish the nap which was interrupted for no good reason.
558 * Several per-interface variables are used to keep track of the process:
559 * active_lease: the lease that is being used on the interface
560 * (null pointer if not configured yet).
561 * offered_leases: leases corresponding to DHCPOFFER messages that have
562 * been sent to us by DHCP servers.
563 * acked_leases: leases corresponding to DHCPACK messages that have been
564 * sent to us by DHCP servers.
565 * sendpacket: DHCP packet we're trying to send.
566 * destination: IP address to send sendpacket to
567 * In addition, there are several relevant per-lease variables.
568 * T1_expiry, T2_expiry, lease_expiry: lease milestones
569 * In the active lease, these control the process of renewing the lease;
570 * In leases on the acked_leases list, this simply determines when we
571 * can no longer legitimately use the lease.
574 void state_reboot (cpp)
575 void *cpp;
577 struct client_state *client = cpp;
579 /* If we don't remember an active lease, go straight to INIT. */
580 if (!client -> active ||
581 client -> active -> is_bootp ||
582 client -> active -> expiry <= cur_time) {
583 state_init (client);
584 return;
587 /* We are in the rebooting state. */
588 client -> state = S_REBOOTING;
590 /* make_request doesn't initialize xid because it normally comes
591 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
592 so pick an xid now. */
593 client -> xid = random ();
595 /* Make a DHCPREQUEST packet, and set appropriate per-interface
596 flags. */
597 make_request (client, client -> active);
598 client -> destination = iaddr_broadcast;
599 client -> first_sending = cur_time;
600 client -> interval = client -> config -> initial_interval;
602 /* Zap the medium list... */
603 client -> medium = (struct string_list *)0;
605 /* Send out the first DHCPREQUEST packet. */
606 send_request (client);
609 /* Called when a lease has completely expired and we've been unable to
610 renew it. */
612 void state_init (cpp)
613 void *cpp;
615 struct client_state *client = cpp;
617 ASSERT_STATE(state, S_INIT);
619 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
620 flags. */
621 make_discover (client, client -> active);
622 client -> xid = client -> packet.xid;
623 client -> destination = iaddr_broadcast;
624 client -> state = S_SELECTING;
625 client -> first_sending = cur_time;
626 client -> interval = client -> config -> initial_interval;
628 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
629 to go out. */
630 send_discover (client);
633 /* state_selecting is called when one or more DHCPOFFER packets have been
634 received and a configurable period of time has passed. */
636 void state_selecting (cpp)
637 void *cpp;
639 struct client_state *client = cpp;
640 struct client_lease *lp, *next, *picked;
643 ASSERT_STATE(state, S_SELECTING);
645 /* Cancel state_selecting and send_discover timeouts, since either
646 one could have got us here. */
647 cancel_timeout (state_selecting, client);
648 cancel_timeout (send_discover, client);
650 /* We have received one or more DHCPOFFER packets. Currently,
651 the only criterion by which we judge leases is whether or
652 not we get a response when we arp for them. */
653 picked = (struct client_lease *)0;
654 for (lp = client -> offered_leases; lp; lp = next) {
655 next = lp -> next;
657 /* Check to see if we got an ARPREPLY for the address
658 in this particular lease. */
659 if (!picked) {
660 picked = lp;
661 picked -> next = (struct client_lease *)0;
662 } else {
663 destroy_client_lease (lp);
666 client -> offered_leases = (struct client_lease *)0;
668 /* If we just tossed all the leases we were offered, go back
669 to square one. */
670 if (!picked) {
671 client -> state = S_INIT;
672 state_init (client);
673 return;
676 /* If it was a BOOTREPLY, we can just take the address right now. */
677 if (picked -> is_bootp) {
678 client -> new = picked;
680 /* Make up some lease expiry times
681 XXX these should be configurable. */
682 client -> new -> expiry = cur_time + 12000;
683 client -> new -> renewal += cur_time + 8000;
684 client -> new -> rebind += cur_time + 10000;
686 client -> state = S_REQUESTING;
688 /* Bind to the address we received. */
689 bind_lease (client);
690 return;
693 /* Go to the REQUESTING state. */
694 client -> destination = iaddr_broadcast;
695 client -> state = S_REQUESTING;
696 client -> first_sending = cur_time;
697 client -> interval = client -> config -> initial_interval;
699 /* Make a DHCPREQUEST packet from the lease we picked. */
700 make_request (client, picked);
701 client -> xid = client -> packet.xid;
703 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
704 destroy_client_lease (picked);
706 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
707 send_request (client);
710 /* state_requesting is called when we receive a DHCPACK message after
711 having sent out one or more DHCPREQUEST packets. */
713 void dhcpack (packet)
714 struct packet *packet;
716 struct interface_info *ip = packet -> interface;
717 struct client_state *client;
718 struct client_lease *lease;
719 struct option_cache *oc;
720 struct data_string ds;
722 /* If we're not receptive to an offer right now, or if the offer
723 has an unrecognizable transaction id, then just drop it. */
724 for (client = ip -> client; client; client = client -> next) {
725 if (client -> xid == packet -> raw -> xid)
726 break;
728 if (!client ||
729 (packet -> interface -> hw_address.hlen - 1 !=
730 packet -> raw -> hlen) ||
731 (memcmp (&packet -> interface -> hw_address.hbuf [1],
732 packet -> raw -> chaddr, packet -> raw -> hlen))) {
733 #if defined (DEBUG)
734 log_debug ("DHCPACK in wrong transaction.");
735 #endif
736 return;
739 if (client -> state != S_REBOOTING &&
740 client -> state != S_REQUESTING &&
741 client -> state != S_RENEWING &&
742 client -> state != S_REBINDING) {
743 #if defined (DEBUG)
744 log_debug ("DHCPACK in wrong state.");
745 #endif
746 return;
749 log_info ("DHCPACK from %s", piaddr (packet -> client_addr));
751 lease = packet_to_lease (packet, client);
752 if (!lease) {
753 log_info ("packet_to_lease failed.");
754 return;
757 client -> new = lease;
759 /* Stop resending DHCPREQUEST. */
760 cancel_timeout (send_request, client);
762 /* Figure out the lease time. */
763 oc = lookup_option (&dhcp_universe, client -> new -> options,
764 DHO_DHCP_LEASE_TIME);
765 memset (&ds, 0, sizeof ds);
766 if (oc &&
767 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
768 packet -> options, client -> new -> options,
769 &global_scope, oc, MDL)) {
770 if (ds.len > 3)
771 client -> new -> expiry = getULong (ds.data);
772 else
773 client -> new -> expiry = 0;
774 data_string_forget (&ds, MDL);
775 } else
776 client -> new -> expiry = 0;
778 if (!client -> new -> expiry) {
779 log_error ("no expiry time on offered lease.");
780 /* XXX this is going to be bad - if this _does_
781 XXX happen, we should probably dynamically
782 XXX disqualify the DHCP server that gave us the
783 XXX bad packet from future selections and
784 XXX then go back into the init state. */
785 state_init (client);
786 return;
789 /* A number that looks negative here is really just very large,
790 because the lease expiry offset is unsigned. */
791 if (client -> new -> expiry < 0)
792 client -> new -> expiry = TIME_MAX;
793 /* Take the server-provided renewal time if there is one. */
794 oc = lookup_option (&dhcp_universe, client -> new -> options,
795 DHO_DHCP_RENEWAL_TIME);
796 if (oc &&
797 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
798 packet -> options, client -> new -> options,
799 &global_scope, oc, MDL)) {
800 if (ds.len > 3)
801 client -> new -> renewal = getULong (ds.data);
802 else
803 client -> new -> renewal = 0;
804 data_string_forget (&ds, MDL);
805 } else
806 client -> new -> renewal = 0;
808 /* If it wasn't specified by the server, calculate it. */
809 if (!client -> new -> renewal)
810 client -> new -> renewal = client -> new -> expiry / 2 + 1;
812 if (client -> new -> renewal <= 0)
813 client -> new -> renewal = TIME_MAX;
815 /* Now introduce some randomness to the renewal time: */
816 if (client -> new -> renewal <= TIME_MAX / 3 - 3)
817 client -> new -> renewal =
818 (((client -> new -> renewal + 3) * 3 / 4) +
819 (random () % /* XXX NUMS */
820 ((client -> new -> renewal + 3) / 4)));
822 /* Same deal with the rebind time. */
823 oc = lookup_option (&dhcp_universe, client -> new -> options,
824 DHO_DHCP_REBINDING_TIME);
825 if (oc &&
826 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
827 packet -> options, client -> new -> options,
828 &global_scope, oc, MDL)) {
829 if (ds.len > 3)
830 client -> new -> rebind = getULong (ds.data);
831 else
832 client -> new -> rebind = 0;
833 data_string_forget (&ds, MDL);
834 } else
835 client -> new -> rebind = 0;
837 if (client -> new -> rebind <= 0) {
838 if (client -> new -> expiry <= TIME_MAX / 7)
839 client -> new -> rebind =
840 client -> new -> expiry * 7 / 8;
841 else
842 client -> new -> rebind =
843 client -> new -> expiry / 8 * 7;
846 /* Make sure our randomness didn't run the renewal time past the
847 rebind time. */
848 if (client -> new -> renewal > client -> new -> rebind) {
849 if (client -> new -> rebind <= TIME_MAX / 3)
850 client -> new -> renewal =
851 client -> new -> rebind * 3 / 4;
852 else
853 client -> new -> renewal =
854 client -> new -> rebind / 4 * 3;
857 client -> new -> expiry += cur_time;
858 /* Lease lengths can never be negative. */
859 if (client -> new -> expiry < cur_time)
860 client -> new -> expiry = TIME_MAX;
861 client -> new -> renewal += cur_time;
862 if (client -> new -> renewal < cur_time)
863 client -> new -> renewal = TIME_MAX;
864 client -> new -> rebind += cur_time;
865 if (client -> new -> rebind < cur_time)
866 client -> new -> rebind = TIME_MAX;
868 bind_lease (client);
871 void bind_lease (client)
872 struct client_state *client;
875 /* Remember the medium. */
876 client -> new -> medium = client -> medium;
878 /* Run the client script with the new parameters. */
879 script_init (client, (client -> state == S_REQUESTING
880 ? "BOUND"
881 : (client -> state == S_RENEWING
882 ? "RENEW"
883 : (client -> state == S_REBOOTING
884 ? "REBOOT" : "REBIND"))),
885 client -> new -> medium);
886 if (client -> active && client -> state != S_REBOOTING)
887 script_write_params (client, "old_", client -> active);
888 script_write_params (client, "new_", client -> new);
889 if (client -> alias)
890 script_write_params (client, "alias_", client -> alias);
892 /* If the BOUND/RENEW code detects another machine using the
893 offered address, it exits nonzero. We need to send a
894 DHCPDECLINE and toss the lease. */
895 if (script_go (client)) {
896 make_decline (client, client -> new);
897 send_decline (client);
898 destroy_client_lease (client -> new);
899 client -> new = (struct client_lease *)0;
900 state_init (client);
901 return;
904 /* Write out the new lease. */
905 write_client_lease (client, client -> new, 0, 0);
907 /* Replace the old active lease with the new one. */
908 if (client -> active)
909 destroy_client_lease (client -> active);
910 client -> active = client -> new;
911 client -> new = (struct client_lease *)0;
913 /* Set up a timeout to start the renewal process. */
914 add_timeout (client -> active -> renewal,
915 state_bound, client, 0, 0);
917 log_info ("bound to %s -- renewal in %ld seconds.",
918 piaddr (client -> active -> address),
919 (long)(client -> active -> renewal - cur_time));
920 client -> state = S_BOUND;
921 reinitialize_interfaces ();
922 if (fixed) {
923 unlink(_PATH_DHCLIENT_PID);
924 exit(0);
926 go_daemon ();
927 if (client -> config -> do_forward_update) {
928 client -> dns_update_timeout = 1;
929 add_timeout (cur_time + 1, client_dns_update_timeout,
930 client, 0, 0);
934 /* state_bound is called when we've successfully bound to a particular
935 lease, but the renewal time on that lease has expired. We are
936 expected to unicast a DHCPREQUEST to the server that gave us our
937 original lease. */
939 void state_bound (cpp)
940 void *cpp;
942 struct client_state *client = cpp;
943 struct option_cache *oc;
944 struct data_string ds;
946 ASSERT_STATE(state, S_BOUND);
948 /* T1 has expired. */
949 make_request (client, client -> active);
950 client -> xid = client -> packet.xid;
952 memset (&ds, 0, sizeof ds);
953 oc = lookup_option (&dhcp_universe, client -> active -> options,
954 DHO_DHCP_SERVER_IDENTIFIER);
955 if (oc &&
956 evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
957 client, (struct option_state *)0,
958 client -> active -> options,
959 &global_scope, oc, MDL)) {
960 if (ds.len > 3) {
961 memcpy (client -> destination.iabuf, ds.data, 4);
962 client -> destination.len = 4;
963 } else
964 client -> destination = iaddr_broadcast;
966 data_string_forget (&ds, MDL);
967 } else
968 client -> destination = iaddr_broadcast;
970 client -> first_sending = cur_time;
971 client -> interval = client -> config -> initial_interval;
972 client -> state = S_RENEWING;
974 /* Send the first packet immediately. */
975 send_request (client);
978 /* state_stop is called when we've been told to shut down. We unconfigure
979 the interfaces, and then stop operating until told otherwise. */
981 void state_stop (cpp)
982 void *cpp;
984 struct client_state *client = cpp;
986 /* Cancel all timeouts. */
987 cancel_timeout (state_selecting, client);
988 cancel_timeout (send_discover, client);
989 cancel_timeout (send_request, client);
990 cancel_timeout (state_bound, client);
992 /* If we have an address, unconfigure it. */
993 if (client -> active) {
994 script_init (client, "STOP", client -> active -> medium);
995 script_write_params (client, "old_", client -> active);
996 if (client -> alias)
997 script_write_params (client, "alias_",
998 client -> alias);
999 script_go (client);
1003 int commit_leases ()
1005 return 0;
1008 int write_lease (lease)
1009 struct lease *lease;
1011 return 0;
1014 int write_host (host)
1015 struct host_decl *host;
1017 return 0;
1020 void db_startup (testp)
1021 int testp;
1025 void bootp (packet)
1026 struct packet *packet;
1028 struct iaddrlist *ap;
1030 if (packet -> raw -> op != BOOTREPLY)
1031 return;
1033 /* If there's a reject list, make sure this packet's sender isn't
1034 on it. */
1035 for (ap = packet -> interface -> client -> config -> reject_list;
1036 ap; ap = ap -> next) {
1037 if (addr_eq (packet -> client_addr, ap -> addr)) {
1038 log_info ("BOOTREPLY from %s rejected.",
1039 piaddr (ap -> addr));
1040 return;
1044 dhcpoffer (packet);
1048 void dhcp (packet)
1049 struct packet *packet;
1051 struct iaddrlist *ap;
1052 void (*handler) PROTO ((struct packet *));
1053 const char *type;
1055 switch (packet -> packet_type) {
1056 case DHCPOFFER:
1057 handler = dhcpoffer;
1058 type = "DHCPOFFER";
1059 break;
1061 case DHCPNAK:
1062 handler = dhcpnak;
1063 type = "DHCPNACK";
1064 break;
1066 case DHCPACK:
1067 handler = dhcpack;
1068 type = "DHCPACK";
1069 break;
1071 default:
1072 return;
1075 /* If there's a reject list, make sure this packet's sender isn't
1076 on it. */
1077 for (ap = packet -> interface -> client -> config -> reject_list;
1078 ap; ap = ap -> next) {
1079 if (addr_eq (packet -> client_addr, ap -> addr)) {
1080 log_info ("%s from %s rejected.",
1081 type, piaddr (ap -> addr));
1082 return;
1085 (*handler) (packet);
1088 void dhcpoffer (packet)
1089 struct packet *packet;
1091 struct interface_info *ip = packet -> interface;
1092 struct client_state *client;
1093 struct client_lease *lease, *lp;
1094 int i;
1095 int stop_selecting;
1096 const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
1097 char obuf [1024];
1099 #ifdef DEBUG_PACKET
1100 dump_packet (packet);
1101 #endif
1103 /* Find a client state that matches the xid... */
1104 for (client = ip -> client; client; client = client -> next)
1105 if (client -> xid == packet -> raw -> xid)
1106 break;
1108 /* If we're not receptive to an offer right now, or if the offer
1109 has an unrecognizable transaction id, then just drop it. */
1110 if (!client ||
1111 client -> state != S_SELECTING ||
1112 (packet -> interface -> hw_address.hlen - 1 !=
1113 packet -> raw -> hlen) ||
1114 (memcmp (&packet -> interface -> hw_address.hbuf [1],
1115 packet -> raw -> chaddr, packet -> raw -> hlen))) {
1116 #if defined (DEBUG)
1117 log_debug ("%s in wrong transaction.", name);
1118 #endif
1119 return;
1122 sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
1125 /* If this lease doesn't supply the minimum required parameters,
1126 blow it off. */
1127 if (client -> config -> required_options) {
1128 for (i = 0; client -> config -> required_options [i]; i++) {
1129 if (!lookup_option
1130 (&dhcp_universe, packet -> options,
1131 client -> config -> required_options [i])) {
1132 log_info ("%s: no %s option.",
1133 obuf, (dhcp_universe.options
1134 [client -> config -> required_options [i]]
1135 -> name));
1136 return;
1141 /* If we've already seen this lease, don't record it again. */
1142 for (lease = client -> offered_leases; lease; lease = lease -> next) {
1143 if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
1144 !memcmp (lease -> address.iabuf,
1145 &packet -> raw -> yiaddr, lease -> address.len)) {
1146 log_debug ("%s: already seen.", obuf);
1147 return;
1151 lease = packet_to_lease (packet, client);
1152 if (!lease) {
1153 log_info ("%s: packet_to_lease failed.", obuf);
1154 return;
1157 /* If this lease was acquired through a BOOTREPLY, record that
1158 fact. */
1159 if (!packet -> options_valid || !packet -> packet_type)
1160 lease -> is_bootp = 1;
1162 /* Record the medium under which this lease was offered. */
1163 lease -> medium = client -> medium;
1165 /* Figure out when we're supposed to stop selecting. */
1166 stop_selecting = (client -> first_sending +
1167 client -> config -> select_interval);
1169 /* If this is the lease we asked for, put it at the head of the
1170 list, and don't mess with the arp request timeout. */
1171 if (lease -> address.len == client -> requested_address.len &&
1172 !memcmp (lease -> address.iabuf,
1173 client -> requested_address.iabuf,
1174 client -> requested_address.len)) {
1175 lease -> next = client -> offered_leases;
1176 client -> offered_leases = lease;
1177 } else {
1178 /* Put the lease at the end of the list. */
1179 lease -> next = (struct client_lease *)0;
1180 if (!client -> offered_leases)
1181 client -> offered_leases = lease;
1182 else {
1183 for (lp = client -> offered_leases; lp -> next;
1184 lp = lp -> next)
1186 lp -> next = lease;
1190 /* If the selecting interval has expired, go immediately to
1191 state_selecting(). Otherwise, time out into
1192 state_selecting at the select interval. */
1193 if (stop_selecting <= 0)
1194 state_selecting (client);
1195 else {
1196 add_timeout (stop_selecting, state_selecting, client, 0, 0);
1197 cancel_timeout (send_discover, client);
1199 log_info ("%s", obuf);
1202 /* Allocate a client_lease structure and initialize it from the parameters
1203 in the specified packet. */
1205 struct client_lease *packet_to_lease (packet, client)
1206 struct packet *packet;
1207 struct client_state *client;
1209 struct client_lease *lease;
1210 unsigned i;
1211 struct option_cache *oc;
1212 struct data_string data;
1214 lease = (struct client_lease *)new_client_lease (MDL);
1216 if (!lease) {
1217 log_error ("packet_to_lease: no memory to record lease.\n");
1218 return (struct client_lease *)0;
1221 memset (lease, 0, sizeof *lease);
1223 /* Copy the lease options. */
1224 option_state_reference (&lease -> options, packet -> options, MDL);
1226 lease -> address.len = sizeof (packet -> raw -> yiaddr);
1227 memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
1228 lease -> address.len);
1230 memset (&data, 0, sizeof data);
1232 if (client -> config -> vendor_space_name) {
1233 i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
1235 /* See if there was a vendor encapsulation option. */
1236 oc = lookup_option (&dhcp_universe, lease -> options, i);
1237 if (oc &&
1238 client -> config -> vendor_space_name &&
1239 evaluate_option_cache (&data, packet,
1240 (struct lease *)0, client,
1241 packet -> options, lease -> options,
1242 &global_scope, oc, MDL)) {
1243 if (data.len) {
1244 parse_encapsulated_suboptions
1245 (packet -> options, &dhcp_options [i],
1246 data.data, data.len, &dhcp_universe,
1247 client -> config -> vendor_space_name
1250 data_string_forget (&data, MDL);
1252 } else
1253 i = 0;
1255 /* Figure out the overload flag. */
1256 oc = lookup_option (&dhcp_universe, lease -> options,
1257 DHO_DHCP_OPTION_OVERLOAD);
1258 if (oc &&
1259 evaluate_option_cache (&data, packet, (struct lease *)0, client,
1260 packet -> options, lease -> options,
1261 &global_scope, oc, MDL)) {
1262 if (data.len > 0)
1263 i = data.data [0];
1264 else
1265 i = 0;
1266 data_string_forget (&data, MDL);
1267 } else
1268 i = 0;
1270 /* If the server name was filled out, copy it. */
1271 if (!(i & 2) && packet -> raw -> sname [0]) {
1272 unsigned len;
1273 /* Don't count on the NUL terminator. */
1274 for (len = 0; len < 64; len++)
1275 if (!packet -> raw -> sname [len])
1276 break;
1277 lease -> server_name = dmalloc (len + 1, MDL);
1278 if (!lease -> server_name) {
1279 log_error ("dhcpoffer: no memory for server name.\n");
1280 destroy_client_lease (lease);
1281 return (struct client_lease *)0;
1282 } else {
1283 memcpy (lease -> server_name,
1284 packet -> raw -> sname, len);
1285 lease -> server_name [len] = 0;
1289 /* Ditto for the filename. */
1290 if (!(i & 1) && packet -> raw -> file [0]) {
1291 unsigned len;
1292 /* Don't count on the NUL terminator. */
1293 for (len = 0; len < 64; len++)
1294 if (!packet -> raw -> file [len])
1295 break;
1296 lease -> filename = dmalloc (len + 1, MDL);
1297 if (!lease -> filename) {
1298 log_error ("dhcpoffer: no memory for filename.\n");
1299 destroy_client_lease (lease);
1300 return (struct client_lease *)0;
1301 } else {
1302 memcpy (lease -> filename,
1303 packet -> raw -> file, len);
1304 lease -> filename [len] = 0;
1308 execute_statements_in_scope ((struct binding_value **)0,
1309 (struct packet *)packet,
1310 (struct lease *)0, client,
1311 lease -> options, lease -> options,
1312 &global_scope,
1313 client -> config -> on_receipt,
1314 (struct group *)0);
1316 return lease;
1319 void dhcpnak (packet)
1320 struct packet *packet;
1322 struct interface_info *ip = packet -> interface;
1323 struct client_state *client;
1325 /* Find a client state that matches the xid... */
1326 for (client = ip -> client; client; client = client -> next)
1327 if (client -> xid == packet -> raw -> xid)
1328 break;
1330 /* If we're not receptive to an offer right now, or if the offer
1331 has an unrecognizable transaction id, then just drop it. */
1332 if (!client ||
1333 (packet -> interface -> hw_address.hlen - 1 !=
1334 packet -> raw -> hlen) ||
1335 (memcmp (&packet -> interface -> hw_address.hbuf [1],
1336 packet -> raw -> chaddr, packet -> raw -> hlen))) {
1337 #if defined (DEBUG)
1338 log_debug ("DHCPNAK in wrong transaction.");
1339 #endif
1340 return;
1343 if (client -> state != S_REBOOTING &&
1344 client -> state != S_REQUESTING &&
1345 client -> state != S_RENEWING &&
1346 client -> state != S_REBINDING) {
1347 #if defined (DEBUG)
1348 log_debug ("DHCPNAK in wrong state.");
1349 #endif
1350 return;
1353 log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
1355 if (!client -> active) {
1356 #if defined (DEBUG)
1357 log_info ("DHCPNAK with no active lease.\n");
1358 #endif
1359 return;
1362 destroy_client_lease (client -> active);
1363 client -> active = (struct client_lease *)0;
1365 /* Stop sending DHCPREQUEST packets... */
1366 cancel_timeout (send_request, client);
1368 client -> state = S_INIT;
1369 state_init (client);
1372 static void limit_interval (client)
1373 struct client_state *client;
1375 if (client -> interval <= client -> config -> backoff_cutoff)
1376 return;
1378 client -> interval = client -> config -> backoff_cutoff / 2;
1379 if (client -> config -> backoff_cutoff)
1380 client -> interval += (random () >> 2) %
1381 client -> config -> backoff_cutoff;
1384 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1385 one after the right interval has expired. If we don't get an offer by
1386 the time we reach the panic interval, call the panic function. */
1388 void send_discover (cpp)
1389 void *cpp;
1391 struct client_state *client = cpp;
1393 int result;
1394 int interval;
1395 int increase = 1;
1397 /* Figure out how long it's been since we started transmitting. */
1398 interval = cur_time - client -> first_sending;
1400 /* If we're past the panic timeout, call the script and tell it
1401 we haven't found anything for this interface yet. */
1402 if (interval > client -> config -> timeout) {
1403 state_panic (client);
1404 return;
1407 /* If we're selecting media, try the whole list before doing
1408 the exponential backoff, but if we've already received an
1409 offer, stop looping, because we obviously have it right. */
1410 if (!client -> offered_leases &&
1411 client -> config -> media) {
1412 int fail = 0;
1413 again:
1414 if (client -> medium) {
1415 client -> medium = client -> medium -> next;
1416 increase = 0;
1418 if (!client -> medium) {
1419 if (fail)
1420 log_fatal ("No valid media types for %s!",
1421 client -> interface -> name);
1422 client -> medium =
1423 client -> config -> media;
1424 increase = 1;
1427 log_info ("Trying medium \"%s\" %d",
1428 client -> medium -> string, increase);
1429 script_init (client, "MEDIUM", client -> medium);
1430 if (script_go (client)) {
1431 fail = 1;
1432 goto again;
1436 /* If we're supposed to increase the interval, do so. If it's
1437 currently zero (i.e., we haven't sent any packets yet), set
1438 it to initial_interval; otherwise, add to it a random number
1439 between zero and two times itself. On average, this means
1440 that it will double with every transmission. */
1441 if (increase) {
1442 if (!client -> interval)
1443 client -> interval =
1444 client -> config -> initial_interval;
1445 else
1446 client -> interval += ((random () >> 2) %
1447 (2 * client -> interval));
1449 /* Don't backoff past cutoff. */
1450 limit_interval (client);
1451 } else if (!client -> interval)
1452 client -> interval = client -> config -> initial_interval;
1454 /* If the backoff would take us to the panic timeout, just use that
1455 as the interval. */
1456 if (cur_time + client -> interval >
1457 client -> first_sending + client -> config -> timeout)
1458 client -> interval =
1459 (client -> first_sending +
1460 client -> config -> timeout) - cur_time + 1;
1462 /* Record the number of seconds since we started sending. */
1463 if (interval < 65536)
1464 client -> packet.secs = htons (interval);
1465 else
1466 client -> packet.secs = htons (65535);
1467 client -> secs = client -> packet.secs;
1469 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
1470 client -> name ? client -> name : client -> interface -> name,
1471 inet_ntoa (sockaddr_broadcast.sin_addr),
1472 ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
1474 /* Send out a packet. */
1475 result = send_packet (client -> interface, (struct packet *)0,
1476 &client -> packet,
1477 client -> packet_length,
1478 inaddr_any, &sockaddr_broadcast,
1479 (struct hardware *)0);
1481 add_timeout (cur_time + client -> interval,
1482 send_discover, client, 0, 0);
1485 /* state_panic gets called if we haven't received any offers in a preset
1486 amount of time. When this happens, we try to use existing leases that
1487 haven't yet expired, and failing that, we call the client script and
1488 hope it can do something. */
1490 void state_panic (cpp)
1491 void *cpp;
1493 struct client_state *client = cpp;
1494 struct client_lease *loop;
1495 struct client_lease *lp;
1497 loop = lp = client -> active;
1499 log_info ("No DHCPOFFERS received.");
1501 /* We may not have an active lease, but we may have some
1502 predefined leases that we can try. */
1503 if (!client -> active && client -> leases)
1504 goto activate_next;
1506 /* Run through the list of leases and see if one can be used. */
1507 while (client -> active) {
1508 if (client -> active -> expiry > cur_time) {
1509 log_info ("Trying recorded lease %s",
1510 piaddr (client -> active -> address));
1511 /* Run the client script with the existing
1512 parameters. */
1513 script_init (client, "TIMEOUT",
1514 client -> active -> medium);
1515 script_write_params (client, "new_", client -> active);
1516 if (client -> alias)
1517 script_write_params (client, "alias_",
1518 client -> alias);
1520 /* If the old lease is still good and doesn't
1521 yet need renewal, go into BOUND state and
1522 timeout at the renewal time. */
1523 if (!script_go (client)) {
1524 if (cur_time < client -> active -> renewal) {
1525 client -> state = S_BOUND;
1526 log_info ("bound: renewal in %ld %s.",
1527 (long)(client -> active -> renewal -
1528 cur_time), "seconds");
1529 add_timeout (client -> active -> renewal,
1530 state_bound, client, 0, 0);
1531 } else {
1532 client -> state = S_BOUND;
1533 log_info ("bound: immediate renewal.");
1534 state_bound (client);
1536 reinitialize_interfaces ();
1537 go_daemon ();
1538 return;
1542 /* If there are no other leases, give up. */
1543 if (!client -> leases) {
1544 client -> leases = client -> active;
1545 client -> active = (struct client_lease *)0;
1546 break;
1549 activate_next:
1550 /* Otherwise, put the active lease at the end of the
1551 lease list, and try another lease.. */
1552 for (lp = client -> leases; lp -> next; lp = lp -> next)
1554 lp -> next = client -> active;
1555 if (lp -> next) {
1556 lp -> next -> next = (struct client_lease *)0;
1558 client -> active = client -> leases;
1559 client -> leases = client -> leases -> next;
1561 /* If we already tried this lease, we've exhausted the
1562 set of leases, so we might as well give up for
1563 now. */
1564 if (client -> active == loop)
1565 break;
1566 else if (!loop)
1567 loop = client -> active;
1570 /* No leases were available, or what was available didn't work, so
1571 tell the shell script that we failed to allocate an address,
1572 and try again later. */
1573 if (onetry) {
1574 if (!quiet)
1575 log_info ("Unable to obtain a lease on first try.%s",
1576 " Exiting.");
1577 exit (2);
1580 log_info ("No working leases in persistent database - sleeping.");
1581 script_init (client, "FAIL", (struct string_list *)0);
1582 if (client -> alias)
1583 script_write_params (client, "alias_", client -> alias);
1584 script_go (client);
1585 client -> state = S_INIT;
1586 add_timeout (cur_time +
1587 ((client -> config -> retry_interval + 1) / 2 +
1588 (random () % client -> config -> retry_interval)),
1589 state_init, client, 0, 0);
1590 go_daemon ();
1593 void send_request (cpp)
1594 void *cpp;
1596 struct client_state *client = cpp;
1598 int result;
1599 int interval;
1600 struct sockaddr_in destination;
1601 struct in_addr from;
1603 /* Figure out how long it's been since we started transmitting. */
1604 interval = cur_time - client -> first_sending;
1606 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1607 past the reboot timeout, go to INIT and see if we can
1608 DISCOVER an address... */
1609 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1610 means either that we're on a network with no DHCP server,
1611 or that our server is down. In the latter case, assuming
1612 that there is a backup DHCP server, DHCPDISCOVER will get
1613 us a new address, but we could also have successfully
1614 reused our old address. In the former case, we're hosed
1615 anyway. This is not a win-prone situation. */
1616 if ((client -> state == S_REBOOTING ||
1617 client -> state == S_REQUESTING) &&
1618 interval > client -> config -> reboot_timeout) {
1619 cancel:
1620 client -> state = S_INIT;
1621 cancel_timeout (send_request, client);
1622 state_init (client);
1623 return;
1626 /* If we're in the reboot state, make sure the media is set up
1627 correctly. */
1628 if (client -> state == S_REBOOTING &&
1629 !client -> medium &&
1630 client -> active -> medium ) {
1631 script_init (client, "MEDIUM", client -> active -> medium);
1633 /* If the medium we chose won't fly, go to INIT state. */
1634 if (script_go (client))
1635 goto cancel;
1637 /* Record the medium. */
1638 client -> medium = client -> active -> medium;
1641 /* If the lease has expired, relinquish the address and go back
1642 to the INIT state. */
1643 if (client -> state != S_REQUESTING &&
1644 cur_time > client -> active -> expiry) {
1645 /* Run the client script with the new parameters. */
1646 script_init (client, "EXPIRE", (struct string_list *)0);
1647 script_write_params (client, "old_", client -> active);
1648 if (client -> alias)
1649 script_write_params (client, "alias_",
1650 client -> alias);
1651 script_go (client);
1653 /* Now do a preinit on the interface so that we can
1654 discover a new address. */
1655 script_init (client, "PREINIT", (struct string_list *)0);
1656 if (client -> alias)
1657 script_write_params (client, "alias_",
1658 client -> alias);
1659 script_go (client);
1661 client -> state = S_INIT;
1662 state_init (client);
1663 return;
1666 /* Do the exponential backoff... */
1667 if (!client -> interval)
1668 client -> interval = client -> config -> initial_interval;
1669 else {
1670 client -> interval += ((random () >> 2) %
1671 (2 * client -> interval));
1674 /* Don't backoff past cutoff. */
1675 limit_interval (client);
1677 /* If the backoff would take us to the expiry time, just set the
1678 timeout to the expiry time. */
1679 if (client -> state != S_REQUESTING &&
1680 cur_time + client -> interval > client -> active -> expiry)
1681 client -> interval =
1682 client -> active -> expiry - cur_time + 1;
1684 /* If the lease T2 time has elapsed, or if we're not yet bound,
1685 broadcast the DHCPREQUEST rather than unicasting. */
1686 memset(&destination, 0, sizeof(destination));
1687 if (client -> state == S_REQUESTING ||
1688 client -> state == S_REBOOTING ||
1689 cur_time > client -> active -> rebind)
1690 destination.sin_addr = sockaddr_broadcast.sin_addr;
1691 else
1692 memcpy (&destination.sin_addr.s_addr,
1693 client -> destination.iabuf,
1694 sizeof destination.sin_addr.s_addr);
1695 destination.sin_port = remote_port;
1696 destination.sin_family = AF_INET;
1697 #ifdef HAVE_SA_LEN
1698 destination.sin_len = sizeof destination;
1699 #endif
1701 if (client -> state == S_RENEWING ||
1702 client -> state == S_REBINDING)
1703 memcpy (&from, client -> active -> address.iabuf,
1704 sizeof from);
1705 else
1706 from.s_addr = INADDR_ANY;
1708 /* Record the number of seconds since we started sending. */
1709 if (client -> state == S_REQUESTING)
1710 client -> packet.secs = client -> secs;
1711 else {
1712 if (interval < 65536)
1713 client -> packet.secs = htons (interval);
1714 else
1715 client -> packet.secs = htons (65535);
1718 log_info ("DHCPREQUEST on %s to %s port %d",
1719 client -> name ? client -> name : client -> interface -> name,
1720 inet_ntoa (destination.sin_addr),
1721 ntohs (destination.sin_port));
1723 if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
1724 fallback_interface)
1725 result = send_packet (fallback_interface,
1726 (struct packet *)0,
1727 &client -> packet,
1728 client -> packet_length,
1729 from, &destination,
1730 (struct hardware *)0);
1731 else
1732 /* Send out a packet. */
1733 result = send_packet (client -> interface, (struct packet *)0,
1734 &client -> packet,
1735 client -> packet_length,
1736 from, &destination,
1737 (struct hardware *)0);
1739 add_timeout (cur_time + client -> interval,
1740 send_request, client, 0, 0);
1743 void send_decline (cpp)
1744 void *cpp;
1746 struct client_state *client = cpp;
1748 int result;
1750 log_info ("DHCPDECLINE on %s to %s port %d",
1751 client -> name ? client -> name : client -> interface -> name,
1752 inet_ntoa (sockaddr_broadcast.sin_addr),
1753 ntohs (sockaddr_broadcast.sin_port));
1755 /* Send out a packet. */
1756 result = send_packet (client -> interface, (struct packet *)0,
1757 &client -> packet,
1758 client -> packet_length,
1759 inaddr_any, &sockaddr_broadcast,
1760 (struct hardware *)0);
1763 void send_release (cpp)
1764 void *cpp;
1766 struct client_state *client = cpp;
1768 int result;
1769 struct sockaddr_in destination;
1770 struct in_addr from;
1772 memset(&destination, 0, sizeof(destination));
1773 memcpy (&from, client -> active -> address.iabuf,
1774 sizeof from);
1775 memcpy (&destination.sin_addr.s_addr,
1776 client -> destination.iabuf,
1777 sizeof destination.sin_addr.s_addr);
1778 destination.sin_port = remote_port;
1779 destination.sin_family = AF_INET;
1780 #ifdef HAVE_SA_LEN
1781 destination.sin_len = sizeof destination;
1782 #endif
1784 /* Set the lease to end now, so that we don't accidentally
1785 reuse it if we restart before the old expiry time. */
1786 client -> active -> expiry =
1787 client -> active -> renewal =
1788 client -> active -> rebind = cur_time;
1789 if (!write_client_lease (client, client -> active, 1, 1)) {
1790 log_error ("Can't release lease: lease write failed.");
1791 return;
1794 log_info ("DHCPRELEASE on %s to %s port %d",
1795 client -> name ? client -> name : client -> interface -> name,
1796 inet_ntoa (destination.sin_addr),
1797 ntohs (destination.sin_port));
1799 if (fallback_interface)
1800 result = send_packet (fallback_interface,
1801 (struct packet *)0,
1802 &client -> packet,
1803 client -> packet_length,
1804 from, &destination,
1805 (struct hardware *)0);
1806 else
1807 /* Send out a packet. */
1808 result = send_packet (client -> interface, (struct packet *)0,
1809 &client -> packet,
1810 client -> packet_length,
1811 from, &destination,
1812 (struct hardware *)0);
1815 void make_client_options (client, lease, type, sid, rip, prl, op)
1816 struct client_state *client;
1817 struct client_lease *lease;
1818 u_int8_t *type;
1819 struct option_cache *sid;
1820 struct iaddr *rip;
1821 u_int32_t *prl;
1822 struct option_state **op;
1824 unsigned i;
1825 struct option_cache *oc;
1826 struct buffer *bp = (struct buffer *)0;
1828 /* If there are any leftover options, get rid of them. */
1829 if (*op)
1830 option_state_dereference (op, MDL);
1832 /* Allocate space for options. */
1833 option_state_allocate (op, MDL);
1835 /* Send the server identifier if provided. */
1836 if (sid)
1837 save_option (&dhcp_universe, *op, sid);
1839 oc = (struct option_cache *)0;
1841 /* Send the requested address if provided. */
1842 if (rip) {
1843 client -> requested_address = *rip;
1844 if (!(make_const_option_cache
1845 (&oc, (struct buffer **)0, rip -> iabuf, rip -> len,
1846 &dhcp_options [DHO_DHCP_REQUESTED_ADDRESS], MDL)))
1847 log_error ("can't make requested address cache.");
1848 else {
1849 save_option (&dhcp_universe, *op, oc);
1850 option_cache_dereference (&oc, MDL);
1852 } else {
1853 client -> requested_address.len = 0;
1856 if (!(make_const_option_cache
1857 (&oc, (struct buffer **)0,
1858 type, 1, &dhcp_options [DHO_DHCP_MESSAGE_TYPE], MDL)))
1859 log_error ("can't make message type.");
1860 else {
1861 save_option (&dhcp_universe, *op, oc);
1862 option_cache_dereference (&oc, MDL);
1865 if (prl) {
1866 /* Figure out how many parameters were requested. */
1867 for (i = 0; prl [i]; i++)
1869 if (!buffer_allocate (&bp, i, MDL))
1870 log_error ("can't make parameter list buffer.");
1871 else {
1872 for (i = 0; prl [i]; i++)
1873 bp -> data [i] = prl [i];
1874 if (!(make_const_option_cache
1875 (&oc, &bp, (u_int8_t *)0, i,
1876 &dhcp_options [DHO_DHCP_PARAMETER_REQUEST_LIST],
1877 MDL)))
1878 log_error ("can't make option cache");
1879 else {
1880 save_option (&dhcp_universe, *op, oc);
1881 option_cache_dereference (&oc, MDL);
1886 /* Run statements that need to be run on transmission. */
1887 if (client -> config -> on_transmission)
1888 execute_statements_in_scope
1889 ((struct binding_value **)0,
1890 (struct packet *)0, (struct lease *)0, client,
1891 (lease ? lease -> options : (struct option_state *)0),
1892 *op, &global_scope,
1893 client -> config -> on_transmission,
1894 (struct group *)0);
1897 void make_discover (client, lease)
1898 struct client_state *client;
1899 struct client_lease *lease;
1901 unsigned char discover = DHCPDISCOVER;
1902 struct option_state *options = (struct option_state *)0;
1904 memset (&client -> packet, 0, sizeof (client -> packet));
1906 make_client_options (client,
1907 lease, &discover, (struct option_cache *)0,
1908 lease ? &lease -> address : (struct iaddr *)0,
1909 client -> config -> requested_options,
1910 &options);
1912 /* Set up the option buffer... */
1913 client -> packet_length =
1914 cons_options ((struct packet *)0, &client -> packet,
1915 (struct lease *)0, client,
1916 /* maximum packet size */1500,
1917 (struct option_state *)0,
1918 options,
1919 /* scope */ &global_scope,
1920 /* overload */ 0,
1921 /* terminate */0,
1922 /* bootpp */0,
1923 (struct data_string *)0,
1924 client -> config -> vendor_space_name);
1926 option_state_dereference (&options, MDL);
1927 if (client -> packet_length < BOOTP_MIN_LEN)
1928 client -> packet_length = BOOTP_MIN_LEN;
1930 client -> packet.op = BOOTREQUEST;
1931 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
1932 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
1933 client -> packet.hops = 0;
1934 client -> packet.xid = random ();
1935 client -> packet.secs = 0; /* filled in by send_discover. */
1937 if (can_receive_unicast_unconfigured (client -> interface))
1938 client -> packet.flags = 0;
1939 else
1940 client -> packet.flags = htons (BOOTP_BROADCAST);
1942 memset (&(client -> packet.ciaddr),
1943 0, sizeof client -> packet.ciaddr);
1944 memset (&(client -> packet.yiaddr),
1945 0, sizeof client -> packet.yiaddr);
1946 memset (&(client -> packet.siaddr),
1947 0, sizeof client -> packet.siaddr);
1948 client -> packet.giaddr = giaddr;
1949 if (client -> interface -> hw_address.hlen > 0)
1950 memcpy (client -> packet.chaddr,
1951 &client -> interface -> hw_address.hbuf [1],
1952 (unsigned)(client -> interface -> hw_address.hlen - 1));
1954 #ifdef DEBUG_PACKET
1955 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
1956 #endif
1960 void make_request (client, lease)
1961 struct client_state *client;
1962 struct client_lease *lease;
1964 unsigned char request = DHCPREQUEST;
1965 struct option_cache *oc;
1967 memset (&client -> packet, 0, sizeof (client -> packet));
1969 if (client -> state == S_REQUESTING)
1970 oc = lookup_option (&dhcp_universe, lease -> options,
1971 DHO_DHCP_SERVER_IDENTIFIER);
1972 else
1973 oc = (struct option_cache *)0;
1975 if (client -> sent_options)
1976 option_state_dereference (&client -> sent_options, MDL);
1978 make_client_options (client, lease, &request, oc,
1979 ((client -> state == S_REQUESTING ||
1980 client -> state == S_REBOOTING)
1981 ? &lease -> address
1982 : (struct iaddr *)0),
1983 client -> config -> requested_options,
1984 &client -> sent_options);
1986 /* Set up the option buffer... */
1987 client -> packet_length =
1988 cons_options ((struct packet *)0, &client -> packet,
1989 (struct lease *)0, client,
1990 /* maximum packet size */1500,
1991 (struct option_state *)0,
1992 client -> sent_options,
1993 /* scope */ &global_scope,
1994 /* overload */ 0,
1995 /* terminate */0,
1996 /* bootpp */0,
1997 (struct data_string *)0,
1998 client -> config -> vendor_space_name);
2000 if (client -> packet_length < BOOTP_MIN_LEN)
2001 client -> packet_length = BOOTP_MIN_LEN;
2003 client -> packet.op = BOOTREQUEST;
2004 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2005 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2006 client -> packet.hops = 0;
2007 client -> packet.xid = client -> xid;
2008 client -> packet.secs = 0; /* Filled in by send_request. */
2010 /* If we own the address we're requesting, put it in ciaddr;
2011 otherwise set ciaddr to zero. */
2012 if (client -> state == S_BOUND ||
2013 client -> state == S_RENEWING ||
2014 client -> state == S_REBINDING) {
2015 memcpy (&client -> packet.ciaddr,
2016 lease -> address.iabuf, lease -> address.len);
2017 client -> packet.flags = 0;
2018 } else {
2019 memset (&client -> packet.ciaddr, 0,
2020 sizeof client -> packet.ciaddr);
2021 if (can_receive_unicast_unconfigured (client -> interface))
2022 client -> packet.flags = 0;
2023 else
2024 client -> packet.flags = htons (BOOTP_BROADCAST);
2027 memset (&client -> packet.yiaddr, 0,
2028 sizeof client -> packet.yiaddr);
2029 memset (&client -> packet.siaddr, 0,
2030 sizeof client -> packet.siaddr);
2031 if (client -> state != S_BOUND &&
2032 client -> state != S_RENEWING)
2033 client -> packet.giaddr = giaddr;
2034 else
2035 memset (&client -> packet.giaddr, 0,
2036 sizeof client -> packet.giaddr);
2037 if (client -> interface -> hw_address.hlen > 0)
2038 memcpy (client -> packet.chaddr,
2039 &client -> interface -> hw_address.hbuf [1],
2040 (unsigned)(client -> interface -> hw_address.hlen - 1));
2042 #ifdef DEBUG_PACKET
2043 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2044 #endif
2047 void make_decline (client, lease)
2048 struct client_state *client;
2049 struct client_lease *lease;
2051 unsigned char decline = DHCPDECLINE;
2052 struct option_cache *oc;
2054 struct option_state *options = (struct option_state *)0;
2056 oc = lookup_option (&dhcp_universe, lease -> options,
2057 DHO_DHCP_SERVER_IDENTIFIER);
2058 make_client_options (client, lease, &decline, oc,
2059 &lease -> address, (u_int32_t *)0, &options);
2061 /* Set up the option buffer... */
2062 memset (&client -> packet, 0, sizeof (client -> packet));
2063 client -> packet_length =
2064 cons_options ((struct packet *)0, &client -> packet,
2065 (struct lease *)0, client, 0,
2066 (struct option_state *)0, options,
2067 &global_scope, 0, 0, 0, (struct data_string *)0,
2068 client -> config -> vendor_space_name);
2069 if (client -> packet_length < BOOTP_MIN_LEN)
2070 client -> packet_length = BOOTP_MIN_LEN;
2071 option_state_dereference (&options, MDL);
2073 client -> packet.op = BOOTREQUEST;
2074 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2075 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2076 client -> packet.hops = 0;
2077 client -> packet.xid = client -> xid;
2078 client -> packet.secs = 0; /* Filled in by send_request. */
2079 if (can_receive_unicast_unconfigured (client -> interface))
2080 client -> packet.flags = 0;
2081 else
2082 client -> packet.flags = htons (BOOTP_BROADCAST);
2084 /* ciaddr must always be zero. */
2085 memset (&client -> packet.ciaddr, 0,
2086 sizeof client -> packet.ciaddr);
2087 memset (&client -> packet.yiaddr, 0,
2088 sizeof client -> packet.yiaddr);
2089 memset (&client -> packet.siaddr, 0,
2090 sizeof client -> packet.siaddr);
2091 client -> packet.giaddr = giaddr;
2092 memcpy (client -> packet.chaddr,
2093 &client -> interface -> hw_address.hbuf [1],
2094 client -> interface -> hw_address.hlen);
2096 #ifdef DEBUG_PACKET
2097 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2098 #endif
2101 void make_release (client, lease)
2102 struct client_state *client;
2103 struct client_lease *lease;
2105 unsigned char request = DHCPRELEASE;
2106 struct option_cache *oc;
2108 struct option_state *options = (struct option_state *)0;
2110 memset (&client -> packet, 0, sizeof (client -> packet));
2112 oc = lookup_option (&dhcp_universe, lease -> options,
2113 DHO_DHCP_SERVER_IDENTIFIER);
2114 make_client_options (client, lease, &request, oc,
2115 (struct iaddr *)0, (u_int32_t *)0,
2116 &options);
2118 /* Set up the option buffer... */
2119 client -> packet_length =
2120 cons_options ((struct packet *)0, &client -> packet,
2121 (struct lease *)0, client,
2122 /* maximum packet size */1500,
2123 (struct option_state *)0,
2124 options,
2125 /* scope */ &global_scope,
2126 /* overload */ 0,
2127 /* terminate */0,
2128 /* bootpp */0,
2129 (struct data_string *)0,
2130 client -> config -> vendor_space_name);
2132 if (client -> packet_length < BOOTP_MIN_LEN)
2133 client -> packet_length = BOOTP_MIN_LEN;
2134 option_state_dereference (&options, MDL);
2136 client -> packet.op = BOOTREQUEST;
2137 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2138 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2139 client -> packet.hops = 0;
2140 client -> packet.xid = random ();
2141 client -> packet.secs = 0;
2142 client -> packet.flags = 0;
2143 memcpy (&client -> packet.ciaddr,
2144 lease -> address.iabuf, lease -> address.len);
2145 memset (&client -> packet.yiaddr, 0,
2146 sizeof client -> packet.yiaddr);
2147 memset (&client -> packet.siaddr, 0,
2148 sizeof client -> packet.siaddr);
2149 client -> packet.giaddr = giaddr;
2150 memcpy (client -> packet.chaddr,
2151 &client -> interface -> hw_address.hbuf [1],
2152 client -> interface -> hw_address.hlen);
2154 #ifdef DEBUG_PACKET
2155 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2156 #endif
2159 void destroy_client_lease (lease)
2160 struct client_lease *lease;
2163 if (lease -> server_name)
2164 dfree (lease -> server_name, MDL);
2165 if (lease -> filename)
2166 dfree (lease -> filename, MDL);
2167 option_state_dereference (&lease -> options, MDL);
2168 free_client_lease (lease, MDL);
2171 FILE *leaseFile;
2173 void rewrite_client_leases ()
2175 struct interface_info *ip;
2176 struct client_state *client;
2177 struct client_lease *lp;
2178 int fd;
2180 if (leaseFile)
2181 fclose (leaseFile);
2182 fd = open (path_dhclient_db, O_WRONLY|O_CREAT|O_TRUNC, 0600);
2183 if (fd != -1)
2184 leaseFile = fdopen (fd, "w");
2185 if (fd == -1 || !leaseFile) {
2186 log_error ("can't create %s: %m", path_dhclient_db);
2187 return;
2190 /* Write out all the leases attached to configured interfaces that
2191 we know about. */
2192 for (ip = interfaces; ip; ip = ip -> next) {
2193 for (client = ip -> client; client; client = client -> next) {
2194 for (lp = client -> leases; lp; lp = lp -> next) {
2195 write_client_lease (client, lp, 1, 0);
2197 if (client -> active)
2198 write_client_lease (client,
2199 client -> active, 1, 0);
2203 /* Write out any leases that are attached to interfaces that aren't
2204 currently configured. */
2205 for (ip = dummy_interfaces; ip; ip = ip -> next) {
2206 for (client = ip -> client; client; client = client -> next) {
2207 for (lp = client -> leases; lp; lp = lp -> next) {
2208 write_client_lease (client, lp, 1, 0);
2210 if (client -> active)
2211 write_client_lease (client,
2212 client -> active, 1, 0);
2215 fflush (leaseFile);
2218 void write_lease_option (struct option_cache *oc,
2219 struct packet *packet, struct lease *lease,
2220 struct client_state *client_state,
2221 struct option_state *in_options,
2222 struct option_state *cfg_options,
2223 struct binding_scope **scope,
2224 struct universe *u, void *stuff)
2226 const char *name, *dot;
2227 struct data_string ds;
2229 memset (&ds, 0, sizeof ds);
2231 if (u != &dhcp_universe) {
2232 name = u -> name;
2233 dot = ".";
2234 } else {
2235 name = "";
2236 dot = "";
2238 if (evaluate_option_cache (&ds, packet, lease, client_state,
2239 in_options, cfg_options, scope, oc, MDL)) {
2240 fprintf (leaseFile,
2241 " option %s%s%s %s;\n",
2242 name, dot, oc -> option -> name,
2243 pretty_print_option (oc -> option,
2244 ds.data, ds.len, 1, 1));
2245 data_string_forget (&ds, MDL);
2249 int write_client_lease (client, lease, rewrite, makesure)
2250 struct client_state *client;
2251 struct client_lease *lease;
2252 int rewrite;
2253 int makesure;
2255 int i;
2256 struct tm *t;
2257 static int leases_written;
2258 struct data_string ds;
2259 int errors = 0;
2260 char *s;
2262 if (!rewrite) {
2263 if (leases_written++ > 20) {
2264 rewrite_client_leases ();
2265 leases_written = 0;
2269 /* If the lease came from the config file, we don't need to stash
2270 a copy in the lease database. */
2271 if (lease -> is_static)
2272 return 1;
2274 if (!leaseFile) { /* XXX */
2275 int fd;
2277 fd = open (path_dhclient_db, O_WRONLY|O_CREAT|O_TRUNC, 0600);
2278 if (fd != -1)
2279 leaseFile = fdopen (fd, "w");
2280 if (fd == -1 || !leaseFile) {
2281 log_error ("can't create %s: %m", path_dhclient_db);
2282 return 0;
2286 errno = 0;
2287 fprintf (leaseFile, "lease {\n");
2288 if (lease -> is_bootp) {
2289 fprintf (leaseFile, " bootp;\n");
2290 if (errno) {
2291 ++errors;
2292 errno = 0;
2295 fprintf (leaseFile, " interface \"%s\";\n",
2296 client -> interface -> name);
2297 if (errno) {
2298 ++errors;
2299 errno = 0;
2301 if (client -> name) {
2302 fprintf (leaseFile, " name \"%s\";\n", client -> name);
2303 if (errno) {
2304 ++errors;
2305 errno = 0;
2308 fprintf (leaseFile, " fixed-address %s;\n",
2309 piaddr (lease -> address));
2310 if (errno) {
2311 ++errors;
2312 errno = 0;
2314 if (lease -> filename) {
2315 s = quotify_string (lease -> filename, MDL);
2316 if (s) {
2317 fprintf (leaseFile, " filename \"%s\";\n", s);
2318 if (errno) {
2319 ++errors;
2320 errno = 0;
2322 dfree (s, MDL);
2323 } else
2324 errors++;
2327 if (lease -> server_name) {
2328 s = quotify_string (lease -> filename, MDL);
2329 if (s) {
2330 fprintf (leaseFile, " server-name \"%s\";\n", s);
2331 if (errno) {
2332 ++errors;
2333 errno = 0;
2335 dfree (s, MDL);
2336 } else
2337 ++errors;
2339 if (lease -> medium) {
2340 s = quotify_string (lease -> medium -> string, MDL);
2341 if (s) {
2342 fprintf (leaseFile, " medium \"%s\";\n", s);
2343 if (errno) {
2344 ++errors;
2345 errno = 0;
2347 dfree (s, MDL);
2348 } else
2349 errors++;
2351 if (errno != 0) {
2352 errors++;
2353 errno = 0;
2356 memset (&ds, 0, sizeof ds);
2358 for (i = 0; i < lease -> options -> universe_count; i++) {
2359 option_space_foreach ((struct packet *)0, (struct lease *)0,
2360 client, (struct option_state *)0,
2361 lease -> options, &global_scope,
2362 universes [i],
2363 client, write_lease_option);
2366 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
2367 somebody invents a time machine, I think we can safely disregard
2368 it. */
2369 t = gmtime (&lease -> renewal);
2370 fprintf (leaseFile,
2371 " renew %d %d/%d/%d %02d:%02d:%02d;\n",
2372 t -> tm_wday, t -> tm_year + 1900,
2373 t -> tm_mon + 1, t -> tm_mday,
2374 t -> tm_hour, t -> tm_min, t -> tm_sec);
2375 if (errno != 0) {
2376 errors++;
2377 errno = 0;
2379 t = gmtime (&lease -> rebind);
2380 fprintf (leaseFile,
2381 " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
2382 t -> tm_wday, t -> tm_year + 1900,
2383 t -> tm_mon + 1, t -> tm_mday,
2384 t -> tm_hour, t -> tm_min, t -> tm_sec);
2385 if (errno != 0) {
2386 errors++;
2387 errno = 0;
2389 t = gmtime (&lease -> expiry);
2390 fprintf (leaseFile,
2391 " expire %d %d/%d/%d %02d:%02d:%02d;\n",
2392 t -> tm_wday, t -> tm_year + 1900,
2393 t -> tm_mon + 1, t -> tm_mday,
2394 t -> tm_hour, t -> tm_min, t -> tm_sec);
2395 if (errno != 0) {
2396 errors++;
2397 errno = 0;
2399 fprintf (leaseFile, "}\n");
2400 if (errno != 0) {
2401 errors++;
2402 errno = 0;
2404 fflush (leaseFile);
2405 if (errno != 0) {
2406 errors++;
2407 errno = 0;
2409 if (!errors && makesure) {
2410 if (fsync (fileno (leaseFile)) < 0) {
2411 log_info ("write_client_lease: %m");
2412 return 0;
2415 return errors ? 0 : 1;
2418 /* Variables holding name of script and file pointer for writing to
2419 script. Needless to say, this is not reentrant - only one script
2420 can be invoked at a time. */
2421 char scriptName [256];
2422 FILE *scriptFile;
2424 void script_init (client, reason, medium)
2425 struct client_state *client;
2426 const char *reason;
2427 struct string_list *medium;
2429 struct string_list *sl, *next;
2431 if (client) {
2432 for (sl = client -> env; sl; sl = next) {
2433 next = sl -> next;
2434 dfree (sl, MDL);
2436 client -> env = (struct string_list *)0;
2437 client -> envc = 0;
2439 if (client -> interface) {
2440 client_envadd (client, "", "interface", "%s",
2441 client -> interface -> name);
2443 if (client -> name)
2444 client_envadd (client,
2445 "", "client", "%s", client -> name);
2446 if (medium)
2447 client_envadd (client,
2448 "", "medium", "%s", medium -> string);
2450 client_envadd (client, "", "reason", "%s", reason);
2451 client_envadd (client, "", "pid", "%ld", (long int)getpid ());
2455 struct envadd_state {
2456 struct client_state *client;
2457 const char *prefix;
2460 void client_option_envadd (struct option_cache *oc,
2461 struct packet *packet, struct lease *lease,
2462 struct client_state *client_state,
2463 struct option_state *in_options,
2464 struct option_state *cfg_options,
2465 struct binding_scope **scope,
2466 struct universe *u, void *stuff)
2468 struct envadd_state *es = stuff;
2469 struct data_string data;
2470 memset (&data, 0, sizeof data);
2472 if (evaluate_option_cache (&data, packet, lease, client_state,
2473 in_options, cfg_options, scope, oc, MDL)) {
2474 if (data.len) {
2475 char name [256];
2476 if (dhcp_option_ev_name (name, sizeof name,
2477 oc -> option)) {
2478 client_envadd (es -> client, es -> prefix,
2479 name, "%s",
2480 (pretty_print_option
2481 (oc -> option,
2482 data.data, data.len,
2483 0, 0)));
2484 data_string_forget (&data, MDL);
2490 void script_write_params (client, prefix, lease)
2491 struct client_state *client;
2492 const char *prefix;
2493 struct client_lease *lease;
2495 int i;
2496 struct data_string data;
2497 struct option_cache *oc;
2498 struct envadd_state es;
2500 es.client = client;
2501 es.prefix = prefix;
2503 client_envadd (client,
2504 prefix, "ip_address", "%s", piaddr (lease -> address));
2506 /* For the benefit of Linux (and operating systems which may
2507 have similar needs), compute the network address based on
2508 the supplied ip address and netmask, if provided. Also
2509 compute the broadcast address (the host address all ones
2510 broadcast address, not the host address all zeroes
2511 broadcast address). */
2513 memset (&data, 0, sizeof data);
2514 oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
2515 if (oc && evaluate_option_cache (&data, (struct packet *)0,
2516 (struct lease *)0, client,
2517 (struct option_state *)0,
2518 lease -> options,
2519 &global_scope, oc, MDL)) {
2520 if (data.len > 3) {
2521 struct iaddr netmask, subnet, broadcast;
2523 if (data.len > sizeof netmask.iabuf)
2524 data.len = sizeof netmask.iabuf;
2525 memcpy (netmask.iabuf, data.data, data.len);
2526 netmask.len = data.len;
2527 data_string_forget (&data, MDL);
2529 subnet = subnet_number (lease -> address, netmask);
2530 if (subnet.len) {
2531 client_envadd (client, prefix, "network_number",
2532 "%s", piaddr (subnet));
2534 oc = lookup_option (&dhcp_universe,
2535 lease -> options,
2536 DHO_BROADCAST_ADDRESS);
2537 if (!oc ||
2538 !(evaluate_option_cache
2539 (&data, (struct packet *)0,
2540 (struct lease *)0, client,
2541 (struct option_state *)0,
2542 lease -> options,
2543 &global_scope, oc, MDL))) {
2544 broadcast = broadcast_addr (subnet, netmask);
2545 if (broadcast.len) {
2546 client_envadd (client,
2547 prefix, "broadcast_address",
2548 "%s", piaddr (broadcast));
2553 data_string_forget (&data, MDL);
2556 if (lease -> filename)
2557 client_envadd (client,
2558 prefix, "filename", "%s", lease -> filename);
2559 if (lease -> server_name)
2560 client_envadd (client, prefix, "server_name",
2561 "%s", lease -> server_name);
2563 for (i = 0; i < lease -> options -> universe_count; i++) {
2564 option_space_foreach ((struct packet *)0, (struct lease *)0,
2565 client, (struct option_state *)0,
2566 lease -> options, &global_scope,
2567 universes [i],
2568 &es, client_option_envadd);
2570 client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry));
2573 int script_go (client)
2574 struct client_state *client;
2576 char *scriptName;
2577 char *argv [2];
2578 char **envp;
2579 char reason [] = "REASON=NBI";
2580 static char client_path [] = CLIENT_PATH;
2581 int i;
2582 struct string_list *sp, *next;
2583 int pid, wpid, wstatus;
2585 if (client)
2586 scriptName = client -> config -> script_name;
2587 else
2588 scriptName = top_level_config.script_name;
2590 envp = dmalloc (((client ? client -> envc : 2) +
2591 client_env_count + 2) * sizeof (char *), MDL);
2592 if (!envp) {
2593 log_error ("No memory for client script environment.");
2594 return 0;
2596 i = 0;
2597 /* Copy out the environment specified on the command line,
2598 if any. */
2599 for (sp = client_env; sp; sp = sp -> next) {
2600 envp [i++] = sp -> string;
2602 /* Copy out the environment specified by dhclient. */
2603 if (client) {
2604 for (sp = client -> env; sp; sp = sp -> next) {
2605 envp [i++] = sp -> string;
2607 } else {
2608 envp [i++] = reason;
2610 /* Set $PATH. */
2611 envp [i++] = client_path;
2612 envp [i] = (char *)0;
2614 argv [0] = scriptName;
2615 argv [1] = (char *)0;
2617 pid = fork ();
2618 if (pid < 0) {
2619 log_error ("fork: %m");
2620 wstatus = 0;
2621 } else if (pid) {
2622 do {
2623 wpid = wait (&wstatus);
2624 } while (wpid != pid && wpid > 0);
2625 if (wpid < 0) {
2626 log_error ("wait: %m");
2627 wstatus = 0;
2629 } else {
2630 execve (scriptName, argv, envp);
2631 log_error ("execve (%s, ...): %m", scriptName);
2632 exit (0);
2635 if (client) {
2636 for (sp = client -> env; sp; sp = next) {
2637 next = sp -> next;
2638 dfree (sp, MDL);
2640 client -> env = (struct string_list *)0;
2641 client -> envc = 0;
2643 dfree (envp, MDL);
2644 GET_TIME (&cur_time);
2645 return (WIFEXITED (wstatus) ?
2646 WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
2649 void client_envadd (struct client_state *client,
2650 const char *prefix, const char *name, const char *fmt, ...)
2652 char spbuf [1024];
2653 char *s;
2654 unsigned len;
2655 struct string_list *val;
2656 va_list list;
2658 va_start (list, fmt);
2659 len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
2660 va_end (list);
2662 val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
2663 len + sizeof *val, MDL);
2664 if (!val)
2665 return;
2666 s = val -> string;
2667 strcpy (s, prefix);
2668 strcat (s, name);
2669 s += strlen (s);
2670 *s++ = '=';
2671 if (len >= sizeof spbuf) {
2672 va_start (list, fmt);
2673 vsnprintf (s, len + 1, fmt, list);
2674 va_end (list);
2675 } else
2676 strcpy (s, spbuf);
2677 val -> next = client -> env;
2678 client -> env = val;
2679 client -> envc++;
2682 int dhcp_option_ev_name (buf, buflen, option)
2683 char *buf;
2684 size_t buflen;
2685 struct option *option;
2687 int i, j;
2688 const char *s;
2690 j = 0;
2691 if (option -> universe != &dhcp_universe) {
2692 s = option -> universe -> name;
2693 i = 0;
2694 } else {
2695 s = option -> name;
2696 i = 1;
2699 do {
2700 while (*s) {
2701 if (j + 1 == buflen)
2702 return 0;
2703 if (*s == '-')
2704 buf [j++] = '_';
2705 else
2706 buf [j++] = *s;
2707 ++s;
2709 if (!i) {
2710 s = option -> name;
2711 if (j + 1 == buflen)
2712 return 0;
2713 buf [j++] = '_';
2715 ++i;
2716 } while (i != 2);
2718 buf [j] = 0;
2719 return 1;
2722 void go_daemon ()
2724 static int state = 0;
2725 int pid;
2726 int i;
2728 /* Don't become a daemon if the user requested otherwise. */
2729 if (no_daemon) {
2730 write_client_pid_file ();
2731 return;
2734 /* Only do it once. */
2735 if (state)
2736 return;
2737 state = 1;
2739 /* Stop logging to stderr... */
2740 log_perror = 0;
2742 /* Become a daemon... */
2743 if ((pid = fork ()) < 0)
2744 log_fatal ("Can't fork daemon: %m");
2745 else if (pid)
2746 exit (0);
2747 /* Become session leader and get pid... */
2748 pid = setsid ();
2750 /* Close standard I/O descriptors. */
2751 close(0);
2752 close(1);
2753 close(2);
2755 /* Reopen them on /dev/null. */
2756 i = open ("/dev/null", O_RDWR);
2757 if (i == 0)
2758 i = open ("/dev/null", O_RDWR);
2759 if (i == 1) {
2760 i = open ("/dev/null", O_RDWR);
2761 log_perror = 0; /* No sense logging to /dev/null. */
2762 } else if (i != -1)
2763 close (i);
2765 write_client_pid_file ();
2768 void write_client_pid_file ()
2770 FILE *pf;
2771 int pfdesc;
2773 pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
2775 if (pfdesc < 0) {
2776 log_error ("Can't create %s: %m", path_dhclient_pid);
2777 return;
2780 pf = fdopen (pfdesc, "w");
2781 if (!pf)
2782 log_error ("Can't fdopen %s: %m", path_dhclient_pid);
2783 else {
2784 fprintf (pf, "%ld\n", (long)getpid ());
2785 fclose (pf);
2789 void client_location_changed ()
2791 struct interface_info *ip;
2792 struct client_state *client;
2794 for (ip = interfaces; ip; ip = ip -> next) {
2795 for (client = ip -> client; client; client = client -> next) {
2796 switch (client -> state) {
2797 case S_SELECTING:
2798 cancel_timeout (send_discover, client);
2799 break;
2801 case S_BOUND:
2802 cancel_timeout (state_bound, client);
2803 break;
2805 case S_REBOOTING:
2806 case S_REQUESTING:
2807 case S_RENEWING:
2808 cancel_timeout (send_request, client);
2809 break;
2811 case S_INIT:
2812 case S_REBINDING:
2813 case S_STOPPED:
2814 break;
2816 client -> state = S_INIT;
2817 state_reboot (client);
2822 void do_release(client)
2823 struct client_state *client;
2825 struct data_string ds;
2826 struct option_cache *oc;
2828 /* Pick a random xid. */
2829 client -> xid = random ();
2831 /* is there even a lease to release? */
2832 if (client -> active) {
2833 /* Make a DHCPRELEASE packet, and set appropriate per-interface
2834 flags. */
2835 make_release (client, client -> active);
2837 memset (&ds, 0, sizeof ds);
2838 oc = lookup_option (&dhcp_universe,
2839 client -> active -> options,
2840 DHO_DHCP_SERVER_IDENTIFIER);
2841 if (oc &&
2842 evaluate_option_cache (&ds, (struct packet *)0,
2843 (struct lease *)0, client,
2844 (struct option_state *)0,
2845 client -> active -> options,
2846 &global_scope, oc, MDL)) {
2847 if (ds.len > 3) {
2848 memcpy (client -> destination.iabuf,
2849 ds.data, 4);
2850 client -> destination.len = 4;
2851 } else
2852 client -> destination = iaddr_broadcast;
2854 data_string_forget (&ds, MDL);
2855 } else
2856 client -> destination = iaddr_broadcast;
2857 client -> first_sending = cur_time;
2858 client -> interval = client -> config -> initial_interval;
2860 /* Zap the medium list... */
2861 client -> medium = (struct string_list *)0;
2863 /* Send out the first and only DHCPRELEASE packet. */
2864 send_release (client);
2866 /* Do the client script RELEASE operation. */
2867 script_init (client,
2868 "RELEASE", (struct string_list *)0);
2869 if (client -> alias)
2870 script_write_params (client, "alias_",
2871 client -> alias);
2872 script_write_params (client, "old_", client -> active);
2873 script_go (client);
2876 /* Cancel any timeouts. */
2877 cancel_timeout (state_bound, client);
2878 cancel_timeout (send_discover, client);
2879 cancel_timeout (state_init, client);
2880 cancel_timeout (send_request, client);
2881 cancel_timeout (state_reboot, client);
2882 client -> state = S_STOPPED;
2885 int dhclient_interface_shutdown_hook (struct interface_info *interface)
2887 do_release (interface -> client);
2889 return 1;
2892 int dhclient_interface_discovery_hook (struct interface_info *tmp)
2894 struct interface_info *last, *ip;
2895 /* See if we can find the client from dummy_interfaces */
2896 last = 0;
2897 for (ip = dummy_interfaces; ip; ip = ip -> next) {
2898 if (!strcmp (ip -> name, tmp -> name)) {
2899 /* Remove from dummy_interfaces */
2900 if (last) {
2901 ip = (struct interface_info *)0;
2902 interface_reference (&ip, last -> next, MDL);
2903 interface_dereference (&last -> next, MDL);
2904 if (ip -> next) {
2905 interface_reference (&last -> next,
2906 ip -> next, MDL);
2907 interface_dereference (&ip -> next,
2908 MDL);
2910 } else {
2911 ip = (struct interface_info *)0;
2912 interface_reference (&ip,
2913 dummy_interfaces, MDL);
2914 interface_dereference (&dummy_interfaces, MDL);
2915 if (ip -> next) {
2916 interface_reference (&dummy_interfaces,
2917 ip -> next, MDL);
2918 interface_dereference (&ip -> next,
2919 MDL);
2922 /* Copy "client" to tmp */
2923 if (ip -> client) {
2924 tmp -> client = ip -> client;
2925 tmp -> client -> interface = tmp;
2927 interface_dereference (&ip, MDL);
2928 break;
2930 last = ip;
2932 return 1;
2935 isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
2937 struct interface_info *ip;
2938 struct client_state *client;
2940 /* This code needs some rethinking. It doesn't test against
2941 a signal name, and it just kind of bulls into doing something
2942 that may or may not be appropriate. */
2944 if (interfaces) {
2945 interface_reference (&interface -> next, interfaces, MDL);
2946 interface_dereference (&interfaces, MDL);
2948 interface_reference (&interfaces, interface, MDL);
2950 discover_interfaces (DISCOVER_UNCONFIGURED);
2952 for (ip = interfaces; ip; ip = ip -> next) {
2953 /* If interfaces were specified, don't configure
2954 interfaces that weren't specified! */
2955 if (ip -> flags & INTERFACE_RUNNING ||
2956 (ip -> flags & (INTERFACE_REQUESTED |
2957 INTERFACE_AUTOMATIC)) !=
2958 INTERFACE_REQUESTED)
2959 continue;
2960 script_init (ip -> client,
2961 "PREINIT", (struct string_list *)0);
2962 if (ip -> client -> alias)
2963 script_write_params (ip -> client, "alias_",
2964 ip -> client -> alias);
2965 script_go (ip -> client);
2968 discover_interfaces (interfaces_requested
2969 ? DISCOVER_REQUESTED
2970 : DISCOVER_RUNNING);
2972 for (ip = interfaces; ip; ip = ip -> next) {
2973 if (ip -> flags & INTERFACE_RUNNING)
2974 continue;
2975 ip -> flags |= INTERFACE_RUNNING;
2976 for (client = ip -> client; client; client = client -> next) {
2977 client -> state = S_INIT;
2978 /* Set up a timeout to start the initialization
2979 process. */
2980 add_timeout (cur_time + random () % 5,
2981 state_reboot, client, 0, 0);
2984 return ISC_R_SUCCESS;
2987 /* The client should never receive a relay agent information option,
2988 so if it does, log it and discard it. */
2990 int parse_agent_information_option (packet, len, data)
2991 struct packet *packet;
2992 int len;
2993 u_int8_t *data;
2995 return 1;
2998 /* The client never sends relay agent information options. */
3000 unsigned cons_agent_information_options (cfg_options, outpacket,
3001 agentix, length)
3002 struct option_state *cfg_options;
3003 struct dhcp_packet *outpacket;
3004 unsigned agentix;
3005 unsigned length;
3007 return length;
3010 static void shutdown_exit (void *foo)
3012 exit (0);
3015 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
3016 control_object_state_t newstate)
3018 struct interface_info *ip;
3019 struct client_state *client;
3021 /* Do the right thing for each interface. */
3022 for (ip = interfaces; ip; ip = ip -> next) {
3023 for (client = ip -> client; client; client = client -> next) {
3024 switch (newstate) {
3025 case server_startup:
3026 return ISC_R_SUCCESS;
3028 case server_running:
3029 return ISC_R_SUCCESS;
3031 case server_shutdown:
3032 if (client -> active &&
3033 client -> active -> expiry > cur_time) {
3034 if (client -> config -> do_forward_update)
3035 client_dns_update (client, 0, 0);
3036 do_release (client);
3038 break;
3040 case server_hibernate:
3041 state_stop (client);
3042 break;
3044 case server_awaken:
3045 state_reboot (client);
3046 break;
3050 if (newstate == server_shutdown)
3051 add_timeout (cur_time + 1, shutdown_exit, 0, 0, 0);
3052 return ISC_R_SUCCESS;
3055 /* Called after a timeout if the DNS update failed on the previous try.
3056 Retries the update, and if it times out, schedules a retry after
3057 ten times as long of a wait. */
3059 void client_dns_update_timeout (void *cp)
3061 struct client_state *client = cp;
3062 isc_result_t status;
3064 if (client -> active) {
3065 status = client_dns_update (client, 1,
3066 (client -> active -> renewal -
3067 cur_time));
3068 if (status == ISC_R_TIMEDOUT) {
3069 client -> dns_update_timeout *= 10;
3070 add_timeout (cur_time + client -> dns_update_timeout,
3071 client_dns_update_timeout, client, 0, 0);
3076 /* See if we should do a DNS update, and if so, do it. */
3078 isc_result_t client_dns_update (struct client_state *client, int addp, int ttl)
3080 struct data_string ddns_fwd_name,
3081 ddns_dhcid, client_identifier;
3082 struct option_cache *oc;
3083 int ignorep;
3084 int result;
3085 isc_result_t rcode;
3087 rcode = ISC_R_FAILURE; /* XXXGCC -Wuninitialized */
3089 /* If we didn't send an FQDN option, we certainly aren't going to
3090 be doing an update. */
3091 if (!client -> sent_options)
3092 return ISC_R_SUCCESS;
3094 /* If we don't have a lease, we can't do an update. */
3095 if (!client -> active)
3096 return ISC_R_SUCCESS;
3098 /* If we set the no client update flag, don't do the update. */
3099 if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
3100 FQDN_NO_CLIENT_UPDATE)) &&
3101 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
3102 (struct lease *)0, client,
3103 client -> sent_options,
3104 (struct option_state *)0,
3105 &global_scope, oc, MDL))
3106 return ISC_R_SUCCESS;
3108 /* If we set the "server, please update" flag, or didn't set it
3109 to false, don't do the update. */
3110 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
3111 FQDN_SERVER_UPDATE)) ||
3112 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
3113 (struct lease *)0, client,
3114 client -> sent_options,
3115 (struct option_state *)0,
3116 &global_scope, oc, MDL))
3117 return ISC_R_SUCCESS;
3119 /* If no FQDN option was supplied, don't do the update. */
3120 memset (&ddns_fwd_name, 0, sizeof ddns_fwd_name);
3121 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
3122 FQDN_FQDN)) ||
3123 !evaluate_option_cache (&ddns_fwd_name, (struct packet *)0,
3124 (struct lease *)0, client,
3125 client -> sent_options,
3126 (struct option_state *)0,
3127 &global_scope, oc, MDL))
3128 return ISC_R_SUCCESS;
3130 #ifndef SMALL
3131 /* Make a dhcid string out of either the client identifier,
3132 if we are sending one, or the interface's MAC address,
3133 otherwise. */
3134 memset (&ddns_dhcid, 0, sizeof ddns_dhcid);
3136 memset (&client_identifier, 0, sizeof client_identifier);
3137 if ((oc = lookup_option (&dhcp_universe, client -> sent_options,
3138 DHO_DHCP_CLIENT_IDENTIFIER)) &&
3139 evaluate_option_cache (&client_identifier, (struct packet *)0,
3140 (struct lease *)0, client,
3141 client -> sent_options,
3142 (struct option_state *)0,
3143 &global_scope, oc, MDL)) {
3144 result = get_dhcid (&ddns_dhcid,
3145 DHO_DHCP_CLIENT_IDENTIFIER,
3146 client_identifier.data,
3147 client_identifier.len);
3148 data_string_forget (&client_identifier, MDL);
3149 } else
3150 result = get_dhcid (&ddns_dhcid, 0,
3151 client -> interface -> hw_address.hbuf,
3152 client -> interface -> hw_address.hlen);
3153 if (!result) {
3154 data_string_forget (&ddns_fwd_name, MDL);
3155 return ISC_R_SUCCESS;
3158 /* Start the resolver, if necessary. */
3159 if (!resolver_inited) {
3160 minires_ninit (&resolver_state);
3161 resolver_inited = 1;
3162 resolver_state.retrans = 1;
3163 resolver_state.retry = 1;
3167 * Perform updates.
3169 if (ddns_fwd_name.len && ddns_dhcid.len) {
3170 if (addp)
3171 rcode = ddns_update_a (&ddns_fwd_name,
3172 client -> active -> address,
3173 &ddns_dhcid, ttl,
3175 else
3176 rcode = ddns_remove_a (&ddns_fwd_name,
3177 client -> active -> address,
3178 &ddns_dhcid);
3179 } else
3180 rcode = ISC_R_FAILURE;
3182 data_string_forget (&ddns_fwd_name, MDL);
3183 data_string_forget (&ddns_dhcid, MDL);
3184 #endif
3185 return rcode;