Pre-2.0 release, MFC firewire disk changes to properly detach SIMs.
[dragonfly.git] / contrib / dhcp-3.0 / client / dhclient.c
blob709c507c601cede972f28505fdea859ba97f8cbb
1 /* dhclient.c
3 DHCP Client. */
5 /*
6 * Copyright (c) 2004 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.129.2.23 2004/11/24 17:39:14 dhankins Exp $ Copyright (c) 2004 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 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 quiet=0;
76 int nowait=0;
78 static void usage PROTO ((void));
80 void do_release(struct client_state *);
82 int main (argc, argv, envp)
83 int argc;
84 char **argv, **envp;
86 int i;
87 struct servent *ent;
88 struct interface_info *ip;
89 struct client_state *client;
90 unsigned seed;
91 char *server = (char *)0;
92 char *relay = (char *)0;
93 isc_result_t status;
94 int release_mode = 0;
95 omapi_object_t *listener;
96 isc_result_t result;
97 int persist = 0;
98 int omapi_port;
99 int no_dhclient_conf = 0;
100 int no_dhclient_db = 0;
101 int no_dhclient_pid = 0;
102 int no_dhclient_script = 0;
103 char *s;
105 /* Make sure we have stdin, stdout and stderr. */
106 i = open ("/dev/null", O_RDWR);
107 if (i == 0)
108 i = open ("/dev/null", O_RDWR);
109 if (i == 1) {
110 i = open ("/dev/null", O_RDWR);
111 log_perror = 0; /* No sense logging to /dev/null. */
112 } else if (i != -1)
113 close (i);
115 #ifdef SYSLOG_4_2
116 openlog ("dhclient", LOG_NDELAY);
117 log_priority = LOG_DAEMON;
118 #else
119 openlog ("dhclient", LOG_NDELAY, LOG_DAEMON);
120 #endif
122 #if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__))
123 setlogmask (LOG_UPTO (LOG_INFO));
124 #endif
126 /* Set up the OMAPI. */
127 status = omapi_init ();
128 if (status != ISC_R_SUCCESS)
129 log_fatal ("Can't initialize OMAPI: %s",
130 isc_result_totext (status));
132 /* Set up the OMAPI wrappers for various server database internal
133 objects. */
134 dhcp_common_objects_setup ();
136 dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
137 dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
138 dhcp_interface_startup_hook = dhclient_interface_startup_hook;
140 for (i = 1; i < argc; i++) {
141 if (!strcmp (argv [i], "-r")) {
142 release_mode = 1;
143 no_daemon = 1;
144 } else if (!strcmp (argv [i], "-p")) {
145 if (++i == argc)
146 usage ();
147 local_port = htons (atoi (argv [i]));
148 log_debug ("binding to user-specified port %d",
149 ntohs (local_port));
150 } else if (!strcmp (argv [i], "-d")) {
151 no_daemon = 1;
152 } else if (!strcmp (argv [i], "-pf")) {
153 if (++i == argc)
154 usage ();
155 path_dhclient_pid = argv [i];
156 no_dhclient_pid = 1;
157 } else if (!strcmp (argv [i], "-cf")) {
158 if (++i == argc)
159 usage ();
160 path_dhclient_conf = argv [i];
161 no_dhclient_conf = 1;
162 } else if (!strcmp (argv [i], "-lf")) {
163 if (++i == argc)
164 usage ();
165 path_dhclient_db = argv [i];
166 no_dhclient_db = 1;
167 } else if (!strcmp (argv [i], "-sf")) {
168 if (++i == argc)
169 usage ();
170 path_dhclient_script = argv [i];
171 no_dhclient_script = 1;
172 } else if (!strcmp (argv [i], "-1")) {
173 onetry = 1;
174 } else if (!strcmp (argv [i], "-q")) {
175 quiet = 1;
176 quiet_interface_discovery = 1;
177 } else if (!strcmp (argv [i], "-s")) {
178 if (++i == argc)
179 usage ();
180 server = argv [i];
181 } else if (!strcmp (argv [i], "-g")) {
182 if (++i == argc)
183 usage ();
184 relay = argv [i];
185 } else if (!strcmp (argv [i], "-nw")) {
186 nowait = 1;
187 } else if (!strcmp (argv [i], "-n")) {
188 /* do not start up any interfaces */
189 interfaces_requested = 1;
190 } else if (!strcmp (argv [i], "-w")) {
191 /* do not exit if there are no broadcast interfaces. */
192 persist = 1;
193 } else if (!strcmp (argv [i], "-e")) {
194 struct string_list *tmp;
195 if (++i == argc)
196 usage ();
197 tmp = dmalloc (strlen (argv [i]) + sizeof *tmp, MDL);
198 if (!tmp)
199 log_fatal ("No memory for %s", argv [i]);
200 strcpy (tmp -> string, argv [i]);
201 tmp -> next = client_env;
202 client_env = tmp;
203 client_env_count++;
204 } else if (!strcmp (argv [i], "--version")) {
205 log_info ("isc-dhclient-%s", DHCP_VERSION);
206 exit (0);
207 } else if (argv [i][0] == '-') {
208 usage ();
209 } else {
210 struct interface_info *tmp = (struct interface_info *)0;
211 status = interface_allocate (&tmp, MDL);
212 if (status != ISC_R_SUCCESS)
213 log_fatal ("Can't record interface %s:%s",
214 argv [i], isc_result_totext (status));
215 if (strlen (argv [i]) > sizeof tmp -> name)
216 log_fatal ("%s: interface name too long (max %ld)",
217 argv [i], (long)strlen (argv [i]));
218 strcpy (tmp -> name, argv [i]);
219 if (interfaces) {
220 interface_reference (&tmp -> next,
221 interfaces, MDL);
222 interface_dereference (&interfaces, MDL);
224 interface_reference (&interfaces, tmp, MDL);
225 tmp -> flags = INTERFACE_REQUESTED;
226 interfaces_requested = 1;
230 if (!no_dhclient_conf && (s = getenv ("PATH_DHCLIENT_CONF"))) {
231 path_dhclient_conf = s;
233 if (!no_dhclient_db && (s = getenv ("PATH_DHCLIENT_DB"))) {
234 path_dhclient_db = s;
236 if (!no_dhclient_pid && (s = getenv ("PATH_DHCLIENT_PID"))) {
237 path_dhclient_pid = s;
239 if (!no_dhclient_script && (s = getenv ("PATH_DHCLIENT_SCRIPT"))) {
240 path_dhclient_script = s;
243 /* first kill of any currently running client */
244 if (release_mode) {
245 FILE *pidfd;
246 pid_t oldpid;
247 long temp;
248 int e;
250 oldpid = 0;
251 if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) {
252 e = fscanf(pidfd, "%ld\n", &temp);
253 oldpid = (pid_t)temp;
255 if (e != 0 && e != EOF) {
256 if (oldpid) {
257 if (kill(oldpid, SIGTERM) == 0)
258 unlink(path_dhclient_pid);
261 fclose(pidfd);
265 if (!quiet) {
266 log_info ("%s %s", message, DHCP_VERSION);
267 log_info (copyright);
268 log_info (arr);
269 log_info (url);
270 log_info ("%s", "");
271 } else
272 log_perror = 0;
274 /* If we're given a relay agent address to insert, for testing
275 purposes, figure out what it is. */
276 if (relay) {
277 if (!inet_aton (relay, &giaddr)) {
278 struct hostent *he;
279 he = gethostbyname (relay);
280 if (he) {
281 memcpy (&giaddr, he -> h_addr_list [0],
282 sizeof giaddr);
283 } else {
284 log_fatal ("%s: no such host", relay);
289 /* Default to the DHCP/BOOTP port. */
290 if (!local_port) {
291 /* If we're faking a relay agent, and we're not using loopback,
292 use the server port, not the client port. */
293 if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
294 local_port = htons(67);
295 } else {
296 ent = getservbyname ("dhcpc", "udp");
297 if (!ent)
298 local_port = htons (68);
299 else
300 local_port = ent -> s_port;
301 #ifndef __CYGWIN32__
302 endservent ();
303 #endif
307 /* If we're faking a relay agent, and we're not using loopback,
308 we're using the server port, not the client port. */
309 if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
310 remote_port = local_port;
311 } else
312 remote_port = htons (ntohs (local_port) - 1); /* XXX */
314 /* Get the current time... */
315 GET_TIME (&cur_time);
317 sockaddr_broadcast.sin_family = AF_INET;
318 sockaddr_broadcast.sin_port = remote_port;
319 if (server) {
320 if (!inet_aton (server, &sockaddr_broadcast.sin_addr)) {
321 struct hostent *he;
322 he = gethostbyname (server);
323 if (he) {
324 memcpy (&sockaddr_broadcast.sin_addr,
325 he -> h_addr_list [0],
326 sizeof sockaddr_broadcast.sin_addr);
327 } else
328 sockaddr_broadcast.sin_addr.s_addr =
329 INADDR_BROADCAST;
331 } else {
332 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
335 inaddr_any.s_addr = INADDR_ANY;
337 /* Discover all the network interfaces. */
338 discover_interfaces (DISCOVER_UNCONFIGURED);
340 /* Parse the dhclient.conf file. */
341 read_client_conf ();
343 /* Parse the lease database. */
344 read_client_leases ();
346 /* Rewrite the lease database... */
347 rewrite_client_leases ();
349 /* XXX */
350 /* config_counter(&snd_counter, &rcv_counter); */
352 /* If no broadcast interfaces were discovered, call the script
353 and tell it so. */
354 if (!interfaces) {
355 /* Call dhclient-script with the NBI flag, in case somebody
356 cares. */
357 script_init ((struct client_state *)0, "NBI",
358 (struct string_list *)0);
359 script_go ((struct client_state *)0);
361 /* If we haven't been asked to persist, waiting for new
362 interfaces, then just exit. */
363 if (!persist) {
364 /* Nothing more to do. */
365 log_info ("No broadcast interfaces found - exiting.");
366 exit (0);
368 } else if (!release_mode) {
369 /* Call the script with the list of interfaces. */
370 for (ip = interfaces; ip; ip = ip -> next) {
371 /* If interfaces were specified, don't configure
372 interfaces that weren't specified! */
373 if (interfaces_requested &&
374 ((ip -> flags & (INTERFACE_REQUESTED |
375 INTERFACE_AUTOMATIC)) !=
376 INTERFACE_REQUESTED))
377 continue;
378 script_init (ip -> client,
379 "PREINIT", (struct string_list *)0);
380 if (ip -> client -> alias)
381 script_write_params (ip -> client, "alias_",
382 ip -> client -> alias);
383 script_go (ip -> client);
387 /* At this point, all the interfaces that the script thinks
388 are relevant should be running, so now we once again call
389 discover_interfaces(), and this time ask it to actually set
390 up the interfaces. */
391 discover_interfaces (interfaces_requested
392 ? DISCOVER_REQUESTED
393 : DISCOVER_RUNNING);
395 /* Make up a seed for the random number generator from current
396 time plus the sum of the last four bytes of each
397 interface's hardware address interpreted as an integer.
398 Not much entropy, but we're booting, so we're not likely to
399 find anything better. */
400 seed = 0;
401 for (ip = interfaces; ip; ip = ip -> next) {
402 int junk;
403 memcpy (&junk,
404 &ip -> hw_address.hbuf [ip -> hw_address.hlen -
405 sizeof seed], sizeof seed);
406 seed += junk;
408 srandom (seed + cur_time);
410 /* Start a configuration state machine for each interface. */
411 for (ip = interfaces; ip; ip = ip -> next) {
412 ip -> flags |= INTERFACE_RUNNING;
413 for (client = ip -> client; client; client = client -> next) {
414 if (release_mode)
415 do_release (client);
416 else {
417 client -> state = S_INIT;
418 /* Set up a timeout to start the initialization
419 process. */
420 add_timeout (cur_time + random () % 5,
421 state_reboot, client, 0, 0);
426 if (release_mode)
427 return 0;
429 /* Start up a listener for the object management API protocol. */
430 if (top_level_config.omapi_port != -1) {
431 listener = (omapi_object_t *)0;
432 result = omapi_generic_new (&listener, MDL);
433 if (result != ISC_R_SUCCESS)
434 log_fatal ("Can't allocate new generic object: %s\n",
435 isc_result_totext (result));
436 result = omapi_protocol_listen (listener,
437 (unsigned)
438 top_level_config.omapi_port,
440 if (result != ISC_R_SUCCESS)
441 log_fatal ("Can't start OMAPI protocol: %s",
442 isc_result_totext (result));
445 /* Set up the bootp packet handler... */
446 bootp_packet_handler = do_packet;
448 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
449 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
450 dmalloc_cutoff_generation = dmalloc_generation;
451 dmalloc_longterm = dmalloc_outstanding;
452 dmalloc_outstanding = 0;
453 #endif
455 /* If we're not supposed to wait before getting the address,
456 don't. */
457 if (nowait)
458 go_daemon ();
460 /* If we're not going to daemonize, write the pid file
461 now. */
462 if (no_daemon || nowait)
463 write_client_pid_file ();
465 /* Start dispatching packets and timeouts... */
466 dispatch ();
468 /*NOTREACHED*/
469 return 0;
472 static void usage ()
474 log_info ("%s %s", message, DHCP_VERSION);
475 log_info (copyright);
476 log_info (arr);
477 log_info (url);
479 log_error ("Usage: dhclient [-1dqr] [-nw] [-p <port>] %s",
480 "[-s server]");
481 log_error (" [-cf config-file] [-lf lease-file]%s",
482 "[-pf pid-file] [-e VAR=val]");
483 log_fatal (" [-sf script-file] [interface]");
486 isc_result_t find_class (struct class **c,
487 const char *s, const char *file, int line)
489 return 0;
492 int check_collection (packet, lease, collection)
493 struct packet *packet;
494 struct lease *lease;
495 struct collection *collection;
497 return 0;
500 void classify (packet, class)
501 struct packet *packet;
502 struct class *class;
506 int unbill_class (lease, class)
507 struct lease *lease;
508 struct class *class;
510 return 0;
513 int find_subnet (struct subnet **sp,
514 struct iaddr addr, const char *file, int line)
516 return 0;
519 /* Individual States:
521 * Each routine is called from the dhclient_state_machine() in one of
522 * these conditions:
523 * -> entering INIT state
524 * -> recvpacket_flag == 0: timeout in this state
525 * -> otherwise: received a packet in this state
527 * Return conditions as handled by dhclient_state_machine():
528 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
529 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
530 * Returns 0: finish the nap which was interrupted for no good reason.
532 * Several per-interface variables are used to keep track of the process:
533 * active_lease: the lease that is being used on the interface
534 * (null pointer if not configured yet).
535 * offered_leases: leases corresponding to DHCPOFFER messages that have
536 * been sent to us by DHCP servers.
537 * acked_leases: leases corresponding to DHCPACK messages that have been
538 * sent to us by DHCP servers.
539 * sendpacket: DHCP packet we're trying to send.
540 * destination: IP address to send sendpacket to
541 * In addition, there are several relevant per-lease variables.
542 * T1_expiry, T2_expiry, lease_expiry: lease milestones
543 * In the active lease, these control the process of renewing the lease;
544 * In leases on the acked_leases list, this simply determines when we
545 * can no longer legitimately use the lease.
548 void state_reboot (cpp)
549 void *cpp;
551 struct client_state *client = cpp;
553 /* If we don't remember an active lease, go straight to INIT. */
554 if (!client -> active ||
555 client -> active -> is_bootp ||
556 client -> active -> expiry <= cur_time) {
557 state_init (client);
558 return;
561 /* We are in the rebooting state. */
562 client -> state = S_REBOOTING;
564 /* make_request doesn't initialize xid because it normally comes
565 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
566 so pick an xid now. */
567 client -> xid = random ();
569 /* Make a DHCPREQUEST packet, and set appropriate per-interface
570 flags. */
571 make_request (client, client -> active);
572 client -> destination = iaddr_broadcast;
573 client -> first_sending = cur_time;
574 client -> interval = client -> config -> initial_interval;
576 /* Zap the medium list... */
577 client -> medium = (struct string_list *)0;
579 /* Send out the first DHCPREQUEST packet. */
580 send_request (client);
583 /* Called when a lease has completely expired and we've been unable to
584 renew it. */
586 void state_init (cpp)
587 void *cpp;
589 struct client_state *client = cpp;
591 ASSERT_STATE(state, S_INIT);
593 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
594 flags. */
595 make_discover (client, client -> active);
596 client -> xid = client -> packet.xid;
597 client -> destination = iaddr_broadcast;
598 client -> state = S_SELECTING;
599 client -> first_sending = cur_time;
600 client -> interval = client -> config -> initial_interval;
602 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
603 to go out. */
604 send_discover (client);
607 /* state_selecting is called when one or more DHCPOFFER packets have been
608 received and a configurable period of time has passed. */
610 void state_selecting (cpp)
611 void *cpp;
613 struct client_state *client = cpp;
614 struct client_lease *lp, *next, *picked;
617 ASSERT_STATE(state, S_SELECTING);
619 /* Cancel state_selecting and send_discover timeouts, since either
620 one could have got us here. */
621 cancel_timeout (state_selecting, client);
622 cancel_timeout (send_discover, client);
624 /* We have received one or more DHCPOFFER packets. Currently,
625 the only criterion by which we judge leases is whether or
626 not we get a response when we arp for them. */
627 picked = (struct client_lease *)0;
628 for (lp = client -> offered_leases; lp; lp = next) {
629 next = lp -> next;
631 /* Check to see if we got an ARPREPLY for the address
632 in this particular lease. */
633 if (!picked) {
634 picked = lp;
635 picked -> next = (struct client_lease *)0;
636 } else {
637 freeit:
638 destroy_client_lease (lp);
641 client -> offered_leases = (struct client_lease *)0;
643 /* If we just tossed all the leases we were offered, go back
644 to square one. */
645 if (!picked) {
646 client -> state = S_INIT;
647 state_init (client);
648 return;
651 /* If it was a BOOTREPLY, we can just take the address right now. */
652 if (picked -> is_bootp) {
653 client -> new = picked;
655 /* Make up some lease expiry times
656 XXX these should be configurable. */
657 client -> new -> expiry = cur_time + 12000;
658 client -> new -> renewal += cur_time + 8000;
659 client -> new -> rebind += cur_time + 10000;
661 client -> state = S_REQUESTING;
663 /* Bind to the address we received. */
664 bind_lease (client);
665 return;
668 /* Go to the REQUESTING state. */
669 client -> destination = iaddr_broadcast;
670 client -> state = S_REQUESTING;
671 client -> first_sending = cur_time;
672 client -> interval = client -> config -> initial_interval;
674 /* Make a DHCPREQUEST packet from the lease we picked. */
675 make_request (client, picked);
676 client -> xid = client -> packet.xid;
678 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
679 destroy_client_lease (picked);
681 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
682 send_request (client);
685 /* state_requesting is called when we receive a DHCPACK message after
686 having sent out one or more DHCPREQUEST packets. */
688 void dhcpack (packet)
689 struct packet *packet;
691 struct interface_info *ip = packet -> interface;
692 struct client_state *client;
693 struct client_lease *lease;
694 struct option_cache *oc;
695 struct data_string ds;
696 int i;
698 /* If we're not receptive to an offer right now, or if the offer
699 has an unrecognizable transaction id, then just drop it. */
700 for (client = ip -> client; client; client = client -> next) {
701 if (client -> xid == packet -> raw -> xid)
702 break;
704 if (!client ||
705 (packet -> interface -> hw_address.hlen - 1 !=
706 packet -> raw -> hlen) ||
707 (memcmp (&packet -> interface -> hw_address.hbuf [1],
708 packet -> raw -> chaddr, packet -> raw -> hlen))) {
709 #if defined (DEBUG)
710 log_debug ("DHCPACK in wrong transaction.");
711 #endif
712 return;
715 if (client -> state != S_REBOOTING &&
716 client -> state != S_REQUESTING &&
717 client -> state != S_RENEWING &&
718 client -> state != S_REBINDING) {
719 #if defined (DEBUG)
720 log_debug ("DHCPACK in wrong state.");
721 #endif
722 return;
725 log_info ("DHCPACK from %s", piaddr (packet -> client_addr));
727 lease = packet_to_lease (packet, client);
728 if (!lease) {
729 log_info ("packet_to_lease failed.");
730 return;
733 client -> new = lease;
735 /* Stop resending DHCPREQUEST. */
736 cancel_timeout (send_request, client);
738 /* Figure out the lease time. */
739 oc = lookup_option (&dhcp_universe, client -> new -> options,
740 DHO_DHCP_LEASE_TIME);
741 memset (&ds, 0, sizeof ds);
742 if (oc &&
743 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
744 packet -> options, client -> new -> options,
745 &global_scope, oc, MDL)) {
746 if (ds.len > 3)
747 client -> new -> expiry = getULong (ds.data);
748 else
749 client -> new -> expiry = 0;
750 data_string_forget (&ds, MDL);
751 } else
752 client -> new -> expiry = 0;
754 if (!client -> new -> expiry) {
755 log_error ("no expiry time on offered lease.");
756 /* XXX this is going to be bad - if this _does_
757 XXX happen, we should probably dynamically
758 XXX disqualify the DHCP server that gave us the
759 XXX bad packet from future selections and
760 XXX then go back into the init state. */
761 state_init (client);
762 return;
765 /* A number that looks negative here is really just very large,
766 because the lease expiry offset is unsigned. */
767 if (client -> new -> expiry < 0)
768 client -> new -> expiry = TIME_MAX;
769 /* Take the server-provided renewal time if there is one. */
770 oc = lookup_option (&dhcp_universe, client -> new -> options,
771 DHO_DHCP_RENEWAL_TIME);
772 if (oc &&
773 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
774 packet -> options, client -> new -> options,
775 &global_scope, oc, MDL)) {
776 if (ds.len > 3)
777 client -> new -> renewal = getULong (ds.data);
778 else
779 client -> new -> renewal = 0;
780 data_string_forget (&ds, MDL);
781 } else
782 client -> new -> renewal = 0;
784 /* If it wasn't specified by the server, calculate it. */
785 if (!client -> new -> renewal)
786 client -> new -> renewal = client -> new -> expiry / 2 + 1;
788 if (client -> new -> renewal <= 0)
789 client -> new -> renewal = TIME_MAX;
791 /* Now introduce some randomness to the renewal time: */
792 if (client -> new -> renewal <= TIME_MAX / 3 - 3)
793 client -> new -> renewal =
794 (((client -> new -> renewal + 3) * 3 / 4) +
795 (random () % /* XXX NUMS */
796 ((client -> new -> renewal + 3) / 4)));
798 /* Same deal with the rebind time. */
799 oc = lookup_option (&dhcp_universe, client -> new -> options,
800 DHO_DHCP_REBINDING_TIME);
801 if (oc &&
802 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
803 packet -> options, client -> new -> options,
804 &global_scope, oc, MDL)) {
805 if (ds.len > 3)
806 client -> new -> rebind = getULong (ds.data);
807 else
808 client -> new -> rebind = 0;
809 data_string_forget (&ds, MDL);
810 } else
811 client -> new -> rebind = 0;
813 if (client -> new -> rebind <= 0) {
814 if (client -> new -> expiry <= TIME_MAX / 7)
815 client -> new -> rebind =
816 client -> new -> expiry * 7 / 8;
817 else
818 client -> new -> rebind =
819 client -> new -> expiry / 8 * 7;
822 /* Make sure our randomness didn't run the renewal time past the
823 rebind time. */
824 if (client -> new -> renewal > client -> new -> rebind) {
825 if (client -> new -> rebind <= TIME_MAX / 3)
826 client -> new -> renewal =
827 client -> new -> rebind * 3 / 4;
828 else
829 client -> new -> renewal =
830 client -> new -> rebind / 4 * 3;
833 client -> new -> expiry += cur_time;
834 /* Lease lengths can never be negative. */
835 if (client -> new -> expiry < cur_time)
836 client -> new -> expiry = TIME_MAX;
837 client -> new -> renewal += cur_time;
838 if (client -> new -> renewal < cur_time)
839 client -> new -> renewal = TIME_MAX;
840 client -> new -> rebind += cur_time;
841 if (client -> new -> rebind < cur_time)
842 client -> new -> rebind = TIME_MAX;
844 bind_lease (client);
847 void bind_lease (client)
848 struct client_state *client;
850 struct interface_info *ip = client -> interface;
852 /* Remember the medium. */
853 client -> new -> medium = client -> medium;
855 /* Run the client script with the new parameters. */
856 script_init (client, (client -> state == S_REQUESTING
857 ? "BOUND"
858 : (client -> state == S_RENEWING
859 ? "RENEW"
860 : (client -> state == S_REBOOTING
861 ? "REBOOT" : "REBIND"))),
862 client -> new -> medium);
863 if (client -> active && client -> state != S_REBOOTING)
864 script_write_params (client, "old_", client -> active);
865 script_write_params (client, "new_", client -> new);
866 if (client -> alias)
867 script_write_params (client, "alias_", client -> alias);
869 /* If the BOUND/RENEW code detects another machine using the
870 offered address, it exits nonzero. We need to send a
871 DHCPDECLINE and toss the lease. */
872 if (script_go (client)) {
873 make_decline (client, client -> new);
874 send_decline (client);
875 destroy_client_lease (client -> new);
876 client -> new = (struct client_lease *)0;
877 state_init (client);
878 return;
881 /* Write out the new lease. */
882 write_client_lease (client, client -> new, 0, 0);
884 /* Replace the old active lease with the new one. */
885 if (client -> active)
886 destroy_client_lease (client -> active);
887 client -> active = client -> new;
888 client -> new = (struct client_lease *)0;
890 /* Set up a timeout to start the renewal process. */
891 add_timeout (client -> active -> renewal,
892 state_bound, client, 0, 0);
894 log_info ("bound to %s -- renewal in %ld seconds.",
895 piaddr (client -> active -> address),
896 (long)(client -> active -> renewal - cur_time));
897 client -> state = S_BOUND;
898 reinitialize_interfaces ();
899 go_daemon ();
900 if (client -> config -> do_forward_update) {
901 client -> dns_update_timeout = 1;
902 add_timeout (cur_time + 1, client_dns_update_timeout,
903 client, 0, 0);
907 /* state_bound is called when we've successfully bound to a particular
908 lease, but the renewal time on that lease has expired. We are
909 expected to unicast a DHCPREQUEST to the server that gave us our
910 original lease. */
912 void state_bound (cpp)
913 void *cpp;
915 struct client_state *client = cpp;
916 int i;
917 struct option_cache *oc;
918 struct data_string ds;
920 ASSERT_STATE(state, S_BOUND);
922 /* T1 has expired. */
923 make_request (client, client -> active);
924 client -> xid = client -> packet.xid;
926 memset (&ds, 0, sizeof ds);
927 oc = lookup_option (&dhcp_universe, client -> active -> options,
928 DHO_DHCP_SERVER_IDENTIFIER);
929 if (oc &&
930 evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
931 client, (struct option_state *)0,
932 client -> active -> options,
933 &global_scope, oc, MDL)) {
934 if (ds.len > 3) {
935 memcpy (client -> destination.iabuf, ds.data, 4);
936 client -> destination.len = 4;
937 } else
938 client -> destination = iaddr_broadcast;
940 data_string_forget (&ds, MDL);
941 } else
942 client -> destination = iaddr_broadcast;
944 client -> first_sending = cur_time;
945 client -> interval = client -> config -> initial_interval;
946 client -> state = S_RENEWING;
948 /* Send the first packet immediately. */
949 send_request (client);
952 /* state_stop is called when we've been told to shut down. We unconfigure
953 the interfaces, and then stop operating until told otherwise. */
955 void state_stop (cpp)
956 void *cpp;
958 struct client_state *client = cpp;
959 int i;
961 /* Cancel all timeouts. */
962 cancel_timeout (state_selecting, client);
963 cancel_timeout (send_discover, client);
964 cancel_timeout (send_request, client);
965 cancel_timeout (state_bound, client);
967 /* If we have an address, unconfigure it. */
968 if (client -> active) {
969 script_init (client, "STOP", client -> active -> medium);
970 script_write_params (client, "old_", client -> active);
971 if (client -> alias)
972 script_write_params (client, "alias_",
973 client -> alias);
974 script_go (client);
978 int commit_leases ()
980 return 0;
983 int write_lease (lease)
984 struct lease *lease;
986 return 0;
989 int write_host (host)
990 struct host_decl *host;
992 return 0;
995 void db_startup (testp)
996 int testp;
1000 void bootp (packet)
1001 struct packet *packet;
1003 struct iaddrlist *ap;
1005 if (packet -> raw -> op != BOOTREPLY)
1006 return;
1008 /* If there's a reject list, make sure this packet's sender isn't
1009 on it. */
1010 for (ap = packet -> interface -> client -> config -> reject_list;
1011 ap; ap = ap -> next) {
1012 if (addr_eq (packet -> client_addr, ap -> addr)) {
1013 log_info ("BOOTREPLY from %s rejected.",
1014 piaddr (ap -> addr));
1015 return;
1019 dhcpoffer (packet);
1023 void dhcp (packet)
1024 struct packet *packet;
1026 struct iaddrlist *ap;
1027 void (*handler) PROTO ((struct packet *));
1028 const char *type;
1030 switch (packet -> packet_type) {
1031 case DHCPOFFER:
1032 handler = dhcpoffer;
1033 type = "DHCPOFFER";
1034 break;
1036 case DHCPNAK:
1037 handler = dhcpnak;
1038 type = "DHCPNACK";
1039 break;
1041 case DHCPACK:
1042 handler = dhcpack;
1043 type = "DHCPACK";
1044 break;
1046 default:
1047 return;
1050 /* If there's a reject list, make sure this packet's sender isn't
1051 on it. */
1052 for (ap = packet -> interface -> client -> config -> reject_list;
1053 ap; ap = ap -> next) {
1054 if (addr_eq (packet -> client_addr, ap -> addr)) {
1055 log_info ("%s from %s rejected.",
1056 type, piaddr (ap -> addr));
1057 return;
1060 (*handler) (packet);
1063 void dhcpoffer (packet)
1064 struct packet *packet;
1066 struct interface_info *ip = packet -> interface;
1067 struct client_state *client;
1068 struct client_lease *lease, *lp;
1069 int i;
1070 int stop_selecting;
1071 const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
1072 struct iaddrlist *ap;
1073 struct option_cache *oc;
1074 char obuf [1024];
1076 #ifdef DEBUG_PACKET
1077 dump_packet (packet);
1078 #endif
1080 /* Find a client state that matches the xid... */
1081 for (client = ip -> client; client; client = client -> next)
1082 if (client -> xid == packet -> raw -> xid)
1083 break;
1085 /* If we're not receptive to an offer right now, or if the offer
1086 has an unrecognizable transaction id, then just drop it. */
1087 if (!client ||
1088 client -> state != S_SELECTING ||
1089 (packet -> interface -> hw_address.hlen - 1 !=
1090 packet -> raw -> hlen) ||
1091 (memcmp (&packet -> interface -> hw_address.hbuf [1],
1092 packet -> raw -> chaddr, packet -> raw -> hlen))) {
1093 #if defined (DEBUG)
1094 log_debug ("%s in wrong transaction.", name);
1095 #endif
1096 return;
1099 sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
1102 /* If this lease doesn't supply the minimum required parameters,
1103 blow it off. */
1104 if (client -> config -> required_options) {
1105 for (i = 0; client -> config -> required_options [i]; i++) {
1106 if (!lookup_option
1107 (&dhcp_universe, packet -> options,
1108 client -> config -> required_options [i])) {
1109 log_info ("%s: no %s option.",
1110 obuf, (dhcp_universe.options
1111 [client -> config -> required_options [i]]
1112 -> name));
1113 return;
1118 /* If we've already seen this lease, don't record it again. */
1119 for (lease = client -> offered_leases; lease; lease = lease -> next) {
1120 if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
1121 !memcmp (lease -> address.iabuf,
1122 &packet -> raw -> yiaddr, lease -> address.len)) {
1123 log_debug ("%s: already seen.", obuf);
1124 return;
1128 lease = packet_to_lease (packet, client);
1129 if (!lease) {
1130 log_info ("%s: packet_to_lease failed.", obuf);
1131 return;
1134 /* If this lease was acquired through a BOOTREPLY, record that
1135 fact. */
1136 if (!packet -> options_valid || !packet -> packet_type)
1137 lease -> is_bootp = 1;
1139 /* Record the medium under which this lease was offered. */
1140 lease -> medium = client -> medium;
1142 /* Figure out when we're supposed to stop selecting. */
1143 stop_selecting = (client -> first_sending +
1144 client -> config -> select_interval);
1146 /* If this is the lease we asked for, put it at the head of the
1147 list, and don't mess with the arp request timeout. */
1148 if (lease -> address.len == client -> requested_address.len &&
1149 !memcmp (lease -> address.iabuf,
1150 client -> requested_address.iabuf,
1151 client -> requested_address.len)) {
1152 lease -> next = client -> offered_leases;
1153 client -> offered_leases = lease;
1154 } else {
1155 /* Put the lease at the end of the list. */
1156 lease -> next = (struct client_lease *)0;
1157 if (!client -> offered_leases)
1158 client -> offered_leases = lease;
1159 else {
1160 for (lp = client -> offered_leases; lp -> next;
1161 lp = lp -> next)
1163 lp -> next = lease;
1167 /* If the selecting interval has expired, go immediately to
1168 state_selecting(). Otherwise, time out into
1169 state_selecting at the select interval. */
1170 if (stop_selecting <= 0)
1171 state_selecting (client);
1172 else {
1173 add_timeout (stop_selecting, state_selecting, client, 0, 0);
1174 cancel_timeout (send_discover, client);
1176 log_info ("%s", obuf);
1179 /* Allocate a client_lease structure and initialize it from the parameters
1180 in the specified packet. */
1182 struct client_lease *packet_to_lease (packet, client)
1183 struct packet *packet;
1184 struct client_state *client;
1186 struct client_lease *lease;
1187 unsigned i;
1188 struct option_cache *oc;
1189 struct data_string data;
1191 lease = (struct client_lease *)new_client_lease (MDL);
1193 if (!lease) {
1194 log_error ("packet_to_lease: no memory to record lease.\n");
1195 return (struct client_lease *)0;
1198 memset (lease, 0, sizeof *lease);
1200 /* Copy the lease options. */
1201 option_state_reference (&lease -> options, packet -> options, MDL);
1203 lease -> address.len = sizeof (packet -> raw -> yiaddr);
1204 memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
1205 lease -> address.len);
1207 memset (&data, 0, sizeof data);
1209 if (client -> config -> vendor_space_name) {
1210 i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
1212 /* See if there was a vendor encapsulation option. */
1213 oc = lookup_option (&dhcp_universe, lease -> options, i);
1214 if (oc &&
1215 client -> config -> vendor_space_name &&
1216 evaluate_option_cache (&data, packet,
1217 (struct lease *)0, client,
1218 packet -> options, lease -> options,
1219 &global_scope, oc, MDL)) {
1220 if (data.len) {
1221 parse_encapsulated_suboptions
1222 (packet -> options, &dhcp_options [i],
1223 data.data, data.len, &dhcp_universe,
1224 client -> config -> vendor_space_name
1227 data_string_forget (&data, MDL);
1229 } else
1230 i = 0;
1232 /* Figure out the overload flag. */
1233 oc = lookup_option (&dhcp_universe, lease -> options,
1234 DHO_DHCP_OPTION_OVERLOAD);
1235 if (oc &&
1236 evaluate_option_cache (&data, packet, (struct lease *)0, client,
1237 packet -> options, lease -> options,
1238 &global_scope, oc, MDL)) {
1239 if (data.len > 0)
1240 i = data.data [0];
1241 else
1242 i = 0;
1243 data_string_forget (&data, MDL);
1244 } else
1245 i = 0;
1247 /* If the server name was filled out, copy it. */
1248 if (!(i & 2) && packet -> raw -> sname [0]) {
1249 unsigned len;
1250 /* Don't count on the NUL terminator. */
1251 for (len = 0; len < 64; len++)
1252 if (!packet -> raw -> sname [len])
1253 break;
1254 lease -> server_name = dmalloc (len + 1, MDL);
1255 if (!lease -> server_name) {
1256 log_error ("dhcpoffer: no memory for filename.\n");
1257 destroy_client_lease (lease);
1258 return (struct client_lease *)0;
1259 } else {
1260 memcpy (lease -> server_name,
1261 packet -> raw -> sname, len);
1262 lease -> server_name [len] = 0;
1266 /* Ditto for the filename. */
1267 if (!(i & 1) && packet -> raw -> file [0]) {
1268 unsigned len;
1269 /* Don't count on the NUL terminator. */
1270 for (len = 0; len < 64; len++)
1271 if (!packet -> raw -> file [len])
1272 break;
1273 lease -> filename = dmalloc (len + 1, MDL);
1274 if (!lease -> filename) {
1275 log_error ("dhcpoffer: no memory for filename.\n");
1276 destroy_client_lease (lease);
1277 return (struct client_lease *)0;
1278 } else {
1279 memcpy (lease -> filename,
1280 packet -> raw -> file, len);
1281 lease -> filename [len] = 0;
1285 execute_statements_in_scope ((struct binding_value **)0,
1286 (struct packet *)packet,
1287 (struct lease *)0, client,
1288 lease -> options, lease -> options,
1289 &global_scope,
1290 client -> config -> on_receipt,
1291 (struct group *)0);
1293 return lease;
1296 void dhcpnak (packet)
1297 struct packet *packet;
1299 struct interface_info *ip = packet -> interface;
1300 struct client_state *client;
1302 /* Find a client state that matches the xid... */
1303 for (client = ip -> client; client; client = client -> next)
1304 if (client -> xid == packet -> raw -> xid)
1305 break;
1307 /* If we're not receptive to an offer right now, or if the offer
1308 has an unrecognizable transaction id, then just drop it. */
1309 if (!client ||
1310 (packet -> interface -> hw_address.hlen - 1 !=
1311 packet -> raw -> hlen) ||
1312 (memcmp (&packet -> interface -> hw_address.hbuf [1],
1313 packet -> raw -> chaddr, packet -> raw -> hlen))) {
1314 #if defined (DEBUG)
1315 log_debug ("DHCPNAK in wrong transaction.");
1316 #endif
1317 return;
1320 if (client -> state != S_REBOOTING &&
1321 client -> state != S_REQUESTING &&
1322 client -> state != S_RENEWING &&
1323 client -> state != S_REBINDING) {
1324 #if defined (DEBUG)
1325 log_debug ("DHCPNAK in wrong state.");
1326 #endif
1327 return;
1330 log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
1332 if (!client -> active) {
1333 #if defined (DEBUG)
1334 log_info ("DHCPNAK with no active lease.\n");
1335 #endif
1336 return;
1339 destroy_client_lease (client -> active);
1340 client -> active = (struct client_lease *)0;
1342 /* Stop sending DHCPREQUEST packets... */
1343 cancel_timeout (send_request, client);
1345 client -> state = S_INIT;
1346 state_init (client);
1349 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1350 one after the right interval has expired. If we don't get an offer by
1351 the time we reach the panic interval, call the panic function. */
1353 void send_discover (cpp)
1354 void *cpp;
1356 struct client_state *client = cpp;
1358 int result;
1359 int interval;
1360 int increase = 1;
1362 /* Figure out how long it's been since we started transmitting. */
1363 interval = cur_time - client -> first_sending;
1365 /* If we're past the panic timeout, call the script and tell it
1366 we haven't found anything for this interface yet. */
1367 if (interval > client -> config -> timeout) {
1368 state_panic (client);
1369 return;
1372 /* If we're selecting media, try the whole list before doing
1373 the exponential backoff, but if we've already received an
1374 offer, stop looping, because we obviously have it right. */
1375 if (!client -> offered_leases &&
1376 client -> config -> media) {
1377 int fail = 0;
1378 again:
1379 if (client -> medium) {
1380 client -> medium = client -> medium -> next;
1381 increase = 0;
1383 if (!client -> medium) {
1384 if (fail)
1385 log_fatal ("No valid media types for %s!",
1386 client -> interface -> name);
1387 client -> medium =
1388 client -> config -> media;
1389 increase = 1;
1392 log_info ("Trying medium \"%s\" %d",
1393 client -> medium -> string, increase);
1394 script_init (client, "MEDIUM", client -> medium);
1395 if (script_go (client)) {
1396 fail = 1;
1397 goto again;
1401 /* If we're supposed to increase the interval, do so. If it's
1402 currently zero (i.e., we haven't sent any packets yet), set
1403 it to initial_interval; otherwise, add to it a random number
1404 between zero and two times itself. On average, this means
1405 that it will double with every transmission. */
1406 if (increase) {
1407 if (!client -> interval)
1408 client -> interval =
1409 client -> config -> initial_interval;
1410 else
1411 client -> interval += ((random () >> 2) %
1412 (2 * client -> interval));
1414 /* Don't backoff past cutoff. */
1415 if (client -> interval >
1416 client -> config -> backoff_cutoff)
1417 client -> interval =
1418 ((client -> config -> backoff_cutoff / 2)
1419 + ((random () >> 2) %
1420 client -> config -> backoff_cutoff));
1421 } else if (!client -> interval)
1422 client -> interval = client -> config -> initial_interval;
1424 /* If the backoff would take us to the panic timeout, just use that
1425 as the interval. */
1426 if (cur_time + client -> interval >
1427 client -> first_sending + client -> config -> timeout)
1428 client -> interval =
1429 (client -> first_sending +
1430 client -> config -> timeout) - cur_time + 1;
1432 /* Record the number of seconds since we started sending. */
1433 if (interval < 65536)
1434 client -> packet.secs = htons (interval);
1435 else
1436 client -> packet.secs = htons (65535);
1437 client -> secs = client -> packet.secs;
1439 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
1440 client -> name ? client -> name : client -> interface -> name,
1441 inet_ntoa (sockaddr_broadcast.sin_addr),
1442 ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
1444 /* Send out a packet. */
1445 result = send_packet (client -> interface, (struct packet *)0,
1446 &client -> packet,
1447 client -> packet_length,
1448 inaddr_any, &sockaddr_broadcast,
1449 (struct hardware *)0);
1451 add_timeout (cur_time + client -> interval,
1452 send_discover, client, 0, 0);
1455 /* state_panic gets called if we haven't received any offers in a preset
1456 amount of time. When this happens, we try to use existing leases that
1457 haven't yet expired, and failing that, we call the client script and
1458 hope it can do something. */
1460 void state_panic (cpp)
1461 void *cpp;
1463 struct client_state *client = cpp;
1464 struct client_lease *loop;
1465 struct client_lease *lp;
1467 loop = lp = client -> active;
1469 log_info ("No DHCPOFFERS received.");
1471 /* We may not have an active lease, but we may have some
1472 predefined leases that we can try. */
1473 if (!client -> active && client -> leases)
1474 goto activate_next;
1476 /* Run through the list of leases and see if one can be used. */
1477 while (client -> active) {
1478 if (client -> active -> expiry > cur_time) {
1479 log_info ("Trying recorded lease %s",
1480 piaddr (client -> active -> address));
1481 /* Run the client script with the existing
1482 parameters. */
1483 script_init (client, "TIMEOUT",
1484 client -> active -> medium);
1485 script_write_params (client, "new_", client -> active);
1486 if (client -> alias)
1487 script_write_params (client, "alias_",
1488 client -> alias);
1490 /* If the old lease is still good and doesn't
1491 yet need renewal, go into BOUND state and
1492 timeout at the renewal time. */
1493 if (!script_go (client)) {
1494 if (cur_time < client -> active -> renewal) {
1495 client -> state = S_BOUND;
1496 log_info ("bound: renewal in %ld %s.",
1497 (long)(client -> active -> renewal -
1498 cur_time), "seconds");
1499 add_timeout (client -> active -> renewal,
1500 state_bound, client, 0, 0);
1501 } else {
1502 client -> state = S_BOUND;
1503 log_info ("bound: immediate renewal.");
1504 state_bound (client);
1506 reinitialize_interfaces ();
1507 go_daemon ();
1508 return;
1512 /* If there are no other leases, give up. */
1513 if (!client -> leases) {
1514 client -> leases = client -> active;
1515 client -> active = (struct client_lease *)0;
1516 break;
1519 activate_next:
1520 /* Otherwise, put the active lease at the end of the
1521 lease list, and try another lease.. */
1522 for (lp = client -> leases; lp -> next; lp = lp -> next)
1524 lp -> next = client -> active;
1525 if (lp -> next) {
1526 lp -> next -> next = (struct client_lease *)0;
1528 client -> active = client -> leases;
1529 client -> leases = client -> leases -> next;
1531 /* If we already tried this lease, we've exhausted the
1532 set of leases, so we might as well give up for
1533 now. */
1534 if (client -> active == loop)
1535 break;
1536 else if (!loop)
1537 loop = client -> active;
1540 /* No leases were available, or what was available didn't work, so
1541 tell the shell script that we failed to allocate an address,
1542 and try again later. */
1543 if (onetry) {
1544 if (!quiet)
1545 log_info ("Unable to obtain a lease on first try.%s",
1546 " Exiting.");
1547 exit (2);
1550 log_info ("No working leases in persistent database - sleeping.");
1551 script_init (client, "FAIL", (struct string_list *)0);
1552 if (client -> alias)
1553 script_write_params (client, "alias_", client -> alias);
1554 script_go (client);
1555 client -> state = S_INIT;
1556 add_timeout (cur_time +
1557 ((client -> config -> retry_interval + 1) / 2 +
1558 (random () % client -> config -> retry_interval)),
1559 state_init, client, 0, 0);
1560 go_daemon ();
1563 void send_request (cpp)
1564 void *cpp;
1566 struct client_state *client = cpp;
1568 int result;
1569 int interval;
1570 struct sockaddr_in destination;
1571 struct in_addr from;
1573 /* Figure out how long it's been since we started transmitting. */
1574 interval = cur_time - client -> first_sending;
1576 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1577 past the reboot timeout, go to INIT and see if we can
1578 DISCOVER an address... */
1579 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1580 means either that we're on a network with no DHCP server,
1581 or that our server is down. In the latter case, assuming
1582 that there is a backup DHCP server, DHCPDISCOVER will get
1583 us a new address, but we could also have successfully
1584 reused our old address. In the former case, we're hosed
1585 anyway. This is not a win-prone situation. */
1586 if ((client -> state == S_REBOOTING ||
1587 client -> state == S_REQUESTING) &&
1588 interval > client -> config -> reboot_timeout) {
1589 cancel:
1590 client -> state = S_INIT;
1591 cancel_timeout (send_request, client);
1592 state_init (client);
1593 return;
1596 /* If we're in the reboot state, make sure the media is set up
1597 correctly. */
1598 if (client -> state == S_REBOOTING &&
1599 !client -> medium &&
1600 client -> active -> medium ) {
1601 script_init (client, "MEDIUM", client -> active -> medium);
1603 /* If the medium we chose won't fly, go to INIT state. */
1604 if (script_go (client))
1605 goto cancel;
1607 /* Record the medium. */
1608 client -> medium = client -> active -> medium;
1611 /* If the lease has expired, relinquish the address and go back
1612 to the INIT state. */
1613 if (client -> state != S_REQUESTING &&
1614 cur_time > client -> active -> expiry) {
1615 /* Run the client script with the new parameters. */
1616 script_init (client, "EXPIRE", (struct string_list *)0);
1617 script_write_params (client, "old_", client -> active);
1618 if (client -> alias)
1619 script_write_params (client, "alias_",
1620 client -> alias);
1621 script_go (client);
1623 /* Now do a preinit on the interface so that we can
1624 discover a new address. */
1625 script_init (client, "PREINIT", (struct string_list *)0);
1626 if (client -> alias)
1627 script_write_params (client, "alias_",
1628 client -> alias);
1629 script_go (client);
1631 client -> state = S_INIT;
1632 state_init (client);
1633 return;
1636 /* Do the exponential backoff... */
1637 if (!client -> interval)
1638 client -> interval = client -> config -> initial_interval;
1639 else {
1640 client -> interval += ((random () >> 2) %
1641 (2 * client -> interval));
1644 /* Don't backoff past cutoff. */
1645 if (client -> interval >
1646 client -> config -> backoff_cutoff)
1647 client -> interval =
1648 ((client -> config -> backoff_cutoff / 2)
1649 + ((random () >> 2) %
1650 client -> config -> backoff_cutoff));
1652 /* If the backoff would take us to the expiry time, just set the
1653 timeout to the expiry time. */
1654 if (client -> state != S_REQUESTING &&
1655 cur_time + client -> interval > client -> active -> expiry)
1656 client -> interval =
1657 client -> active -> expiry - cur_time + 1;
1659 /* If the lease T2 time has elapsed, or if we're not yet bound,
1660 broadcast the DHCPREQUEST rather than unicasting. */
1661 if (client -> state == S_REQUESTING ||
1662 client -> state == S_REBOOTING ||
1663 cur_time > client -> active -> rebind)
1664 destination.sin_addr = sockaddr_broadcast.sin_addr;
1665 else
1666 memcpy (&destination.sin_addr.s_addr,
1667 client -> destination.iabuf,
1668 sizeof destination.sin_addr.s_addr);
1669 destination.sin_port = remote_port;
1670 destination.sin_family = AF_INET;
1671 #ifdef HAVE_SA_LEN
1672 destination.sin_len = sizeof destination;
1673 #endif
1675 if (client -> state == S_RENEWING ||
1676 client -> state == S_REBINDING)
1677 memcpy (&from, client -> active -> address.iabuf,
1678 sizeof from);
1679 else
1680 from.s_addr = INADDR_ANY;
1682 /* Record the number of seconds since we started sending. */
1683 if (client -> state == S_REQUESTING)
1684 client -> packet.secs = client -> secs;
1685 else {
1686 if (interval < 65536)
1687 client -> packet.secs = htons (interval);
1688 else
1689 client -> packet.secs = htons (65535);
1692 log_info ("DHCPREQUEST on %s to %s port %d",
1693 client -> name ? client -> name : client -> interface -> name,
1694 inet_ntoa (destination.sin_addr),
1695 ntohs (destination.sin_port));
1697 if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
1698 fallback_interface)
1699 result = send_packet (fallback_interface,
1700 (struct packet *)0,
1701 &client -> packet,
1702 client -> packet_length,
1703 from, &destination,
1704 (struct hardware *)0);
1705 else
1706 /* Send out a packet. */
1707 result = send_packet (client -> interface, (struct packet *)0,
1708 &client -> packet,
1709 client -> packet_length,
1710 from, &destination,
1711 (struct hardware *)0);
1713 add_timeout (cur_time + client -> interval,
1714 send_request, client, 0, 0);
1717 void send_decline (cpp)
1718 void *cpp;
1720 struct client_state *client = cpp;
1722 int result;
1724 log_info ("DHCPDECLINE on %s to %s port %d",
1725 client -> name ? client -> name : client -> interface -> name,
1726 inet_ntoa (sockaddr_broadcast.sin_addr),
1727 ntohs (sockaddr_broadcast.sin_port));
1729 /* Send out a packet. */
1730 result = send_packet (client -> interface, (struct packet *)0,
1731 &client -> packet,
1732 client -> packet_length,
1733 inaddr_any, &sockaddr_broadcast,
1734 (struct hardware *)0);
1737 void send_release (cpp)
1738 void *cpp;
1740 struct client_state *client = cpp;
1742 int result;
1743 struct sockaddr_in destination;
1744 struct in_addr from;
1746 memcpy (&from, client -> active -> address.iabuf,
1747 sizeof from);
1748 memcpy (&destination.sin_addr.s_addr,
1749 client -> destination.iabuf,
1750 sizeof destination.sin_addr.s_addr);
1751 destination.sin_port = remote_port;
1752 destination.sin_family = AF_INET;
1753 #ifdef HAVE_SA_LEN
1754 destination.sin_len = sizeof destination;
1755 #endif
1757 /* Set the lease to end now, so that we don't accidentally
1758 reuse it if we restart before the old expiry time. */
1759 client -> active -> expiry =
1760 client -> active -> renewal =
1761 client -> active -> rebind = cur_time;
1762 if (!write_client_lease (client, client -> active, 1, 1)) {
1763 log_error ("Can't release lease: lease write failed.");
1764 return;
1767 log_info ("DHCPRELEASE on %s to %s port %d",
1768 client -> name ? client -> name : client -> interface -> name,
1769 inet_ntoa (destination.sin_addr),
1770 ntohs (destination.sin_port));
1772 if (fallback_interface)
1773 result = send_packet (fallback_interface,
1774 (struct packet *)0,
1775 &client -> packet,
1776 client -> packet_length,
1777 from, &destination,
1778 (struct hardware *)0);
1779 else
1780 /* Send out a packet. */
1781 result = send_packet (client -> interface, (struct packet *)0,
1782 &client -> packet,
1783 client -> packet_length,
1784 from, &destination,
1785 (struct hardware *)0);
1788 void make_client_options (client, lease, type, sid, rip, prl, op)
1789 struct client_state *client;
1790 struct client_lease *lease;
1791 u_int8_t *type;
1792 struct option_cache *sid;
1793 struct iaddr *rip;
1794 u_int32_t *prl;
1795 struct option_state **op;
1797 unsigned i;
1798 struct option_cache *oc;
1799 struct buffer *bp = (struct buffer *)0;
1801 /* If there are any leftover options, get rid of them. */
1802 if (*op)
1803 option_state_dereference (op, MDL);
1805 /* Allocate space for options. */
1806 option_state_allocate (op, MDL);
1808 /* Send the server identifier if provided. */
1809 if (sid)
1810 save_option (&dhcp_universe, *op, sid);
1812 oc = (struct option_cache *)0;
1814 /* Send the requested address if provided. */
1815 if (rip) {
1816 client -> requested_address = *rip;
1817 if (!(make_const_option_cache
1818 (&oc, (struct buffer **)0, rip -> iabuf, rip -> len,
1819 &dhcp_options [DHO_DHCP_REQUESTED_ADDRESS], MDL)))
1820 log_error ("can't make requested address cache.");
1821 else {
1822 save_option (&dhcp_universe, *op, oc);
1823 option_cache_dereference (&oc, MDL);
1825 } else {
1826 client -> requested_address.len = 0;
1829 if (!(make_const_option_cache
1830 (&oc, (struct buffer **)0,
1831 type, 1, &dhcp_options [DHO_DHCP_MESSAGE_TYPE], MDL)))
1832 log_error ("can't make message type.");
1833 else {
1834 save_option (&dhcp_universe, *op, oc);
1835 option_cache_dereference (&oc, MDL);
1838 if (prl) {
1839 /* Figure out how many parameters were requested. */
1840 for (i = 0; prl [i]; i++)
1842 if (!buffer_allocate (&bp, i, MDL))
1843 log_error ("can't make parameter list buffer.");
1844 else {
1845 for (i = 0; prl [i]; i++)
1846 bp -> data [i] = prl [i];
1847 if (!(make_const_option_cache
1848 (&oc, &bp, (u_int8_t *)0, i,
1849 &dhcp_options [DHO_DHCP_PARAMETER_REQUEST_LIST],
1850 MDL)))
1851 log_error ("can't make option cache");
1852 else {
1853 save_option (&dhcp_universe, *op, oc);
1854 option_cache_dereference (&oc, MDL);
1859 /* Run statements that need to be run on transmission. */
1860 if (client -> config -> on_transmission)
1861 execute_statements_in_scope
1862 ((struct binding_value **)0,
1863 (struct packet *)0, (struct lease *)0, client,
1864 (lease ? lease -> options : (struct option_state *)0),
1865 *op, &global_scope,
1866 client -> config -> on_transmission,
1867 (struct group *)0);
1870 void make_discover (client, lease)
1871 struct client_state *client;
1872 struct client_lease *lease;
1874 unsigned char discover = DHCPDISCOVER;
1875 int i;
1876 struct option_state *options = (struct option_state *)0;
1878 memset (&client -> packet, 0, sizeof (client -> packet));
1880 make_client_options (client,
1881 lease, &discover, (struct option_cache *)0,
1882 lease ? &lease -> address : (struct iaddr *)0,
1883 client -> config -> requested_options,
1884 &options);
1886 /* Set up the option buffer... */
1887 client -> packet_length =
1888 cons_options ((struct packet *)0, &client -> packet,
1889 (struct lease *)0, client,
1890 /* maximum packet size */1500,
1891 (struct option_state *)0,
1892 options,
1893 /* scope */ &global_scope,
1894 /* overload */ 0,
1895 /* terminate */0,
1896 /* bootpp */0,
1897 (struct data_string *)0,
1898 client -> config -> vendor_space_name);
1900 option_state_dereference (&options, MDL);
1901 if (client -> packet_length < BOOTP_MIN_LEN)
1902 client -> packet_length = BOOTP_MIN_LEN;
1904 client -> packet.op = BOOTREQUEST;
1905 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
1906 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
1907 client -> packet.hops = 0;
1908 client -> packet.xid = random ();
1909 client -> packet.secs = 0; /* filled in by send_discover. */
1911 if (can_receive_unicast_unconfigured (client -> interface))
1912 client -> packet.flags = 0;
1913 else
1914 client -> packet.flags = htons (BOOTP_BROADCAST);
1916 memset (&(client -> packet.ciaddr),
1917 0, sizeof client -> packet.ciaddr);
1918 memset (&(client -> packet.yiaddr),
1919 0, sizeof client -> packet.yiaddr);
1920 memset (&(client -> packet.siaddr),
1921 0, sizeof client -> packet.siaddr);
1922 client -> packet.giaddr = giaddr;
1923 if (client -> interface -> hw_address.hlen > 0)
1924 memcpy (client -> packet.chaddr,
1925 &client -> interface -> hw_address.hbuf [1],
1926 (unsigned)(client -> interface -> hw_address.hlen - 1));
1928 #ifdef DEBUG_PACKET
1929 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
1930 #endif
1934 void make_request (client, lease)
1935 struct client_state *client;
1936 struct client_lease *lease;
1938 unsigned char request = DHCPREQUEST;
1939 int i, j;
1940 unsigned char *tmp, *digest;
1941 unsigned char *old_digest_loc;
1942 struct option_cache *oc;
1944 memset (&client -> packet, 0, sizeof (client -> packet));
1946 if (client -> state == S_REQUESTING)
1947 oc = lookup_option (&dhcp_universe, lease -> options,
1948 DHO_DHCP_SERVER_IDENTIFIER);
1949 else
1950 oc = (struct option_cache *)0;
1952 if (client -> sent_options)
1953 option_state_dereference (&client -> sent_options, MDL);
1955 make_client_options (client, lease, &request, oc,
1956 ((client -> state == S_REQUESTING ||
1957 client -> state == S_REBOOTING)
1958 ? &lease -> address
1959 : (struct iaddr *)0),
1960 client -> config -> requested_options,
1961 &client -> sent_options);
1963 /* Set up the option buffer... */
1964 client -> packet_length =
1965 cons_options ((struct packet *)0, &client -> packet,
1966 (struct lease *)0, client,
1967 /* maximum packet size */1500,
1968 (struct option_state *)0,
1969 client -> sent_options,
1970 /* scope */ &global_scope,
1971 /* overload */ 0,
1972 /* terminate */0,
1973 /* bootpp */0,
1974 (struct data_string *)0,
1975 client -> config -> vendor_space_name);
1977 if (client -> packet_length < BOOTP_MIN_LEN)
1978 client -> packet_length = BOOTP_MIN_LEN;
1980 client -> packet.op = BOOTREQUEST;
1981 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
1982 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
1983 client -> packet.hops = 0;
1984 client -> packet.xid = client -> xid;
1985 client -> packet.secs = 0; /* Filled in by send_request. */
1987 /* If we own the address we're requesting, put it in ciaddr;
1988 otherwise set ciaddr to zero. */
1989 if (client -> state == S_BOUND ||
1990 client -> state == S_RENEWING ||
1991 client -> state == S_REBINDING) {
1992 memcpy (&client -> packet.ciaddr,
1993 lease -> address.iabuf, lease -> address.len);
1994 client -> packet.flags = 0;
1995 } else {
1996 memset (&client -> packet.ciaddr, 0,
1997 sizeof client -> packet.ciaddr);
1998 if (can_receive_unicast_unconfigured (client -> interface))
1999 client -> packet.flags = 0;
2000 else
2001 client -> packet.flags = htons (BOOTP_BROADCAST);
2004 memset (&client -> packet.yiaddr, 0,
2005 sizeof client -> packet.yiaddr);
2006 memset (&client -> packet.siaddr, 0,
2007 sizeof client -> packet.siaddr);
2008 if (client -> state != S_BOUND &&
2009 client -> state != S_RENEWING)
2010 client -> packet.giaddr = giaddr;
2011 else
2012 memset (&client -> packet.giaddr, 0,
2013 sizeof client -> packet.giaddr);
2014 if (client -> interface -> hw_address.hlen > 0)
2015 memcpy (client -> packet.chaddr,
2016 &client -> interface -> hw_address.hbuf [1],
2017 (unsigned)(client -> interface -> hw_address.hlen - 1));
2019 #ifdef DEBUG_PACKET
2020 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2021 #endif
2024 void make_decline (client, lease)
2025 struct client_state *client;
2026 struct client_lease *lease;
2028 unsigned char decline = DHCPDECLINE;
2029 int i;
2030 struct option_cache *oc;
2032 struct option_state *options = (struct option_state *)0;
2034 oc = lookup_option (&dhcp_universe, lease -> options,
2035 DHO_DHCP_SERVER_IDENTIFIER);
2036 make_client_options (client, lease, &decline, oc,
2037 &lease -> address, (u_int32_t *)0, &options);
2039 /* Set up the option buffer... */
2040 memset (&client -> packet, 0, sizeof (client -> packet));
2041 client -> packet_length =
2042 cons_options ((struct packet *)0, &client -> packet,
2043 (struct lease *)0, client, 0,
2044 (struct option_state *)0, options,
2045 &global_scope, 0, 0, 0, (struct data_string *)0,
2046 client -> config -> vendor_space_name);
2047 option_state_dereference (&options, MDL);
2048 if (client -> packet_length < BOOTP_MIN_LEN)
2049 client -> packet_length = BOOTP_MIN_LEN;
2050 option_state_dereference (&options, MDL);
2052 client -> packet.op = BOOTREQUEST;
2053 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2054 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2055 client -> packet.hops = 0;
2056 client -> packet.xid = client -> xid;
2057 client -> packet.secs = 0; /* Filled in by send_request. */
2058 if (can_receive_unicast_unconfigured (client -> interface))
2059 client -> packet.flags = 0;
2060 else
2061 client -> packet.flags = htons (BOOTP_BROADCAST);
2063 /* ciaddr must always be zero. */
2064 memset (&client -> packet.ciaddr, 0,
2065 sizeof client -> packet.ciaddr);
2066 memset (&client -> packet.yiaddr, 0,
2067 sizeof client -> packet.yiaddr);
2068 memset (&client -> packet.siaddr, 0,
2069 sizeof client -> packet.siaddr);
2070 client -> packet.giaddr = giaddr;
2071 memcpy (client -> packet.chaddr,
2072 &client -> interface -> hw_address.hbuf [1],
2073 client -> interface -> hw_address.hlen);
2075 #ifdef DEBUG_PACKET
2076 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2077 #endif
2080 void make_release (client, lease)
2081 struct client_state *client;
2082 struct client_lease *lease;
2084 unsigned char request = DHCPRELEASE;
2085 int i;
2086 struct option_cache *oc;
2088 struct option_state *options = (struct option_state *)0;
2090 memset (&client -> packet, 0, sizeof (client -> packet));
2092 oc = lookup_option (&dhcp_universe, lease -> options,
2093 DHO_DHCP_SERVER_IDENTIFIER);
2094 make_client_options (client, lease, &request, oc,
2095 (struct iaddr *)0, (u_int32_t *)0,
2096 &options);
2098 /* Set up the option buffer... */
2099 client -> packet_length =
2100 cons_options ((struct packet *)0, &client -> packet,
2101 (struct lease *)0, client,
2102 /* maximum packet size */1500,
2103 (struct option_state *)0,
2104 options,
2105 /* scope */ &global_scope,
2106 /* overload */ 0,
2107 /* terminate */0,
2108 /* bootpp */0,
2109 (struct data_string *)0,
2110 client -> config -> vendor_space_name);
2112 if (client -> packet_length < BOOTP_MIN_LEN)
2113 client -> packet_length = BOOTP_MIN_LEN;
2114 option_state_dereference (&options, MDL);
2116 client -> packet.op = BOOTREQUEST;
2117 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2118 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2119 client -> packet.hops = 0;
2120 client -> packet.xid = random ();
2121 client -> packet.secs = 0;
2122 client -> packet.flags = 0;
2123 memcpy (&client -> packet.ciaddr,
2124 lease -> address.iabuf, lease -> address.len);
2125 memset (&client -> packet.yiaddr, 0,
2126 sizeof client -> packet.yiaddr);
2127 memset (&client -> packet.siaddr, 0,
2128 sizeof client -> packet.siaddr);
2129 client -> packet.giaddr = giaddr;
2130 memcpy (client -> packet.chaddr,
2131 &client -> interface -> hw_address.hbuf [1],
2132 client -> interface -> hw_address.hlen);
2134 #ifdef DEBUG_PACKET
2135 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2136 #endif
2139 void destroy_client_lease (lease)
2140 struct client_lease *lease;
2142 int i;
2144 if (lease -> server_name)
2145 dfree (lease -> server_name, MDL);
2146 if (lease -> filename)
2147 dfree (lease -> filename, MDL);
2148 option_state_dereference (&lease -> options, MDL);
2149 free_client_lease (lease, MDL);
2152 FILE *leaseFile;
2154 void rewrite_client_leases ()
2156 struct interface_info *ip;
2157 struct client_state *client;
2158 struct client_lease *lp;
2160 if (leaseFile)
2161 fclose (leaseFile);
2162 leaseFile = fopen (path_dhclient_db, "w");
2163 if (!leaseFile) {
2164 log_error ("can't create %s: %m", path_dhclient_db);
2165 return;
2168 /* Write out all the leases attached to configured interfaces that
2169 we know about. */
2170 for (ip = interfaces; ip; ip = ip -> next) {
2171 for (client = ip -> client; client; client = client -> next) {
2172 for (lp = client -> leases; lp; lp = lp -> next) {
2173 write_client_lease (client, lp, 1, 0);
2175 if (client -> active)
2176 write_client_lease (client,
2177 client -> active, 1, 0);
2181 /* Write out any leases that are attached to interfaces that aren't
2182 currently configured. */
2183 for (ip = dummy_interfaces; ip; ip = ip -> next) {
2184 for (client = ip -> client; client; client = client -> next) {
2185 for (lp = client -> leases; lp; lp = lp -> next) {
2186 write_client_lease (client, lp, 1, 0);
2188 if (client -> active)
2189 write_client_lease (client,
2190 client -> active, 1, 0);
2193 fflush (leaseFile);
2196 void write_lease_option (struct option_cache *oc,
2197 struct packet *packet, struct lease *lease,
2198 struct client_state *client_state,
2199 struct option_state *in_options,
2200 struct option_state *cfg_options,
2201 struct binding_scope **scope,
2202 struct universe *u, void *stuff)
2204 const char *name, *dot;
2205 struct data_string ds;
2206 int status;
2207 struct client_state *client;
2209 memset (&ds, 0, sizeof ds);
2211 if (u != &dhcp_universe) {
2212 name = u -> name;
2213 dot = ".";
2214 } else {
2215 name = "";
2216 dot = "";
2218 if (evaluate_option_cache (&ds, packet, lease, client_state,
2219 in_options, cfg_options, scope, oc, MDL)) {
2220 fprintf (leaseFile,
2221 " option %s%s%s %s;\n",
2222 name, dot, oc -> option -> name,
2223 pretty_print_option (oc -> option,
2224 ds.data, ds.len, 1, 1));
2225 data_string_forget (&ds, MDL);
2229 int write_client_lease (client, lease, rewrite, makesure)
2230 struct client_state *client;
2231 struct client_lease *lease;
2232 int rewrite;
2233 int makesure;
2235 int i;
2236 struct tm *t;
2237 static int leases_written;
2238 struct option_cache *oc;
2239 struct data_string ds;
2240 pair *hash;
2241 int errors = 0;
2242 char *s;
2244 if (!rewrite) {
2245 if (leases_written++ > 20) {
2246 rewrite_client_leases ();
2247 leases_written = 0;
2251 /* If the lease came from the config file, we don't need to stash
2252 a copy in the lease database. */
2253 if (lease -> is_static)
2254 return 1;
2256 if (!leaseFile) { /* XXX */
2257 leaseFile = fopen (path_dhclient_db, "w");
2258 if (!leaseFile) {
2259 log_error ("can't create %s: %m", path_dhclient_db);
2260 return 0;
2264 errno = 0;
2265 fprintf (leaseFile, "lease {\n");
2266 if (lease -> is_bootp) {
2267 fprintf (leaseFile, " bootp;\n");
2268 if (errno) {
2269 ++errors;
2270 errno = 0;
2273 fprintf (leaseFile, " interface \"%s\";\n",
2274 client -> interface -> name);
2275 if (errno) {
2276 ++errors;
2277 errno = 0;
2279 if (client -> name) {
2280 fprintf (leaseFile, " name \"%s\";\n", client -> name);
2281 if (errno) {
2282 ++errors;
2283 errno = 0;
2286 fprintf (leaseFile, " fixed-address %s;\n",
2287 piaddr (lease -> address));
2288 if (errno) {
2289 ++errors;
2290 errno = 0;
2292 if (lease -> filename) {
2293 s = quotify_string (lease -> filename, MDL);
2294 if (s) {
2295 fprintf (leaseFile, " filename \"%s\";\n", s);
2296 if (errno) {
2297 ++errors;
2298 errno = 0;
2300 dfree (s, MDL);
2301 } else
2302 errors++;
2305 if (lease -> server_name) {
2306 s = quotify_string (lease -> filename, MDL);
2307 if (s) {
2308 fprintf (leaseFile, " server-name \"%s\";\n", s);
2309 if (errno) {
2310 ++errors;
2311 errno = 0;
2313 dfree (s, MDL);
2314 } else
2315 ++errors;
2317 if (lease -> medium) {
2318 s = quotify_string (lease -> medium -> string, MDL);
2319 if (s) {
2320 fprintf (leaseFile, " medium \"%s\";\n", s);
2321 if (errno) {
2322 ++errors;
2323 errno = 0;
2325 dfree (s, MDL);
2326 } else
2327 errors++;
2329 if (errno != 0) {
2330 errors++;
2331 errno = 0;
2334 memset (&ds, 0, sizeof ds);
2336 for (i = 0; i < lease -> options -> universe_count; i++) {
2337 option_space_foreach ((struct packet *)0, (struct lease *)0,
2338 client, (struct option_state *)0,
2339 lease -> options, &global_scope,
2340 universes [i],
2341 client, write_lease_option);
2344 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
2345 somebody invents a time machine, I think we can safely disregard
2346 it. */
2347 t = gmtime (&lease -> renewal);
2348 fprintf (leaseFile,
2349 " renew %d %d/%d/%d %02d:%02d:%02d;\n",
2350 t -> tm_wday, t -> tm_year + 1900,
2351 t -> tm_mon + 1, t -> tm_mday,
2352 t -> tm_hour, t -> tm_min, t -> tm_sec);
2353 if (errno != 0) {
2354 errors++;
2355 errno = 0;
2357 t = gmtime (&lease -> rebind);
2358 fprintf (leaseFile,
2359 " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
2360 t -> tm_wday, t -> tm_year + 1900,
2361 t -> tm_mon + 1, t -> tm_mday,
2362 t -> tm_hour, t -> tm_min, t -> tm_sec);
2363 if (errno != 0) {
2364 errors++;
2365 errno = 0;
2367 t = gmtime (&lease -> expiry);
2368 fprintf (leaseFile,
2369 " expire %d %d/%d/%d %02d:%02d:%02d;\n",
2370 t -> tm_wday, t -> tm_year + 1900,
2371 t -> tm_mon + 1, t -> tm_mday,
2372 t -> tm_hour, t -> tm_min, t -> tm_sec);
2373 if (errno != 0) {
2374 errors++;
2375 errno = 0;
2377 fprintf (leaseFile, "}\n");
2378 if (errno != 0) {
2379 errors++;
2380 errno = 0;
2382 fflush (leaseFile);
2383 if (errno != 0) {
2384 errors++;
2385 errno = 0;
2387 if (!errors && makesure) {
2388 if (fsync (fileno (leaseFile)) < 0) {
2389 log_info ("write_client_lease: %m");
2390 return 0;
2393 return errors ? 0 : 1;
2396 /* Variables holding name of script and file pointer for writing to
2397 script. Needless to say, this is not reentrant - only one script
2398 can be invoked at a time. */
2399 char scriptName [256];
2400 FILE *scriptFile;
2402 void script_init (client, reason, medium)
2403 struct client_state *client;
2404 const char *reason;
2405 struct string_list *medium;
2407 struct string_list *sl, *next;
2409 if (client) {
2410 for (sl = client -> env; sl; sl = next) {
2411 next = sl -> next;
2412 dfree (sl, MDL);
2414 client -> env = (struct string_list *)0;
2415 client -> envc = 0;
2417 if (client -> interface) {
2418 client_envadd (client, "", "interface", "%s",
2419 client -> interface -> name);
2421 if (client -> name)
2422 client_envadd (client,
2423 "", "client", "%s", client -> name);
2424 if (medium)
2425 client_envadd (client,
2426 "", "medium", "%s", medium -> string);
2428 client_envadd (client, "", "reason", "%s", reason);
2429 client_envadd (client, "", "pid", "%ld", (long int)getpid ());
2433 struct envadd_state {
2434 struct client_state *client;
2435 const char *prefix;
2438 void client_option_envadd (struct option_cache *oc,
2439 struct packet *packet, struct lease *lease,
2440 struct client_state *client_state,
2441 struct option_state *in_options,
2442 struct option_state *cfg_options,
2443 struct binding_scope **scope,
2444 struct universe *u, void *stuff)
2446 struct envadd_state *es = stuff;
2447 struct data_string data;
2448 memset (&data, 0, sizeof data);
2450 if (evaluate_option_cache (&data, packet, lease, client_state,
2451 in_options, cfg_options, scope, oc, MDL)) {
2452 if (data.len) {
2453 char name [256];
2454 if (dhcp_option_ev_name (name, sizeof name,
2455 oc -> option)) {
2456 client_envadd (es -> client, es -> prefix,
2457 name, "%s",
2458 (pretty_print_option
2459 (oc -> option,
2460 data.data, data.len,
2461 0, 0)));
2462 data_string_forget (&data, MDL);
2468 void script_write_params (client, prefix, lease)
2469 struct client_state *client;
2470 const char *prefix;
2471 struct client_lease *lease;
2473 int i;
2474 struct data_string data;
2475 struct option_cache *oc;
2476 pair *hash;
2477 char *s, *t;
2478 struct envadd_state es;
2480 es.client = client;
2481 es.prefix = prefix;
2483 client_envadd (client,
2484 prefix, "ip_address", "%s", piaddr (lease -> address));
2486 /* For the benefit of Linux (and operating systems which may
2487 have similar needs), compute the network address based on
2488 the supplied ip address and netmask, if provided. Also
2489 compute the broadcast address (the host address all ones
2490 broadcast address, not the host address all zeroes
2491 broadcast address). */
2493 memset (&data, 0, sizeof data);
2494 oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
2495 if (oc && evaluate_option_cache (&data, (struct packet *)0,
2496 (struct lease *)0, client,
2497 (struct option_state *)0,
2498 lease -> options,
2499 &global_scope, oc, MDL)) {
2500 if (data.len > 3) {
2501 struct iaddr netmask, subnet, broadcast;
2503 memcpy (netmask.iabuf, data.data, data.len);
2504 netmask.len = data.len;
2505 data_string_forget (&data, MDL);
2507 subnet = subnet_number (lease -> address, netmask);
2508 if (subnet.len) {
2509 client_envadd (client, prefix, "network_number",
2510 "%s", piaddr (subnet));
2512 oc = lookup_option (&dhcp_universe,
2513 lease -> options,
2514 DHO_BROADCAST_ADDRESS);
2515 if (!oc ||
2516 !(evaluate_option_cache
2517 (&data, (struct packet *)0,
2518 (struct lease *)0, client,
2519 (struct option_state *)0,
2520 lease -> options,
2521 &global_scope, oc, MDL))) {
2522 broadcast = broadcast_addr (subnet, netmask);
2523 if (broadcast.len) {
2524 client_envadd (client,
2525 prefix, "broadcast_address",
2526 "%s", piaddr (broadcast));
2531 data_string_forget (&data, MDL);
2534 if (lease -> filename)
2535 client_envadd (client,
2536 prefix, "filename", "%s", lease -> filename);
2537 if (lease -> server_name)
2538 client_envadd (client, prefix, "server_name",
2539 "%s", lease -> server_name);
2541 for (i = 0; i < lease -> options -> universe_count; i++) {
2542 option_space_foreach ((struct packet *)0, (struct lease *)0,
2543 client, (struct option_state *)0,
2544 lease -> options, &global_scope,
2545 universes [i],
2546 &es, client_option_envadd);
2548 client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry));
2551 int script_go (client)
2552 struct client_state *client;
2554 int rval;
2555 char *scriptName;
2556 char *argv [2];
2557 char **envp;
2558 char *epp [3];
2559 char reason [] = "REASON=NBI";
2560 static char client_path [] = CLIENT_PATH;
2561 int i;
2562 struct string_list *sp, *next;
2563 int pid, wpid, wstatus;
2565 if (client)
2566 scriptName = client -> config -> script_name;
2567 else
2568 scriptName = top_level_config.script_name;
2570 envp = dmalloc (((client ? client -> envc : 2) +
2571 client_env_count + 2) * sizeof (char *), MDL);
2572 if (!envp) {
2573 log_error ("No memory for client script environment.");
2574 return 0;
2576 i = 0;
2577 /* Copy out the environment specified on the command line,
2578 if any. */
2579 for (sp = client_env; sp; sp = sp -> next) {
2580 envp [i++] = sp -> string;
2582 /* Copy out the environment specified by dhclient. */
2583 if (client) {
2584 for (sp = client -> env; sp; sp = sp -> next) {
2585 envp [i++] = sp -> string;
2587 } else {
2588 envp [i++] = reason;
2590 /* Set $PATH. */
2591 envp [i++] = client_path;
2592 envp [i] = (char *)0;
2594 argv [0] = scriptName;
2595 argv [1] = (char *)0;
2597 pid = fork ();
2598 if (pid < 0) {
2599 log_error ("fork: %m");
2600 wstatus = 0;
2601 } else if (pid) {
2602 do {
2603 wpid = wait (&wstatus);
2604 } while (wpid != pid && wpid > 0);
2605 if (wpid < 0) {
2606 log_error ("wait: %m");
2607 wstatus = 0;
2609 } else {
2610 execve (scriptName, argv, envp);
2611 log_error ("execve (%s, ...): %m", scriptName);
2612 exit (0);
2615 if (client) {
2616 for (sp = client -> env; sp; sp = next) {
2617 next = sp -> next;
2618 dfree (sp, MDL);
2620 client -> env = (struct string_list *)0;
2621 client -> envc = 0;
2623 dfree (envp, MDL);
2624 GET_TIME (&cur_time);
2625 return (WIFEXITED (wstatus) ?
2626 WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
2629 void client_envadd (struct client_state *client,
2630 const char *prefix, const char *name, const char *fmt, ...)
2632 char spbuf [1024];
2633 char *s;
2634 unsigned len, i;
2635 struct string_list *val;
2636 va_list list;
2638 va_start (list, fmt);
2639 len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
2640 va_end (list);
2642 val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
2643 len + sizeof *val, MDL);
2644 if (!val)
2645 return;
2646 s = val -> string;
2647 strcpy (s, prefix);
2648 strcat (s, name);
2649 s += strlen (s);
2650 *s++ = '=';
2651 if (len >= sizeof spbuf) {
2652 va_start (list, fmt);
2653 vsnprintf (s, len + 1, fmt, list);
2654 va_end (list);
2655 } else
2656 strcpy (s, spbuf);
2657 val -> next = client -> env;
2658 client -> env = val;
2659 client -> envc++;
2662 int dhcp_option_ev_name (buf, buflen, option)
2663 char *buf;
2664 size_t buflen;
2665 struct option *option;
2667 int i, j;
2668 const char *s;
2670 j = 0;
2671 if (option -> universe != &dhcp_universe) {
2672 s = option -> universe -> name;
2673 i = 0;
2674 } else {
2675 s = option -> name;
2676 i = 1;
2679 do {
2680 while (*s) {
2681 if (j + 1 == buflen)
2682 return 0;
2683 if (*s == '-')
2684 buf [j++] = '_';
2685 else
2686 buf [j++] = *s;
2687 ++s;
2689 if (!i) {
2690 s = option -> name;
2691 if (j + 1 == buflen)
2692 return 0;
2693 buf [j++] = '_';
2695 ++i;
2696 } while (i != 2);
2698 buf [j] = 0;
2699 return 1;
2702 void go_daemon ()
2704 static int state = 0;
2705 int pid;
2706 int i;
2708 /* Don't become a daemon if the user requested otherwise. */
2709 if (no_daemon) {
2710 write_client_pid_file ();
2711 return;
2714 /* Only do it once. */
2715 if (state)
2716 return;
2717 state = 1;
2719 /* Stop logging to stderr... */
2720 log_perror = 0;
2722 /* Become a daemon... */
2723 if ((pid = fork ()) < 0)
2724 log_fatal ("Can't fork daemon: %m");
2725 else if (pid)
2726 exit (0);
2727 /* Become session leader and get pid... */
2728 pid = setsid ();
2730 /* Close standard I/O descriptors. */
2731 close(0);
2732 close(1);
2733 close(2);
2735 /* Reopen them on /dev/null. */
2736 i = open ("/dev/null", O_RDWR);
2737 if (i == 0)
2738 i = open ("/dev/null", O_RDWR);
2739 if (i == 1) {
2740 i = open ("/dev/null", O_RDWR);
2741 log_perror = 0; /* No sense logging to /dev/null. */
2742 } else if (i != -1)
2743 close (i);
2745 write_client_pid_file ();
2748 void write_client_pid_file ()
2750 FILE *pf;
2751 int pfdesc;
2753 pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
2755 if (pfdesc < 0) {
2756 log_error ("Can't create %s: %m", path_dhclient_pid);
2757 return;
2760 pf = fdopen (pfdesc, "w");
2761 if (!pf)
2762 log_error ("Can't fdopen %s: %m", path_dhclient_pid);
2763 else {
2764 fprintf (pf, "%ld\n", (long)getpid ());
2765 fclose (pf);
2769 void client_location_changed ()
2771 struct interface_info *ip;
2772 struct client_state *client;
2774 for (ip = interfaces; ip; ip = ip -> next) {
2775 for (client = ip -> client; client; client = client -> next) {
2776 switch (client -> state) {
2777 case S_SELECTING:
2778 cancel_timeout (send_discover, client);
2779 break;
2781 case S_BOUND:
2782 cancel_timeout (state_bound, client);
2783 break;
2785 case S_REBOOTING:
2786 case S_REQUESTING:
2787 case S_RENEWING:
2788 cancel_timeout (send_request, client);
2789 break;
2791 case S_INIT:
2792 case S_REBINDING:
2793 case S_STOPPED:
2794 break;
2796 client -> state = S_INIT;
2797 state_reboot (client);
2802 void do_release(client)
2803 struct client_state *client;
2805 struct data_string ds;
2806 struct option_cache *oc;
2808 /* Pick a random xid. */
2809 client -> xid = random ();
2811 /* is there even a lease to release? */
2812 if (client -> active) {
2813 /* Make a DHCPRELEASE packet, and set appropriate per-interface
2814 flags. */
2815 make_release (client, client -> active);
2817 memset (&ds, 0, sizeof ds);
2818 oc = lookup_option (&dhcp_universe,
2819 client -> active -> options,
2820 DHO_DHCP_SERVER_IDENTIFIER);
2821 if (oc &&
2822 evaluate_option_cache (&ds, (struct packet *)0,
2823 (struct lease *)0, client,
2824 (struct option_state *)0,
2825 client -> active -> options,
2826 &global_scope, oc, MDL)) {
2827 if (ds.len > 3) {
2828 memcpy (client -> destination.iabuf,
2829 ds.data, 4);
2830 client -> destination.len = 4;
2831 } else
2832 client -> destination = iaddr_broadcast;
2834 data_string_forget (&ds, MDL);
2835 } else
2836 client -> destination = iaddr_broadcast;
2837 client -> first_sending = cur_time;
2838 client -> interval = client -> config -> initial_interval;
2840 /* Zap the medium list... */
2841 client -> medium = (struct string_list *)0;
2843 /* Send out the first and only DHCPRELEASE packet. */
2844 send_release (client);
2846 /* Do the client script RELEASE operation. */
2847 script_init (client,
2848 "RELEASE", (struct string_list *)0);
2849 if (client -> alias)
2850 script_write_params (client, "alias_",
2851 client -> alias);
2852 script_write_params (client, "old_", client -> active);
2853 script_go (client);
2856 /* Cancel any timeouts. */
2857 cancel_timeout (state_bound, client);
2858 cancel_timeout (send_discover, client);
2859 cancel_timeout (state_init, client);
2860 cancel_timeout (send_request, client);
2861 cancel_timeout (state_reboot, client);
2862 client -> state = S_STOPPED;
2865 int dhclient_interface_shutdown_hook (struct interface_info *interface)
2867 do_release (interface -> client);
2869 return 1;
2872 int dhclient_interface_discovery_hook (struct interface_info *tmp)
2874 struct interface_info *last, *ip;
2875 /* See if we can find the client from dummy_interfaces */
2876 last = 0;
2877 for (ip = dummy_interfaces; ip; ip = ip -> next) {
2878 if (!strcmp (ip -> name, tmp -> name)) {
2879 /* Remove from dummy_interfaces */
2880 if (last) {
2881 ip = (struct interface_info *)0;
2882 interface_reference (&ip, last -> next, MDL);
2883 interface_dereference (&last -> next, MDL);
2884 if (ip -> next) {
2885 interface_reference (&last -> next,
2886 ip -> next, MDL);
2887 interface_dereference (&ip -> next,
2888 MDL);
2890 } else {
2891 ip = (struct interface_info *)0;
2892 interface_reference (&ip,
2893 dummy_interfaces, MDL);
2894 interface_dereference (&dummy_interfaces, MDL);
2895 if (ip -> next) {
2896 interface_reference (&dummy_interfaces,
2897 ip -> next, MDL);
2898 interface_dereference (&ip -> next,
2899 MDL);
2902 /* Copy "client" to tmp */
2903 if (ip -> client) {
2904 tmp -> client = ip -> client;
2905 tmp -> client -> interface = tmp;
2907 interface_dereference (&ip, MDL);
2908 break;
2910 last = ip;
2912 return 1;
2915 isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
2917 struct interface_info *ip;
2918 struct client_state *client;
2920 /* This code needs some rethinking. It doesn't test against
2921 a signal name, and it just kind of bulls into doing something
2922 that may or may not be appropriate. */
2924 if (interfaces) {
2925 interface_reference (&interface -> next, interfaces, MDL);
2926 interface_dereference (&interfaces, MDL);
2928 interface_reference (&interfaces, interface, MDL);
2930 discover_interfaces (DISCOVER_UNCONFIGURED);
2932 for (ip = interfaces; ip; ip = ip -> next) {
2933 /* If interfaces were specified, don't configure
2934 interfaces that weren't specified! */
2935 if (ip -> flags & INTERFACE_RUNNING ||
2936 (ip -> flags & (INTERFACE_REQUESTED |
2937 INTERFACE_AUTOMATIC)) !=
2938 INTERFACE_REQUESTED)
2939 continue;
2940 script_init (ip -> client,
2941 "PREINIT", (struct string_list *)0);
2942 if (ip -> client -> alias)
2943 script_write_params (ip -> client, "alias_",
2944 ip -> client -> alias);
2945 script_go (ip -> client);
2948 discover_interfaces (interfaces_requested
2949 ? DISCOVER_REQUESTED
2950 : DISCOVER_RUNNING);
2952 for (ip = interfaces; ip; ip = ip -> next) {
2953 if (ip -> flags & INTERFACE_RUNNING)
2954 continue;
2955 ip -> flags |= INTERFACE_RUNNING;
2956 for (client = ip -> client; client; client = client -> next) {
2957 client -> state = S_INIT;
2958 /* Set up a timeout to start the initialization
2959 process. */
2960 add_timeout (cur_time + random () % 5,
2961 state_reboot, client, 0, 0);
2964 return ISC_R_SUCCESS;
2967 /* The client should never receive a relay agent information option,
2968 so if it does, log it and discard it. */
2970 int parse_agent_information_option (packet, len, data)
2971 struct packet *packet;
2972 int len;
2973 u_int8_t *data;
2975 return 1;
2978 /* The client never sends relay agent information options. */
2980 unsigned cons_agent_information_options (cfg_options, outpacket,
2981 agentix, length)
2982 struct option_state *cfg_options;
2983 struct dhcp_packet *outpacket;
2984 unsigned agentix;
2985 unsigned length;
2987 return length;
2990 static void shutdown_exit (void *foo)
2992 exit (0);
2995 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
2996 control_object_state_t newstate)
2998 struct interface_info *ip;
2999 struct client_state *client;
3001 /* Do the right thing for each interface. */
3002 for (ip = interfaces; ip; ip = ip -> next) {
3003 for (client = ip -> client; client; client = client -> next) {
3004 switch (newstate) {
3005 case server_startup:
3006 return ISC_R_SUCCESS;
3008 case server_running:
3009 return ISC_R_SUCCESS;
3011 case server_shutdown:
3012 if (client -> active &&
3013 client -> active -> expiry > cur_time) {
3014 if (client -> config -> do_forward_update)
3015 client_dns_update (client, 0, 0);
3016 do_release (client);
3018 break;
3020 case server_hibernate:
3021 state_stop (client);
3022 break;
3024 case server_awaken:
3025 state_reboot (client);
3026 break;
3030 if (newstate == server_shutdown)
3031 add_timeout (cur_time + 1, shutdown_exit, 0, 0, 0);
3032 return ISC_R_SUCCESS;
3035 /* Called after a timeout if the DNS update failed on the previous try.
3036 Retries the update, and if it times out, schedules a retry after
3037 ten times as long of a wait. */
3039 void client_dns_update_timeout (void *cp)
3041 struct client_state *client = cp;
3042 isc_result_t status;
3044 if (client -> active) {
3045 status = client_dns_update (client, 1,
3046 (client -> active -> renewal -
3047 cur_time));
3048 if (status == ISC_R_TIMEDOUT) {
3049 client -> dns_update_timeout *= 10;
3050 add_timeout (cur_time + client -> dns_update_timeout,
3051 client_dns_update_timeout, client, 0, 0);
3056 /* See if we should do a DNS update, and if so, do it. */
3058 isc_result_t client_dns_update (struct client_state *client, int addp, int ttl)
3060 struct data_string ddns_fqdn, ddns_fwd_name,
3061 ddns_dhcid, client_identifier;
3062 struct option_cache *oc;
3063 int ignorep;
3064 int result;
3065 isc_result_t rcode;
3067 /* If we didn't send an FQDN option, we certainly aren't going to
3068 be doing an update. */
3069 if (!client -> sent_options)
3070 return ISC_R_SUCCESS;
3072 /* If we don't have a lease, we can't do an update. */
3073 if (!client -> active)
3074 return ISC_R_SUCCESS;
3076 /* If we set the no client update flag, don't do the update. */
3077 if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
3078 FQDN_NO_CLIENT_UPDATE)) &&
3079 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
3080 (struct lease *)0, client,
3081 client -> sent_options,
3082 (struct option_state *)0,
3083 &global_scope, oc, MDL))
3084 return ISC_R_SUCCESS;
3086 /* If we set the "server, please update" flag, or didn't set it
3087 to false, don't do the update. */
3088 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
3089 FQDN_SERVER_UPDATE)) ||
3090 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
3091 (struct lease *)0, client,
3092 client -> sent_options,
3093 (struct option_state *)0,
3094 &global_scope, oc, MDL))
3095 return ISC_R_SUCCESS;
3097 /* If no FQDN option was supplied, don't do the update. */
3098 memset (&ddns_fwd_name, 0, sizeof ddns_fwd_name);
3099 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
3100 FQDN_FQDN)) ||
3101 !evaluate_option_cache (&ddns_fwd_name, (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 /* Make a dhcid string out of either the client identifier,
3109 if we are sending one, or the interface's MAC address,
3110 otherwise. */
3111 memset (&ddns_dhcid, 0, sizeof ddns_dhcid);
3113 memset (&client_identifier, 0, sizeof client_identifier);
3114 if ((oc = lookup_option (&dhcp_universe, client -> sent_options,
3115 DHO_DHCP_CLIENT_IDENTIFIER)) &&
3116 evaluate_option_cache (&client_identifier, (struct packet *)0,
3117 (struct lease *)0, client,
3118 client -> sent_options,
3119 (struct option_state *)0,
3120 &global_scope, oc, MDL)) {
3121 result = get_dhcid (&ddns_dhcid,
3122 DHO_DHCP_CLIENT_IDENTIFIER,
3123 client_identifier.data,
3124 client_identifier.len);
3125 data_string_forget (&client_identifier, MDL);
3126 } else
3127 result = get_dhcid (&ddns_dhcid, 0,
3128 client -> interface -> hw_address.hbuf,
3129 client -> interface -> hw_address.hlen);
3130 if (!result) {
3131 data_string_forget (&ddns_fwd_name, MDL);
3132 return ISC_R_SUCCESS;
3135 /* Start the resolver, if necessary. */
3136 if (!resolver_inited) {
3137 minires_ninit (&resolver_state);
3138 resolver_inited = 1;
3139 resolver_state.retrans = 1;
3140 resolver_state.retry = 1;
3144 * Perform updates.
3146 if (ddns_fwd_name.len && ddns_dhcid.len) {
3147 if (addp)
3148 rcode = ddns_update_a (&ddns_fwd_name,
3149 client -> active -> address,
3150 &ddns_dhcid, ttl,
3152 else
3153 rcode = ddns_remove_a (&ddns_fwd_name,
3154 client -> active -> address,
3155 &ddns_dhcid);
3156 } else
3157 rcode = ISC_R_FAILURE;
3159 data_string_forget (&ddns_fwd_name, MDL);
3160 data_string_forget (&ddns_dhcid, MDL);
3161 return rcode;