1: /* dhclient.c
2:
3: DHCP Client. */
4:
5: /*
6: * Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
7: * Copyright (c) 1995-2003 by Internet Software Consortium
8: *
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.
12: *
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.
20: *
21: * Internet Systems Consortium, Inc.
22: * 950 Charter Street
23: * Redwood City, CA 94063
24: * <info@isc.org>
25: * https://www.isc.org/
26: *
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.
31: */
32:
33: #include "dhcpd.h"
34: #include <syslog.h>
35: #include <signal.h>
36: #include <errno.h>
37: #include <sys/time.h>
38: #include <sys/wait.h>
39: #include <limits.h>
40:
41: TIME default_lease_time = 43200; /* 12 hours... */
42: TIME max_lease_time = 86400; /* 24 hours... */
43:
44: const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
45: const char *path_dhclient_db = NULL;
46: const char *path_dhclient_pid = NULL;
47: static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
48: char *path_dhclient_script = path_dhclient_script_array;
49:
50: /* False (default) => we write and use a pid file */
51: isc_boolean_t no_pid_file = ISC_FALSE;
52:
53: int dhcp_max_agent_option_packet_length = 0;
54:
55: int interfaces_requested = 0;
56:
57: struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
58: struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
59: struct in_addr inaddr_any;
60: struct sockaddr_in sockaddr_broadcast;
61: struct in_addr giaddr;
62: struct data_string default_duid;
63:
64: /* ASSERT_STATE() does nothing now; it used to be
65: assert (state_is == state_shouldbe). */
66: #define ASSERT_STATE(state_is, state_shouldbe) {}
67:
68: static const char copyright[] =
69: "Copyright 2004-2012 Internet Systems Consortium.";
70: static const char arr [] = "All rights reserved.";
71: static const char message [] = "Internet Systems Consortium DHCP Client";
72: static const char url [] =
73: "For info, please visit https://www.isc.org/software/dhcp/";
74:
75: u_int16_t local_port = 0;
76: u_int16_t remote_port = 0;
77: int no_daemon = 0;
78: struct string_list *client_env = NULL;
79: int client_env_count = 0;
80: int onetry = 0;
81: int quiet = 1;
82: int nowait = 0;
83: int stateless = 0;
84: int wanted_ia_na = -1; /* the absolute value is the real one. */
85: int wanted_ia_ta = 0;
86: int wanted_ia_pd = 0;
87: char *mockup_relay = NULL;
88:
89: void run_stateless(int exit_mode);
90:
91: static void usage(void);
92:
93: static isc_result_t write_duid(struct data_string *duid);
94: static void add_reject(struct packet *packet);
95:
96: static int check_domain_name(const char *ptr, size_t len, int dots);
97: static int check_domain_name_list(const char *ptr, size_t len, int dots);
98: static int check_option_values(struct universe *universe, unsigned int opt,
99: const char *ptr, size_t len);
100:
101: int
102: main(int argc, char **argv) {
103: int fd;
104: int i;
105: struct interface_info *ip;
106: struct client_state *client;
107: unsigned seed;
108: char *server = NULL;
109: isc_result_t status;
110: int exit_mode = 0;
111: int release_mode = 0;
112: struct timeval tv;
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: #ifdef DHCPv6
121: int local_family_set = 0;
122: #endif /* DHCPv6 */
123: char *s;
124:
125: /* Initialize client globals. */
126: memset(&default_duid, 0, sizeof(default_duid));
127:
128: /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
129: 2 (stderr) are open. To do this, we assume that when we
130: open a file the lowest available file descriptor is used. */
131: fd = open("/dev/null", O_RDWR);
132: if (fd == 0)
133: fd = open("/dev/null", O_RDWR);
134: if (fd == 1)
135: fd = open("/dev/null", O_RDWR);
136: if (fd == 2)
137: log_perror = 0; /* No sense logging to /dev/null. */
138: else if (fd != -1)
139: close(fd);
140:
141: openlog("dhclient", LOG_NDELAY, LOG_DAEMON);
142:
143: #if !(defined(DEBUG) || defined(__CYGWIN32__))
144: setlogmask(LOG_UPTO(LOG_INFO));
145: #endif
146:
147: /*
148: * Set up the signal handlers, currently we only
149: * have one to ignore sigpipe.
150: */
151: if (dhcp_handle_signal(SIGPIPE, SIG_IGN) != ISC_R_SUCCESS) {
152: log_fatal("Can't set up signal handler");
153: }
154:
155: /* Set up the OMAPI. */
156: status = omapi_init();
157: if (status != ISC_R_SUCCESS)
158: log_fatal("Can't initialize OMAPI: %s",
159: isc_result_totext(status));
160:
161: /* Set up the OMAPI wrappers for various server database internal
162: objects. */
163: dhcp_common_objects_setup();
164:
165: dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
166: dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
167: dhcp_interface_startup_hook = dhclient_interface_startup_hook;
168:
169: for (i = 1; i < argc; i++) {
170: if (!strcmp(argv[i], "-r")) {
171: release_mode = 1;
172: no_daemon = 1;
173: #ifdef DHCPv6
174: } else if (!strcmp(argv[i], "-4")) {
175: if (local_family_set && local_family != AF_INET)
176: log_fatal("Client can only do v4 or v6, not "
177: "both.");
178: local_family_set = 1;
179: local_family = AF_INET;
180: } else if (!strcmp(argv[i], "-6")) {
181: if (local_family_set && local_family != AF_INET6)
182: log_fatal("Client can only do v4 or v6, not "
183: "both.");
184: local_family_set = 1;
185: local_family = AF_INET6;
186: #endif /* DHCPv6 */
187: } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */
188: release_mode = 0;
189: no_daemon = 0;
190: exit_mode = 1;
191: } else if (!strcmp(argv[i], "-p")) {
192: if (++i == argc)
193: usage();
194: local_port = validate_port(argv[i]);
195: log_debug("binding to user-specified port %d",
196: ntohs(local_port));
197: } else if (!strcmp(argv[i], "-d")) {
198: no_daemon = 1;
199: quiet = 0;
200: } else if (!strcmp(argv[i], "-pf")) {
201: if (++i == argc)
202: usage();
203: path_dhclient_pid = argv[i];
204: no_dhclient_pid = 1;
205: } else if (!strcmp(argv[i], "--no-pid")) {
206: no_pid_file = ISC_TRUE;
207: } else if (!strcmp(argv[i], "-cf")) {
208: if (++i == argc)
209: usage();
210: path_dhclient_conf = argv[i];
211: no_dhclient_conf = 1;
212: } else if (!strcmp(argv[i], "-lf")) {
213: if (++i == argc)
214: usage();
215: path_dhclient_db = argv[i];
216: no_dhclient_db = 1;
217: } else if (!strcmp(argv[i], "-sf")) {
218: if (++i == argc)
219: usage();
220: path_dhclient_script = argv[i];
221: no_dhclient_script = 1;
222: } else if (!strcmp(argv[i], "-1")) {
223: onetry = 1;
224: } else if (!strcmp(argv[i], "-q")) {
225: quiet = 1;
226: } else if (!strcmp(argv[i], "-s")) {
227: if (++i == argc)
228: usage();
229: server = argv[i];
230: } else if (!strcmp(argv[i], "-g")) {
231: if (++i == argc)
232: usage();
233: mockup_relay = argv[i];
234: } else if (!strcmp(argv[i], "-nw")) {
235: nowait = 1;
236: } else if (!strcmp(argv[i], "-n")) {
237: /* do not start up any interfaces */
238: interfaces_requested = -1;
239: } else if (!strcmp(argv[i], "-w")) {
240: /* do not exit if there are no broadcast interfaces. */
241: persist = 1;
242: } else if (!strcmp(argv[i], "-e")) {
243: struct string_list *tmp;
244: if (++i == argc)
245: usage();
246: tmp = dmalloc(strlen(argv[i]) + sizeof *tmp, MDL);
247: if (!tmp)
248: log_fatal("No memory for %s", argv[i]);
249: strcpy(tmp->string, argv[i]);
250: tmp->next = client_env;
251: client_env = tmp;
252: client_env_count++;
253: #ifdef DHCPv6
254: } else if (!strcmp(argv[i], "-S")) {
255: if (local_family_set && (local_family == AF_INET)) {
256: usage();
257: }
258: local_family_set = 1;
259: local_family = AF_INET6;
260: wanted_ia_na = 0;
261: stateless = 1;
262: } else if (!strcmp(argv[i], "-N")) {
263: if (local_family_set && (local_family == AF_INET)) {
264: usage();
265: }
266: local_family_set = 1;
267: local_family = AF_INET6;
268: if (wanted_ia_na < 0) {
269: wanted_ia_na = 0;
270: }
271: wanted_ia_na++;
272: } else if (!strcmp(argv[i], "-T")) {
273: if (local_family_set && (local_family == AF_INET)) {
274: usage();
275: }
276: local_family_set = 1;
277: local_family = AF_INET6;
278: if (wanted_ia_na < 0) {
279: wanted_ia_na = 0;
280: }
281: wanted_ia_ta++;
282: } else if (!strcmp(argv[i], "-P")) {
283: if (local_family_set && (local_family == AF_INET)) {
284: usage();
285: }
286: local_family_set = 1;
287: local_family = AF_INET6;
288: if (wanted_ia_na < 0) {
289: wanted_ia_na = 0;
290: }
291: wanted_ia_pd++;
292: #endif /* DHCPv6 */
293: } else if (!strcmp(argv[i], "-v")) {
294: quiet = 0;
295: } else if (!strcmp(argv[i], "--version")) {
296: log_info("isc-dhclient-%s", PACKAGE_VERSION);
297: exit(0);
298: } else if (argv[i][0] == '-') {
299: usage();
300: } else if (interfaces_requested < 0) {
301: usage();
302: } else {
303: struct interface_info *tmp = NULL;
304:
305: status = interface_allocate(&tmp, MDL);
306: if (status != ISC_R_SUCCESS)
307: log_fatal("Can't record interface %s:%s",
308: argv[i], isc_result_totext(status));
309: if (strlen(argv[i]) >= sizeof(tmp->name))
310: log_fatal("%s: interface name too long (is %ld)",
311: argv[i], (long)strlen(argv[i]));
312: strcpy(tmp->name, argv[i]);
313: if (interfaces) {
314: interface_reference(&tmp->next,
315: interfaces, MDL);
316: interface_dereference(&interfaces, MDL);
317: }
318: interface_reference(&interfaces, tmp, MDL);
319: tmp->flags = INTERFACE_REQUESTED;
320: interfaces_requested++;
321: }
322: }
323:
324: if (wanted_ia_na < 0) {
325: wanted_ia_na = 1;
326: }
327:
328: /* Support only one (requested) interface for Prefix Delegation. */
329: if (wanted_ia_pd && (interfaces_requested != 1)) {
330: usage();
331: }
332:
333: if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
334: path_dhclient_conf = s;
335: }
336: if (!no_dhclient_db && (s = getenv("PATH_DHCLIENT_DB"))) {
337: path_dhclient_db = s;
338: }
339: if (!no_dhclient_pid && (s = getenv("PATH_DHCLIENT_PID"))) {
340: path_dhclient_pid = s;
341: }
342: if (!no_dhclient_script && (s = getenv("PATH_DHCLIENT_SCRIPT"))) {
343: path_dhclient_script = s;
344: }
345:
346: /* Set up the initial dhcp option universe. */
347: initialize_common_option_spaces();
348:
349: /* Assign v4 or v6 specific running parameters. */
350: if (local_family == AF_INET)
351: dhcpv4_client_assignments();
352: #ifdef DHCPv6
353: else if (local_family == AF_INET6)
354: dhcpv6_client_assignments();
355: #endif /* DHCPv6 */
356: else
357: log_fatal("Impossible condition at %s:%d.", MDL);
358:
359: /*
360: * convert relative path names to absolute, for files that need
361: * to be reopened after chdir() has been called
362: */
363: if (path_dhclient_db[0] != '/') {
364: char *path = dmalloc(PATH_MAX, MDL);
365: if (path == NULL)
366: log_fatal("No memory for filename\n");
367: path_dhclient_db = realpath(path_dhclient_db, path);
368: if (path_dhclient_db == NULL)
369: log_fatal("%s: %s", path, strerror(errno));
370: }
371:
372: if (path_dhclient_script[0] != '/') {
373: char *path = dmalloc(PATH_MAX, MDL);
374: if (path == NULL)
375: log_fatal("No memory for filename\n");
376: path_dhclient_script = realpath(path_dhclient_script, path);
377: if (path_dhclient_script == NULL)
378: log_fatal("%s: %s", path, strerror(errno));
379: }
380:
381: /*
382: * See if we should kill off any currently running client
383: * we don't try to kill it off if the user told us not
384: * to write a pid file - we assume they are controlling
385: * the process in some other fashion.
386: */
387: if ((release_mode || exit_mode) && (no_pid_file == ISC_FALSE)) {
388: FILE *pidfd;
389: pid_t oldpid;
390: long temp;
391: int e;
392:
393: oldpid = 0;
394: if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) {
395: e = fscanf(pidfd, "%ld\n", &temp);
396: oldpid = (pid_t)temp;
397:
398: if (e != 0 && e != EOF) {
399: if (oldpid)
400: kill(oldpid, SIGTERM);
401: }
402: fclose(pidfd);
403: }
404: }
405:
406: if (!quiet) {
407: log_info("%s %s", message, PACKAGE_VERSION);
408: log_info(copyright);
409: log_info(arr);
410: log_info(url);
411: log_info("%s", "");
412: } else {
413: log_perror = 0;
414: quiet_interface_discovery = 1;
415: }
416:
417: /* If we're given a relay agent address to insert, for testing
418: purposes, figure out what it is. */
419: if (mockup_relay) {
420: if (!inet_aton(mockup_relay, &giaddr)) {
421: struct hostent *he;
422: he = gethostbyname(mockup_relay);
423: if (he) {
424: memcpy(&giaddr, he->h_addr_list[0],
425: sizeof giaddr);
426: } else {
427: log_fatal("%s: no such host", mockup_relay);
428: }
429: }
430: }
431:
432: /* Get the current time... */
433: gettimeofday(&cur_tv, NULL);
434:
435: sockaddr_broadcast.sin_family = AF_INET;
436: sockaddr_broadcast.sin_port = remote_port;
437: if (server) {
438: if (!inet_aton(server, &sockaddr_broadcast.sin_addr)) {
439: struct hostent *he;
440: he = gethostbyname(server);
441: if (he) {
442: memcpy(&sockaddr_broadcast.sin_addr,
443: he->h_addr_list[0],
444: sizeof sockaddr_broadcast.sin_addr);
445: } else
446: sockaddr_broadcast.sin_addr.s_addr =
447: INADDR_BROADCAST;
448: }
449: } else {
450: sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
451: }
452:
453: inaddr_any.s_addr = INADDR_ANY;
454:
455: /* Stateless special case. */
456: if (stateless) {
457: if (release_mode || (wanted_ia_na > 0) ||
458: wanted_ia_ta || wanted_ia_pd ||
459: (interfaces_requested != 1)) {
460: usage();
461: }
462: run_stateless(exit_mode);
463: return 0;
464: }
465:
466: /* Discover all the network interfaces. */
467: discover_interfaces(DISCOVER_UNCONFIGURED);
468:
469: /* Parse the dhclient.conf file. */
470: read_client_conf();
471:
472: /* Parse the lease database. */
473: read_client_leases();
474:
475: /* Rewrite the lease database... */
476: rewrite_client_leases();
477:
478: /* XXX */
479: /* config_counter(&snd_counter, &rcv_counter); */
480:
481: /*
482: * If no broadcast interfaces were discovered, call the script
483: * and tell it so.
484: */
485: if (!interfaces) {
486: /*
487: * Call dhclient-script with the NBI flag,
488: * in case somebody cares.
489: */
490: script_init(NULL, "NBI", NULL);
491: script_go(NULL);
492:
493: /*
494: * If we haven't been asked to persist, waiting for new
495: * interfaces, then just exit.
496: */
497: if (!persist) {
498: /* Nothing more to do. */
499: log_info("No broadcast interfaces found - exiting.");
500: exit(0);
501: }
502: } else if (!release_mode && !exit_mode) {
503: /* Call the script with the list of interfaces. */
504: for (ip = interfaces; ip; ip = ip->next) {
505: /*
506: * If interfaces were specified, don't configure
507: * interfaces that weren't specified!
508: */
509: if ((interfaces_requested > 0) &&
510: ((ip->flags & (INTERFACE_REQUESTED |
511: INTERFACE_AUTOMATIC)) !=
512: INTERFACE_REQUESTED))
513: continue;
514:
515: if (local_family == AF_INET6) {
516: script_init(ip->client, "PREINIT6", NULL);
517: } else {
518: script_init(ip->client, "PREINIT", NULL);
519: if (ip->client->alias != NULL)
520: script_write_params(ip->client,
521: "alias_",
522: ip->client->alias);
523: }
524: script_go(ip->client);
525: }
526: }
527:
528: /* At this point, all the interfaces that the script thinks
529: are relevant should be running, so now we once again call
530: discover_interfaces(), and this time ask it to actually set
531: up the interfaces. */
532: discover_interfaces(interfaces_requested != 0
533: ? DISCOVER_REQUESTED
534: : DISCOVER_RUNNING);
535:
536: /* Make up a seed for the random number generator from current
537: time plus the sum of the last four bytes of each
538: interface's hardware address interpreted as an integer.
539: Not much entropy, but we're booting, so we're not likely to
540: find anything better. */
541: seed = 0;
542: for (ip = interfaces; ip; ip = ip->next) {
543: int junk;
544: memcpy(&junk,
545: &ip->hw_address.hbuf[ip->hw_address.hlen -
546: sizeof seed], sizeof seed);
547: seed += junk;
548: }
549: srandom(seed + cur_time + (unsigned)getpid());
550:
551: /* Start a configuration state machine for each interface. */
552: #ifdef DHCPv6
553: if (local_family == AF_INET6) {
554: /* Establish a default DUID. This may be moved to the
555: * DHCPv4 area later.
556: */
557: if (default_duid.len == 0) {
558: if (default_duid.buffer != NULL)
559: data_string_forget(&default_duid, MDL);
560:
561: form_duid(&default_duid, MDL);
562: write_duid(&default_duid);
563: }
564:
565: for (ip = interfaces ; ip != NULL ; ip = ip->next) {
566: for (client = ip->client ; client != NULL ;
567: client = client->next) {
568: if (release_mode) {
569: start_release6(client);
570: continue;
571: } else if (exit_mode) {
572: unconfigure6(client, "STOP6");
573: continue;
574: }
575:
576: /* If we have a previous binding, Confirm
577: * that we can (or can't) still use it.
578: */
579: if ((client->active_lease != NULL) &&
580: !client->active_lease->released)
581: start_confirm6(client);
582: else
583: start_init6(client);
584: }
585: }
586: } else
587: #endif /* DHCPv6 */
588: {
589: for (ip = interfaces ; ip ; ip = ip->next) {
590: ip->flags |= INTERFACE_RUNNING;
591: for (client = ip->client ; client ;
592: client = client->next) {
593: if (exit_mode)
594: state_stop(client);
595: else if (release_mode)
596: do_release(client);
597: else {
598: client->state = S_INIT;
599:
600: if (top_level_config.initial_delay>0)
601: {
602: tv.tv_sec = 0;
603: if (top_level_config.
604: initial_delay>1)
605: tv.tv_sec = cur_time
606: + random()
607: % (top_level_config.
608: initial_delay-1);
609: tv.tv_usec = random()
610: % 1000000;
611: /*
612: * this gives better
613: * distribution than just
614: *whole seconds
615: */
616: add_timeout(&tv, state_reboot,
617: client, 0, 0);
618: } else {
619: state_reboot(client);
620: }
621: }
622: }
623: }
624: }
625:
626: if (exit_mode)
627: return 0;
628: if (release_mode) {
629: #ifndef DHCPv6
630: return 0;
631: #else
632: if (local_family == AF_INET6) {
633: if (onetry)
634: return 0;
635: } else
636: return 0;
637: #endif /* DHCPv6 */
638: }
639:
640: /* Start up a listener for the object management API protocol. */
641: if (top_level_config.omapi_port != -1) {
642: listener = NULL;
643: result = omapi_generic_new(&listener, MDL);
644: if (result != ISC_R_SUCCESS)
645: log_fatal("Can't allocate new generic object: %s\n",
646: isc_result_totext(result));
647: result = omapi_protocol_listen(listener,
648: (unsigned)
649: top_level_config.omapi_port,
650: 1);
651: if (result != ISC_R_SUCCESS)
652: log_fatal("Can't start OMAPI protocol: %s",
653: isc_result_totext (result));
654: }
655:
656: /* Set up the bootp packet handler... */
657: bootp_packet_handler = do_packet;
658: #ifdef DHCPv6
659: dhcpv6_packet_handler = do_packet6;
660: #endif /* DHCPv6 */
661:
662: #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
663: defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
664: dmalloc_cutoff_generation = dmalloc_generation;
665: dmalloc_longterm = dmalloc_outstanding;
666: dmalloc_outstanding = 0;
667: #endif
668:
669: /* If we're not supposed to wait before getting the address,
670: don't. */
671: if (nowait)
672: go_daemon();
673:
674: /* If we're not going to daemonize, write the pid file
675: now. */
676: if (no_daemon || nowait)
677: write_client_pid_file();
678:
679: /* Start dispatching packets and timeouts... */
680: dispatch();
681:
682: /*NOTREACHED*/
683: return 0;
684: }
685:
686: static void usage()
687: {
688: log_info("%s %s", message, PACKAGE_VERSION);
689: log_info(copyright);
690: log_info(arr);
691: log_info(url);
692:
693:
694: log_fatal("Usage: dhclient "
695: #ifdef DHCPv6
696: "[-4|-6] [-SNTP1dvrx] [-nw] [-p <port>]\n"
697: #else /* DHCPv6 */
698: "[-1dvrx] [-nw] [-p <port>]\n"
699: #endif /* DHCPv6 */
700: " [-s server-addr] [-cf config-file] "
701: "[-lf lease-file]\n"
702: " [-pf pid-file] [--no-pid] [-e VAR=val]\n"
703: " [-sf script-file] [interface]");
704: }
705:
706: void run_stateless(int exit_mode)
707: {
708: #ifdef DHCPv6
709: struct client_state *client;
710: omapi_object_t *listener;
711: isc_result_t result;
712:
713: /* Discover the network interface. */
714: discover_interfaces(DISCOVER_REQUESTED);
715:
716: if (!interfaces)
717: usage();
718:
719: /* Parse the dhclient.conf file. */
720: read_client_conf();
721:
722: /* Parse the lease database. */
723: read_client_leases();
724:
725: /* Establish a default DUID. */
726: if (default_duid.len == 0) {
727: if (default_duid.buffer != NULL)
728: data_string_forget(&default_duid, MDL);
729:
730: form_duid(&default_duid, MDL);
731: }
732:
733: /* Start a configuration state machine. */
734: for (client = interfaces->client ;
735: client != NULL ;
736: client = client->next) {
737: if (exit_mode) {
738: unconfigure6(client, "STOP6");
739: continue;
740: }
741: start_info_request6(client);
742: }
743: if (exit_mode)
744: return;
745:
746: /* Start up a listener for the object management API protocol. */
747: if (top_level_config.omapi_port != -1) {
748: listener = NULL;
749: result = omapi_generic_new(&listener, MDL);
750: if (result != ISC_R_SUCCESS)
751: log_fatal("Can't allocate new generic object: %s\n",
752: isc_result_totext(result));
753: result = omapi_protocol_listen(listener,
754: (unsigned)
755: top_level_config.omapi_port,
756: 1);
757: if (result != ISC_R_SUCCESS)
758: log_fatal("Can't start OMAPI protocol: %s",
759: isc_result_totext(result));
760: }
761:
762: /* Set up the packet handler... */
763: dhcpv6_packet_handler = do_packet6;
764:
765: #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
766: defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
767: dmalloc_cutoff_generation = dmalloc_generation;
768: dmalloc_longterm = dmalloc_outstanding;
769: dmalloc_outstanding = 0;
770: #endif
771:
772: /* If we're not supposed to wait before getting the address,
773: don't. */
774: if (nowait)
775: go_daemon();
776:
777: /* If we're not going to daemonize, write the pid file
778: now. */
779: if (no_daemon || nowait)
780: write_client_pid_file();
781:
782: /* Start dispatching packets and timeouts... */
783: dispatch();
784:
785: /*NOTREACHED*/
786: #endif /* DHCPv6 */
787: return;
788: }
789:
790: isc_result_t find_class (struct class **c,
791: const char *s, const char *file, int line)
792: {
793: return 0;
794: }
795:
796: int check_collection (packet, lease, collection)
797: struct packet *packet;
798: struct lease *lease;
799: struct collection *collection;
800: {
801: return 0;
802: }
803:
804: void classify (packet, class)
805: struct packet *packet;
806: struct class *class;
807: {
808: }
809:
810: int unbill_class (lease, class)
811: struct lease *lease;
812: struct class *class;
813: {
814: return 0;
815: }
816:
817: int find_subnet (struct subnet **sp,
818: struct iaddr addr, const char *file, int line)
819: {
820: return 0;
821: }
822:
823: /* Individual States:
824: *
825: * Each routine is called from the dhclient_state_machine() in one of
826: * these conditions:
827: * -> entering INIT state
828: * -> recvpacket_flag == 0: timeout in this state
829: * -> otherwise: received a packet in this state
830: *
831: * Return conditions as handled by dhclient_state_machine():
832: * Returns 1, sendpacket_flag = 1: send packet, reset timer.
833: * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
834: * Returns 0: finish the nap which was interrupted for no good reason.
835: *
836: * Several per-interface variables are used to keep track of the process:
837: * active_lease: the lease that is being used on the interface
838: * (null pointer if not configured yet).
839: * offered_leases: leases corresponding to DHCPOFFER messages that have
840: * been sent to us by DHCP servers.
841: * acked_leases: leases corresponding to DHCPACK messages that have been
842: * sent to us by DHCP servers.
843: * sendpacket: DHCP packet we're trying to send.
844: * destination: IP address to send sendpacket to
845: * In addition, there are several relevant per-lease variables.
846: * T1_expiry, T2_expiry, lease_expiry: lease milestones
847: * In the active lease, these control the process of renewing the lease;
848: * In leases on the acked_leases list, this simply determines when we
849: * can no longer legitimately use the lease.
850: */
851:
852: void state_reboot (cpp)
853: void *cpp;
854: {
855: struct client_state *client = cpp;
856:
857: /* If we don't remember an active lease, go straight to INIT. */
858: if (!client -> active ||
859: client -> active -> is_bootp ||
860: client -> active -> expiry <= cur_time) {
861: state_init (client);
862: return;
863: }
864:
865: /* We are in the rebooting state. */
866: client -> state = S_REBOOTING;
867:
868: /*
869: * make_request doesn't initialize xid because it normally comes
870: * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
871: * so pick an xid now.
872: */
873: client -> xid = random ();
874:
875: /*
876: * Make a DHCPREQUEST packet, and set
877: * appropriate per-interface flags.
878: */
879: make_request (client, client -> active);
880: client -> destination = iaddr_broadcast;
881: client -> first_sending = cur_time;
882: client -> interval = client -> config -> initial_interval;
883:
884: /* Zap the medium list... */
885: client -> medium = NULL;
886:
887: /* Send out the first DHCPREQUEST packet. */
888: send_request (client);
889: }
890:
891: /* Called when a lease has completely expired and we've been unable to
892: renew it. */
893:
894: void state_init (cpp)
895: void *cpp;
896: {
897: struct client_state *client = cpp;
898:
899: ASSERT_STATE(state, S_INIT);
900:
901: /* Make a DHCPDISCOVER packet, and set appropriate per-interface
902: flags. */
903: make_discover (client, client -> active);
904: client -> xid = client -> packet.xid;
905: client -> destination = iaddr_broadcast;
906: client -> state = S_SELECTING;
907: client -> first_sending = cur_time;
908: client -> interval = client -> config -> initial_interval;
909:
910: /* Add an immediate timeout to cause the first DHCPDISCOVER packet
911: to go out. */
912: send_discover (client);
913: }
914:
915: /*
916: * state_selecting is called when one or more DHCPOFFER packets have been
917: * received and a configurable period of time has passed.
918: */
919:
920: void state_selecting (cpp)
921: void *cpp;
922: {
923: struct client_state *client = cpp;
924: struct client_lease *lp, *next, *picked;
925:
926:
927: ASSERT_STATE(state, S_SELECTING);
928:
929: /*
930: * Cancel state_selecting and send_discover timeouts, since either
931: * one could have got us here.
932: */
933: cancel_timeout (state_selecting, client);
934: cancel_timeout (send_discover, client);
935:
936: /*
937: * We have received one or more DHCPOFFER packets. Currently,
938: * the only criterion by which we judge leases is whether or
939: * not we get a response when we arp for them.
940: */
941: picked = NULL;
942: for (lp = client -> offered_leases; lp; lp = next) {
943: next = lp -> next;
944:
945: /*
946: * Check to see if we got an ARPREPLY for the address
947: * in this particular lease.
948: */
949: if (!picked) {
950: picked = lp;
951: picked -> next = NULL;
952: } else {
953: destroy_client_lease (lp);
954: }
955: }
956: client -> offered_leases = NULL;
957:
958: /*
959: * If we just tossed all the leases we were offered, go back
960: * to square one.
961: */
962: if (!picked) {
963: client -> state = S_INIT;
964: state_init (client);
965: return;
966: }
967:
968: /* If it was a BOOTREPLY, we can just take the address right now. */
969: if (picked -> is_bootp) {
970: client -> new = picked;
971:
972: /* Make up some lease expiry times
973: XXX these should be configurable. */
974: client -> new -> expiry = cur_time + 12000;
975: client -> new -> renewal += cur_time + 8000;
976: client -> new -> rebind += cur_time + 10000;
977:
978: client -> state = S_REQUESTING;
979:
980: /* Bind to the address we received. */
981: bind_lease (client);
982: return;
983: }
984:
985: /* Go to the REQUESTING state. */
986: client -> destination = iaddr_broadcast;
987: client -> state = S_REQUESTING;
988: client -> first_sending = cur_time;
989: client -> interval = client -> config -> initial_interval;
990:
991: /* Make a DHCPREQUEST packet from the lease we picked. */
992: make_request (client, picked);
993: client -> xid = client -> packet.xid;
994:
995: /* Toss the lease we picked - we'll get it back in a DHCPACK. */
996: destroy_client_lease (picked);
997:
998: /* Add an immediate timeout to send the first DHCPREQUEST packet. */
999: send_request (client);
1000: }
1001:
1002: /* state_requesting is called when we receive a DHCPACK message after
1003: having sent out one or more DHCPREQUEST packets. */
1004:
1005: void dhcpack (packet)
1006: struct packet *packet;
1007: {
1008: struct interface_info *ip = packet -> interface;
1009: struct client_state *client;
1010: struct client_lease *lease;
1011: struct option_cache *oc;
1012: struct data_string ds;
1013:
1014: /* If we're not receptive to an offer right now, or if the offer
1015: has an unrecognizable transaction id, then just drop it. */
1016: for (client = ip -> client; client; client = client -> next) {
1017: if (client -> xid == packet -> raw -> xid)
1018: break;
1019: }
1020: if (!client ||
1021: (packet -> interface -> hw_address.hlen - 1 !=
1022: packet -> raw -> hlen) ||
1023: (memcmp (&packet -> interface -> hw_address.hbuf [1],
1024: packet -> raw -> chaddr, packet -> raw -> hlen))) {
1025: #if defined (DEBUG)
1026: log_debug ("DHCPACK in wrong transaction.");
1027: #endif
1028: return;
1029: }
1030:
1031: if (client -> state != S_REBOOTING &&
1032: client -> state != S_REQUESTING &&
1033: client -> state != S_RENEWING &&
1034: client -> state != S_REBINDING) {
1035: #if defined (DEBUG)
1036: log_debug ("DHCPACK in wrong state.");
1037: #endif
1038: return;
1039: }
1040:
1041: log_info ("DHCPACK from %s", piaddr (packet -> client_addr));
1042:
1043: lease = packet_to_lease (packet, client);
1044: if (!lease) {
1045: log_info ("packet_to_lease failed.");
1046: return;
1047: }
1048:
1049: client -> new = lease;
1050:
1051: /* Stop resending DHCPREQUEST. */
1052: cancel_timeout (send_request, client);
1053:
1054: /* Figure out the lease time. */
1055: oc = lookup_option (&dhcp_universe, client -> new -> options,
1056: DHO_DHCP_LEASE_TIME);
1057: memset (&ds, 0, sizeof ds);
1058: if (oc &&
1059: evaluate_option_cache (&ds, packet, (struct lease *)0, client,
1060: packet -> options, client -> new -> options,
1061: &global_scope, oc, MDL)) {
1062: if (ds.len > 3)
1063: client -> new -> expiry = getULong (ds.data);
1064: else
1065: client -> new -> expiry = 0;
1066: data_string_forget (&ds, MDL);
1067: } else
1068: client -> new -> expiry = 0;
1069:
1070: if (client->new->expiry == 0) {
1071: struct timeval tv;
1072:
1073: log_error ("no expiry time on offered lease.");
1074:
1075: /* Quench this (broken) server. Return to INIT to reselect. */
1076: add_reject(packet);
1077:
1078: /* 1/2 second delay to restart at INIT. */
1079: tv.tv_sec = cur_tv.tv_sec;
1080: tv.tv_usec = cur_tv.tv_usec + 500000;
1081:
1082: if (tv.tv_usec >= 1000000) {
1083: tv.tv_sec++;
1084: tv.tv_usec -= 1000000;
1085: }
1086:
1087: add_timeout(&tv, state_init, client, 0, 0);
1088: return;
1089: }
1090:
1091: /*
1092: * A number that looks negative here is really just very large,
1093: * because the lease expiry offset is unsigned.
1094: */
1095: if (client->new->expiry < 0)
1096: client->new->expiry = TIME_MAX;
1097:
1098: /* Take the server-provided renewal time if there is one. */
1099: oc = lookup_option (&dhcp_universe, client -> new -> options,
1100: DHO_DHCP_RENEWAL_TIME);
1101: if (oc &&
1102: evaluate_option_cache (&ds, packet, (struct lease *)0, client,
1103: packet -> options, client -> new -> options,
1104: &global_scope, oc, MDL)) {
1105: if (ds.len > 3)
1106: client -> new -> renewal = getULong (ds.data);
1107: else
1108: client -> new -> renewal = 0;
1109: data_string_forget (&ds, MDL);
1110: } else
1111: client -> new -> renewal = 0;
1112:
1113: /* If it wasn't specified by the server, calculate it. */
1114: if (!client -> new -> renewal)
1115: client -> new -> renewal = client -> new -> expiry / 2 + 1;
1116:
1117: if (client -> new -> renewal <= 0)
1118: client -> new -> renewal = TIME_MAX;
1119:
1120: /* Now introduce some randomness to the renewal time: */
1121: if (client->new->renewal <= ((TIME_MAX / 3) - 3))
1122: client->new->renewal = (((client->new->renewal * 3) + 3) / 4) +
1123: (((random() % client->new->renewal) + 3) / 4);
1124:
1125: /* Same deal with the rebind time. */
1126: oc = lookup_option (&dhcp_universe, client -> new -> options,
1127: DHO_DHCP_REBINDING_TIME);
1128: if (oc &&
1129: evaluate_option_cache (&ds, packet, (struct lease *)0, client,
1130: packet -> options, client -> new -> options,
1131: &global_scope, oc, MDL)) {
1132: if (ds.len > 3)
1133: client -> new -> rebind = getULong (ds.data);
1134: else
1135: client -> new -> rebind = 0;
1136: data_string_forget (&ds, MDL);
1137: } else
1138: client -> new -> rebind = 0;
1139:
1140: if (client -> new -> rebind <= 0) {
1141: if (client -> new -> expiry <= TIME_MAX / 7)
1142: client -> new -> rebind =
1143: client -> new -> expiry * 7 / 8;
1144: else
1145: client -> new -> rebind =
1146: client -> new -> expiry / 8 * 7;
1147: }
1148:
1149: /* Make sure our randomness didn't run the renewal time past the
1150: rebind time. */
1151: if (client -> new -> renewal > client -> new -> rebind) {
1152: if (client -> new -> rebind <= TIME_MAX / 3)
1153: client -> new -> renewal =
1154: client -> new -> rebind * 3 / 4;
1155: else
1156: client -> new -> renewal =
1157: client -> new -> rebind / 4 * 3;
1158: }
1159:
1160: client -> new -> expiry += cur_time;
1161: /* Lease lengths can never be negative. */
1162: if (client -> new -> expiry < cur_time)
1163: client -> new -> expiry = TIME_MAX;
1164: client -> new -> renewal += cur_time;
1165: if (client -> new -> renewal < cur_time)
1166: client -> new -> renewal = TIME_MAX;
1167: client -> new -> rebind += cur_time;
1168: if (client -> new -> rebind < cur_time)
1169: client -> new -> rebind = TIME_MAX;
1170:
1171: bind_lease (client);
1172: }
1173:
1174: void bind_lease (client)
1175: struct client_state *client;
1176: {
1177: struct timeval tv;
1178:
1179: /* Remember the medium. */
1180: client -> new -> medium = client -> medium;
1181:
1182: /* Run the client script with the new parameters. */
1183: script_init (client, (client -> state == S_REQUESTING
1184: ? "BOUND"
1185: : (client -> state == S_RENEWING
1186: ? "RENEW"
1187: : (client -> state == S_REBOOTING
1188: ? "REBOOT" : "REBIND"))),
1189: client -> new -> medium);
1190: if (client -> active && client -> state != S_REBOOTING)
1191: script_write_params (client, "old_", client -> active);
1192: script_write_params (client, "new_", client -> new);
1193: if (client -> alias)
1194: script_write_params (client, "alias_", client -> alias);
1195:
1196: /* If the BOUND/RENEW code detects another machine using the
1197: offered address, it exits nonzero. We need to send a
1198: DHCPDECLINE and toss the lease. */
1199: if (script_go (client)) {
1200: make_decline (client, client -> new);
1201: send_decline (client);
1202: destroy_client_lease (client -> new);
1203: client -> new = (struct client_lease *)0;
1204: state_init (client);
1205: return;
1206: }
1207:
1208: /* Write out the new lease if it has been long enough. */
1209: if (!client->last_write ||
1210: (cur_time - client->last_write) >= MIN_LEASE_WRITE)
1211: write_client_lease(client, client->new, 0, 0);
1212:
1213: /* Replace the old active lease with the new one. */
1214: if (client -> active)
1215: destroy_client_lease (client -> active);
1216: client -> active = client -> new;
1217: client -> new = (struct client_lease *)0;
1218:
1219: /* Set up a timeout to start the renewal process. */
1220: tv.tv_sec = client->active->renewal;
1221: tv.tv_usec = ((client->active->renewal - cur_tv.tv_sec) > 1) ?
1222: random() % 1000000 : cur_tv.tv_usec;
1223: add_timeout(&tv, state_bound, client, 0, 0);
1224:
1225: log_info ("bound to %s -- renewal in %ld seconds.",
1226: piaddr (client -> active -> address),
1227: (long)(client -> active -> renewal - cur_time));
1228: client -> state = S_BOUND;
1229: reinitialize_interfaces ();
1230: go_daemon ();
1231: if (client->config->do_forward_update)
1232: dhclient_schedule_updates(client, &client->active->address,
1233: 1);
1234: }
1235:
1236: /* state_bound is called when we've successfully bound to a particular
1237: lease, but the renewal time on that lease has expired. We are
1238: expected to unicast a DHCPREQUEST to the server that gave us our
1239: original lease. */
1240:
1241: void state_bound (cpp)
1242: void *cpp;
1243: {
1244: struct client_state *client = cpp;
1245: struct option_cache *oc;
1246: struct data_string ds;
1247:
1248: ASSERT_STATE(state, S_BOUND);
1249:
1250: /* T1 has expired. */
1251: make_request (client, client -> active);
1252: client -> xid = client -> packet.xid;
1253:
1254: memset (&ds, 0, sizeof ds);
1255: oc = lookup_option (&dhcp_universe, client -> active -> options,
1256: DHO_DHCP_SERVER_IDENTIFIER);
1257: if (oc &&
1258: evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
1259: client, (struct option_state *)0,
1260: client -> active -> options,
1261: &global_scope, oc, MDL)) {
1262: if (ds.len > 3) {
1263: memcpy (client -> destination.iabuf, ds.data, 4);
1264: client -> destination.len = 4;
1265: } else
1266: client -> destination = iaddr_broadcast;
1267:
1268: data_string_forget (&ds, MDL);
1269: } else
1270: client -> destination = iaddr_broadcast;
1271:
1272: client -> first_sending = cur_time;
1273: client -> interval = client -> config -> initial_interval;
1274: client -> state = S_RENEWING;
1275:
1276: /* Send the first packet immediately. */
1277: send_request (client);
1278: }
1279:
1280: /* state_stop is called when we've been told to shut down. We unconfigure
1281: the interfaces, and then stop operating until told otherwise. */
1282:
1283: void state_stop (cpp)
1284: void *cpp;
1285: {
1286: struct client_state *client = cpp;
1287:
1288: /* Cancel all timeouts. */
1289: cancel_timeout(state_selecting, client);
1290: cancel_timeout(send_discover, client);
1291: cancel_timeout(send_request, client);
1292: cancel_timeout(state_bound, client);
1293:
1294: /* If we have an address, unconfigure it. */
1295: if (client->active) {
1296: script_init(client, "STOP", client->active->medium);
1297: script_write_params(client, "old_", client->active);
1298: if (client->alias)
1299: script_write_params(client, "alias_", client->alias);
1300: script_go(client);
1301: }
1302: }
1303:
1304: int commit_leases ()
1305: {
1306: return 0;
1307: }
1308:
1309: int write_lease (lease)
1310: struct lease *lease;
1311: {
1312: return 0;
1313: }
1314:
1315: int write_host (host)
1316: struct host_decl *host;
1317: {
1318: return 0;
1319: }
1320:
1321: void db_startup (testp)
1322: int testp;
1323: {
1324: }
1325:
1326: void bootp (packet)
1327: struct packet *packet;
1328: {
1329: struct iaddrmatchlist *ap;
1330: char addrbuf[4*16];
1331: char maskbuf[4*16];
1332:
1333: if (packet -> raw -> op != BOOTREPLY)
1334: return;
1335:
1336: /* If there's a reject list, make sure this packet's sender isn't
1337: on it. */
1338: for (ap = packet -> interface -> client -> config -> reject_list;
1339: ap; ap = ap -> next) {
1340: if (addr_match(&packet->client_addr, &ap->match)) {
1341:
1342: /* piaddr() returns its result in a static
1343: buffer sized 4*16 (see common/inet.c). */
1344:
1345: strcpy(addrbuf, piaddr(ap->match.addr));
1346: strcpy(maskbuf, piaddr(ap->match.mask));
1347:
1348: log_info("BOOTREPLY from %s rejected by rule %s "
1349: "mask %s.", piaddr(packet->client_addr),
1350: addrbuf, maskbuf);
1351: return;
1352: }
1353: }
1354:
1355: dhcpoffer (packet);
1356:
1357: }
1358:
1359: void dhcp (packet)
1360: struct packet *packet;
1361: {
1362: struct iaddrmatchlist *ap;
1363: void (*handler) (struct packet *);
1364: const char *type;
1365: char addrbuf[4*16];
1366: char maskbuf[4*16];
1367:
1368: switch (packet -> packet_type) {
1369: case DHCPOFFER:
1370: handler = dhcpoffer;
1371: type = "DHCPOFFER";
1372: break;
1373:
1374: case DHCPNAK:
1375: handler = dhcpnak;
1376: type = "DHCPNACK";
1377: break;
1378:
1379: case DHCPACK:
1380: handler = dhcpack;
1381: type = "DHCPACK";
1382: break;
1383:
1384: default:
1385: return;
1386: }
1387:
1388: /* If there's a reject list, make sure this packet's sender isn't
1389: on it. */
1390: for (ap = packet -> interface -> client -> config -> reject_list;
1391: ap; ap = ap -> next) {
1392: if (addr_match(&packet->client_addr, &ap->match)) {
1393:
1394: /* piaddr() returns its result in a static
1395: buffer sized 4*16 (see common/inet.c). */
1396:
1397: strcpy(addrbuf, piaddr(ap->match.addr));
1398: strcpy(maskbuf, piaddr(ap->match.mask));
1399:
1400: log_info("%s from %s rejected by rule %s mask %s.",
1401: type, piaddr(packet->client_addr),
1402: addrbuf, maskbuf);
1403: return;
1404: }
1405: }
1406: (*handler) (packet);
1407: }
1408:
1409: #ifdef DHCPv6
1410: void
1411: dhcpv6(struct packet *packet) {
1412: struct iaddrmatchlist *ap;
1413: struct client_state *client;
1414: char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
1415:
1416: /* Silently drop bogus messages. */
1417: if (packet->dhcpv6_msg_type >= dhcpv6_type_name_max)
1418: return;
1419:
1420: /* Discard, with log, packets from quenched sources. */
1421: for (ap = packet->interface->client->config->reject_list ;
1422: ap ; ap = ap->next) {
1423: if (addr_match(&packet->client_addr, &ap->match)) {
1424: strcpy(addrbuf, piaddr(packet->client_addr));
1425: log_info("%s from %s rejected by rule %s",
1426: dhcpv6_type_names[packet->dhcpv6_msg_type],
1427: addrbuf,
1428: piaddrmask(&ap->match.addr, &ap->match.mask));
1429: return;
1430: }
1431: }
1432:
1433: /* Screen out nonsensical messages. */
1434: switch(packet->dhcpv6_msg_type) {
1435: case DHCPV6_ADVERTISE:
1436: case DHCPV6_RECONFIGURE:
1437: if (stateless)
1438: return;
1439: /* Falls through */
1440: case DHCPV6_REPLY:
1441: log_info("RCV: %s message on %s from %s.",
1442: dhcpv6_type_names[packet->dhcpv6_msg_type],
1443: packet->interface->name, piaddr(packet->client_addr));
1444: break;
1445:
1446: default:
1447: return;
1448: }
1449:
1450: /* Find a client state that matches the incoming XID. */
1451: for (client = packet->interface->client ; client ;
1452: client = client->next) {
1453: if (memcmp(&client->dhcpv6_transaction_id,
1454: packet->dhcpv6_transaction_id, 3) == 0) {
1455: client->v6_handler(packet, client);
1456: return;
1457: }
1458: }
1459:
1460: /* XXX: temporary log for debugging */
1461: log_info("Packet received, but nothing done with it.");
1462: }
1463: #endif /* DHCPv6 */
1464:
1465: void dhcpoffer (packet)
1466: struct packet *packet;
1467: {
1468: struct interface_info *ip = packet -> interface;
1469: struct client_state *client;
1470: struct client_lease *lease, *lp;
1471: struct option **req;
1472: int i;
1473: int stop_selecting;
1474: const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
1475: char obuf [1024];
1476: struct timeval tv;
1477:
1478: #ifdef DEBUG_PACKET
1479: dump_packet (packet);
1480: #endif
1481:
1482: /* Find a client state that matches the xid... */
1483: for (client = ip -> client; client; client = client -> next)
1484: if (client -> xid == packet -> raw -> xid)
1485: break;
1486:
1487: /* If we're not receptive to an offer right now, or if the offer
1488: has an unrecognizable transaction id, then just drop it. */
1489: if (!client ||
1490: client -> state != S_SELECTING ||
1491: (packet -> interface -> hw_address.hlen - 1 !=
1492: packet -> raw -> hlen) ||
1493: (memcmp (&packet -> interface -> hw_address.hbuf [1],
1494: packet -> raw -> chaddr, packet -> raw -> hlen))) {
1495: #if defined (DEBUG)
1496: log_debug ("%s in wrong transaction.", name);
1497: #endif
1498: return;
1499: }
1500:
1501: sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
1502:
1503:
1504: /* If this lease doesn't supply the minimum required DHCPv4 parameters,
1505: * ignore it.
1506: */
1507: req = client->config->required_options;
1508: if (req != NULL) {
1509: for (i = 0 ; req[i] != NULL ; i++) {
1510: if ((req[i]->universe == &dhcp_universe) &&
1511: !lookup_option(&dhcp_universe, packet->options,
1512: req[i]->code)) {
1513: struct option *option = NULL;
1514: unsigned code = req[i]->code;
1515:
1516: option_code_hash_lookup(&option,
1517: dhcp_universe.code_hash,
1518: &code, 0, MDL);
1519:
1520: if (option)
1521: log_info("%s: no %s option.", obuf,
1522: option->name);
1523: else
1524: log_info("%s: no unknown-%u option.",
1525: obuf, code);
1526:
1527: option_dereference(&option, MDL);
1528:
1529: return;
1530: }
1531: }
1532: }
1533:
1534: /* If we've already seen this lease, don't record it again. */
1535: for (lease = client -> offered_leases; lease; lease = lease -> next) {
1536: if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
1537: !memcmp (lease -> address.iabuf,
1538: &packet -> raw -> yiaddr, lease -> address.len)) {
1539: log_debug ("%s: already seen.", obuf);
1540: return;
1541: }
1542: }
1543:
1544: lease = packet_to_lease (packet, client);
1545: if (!lease) {
1546: log_info ("%s: packet_to_lease failed.", obuf);
1547: return;
1548: }
1549:
1550: /* If this lease was acquired through a BOOTREPLY, record that
1551: fact. */
1552: if (!packet -> options_valid || !packet -> packet_type)
1553: lease -> is_bootp = 1;
1554:
1555: /* Record the medium under which this lease was offered. */
1556: lease -> medium = client -> medium;
1557:
1558: /* Figure out when we're supposed to stop selecting. */
1559: stop_selecting = (client -> first_sending +
1560: client -> config -> select_interval);
1561:
1562: /* If this is the lease we asked for, put it at the head of the
1563: list, and don't mess with the arp request timeout. */
1564: if (lease -> address.len == client -> requested_address.len &&
1565: !memcmp (lease -> address.iabuf,
1566: client -> requested_address.iabuf,
1567: client -> requested_address.len)) {
1568: lease -> next = client -> offered_leases;
1569: client -> offered_leases = lease;
1570: } else {
1571: /* Put the lease at the end of the list. */
1572: lease -> next = (struct client_lease *)0;
1573: if (!client -> offered_leases)
1574: client -> offered_leases = lease;
1575: else {
1576: for (lp = client -> offered_leases; lp -> next;
1577: lp = lp -> next)
1578: ;
1579: lp -> next = lease;
1580: }
1581: }
1582:
1583: /* If the selecting interval has expired, go immediately to
1584: state_selecting(). Otherwise, time out into
1585: state_selecting at the select interval. */
1586: if (stop_selecting <= cur_tv.tv_sec)
1587: state_selecting (client);
1588: else {
1589: tv.tv_sec = stop_selecting;
1590: tv.tv_usec = cur_tv.tv_usec;
1591: add_timeout(&tv, state_selecting, client, 0, 0);
1592: cancel_timeout(send_discover, client);
1593: }
1594: log_info("%s", obuf);
1595: }
1596:
1597: /* Allocate a client_lease structure and initialize it from the parameters
1598: in the specified packet. */
1599:
1600: struct client_lease *packet_to_lease (packet, client)
1601: struct packet *packet;
1602: struct client_state *client;
1603: {
1604: struct client_lease *lease;
1605: unsigned i;
1606: struct option_cache *oc;
1607: struct option *option = NULL;
1608: struct data_string data;
1609:
1610: lease = (struct client_lease *)new_client_lease (MDL);
1611:
1612: if (!lease) {
1613: log_error ("packet_to_lease: no memory to record lease.\n");
1614: return (struct client_lease *)0;
1615: }
1616:
1617: memset (lease, 0, sizeof *lease);
1618:
1619: /* Copy the lease options. */
1620: option_state_reference (&lease -> options, packet -> options, MDL);
1621:
1622: lease -> address.len = sizeof (packet -> raw -> yiaddr);
1623: memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
1624: lease -> address.len);
1625:
1626: memset (&data, 0, sizeof data);
1627:
1628: if (client -> config -> vendor_space_name) {
1629: i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
1630:
1631: /* See if there was a vendor encapsulation option. */
1632: oc = lookup_option (&dhcp_universe, lease -> options, i);
1633: if (oc &&
1634: client -> config -> vendor_space_name &&
1635: evaluate_option_cache (&data, packet,
1636: (struct lease *)0, client,
1637: packet -> options, lease -> options,
1638: &global_scope, oc, MDL)) {
1639: if (data.len) {
1640: if (!option_code_hash_lookup(&option,
1641: dhcp_universe.code_hash,
1642: &i, 0, MDL))
1643: log_fatal("Unable to find VENDOR "
1644: "option (%s:%d).", MDL);
1645: parse_encapsulated_suboptions
1646: (packet -> options, option,
1647: data.data, data.len, &dhcp_universe,
1648: client -> config -> vendor_space_name
1649: );
1650:
1651: option_dereference(&option, MDL);
1652: }
1653: data_string_forget (&data, MDL);
1654: }
1655: } else
1656: i = 0;
1657:
1658: /* Figure out the overload flag. */
1659: oc = lookup_option (&dhcp_universe, lease -> options,
1660: DHO_DHCP_OPTION_OVERLOAD);
1661: if (oc &&
1662: evaluate_option_cache (&data, packet, (struct lease *)0, client,
1663: packet -> options, lease -> options,
1664: &global_scope, oc, MDL)) {
1665: if (data.len > 0)
1666: i = data.data [0];
1667: else
1668: i = 0;
1669: data_string_forget (&data, MDL);
1670: } else
1671: i = 0;
1672:
1673: /* If the server name was filled out, copy it. */
1674: if (!(i & 2) && packet -> raw -> sname [0]) {
1675: unsigned len;
1676: /* Don't count on the NUL terminator. */
1677: for (len = 0; len < DHCP_SNAME_LEN; len++)
1678: if (!packet -> raw -> sname [len])
1679: break;
1680: lease -> server_name = dmalloc (len + 1, MDL);
1681: if (!lease -> server_name) {
1682: log_error ("dhcpoffer: no memory for server name.\n");
1683: destroy_client_lease (lease);
1684: return (struct client_lease *)0;
1685: } else {
1686: memcpy (lease -> server_name,
1687: packet -> raw -> sname, len);
1688: lease -> server_name [len] = 0;
1689: }
1690: }
1691:
1692: /* Ditto for the filename. */
1693: if (!(i & 1) && packet -> raw -> file [0]) {
1694: unsigned len;
1695: /* Don't count on the NUL terminator. */
1696: for (len = 0; len < DHCP_FILE_LEN; len++)
1697: if (!packet -> raw -> file [len])
1698: break;
1699: lease -> filename = dmalloc (len + 1, MDL);
1700: if (!lease -> filename) {
1701: log_error ("dhcpoffer: no memory for filename.\n");
1702: destroy_client_lease (lease);
1703: return (struct client_lease *)0;
1704: } else {
1705: memcpy (lease -> filename,
1706: packet -> raw -> file, len);
1707: lease -> filename [len] = 0;
1708: }
1709: }
1710:
1711: execute_statements_in_scope ((struct binding_value **)0,
1712: (struct packet *)packet,
1713: (struct lease *)0, client,
1714: lease -> options, lease -> options,
1715: &global_scope,
1716: client -> config -> on_receipt,
1717: (struct group *)0);
1718:
1719: return lease;
1720: }
1721:
1722: void dhcpnak (packet)
1723: struct packet *packet;
1724: {
1725: struct interface_info *ip = packet -> interface;
1726: struct client_state *client;
1727:
1728: /* Find a client state that matches the xid... */
1729: for (client = ip -> client; client; client = client -> next)
1730: if (client -> xid == packet -> raw -> xid)
1731: break;
1732:
1733: /* If we're not receptive to an offer right now, or if the offer
1734: has an unrecognizable transaction id, then just drop it. */
1735: if (!client ||
1736: (packet -> interface -> hw_address.hlen - 1 !=
1737: packet -> raw -> hlen) ||
1738: (memcmp (&packet -> interface -> hw_address.hbuf [1],
1739: packet -> raw -> chaddr, packet -> raw -> hlen))) {
1740: #if defined (DEBUG)
1741: log_debug ("DHCPNAK in wrong transaction.");
1742: #endif
1743: return;
1744: }
1745:
1746: if (client -> state != S_REBOOTING &&
1747: client -> state != S_REQUESTING &&
1748: client -> state != S_RENEWING &&
1749: client -> state != S_REBINDING) {
1750: #if defined (DEBUG)
1751: log_debug ("DHCPNAK in wrong state.");
1752: #endif
1753: return;
1754: }
1755:
1756: log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
1757:
1758: if (!client -> active) {
1759: #if defined (DEBUG)
1760: log_info ("DHCPNAK with no active lease.\n");
1761: #endif
1762: return;
1763: }
1764:
1765: /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
1766: * to indicate that we want all old bindings to be removed. (It
1767: * is possible that we may get a NAK while in the RENEW state,
1768: * so we might have bindings active at that time)
1769: */
1770: script_init(client, "EXPIRE", NULL);
1771: script_write_params(client, "old_", client->active);
1772: if (client->alias)
1773: script_write_params(client, "alias_", client->alias);
1774: script_go(client);
1775:
1776: destroy_client_lease (client -> active);
1777: client -> active = (struct client_lease *)0;
1778:
1779: /* Stop sending DHCPREQUEST packets... */
1780: cancel_timeout (send_request, client);
1781:
1782: /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
1783: * down (this expunges any routes and arp cache). This makes the
1784: * interface unusable by state_init(), which we call next. So, we
1785: * need to 'PREINIT' the interface to bring it back up.
1786: */
1787: script_init(client, "PREINIT", NULL);
1788: if (client->alias)
1789: script_write_params(client, "alias_", client->alias);
1790: script_go(client);
1791:
1792: client -> state = S_INIT;
1793: state_init (client);
1794: }
1795:
1796: /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1797: one after the right interval has expired. If we don't get an offer by
1798: the time we reach the panic interval, call the panic function. */
1799:
1800: void send_discover (cpp)
1801: void *cpp;
1802: {
1803: struct client_state *client = cpp;
1804:
1805: int result;
1806: int interval;
1807: int increase = 1;
1808: struct timeval tv;
1809:
1810: /* Figure out how long it's been since we started transmitting. */
1811: interval = cur_time - client -> first_sending;
1812:
1813: /* If we're past the panic timeout, call the script and tell it
1814: we haven't found anything for this interface yet. */
1815: if (interval > client -> config -> timeout) {
1816: state_panic (client);
1817: return;
1818: }
1819:
1820: /* If we're selecting media, try the whole list before doing
1821: the exponential backoff, but if we've already received an
1822: offer, stop looping, because we obviously have it right. */
1823: if (!client -> offered_leases &&
1824: client -> config -> media) {
1825: int fail = 0;
1826: again:
1827: if (client -> medium) {
1828: client -> medium = client -> medium -> next;
1829: increase = 0;
1830: }
1831: if (!client -> medium) {
1832: if (fail)
1833: log_fatal ("No valid media types for %s!",
1834: client -> interface -> name);
1835: client -> medium =
1836: client -> config -> media;
1837: increase = 1;
1838: }
1839:
1840: log_info ("Trying medium \"%s\" %d",
1841: client -> medium -> string, increase);
1842: script_init (client, "MEDIUM", client -> medium);
1843: if (script_go (client)) {
1844: fail = 1;
1845: goto again;
1846: }
1847: }
1848:
1849: /* If we're supposed to increase the interval, do so. If it's
1850: currently zero (i.e., we haven't sent any packets yet), set
1851: it to initial_interval; otherwise, add to it a random number
1852: between zero and two times itself. On average, this means
1853: that it will double with every transmission. */
1854: if (increase) {
1855: if (!client->interval)
1856: client->interval = client->config->initial_interval;
1857: else
1858: client->interval += random() % (2 * client->interval);
1859:
1860: /* Don't backoff past cutoff. */
1861: if (client->interval > client->config->backoff_cutoff)
1862: client->interval = (client->config->backoff_cutoff / 2)
1863: + (random() % client->config->backoff_cutoff);
1864: } else if (!client->interval)
1865: client->interval = client->config->initial_interval;
1866:
1867: /* If the backoff would take us to the panic timeout, just use that
1868: as the interval. */
1869: if (cur_time + client -> interval >
1870: client -> first_sending + client -> config -> timeout)
1871: client -> interval =
1872: (client -> first_sending +
1873: client -> config -> timeout) - cur_time + 1;
1874:
1875: /* Record the number of seconds since we started sending. */
1876: if (interval < 65536)
1877: client -> packet.secs = htons (interval);
1878: else
1879: client -> packet.secs = htons (65535);
1880: client -> secs = client -> packet.secs;
1881:
1882: log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
1883: client -> name ? client -> name : client -> interface -> name,
1884: inet_ntoa (sockaddr_broadcast.sin_addr),
1885: ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
1886:
1887: /* Send out a packet. */
1888: result = send_packet(client->interface, NULL, &client->packet,
1889: client->packet_length, inaddr_any,
1890: &sockaddr_broadcast, NULL);
1891: if (result < 0) {
1892: log_error("%s:%d: Failed to send %d byte long packet over %s "
1893: "interface.", MDL, client->packet_length,
1894: client->interface->name);
1895: }
1896:
1897: /*
1898: * If we used 0 microseconds here, and there were other clients on the
1899: * same network with a synchronized local clock (ntp), and a similar
1900: * zero-microsecond-scheduler behavior, then we could be participating
1901: * in a sub-second DOS ttck.
1902: */
1903: tv.tv_sec = cur_tv.tv_sec + client->interval;
1904: tv.tv_usec = client->interval > 1 ? random() % 1000000 : cur_tv.tv_usec;
1905: add_timeout(&tv, send_discover, client, 0, 0);
1906: }
1907:
1908: /* state_panic gets called if we haven't received any offers in a preset
1909: amount of time. When this happens, we try to use existing leases that
1910: haven't yet expired, and failing that, we call the client script and
1911: hope it can do something. */
1912:
1913: void state_panic (cpp)
1914: void *cpp;
1915: {
1916: struct client_state *client = cpp;
1917: struct client_lease *loop;
1918: struct client_lease *lp;
1919: struct timeval tv;
1920:
1921: loop = lp = client -> active;
1922:
1923: log_info ("No DHCPOFFERS received.");
1924:
1925: /* We may not have an active lease, but we may have some
1926: predefined leases that we can try. */
1927: if (!client -> active && client -> leases)
1928: goto activate_next;
1929:
1930: /* Run through the list of leases and see if one can be used. */
1931: while (client -> active) {
1932: if (client -> active -> expiry > cur_time) {
1933: log_info ("Trying recorded lease %s",
1934: piaddr (client -> active -> address));
1935: /* Run the client script with the existing
1936: parameters. */
1937: script_init (client, "TIMEOUT",
1938: client -> active -> medium);
1939: script_write_params (client, "new_", client -> active);
1940: if (client -> alias)
1941: script_write_params (client, "alias_",
1942: client -> alias);
1943:
1944: /* If the old lease is still good and doesn't
1945: yet need renewal, go into BOUND state and
1946: timeout at the renewal time. */
1947: if (!script_go (client)) {
1948: if (cur_time < client -> active -> renewal) {
1949: client -> state = S_BOUND;
1950: log_info ("bound: renewal in %ld %s.",
1951: (long)(client -> active -> renewal -
1952: cur_time), "seconds");
1953: tv.tv_sec = client->active->renewal;
1954: tv.tv_usec = ((client->active->renewal -
1955: cur_time) > 1) ?
1956: random() % 1000000 :
1957: cur_tv.tv_usec;
1958: add_timeout(&tv, state_bound, client, 0, 0);
1959: } else {
1960: client -> state = S_BOUND;
1961: log_info ("bound: immediate renewal.");
1962: state_bound (client);
1963: }
1964: reinitialize_interfaces ();
1965: go_daemon ();
1966: return;
1967: }
1968: }
1969:
1970: /* If there are no other leases, give up. */
1971: if (!client -> leases) {
1972: client -> leases = client -> active;
1973: client -> active = (struct client_lease *)0;
1974: break;
1975: }
1976:
1977: activate_next:
1978: /* Otherwise, put the active lease at the end of the
1979: lease list, and try another lease.. */
1980: for (lp = client -> leases; lp -> next; lp = lp -> next)
1981: ;
1982: lp -> next = client -> active;
1983: if (lp -> next) {
1984: lp -> next -> next = (struct client_lease *)0;
1985: }
1986: client -> active = client -> leases;
1987: client -> leases = client -> leases -> next;
1988:
1989: /* If we already tried this lease, we've exhausted the
1990: set of leases, so we might as well give up for
1991: now. */
1992: if (client -> active == loop)
1993: break;
1994: else if (!loop)
1995: loop = client -> active;
1996: }
1997:
1998: /* No leases were available, or what was available didn't work, so
1999: tell the shell script that we failed to allocate an address,
2000: and try again later. */
2001: if (onetry) {
2002: if (!quiet)
2003: log_info ("Unable to obtain a lease on first try.%s",
2004: " Exiting.");
2005: exit (2);
2006: }
2007:
2008: log_info ("No working leases in persistent database - sleeping.");
2009: script_init (client, "FAIL", (struct string_list *)0);
2010: if (client -> alias)
2011: script_write_params (client, "alias_", client -> alias);
2012: script_go (client);
2013: client -> state = S_INIT;
2014: tv.tv_sec = cur_tv.tv_sec + ((client->config->retry_interval + 1) / 2 +
2015: (random() % client->config->retry_interval));
2016: tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
2017: random() % 1000000 : cur_tv.tv_usec;
2018: add_timeout(&tv, state_init, client, 0, 0);
2019: go_daemon ();
2020: }
2021:
2022: void send_request (cpp)
2023: void *cpp;
2024: {
2025: struct client_state *client = cpp;
2026:
2027: int result;
2028: int interval;
2029: struct sockaddr_in destination;
2030: struct in_addr from;
2031: struct timeval tv;
2032:
2033: /* Figure out how long it's been since we started transmitting. */
2034: interval = cur_time - client -> first_sending;
2035:
2036: /* If we're in the INIT-REBOOT or REQUESTING state and we're
2037: past the reboot timeout, go to INIT and see if we can
2038: DISCOVER an address... */
2039: /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
2040: means either that we're on a network with no DHCP server,
2041: or that our server is down. In the latter case, assuming
2042: that there is a backup DHCP server, DHCPDISCOVER will get
2043: us a new address, but we could also have successfully
2044: reused our old address. In the former case, we're hosed
2045: anyway. This is not a win-prone situation. */
2046: if ((client -> state == S_REBOOTING ||
2047: client -> state == S_REQUESTING) &&
2048: interval > client -> config -> reboot_timeout) {
2049: cancel:
2050: client -> state = S_INIT;
2051: cancel_timeout (send_request, client);
2052: state_init (client);
2053: return;
2054: }
2055:
2056: /* If we're in the reboot state, make sure the media is set up
2057: correctly. */
2058: if (client -> state == S_REBOOTING &&
2059: !client -> medium &&
2060: client -> active -> medium ) {
2061: script_init (client, "MEDIUM", client -> active -> medium);
2062:
2063: /* If the medium we chose won't fly, go to INIT state. */
2064: if (script_go (client))
2065: goto cancel;
2066:
2067: /* Record the medium. */
2068: client -> medium = client -> active -> medium;
2069: }
2070:
2071: /* If the lease has expired, relinquish the address and go back
2072: to the INIT state. */
2073: if (client -> state != S_REQUESTING &&
2074: cur_time > client -> active -> expiry) {
2075: /* Run the client script with the new parameters. */
2076: script_init (client, "EXPIRE", (struct string_list *)0);
2077: script_write_params (client, "old_", client -> active);
2078: if (client -> alias)
2079: script_write_params (client, "alias_",
2080: client -> alias);
2081: script_go (client);
2082:
2083: /* Now do a preinit on the interface so that we can
2084: discover a new address. */
2085: script_init (client, "PREINIT", (struct string_list *)0);
2086: if (client -> alias)
2087: script_write_params (client, "alias_",
2088: client -> alias);
2089: script_go (client);
2090:
2091: client -> state = S_INIT;
2092: state_init (client);
2093: return;
2094: }
2095:
2096: /* Do the exponential backoff... */
2097: if (!client -> interval)
2098: client -> interval = client -> config -> initial_interval;
2099: else {
2100: client -> interval += ((random () >> 2) %
2101: (2 * client -> interval));
2102: }
2103:
2104: /* Don't backoff past cutoff. */
2105: if (client -> interval >
2106: client -> config -> backoff_cutoff)
2107: client -> interval =
2108: ((client -> config -> backoff_cutoff / 2)
2109: + ((random () >> 2) %
2110: client -> config -> backoff_cutoff));
2111:
2112: /* If the backoff would take us to the expiry time, just set the
2113: timeout to the expiry time. */
2114: if (client -> state != S_REQUESTING &&
2115: cur_time + client -> interval > client -> active -> expiry)
2116: client -> interval =
2117: client -> active -> expiry - cur_time + 1;
2118:
2119: /* If the lease T2 time has elapsed, or if we're not yet bound,
2120: broadcast the DHCPREQUEST rather than unicasting. */
2121: if (client -> state == S_REQUESTING ||
2122: client -> state == S_REBOOTING ||
2123: cur_time > client -> active -> rebind)
2124: destination.sin_addr = sockaddr_broadcast.sin_addr;
2125: else
2126: memcpy (&destination.sin_addr.s_addr,
2127: client -> destination.iabuf,
2128: sizeof destination.sin_addr.s_addr);
2129: destination.sin_port = remote_port;
2130: destination.sin_family = AF_INET;
2131: #ifdef HAVE_SA_LEN
2132: destination.sin_len = sizeof destination;
2133: #endif
2134:
2135: if (client -> state == S_RENEWING ||
2136: client -> state == S_REBINDING)
2137: memcpy (&from, client -> active -> address.iabuf,
2138: sizeof from);
2139: else
2140: from.s_addr = INADDR_ANY;
2141:
2142: /* Record the number of seconds since we started sending. */
2143: if (client -> state == S_REQUESTING)
2144: client -> packet.secs = client -> secs;
2145: else {
2146: if (interval < 65536)
2147: client -> packet.secs = htons (interval);
2148: else
2149: client -> packet.secs = htons (65535);
2150: }
2151:
2152: log_info ("DHCPREQUEST on %s to %s port %d",
2153: client -> name ? client -> name : client -> interface -> name,
2154: inet_ntoa (destination.sin_addr),
2155: ntohs (destination.sin_port));
2156:
2157: if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
2158: fallback_interface) {
2159: result = send_packet(fallback_interface, NULL, &client->packet,
2160: client->packet_length, from, &destination,
2161: NULL);
2162: if (result < 0) {
2163: log_error("%s:%d: Failed to send %d byte long packet "
2164: "over %s interface.", MDL,
2165: client->packet_length,
2166: fallback_interface->name);
2167: }
2168: }
2169: else {
2170: /* Send out a packet. */
2171: result = send_packet(client->interface, NULL, &client->packet,
2172: client->packet_length, from, &destination,
2173: NULL);
2174: if (result < 0) {
2175: log_error("%s:%d: Failed to send %d byte long packet"
2176: " over %s interface.", MDL,
2177: client->packet_length,
2178: client->interface->name);
2179: }
2180: }
2181:
2182: tv.tv_sec = cur_tv.tv_sec + client->interval;
2183: tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
2184: random() % 1000000 : cur_tv.tv_usec;
2185: add_timeout(&tv, send_request, client, 0, 0);
2186: }
2187:
2188: void send_decline (cpp)
2189: void *cpp;
2190: {
2191: struct client_state *client = cpp;
2192:
2193: int result;
2194:
2195: log_info ("DHCPDECLINE on %s to %s port %d",
2196: client->name ? client->name : client->interface->name,
2197: inet_ntoa(sockaddr_broadcast.sin_addr),
2198: ntohs(sockaddr_broadcast.sin_port));
2199:
2200: /* Send out a packet. */
2201: result = send_packet(client->interface, NULL, &client->packet,
2202: client->packet_length, inaddr_any,
2203: &sockaddr_broadcast, NULL);
2204: if (result < 0) {
2205: log_error("%s:%d: Failed to send %d byte long packet over %s"
2206: " interface.", MDL, client->packet_length,
2207: client->interface->name);
2208: }
2209: }
2210:
2211: void send_release (cpp)
2212: void *cpp;
2213: {
2214: struct client_state *client = cpp;
2215:
2216: int result;
2217: struct sockaddr_in destination;
2218: struct in_addr from;
2219:
2220: memcpy (&from, client -> active -> address.iabuf,
2221: sizeof from);
2222: memcpy (&destination.sin_addr.s_addr,
2223: client -> destination.iabuf,
2224: sizeof destination.sin_addr.s_addr);
2225: destination.sin_port = remote_port;
2226: destination.sin_family = AF_INET;
2227: #ifdef HAVE_SA_LEN
2228: destination.sin_len = sizeof destination;
2229: #endif
2230:
2231: /* Set the lease to end now, so that we don't accidentally
2232: reuse it if we restart before the old expiry time. */
2233: client -> active -> expiry =
2234: client -> active -> renewal =
2235: client -> active -> rebind = cur_time;
2236: if (!write_client_lease (client, client -> active, 1, 1)) {
2237: log_error ("Can't release lease: lease write failed.");
2238: return;
2239: }
2240:
2241: log_info ("DHCPRELEASE on %s to %s port %d",
2242: client -> name ? client -> name : client -> interface -> name,
2243: inet_ntoa (destination.sin_addr),
2244: ntohs (destination.sin_port));
2245:
2246: if (fallback_interface) {
2247: result = send_packet(fallback_interface, NULL, &client->packet,
2248: client->packet_length, from, &destination,
2249: NULL);
2250: if (result < 0) {
2251: log_error("%s:%d: Failed to send %d byte long packet"
2252: " over %s interface.", MDL,
2253: client->packet_length,
2254: fallback_interface->name);
2255: }
2256: } else {
2257: /* Send out a packet. */
2258: result = send_packet(client->interface, NULL, &client->packet,
2259: client->packet_length, from, &destination,
2260: NULL);
2261: if (result < 0) {
2262: log_error ("%s:%d: Failed to send %d byte long packet"
2263: " over %s interface.", MDL,
2264: client->packet_length,
2265: client->interface->name);
2266: }
2267:
2268: }
2269: }
2270:
2271: void
2272: make_client_options(struct client_state *client, struct client_lease *lease,
2273: u_int8_t *type, struct option_cache *sid,
2274: struct iaddr *rip, struct option **prl,
2275: struct option_state **op)
2276: {
2277: unsigned i;
2278: struct option_cache *oc;
2279: struct option *option = NULL;
2280: struct buffer *bp = (struct buffer *)0;
2281:
2282: /* If there are any leftover options, get rid of them. */
2283: if (*op)
2284: option_state_dereference (op, MDL);
2285:
2286: /* Allocate space for options. */
2287: option_state_allocate (op, MDL);
2288:
2289: /* Send the server identifier if provided. */
2290: if (sid)
2291: save_option (&dhcp_universe, *op, sid);
2292:
2293: oc = (struct option_cache *)0;
2294:
2295: /* Send the requested address if provided. */
2296: if (rip) {
2297: client -> requested_address = *rip;
2298: i = DHO_DHCP_REQUESTED_ADDRESS;
2299: if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
2300: &i, 0, MDL) &&
2301: make_const_option_cache(&oc, NULL, rip->iabuf, rip->len,
2302: option, MDL)))
2303: log_error ("can't make requested address cache.");
2304: else {
2305: save_option (&dhcp_universe, *op, oc);
2306: option_cache_dereference (&oc, MDL);
2307: }
2308: option_dereference(&option, MDL);
2309: } else {
2310: client -> requested_address.len = 0;
2311: }
2312:
2313: i = DHO_DHCP_MESSAGE_TYPE;
2314: if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
2315: MDL) &&
2316: make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
2317: log_error ("can't make message type.");
2318: else {
2319: save_option (&dhcp_universe, *op, oc);
2320: option_cache_dereference (&oc, MDL);
2321: }
2322: option_dereference(&option, MDL);
2323:
2324: if (prl) {
2325: int len;
2326:
2327: /* Probe the length of the list. */
2328: len = 0;
2329: for (i = 0 ; prl[i] != NULL ; i++)
2330: if (prl[i]->universe == &dhcp_universe)
2331: len++;
2332:
2333: if (!buffer_allocate (&bp, len, MDL))
2334: log_error ("can't make parameter list buffer.");
2335: else {
2336: unsigned code = DHO_DHCP_PARAMETER_REQUEST_LIST;
2337:
2338: len = 0;
2339: for (i = 0 ; prl[i] != NULL ; i++)
2340: if (prl[i]->universe == &dhcp_universe)
2341: bp->data[len++] = prl[i]->code;
2342:
2343: if (!(option_code_hash_lookup(&option,
2344: dhcp_universe.code_hash,
2345: &code, 0, MDL) &&
2346: make_const_option_cache(&oc, &bp, NULL, len,
2347: option, MDL)))
2348: log_error ("can't make option cache");
2349: else {
2350: save_option (&dhcp_universe, *op, oc);
2351: option_cache_dereference (&oc, MDL);
2352: }
2353: option_dereference(&option, MDL);
2354: }
2355: }
2356:
2357: /* Run statements that need to be run on transmission. */
2358: if (client -> config -> on_transmission)
2359: execute_statements_in_scope
2360: ((struct binding_value **)0,
2361: (struct packet *)0, (struct lease *)0, client,
2362: (lease ? lease -> options : (struct option_state *)0),
2363: *op, &global_scope,
2364: client -> config -> on_transmission,
2365: (struct group *)0);
2366: }
2367:
2368: void make_discover (client, lease)
2369: struct client_state *client;
2370: struct client_lease *lease;
2371: {
2372: unsigned char discover = DHCPDISCOVER;
2373: struct option_state *options = (struct option_state *)0;
2374:
2375: memset (&client -> packet, 0, sizeof (client -> packet));
2376:
2377: make_client_options (client,
2378: lease, &discover, (struct option_cache *)0,
2379: lease ? &lease -> address : (struct iaddr *)0,
2380: client -> config -> requested_options,
2381: &options);
2382:
2383: /* Set up the option buffer... */
2384: client -> packet_length =
2385: cons_options ((struct packet *)0, &client -> packet,
2386: (struct lease *)0, client,
2387: /* maximum packet size */1500,
2388: (struct option_state *)0,
2389: options,
2390: /* scope */ &global_scope,
2391: /* overload */ 0,
2392: /* terminate */0,
2393: /* bootpp */0,
2394: (struct data_string *)0,
2395: client -> config -> vendor_space_name);
2396:
2397: option_state_dereference (&options, MDL);
2398: if (client -> packet_length < BOOTP_MIN_LEN)
2399: client -> packet_length = BOOTP_MIN_LEN;
2400:
2401: client -> packet.op = BOOTREQUEST;
2402: client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2403: client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2404: client -> packet.hops = 0;
2405: client -> packet.xid = random ();
2406: client -> packet.secs = 0; /* filled in by send_discover. */
2407:
2408: if (can_receive_unicast_unconfigured (client -> interface))
2409: client -> packet.flags = 0;
2410: else
2411: client -> packet.flags = htons (BOOTP_BROADCAST);
2412:
2413: memset (&(client -> packet.ciaddr),
2414: 0, sizeof client -> packet.ciaddr);
2415: memset (&(client -> packet.yiaddr),
2416: 0, sizeof client -> packet.yiaddr);
2417: memset (&(client -> packet.siaddr),
2418: 0, sizeof client -> packet.siaddr);
2419: client -> packet.giaddr = giaddr;
2420: if (client -> interface -> hw_address.hlen > 0)
2421: memcpy (client -> packet.chaddr,
2422: &client -> interface -> hw_address.hbuf [1],
2423: (unsigned)(client -> interface -> hw_address.hlen - 1));
2424:
2425: #ifdef DEBUG_PACKET
2426: dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2427: #endif
2428: }
2429:
2430:
2431: void make_request (client, lease)
2432: struct client_state *client;
2433: struct client_lease *lease;
2434: {
2435: unsigned char request = DHCPREQUEST;
2436: struct option_cache *oc;
2437:
2438: memset (&client -> packet, 0, sizeof (client -> packet));
2439:
2440: if (client -> state == S_REQUESTING)
2441: oc = lookup_option (&dhcp_universe, lease -> options,
2442: DHO_DHCP_SERVER_IDENTIFIER);
2443: else
2444: oc = (struct option_cache *)0;
2445:
2446: if (client -> sent_options)
2447: option_state_dereference (&client -> sent_options, MDL);
2448:
2449: make_client_options (client, lease, &request, oc,
2450: ((client -> state == S_REQUESTING ||
2451: client -> state == S_REBOOTING)
2452: ? &lease -> address
2453: : (struct iaddr *)0),
2454: client -> config -> requested_options,
2455: &client -> sent_options);
2456:
2457: /* Set up the option buffer... */
2458: client -> packet_length =
2459: cons_options ((struct packet *)0, &client -> packet,
2460: (struct lease *)0, client,
2461: /* maximum packet size */1500,
2462: (struct option_state *)0,
2463: client -> sent_options,
2464: /* scope */ &global_scope,
2465: /* overload */ 0,
2466: /* terminate */0,
2467: /* bootpp */0,
2468: (struct data_string *)0,
2469: client -> config -> vendor_space_name);
2470:
2471: if (client -> packet_length < BOOTP_MIN_LEN)
2472: client -> packet_length = BOOTP_MIN_LEN;
2473:
2474: client -> packet.op = BOOTREQUEST;
2475: client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2476: client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2477: client -> packet.hops = 0;
2478: client -> packet.xid = client -> xid;
2479: client -> packet.secs = 0; /* Filled in by send_request. */
2480:
2481: /* If we own the address we're requesting, put it in ciaddr;
2482: otherwise set ciaddr to zero. */
2483: if (client -> state == S_BOUND ||
2484: client -> state == S_RENEWING ||
2485: client -> state == S_REBINDING) {
2486: memcpy (&client -> packet.ciaddr,
2487: lease -> address.iabuf, lease -> address.len);
2488: client -> packet.flags = 0;
2489: } else {
2490: memset (&client -> packet.ciaddr, 0,
2491: sizeof client -> packet.ciaddr);
2492: if (can_receive_unicast_unconfigured (client -> interface))
2493: client -> packet.flags = 0;
2494: else
2495: client -> packet.flags = htons (BOOTP_BROADCAST);
2496: }
2497:
2498: memset (&client -> packet.yiaddr, 0,
2499: sizeof client -> packet.yiaddr);
2500: memset (&client -> packet.siaddr, 0,
2501: sizeof client -> packet.siaddr);
2502: if (client -> state != S_BOUND &&
2503: client -> state != S_RENEWING)
2504: client -> packet.giaddr = giaddr;
2505: else
2506: memset (&client -> packet.giaddr, 0,
2507: sizeof client -> packet.giaddr);
2508: if (client -> interface -> hw_address.hlen > 0)
2509: memcpy (client -> packet.chaddr,
2510: &client -> interface -> hw_address.hbuf [1],
2511: (unsigned)(client -> interface -> hw_address.hlen - 1));
2512:
2513: #ifdef DEBUG_PACKET
2514: dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2515: #endif
2516: }
2517:
2518: void make_decline (client, lease)
2519: struct client_state *client;
2520: struct client_lease *lease;
2521: {
2522: unsigned char decline = DHCPDECLINE;
2523: struct option_cache *oc;
2524:
2525: struct option_state *options = (struct option_state *)0;
2526:
2527: /* Create the options cache. */
2528: oc = lookup_option (&dhcp_universe, lease -> options,
2529: DHO_DHCP_SERVER_IDENTIFIER);
2530: make_client_options(client, lease, &decline, oc, &lease->address,
2531: NULL, &options);
2532:
2533: /* Consume the options cache into the option buffer. */
2534: memset (&client -> packet, 0, sizeof (client -> packet));
2535: client -> packet_length =
2536: cons_options ((struct packet *)0, &client -> packet,
2537: (struct lease *)0, client, 0,
2538: (struct option_state *)0, options,
2539: &global_scope, 0, 0, 0, (struct data_string *)0,
2540: client -> config -> vendor_space_name);
2541:
2542: /* Destroy the options cache. */
2543: option_state_dereference (&options, MDL);
2544:
2545: if (client -> packet_length < BOOTP_MIN_LEN)
2546: client -> packet_length = BOOTP_MIN_LEN;
2547:
2548: client -> packet.op = BOOTREQUEST;
2549: client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2550: client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2551: client -> packet.hops = 0;
2552: client -> packet.xid = client -> xid;
2553: client -> packet.secs = 0; /* Filled in by send_request. */
2554: if (can_receive_unicast_unconfigured (client -> interface))
2555: client -> packet.flags = 0;
2556: else
2557: client -> packet.flags = htons (BOOTP_BROADCAST);
2558:
2559: /* ciaddr must always be zero. */
2560: memset (&client -> packet.ciaddr, 0,
2561: sizeof client -> packet.ciaddr);
2562: memset (&client -> packet.yiaddr, 0,
2563: sizeof client -> packet.yiaddr);
2564: memset (&client -> packet.siaddr, 0,
2565: sizeof client -> packet.siaddr);
2566: client -> packet.giaddr = giaddr;
2567: memcpy (client -> packet.chaddr,
2568: &client -> interface -> hw_address.hbuf [1],
2569: client -> interface -> hw_address.hlen);
2570:
2571: #ifdef DEBUG_PACKET
2572: dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2573: #endif
2574: }
2575:
2576: void make_release (client, lease)
2577: struct client_state *client;
2578: struct client_lease *lease;
2579: {
2580: unsigned char request = DHCPRELEASE;
2581: struct option_cache *oc;
2582:
2583: struct option_state *options = (struct option_state *)0;
2584:
2585: memset (&client -> packet, 0, sizeof (client -> packet));
2586:
2587: oc = lookup_option (&dhcp_universe, lease -> options,
2588: DHO_DHCP_SERVER_IDENTIFIER);
2589: make_client_options(client, lease, &request, oc, NULL, NULL, &options);
2590:
2591: /* Set up the option buffer... */
2592: client -> packet_length =
2593: cons_options ((struct packet *)0, &client -> packet,
2594: (struct lease *)0, client,
2595: /* maximum packet size */1500,
2596: (struct option_state *)0,
2597: options,
2598: /* scope */ &global_scope,
2599: /* overload */ 0,
2600: /* terminate */0,
2601: /* bootpp */0,
2602: (struct data_string *)0,
2603: client -> config -> vendor_space_name);
2604:
2605: if (client -> packet_length < BOOTP_MIN_LEN)
2606: client -> packet_length = BOOTP_MIN_LEN;
2607: option_state_dereference (&options, MDL);
2608:
2609: client -> packet.op = BOOTREQUEST;
2610: client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2611: client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
2612: client -> packet.hops = 0;
2613: client -> packet.xid = random ();
2614: client -> packet.secs = 0;
2615: client -> packet.flags = 0;
2616: memcpy (&client -> packet.ciaddr,
2617: lease -> address.iabuf, lease -> address.len);
2618: memset (&client -> packet.yiaddr, 0,
2619: sizeof client -> packet.yiaddr);
2620: memset (&client -> packet.siaddr, 0,
2621: sizeof client -> packet.siaddr);
2622: client -> packet.giaddr = giaddr;
2623: memcpy (client -> packet.chaddr,
2624: &client -> interface -> hw_address.hbuf [1],
2625: client -> interface -> hw_address.hlen);
2626:
2627: #ifdef DEBUG_PACKET
2628: dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
2629: #endif
2630: }
2631:
2632: void destroy_client_lease (lease)
2633: struct client_lease *lease;
2634: {
2635: if (lease -> server_name)
2636: dfree (lease -> server_name, MDL);
2637: if (lease -> filename)
2638: dfree (lease -> filename, MDL);
2639: option_state_dereference (&lease -> options, MDL);
2640: free_client_lease (lease, MDL);
2641: }
2642:
2643: FILE *leaseFile = NULL;
2644: int leases_written = 0;
2645:
2646: void rewrite_client_leases ()
2647: {
2648: struct interface_info *ip;
2649: struct client_state *client;
2650: struct client_lease *lp;
2651:
2652: if (leaseFile != NULL)
2653: fclose (leaseFile);
2654: leaseFile = fopen (path_dhclient_db, "w");
2655: if (leaseFile == NULL) {
2656: log_error ("can't create %s: %m", path_dhclient_db);
2657: return;
2658: }
2659:
2660: /* If there is a default duid, write it out. */
2661: if (default_duid.len != 0)
2662: write_duid(&default_duid);
2663:
2664: /* Write out all the leases attached to configured interfaces that
2665: we know about. */
2666: for (ip = interfaces; ip; ip = ip -> next) {
2667: for (client = ip -> client; client; client = client -> next) {
2668: for (lp = client -> leases; lp; lp = lp -> next) {
2669: write_client_lease (client, lp, 1, 0);
2670: }
2671: if (client -> active)
2672: write_client_lease (client,
2673: client -> active, 1, 0);
2674:
2675: if (client->active_lease != NULL)
2676: write_client6_lease(client,
2677: client->active_lease,
2678: 1, 0);
2679:
2680: /* Reset last_write after rewrites. */
2681: client->last_write = 0;
2682: }
2683: }
2684:
2685: /* Write out any leases that are attached to interfaces that aren't
2686: currently configured. */
2687: for (ip = dummy_interfaces; ip; ip = ip -> next) {
2688: for (client = ip -> client; client; client = client -> next) {
2689: for (lp = client -> leases; lp; lp = lp -> next) {
2690: write_client_lease (client, lp, 1, 0);
2691: }
2692: if (client -> active)
2693: write_client_lease (client,
2694: client -> active, 1, 0);
2695:
2696: if (client->active_lease != NULL)
2697: write_client6_lease(client,
2698: client->active_lease,
2699: 1, 0);
2700:
2701: /* Reset last_write after rewrites. */
2702: client->last_write = 0;
2703: }
2704: }
2705: fflush (leaseFile);
2706: }
2707:
2708: void write_lease_option (struct option_cache *oc,
2709: struct packet *packet, struct lease *lease,
2710: struct client_state *client_state,
2711: struct option_state *in_options,
2712: struct option_state *cfg_options,
2713: struct binding_scope **scope,
2714: struct universe *u, void *stuff)
2715: {
2716: const char *name, *dot;
2717: struct data_string ds;
2718: char *preamble = stuff;
2719:
2720: memset (&ds, 0, sizeof ds);
2721:
2722: if (u != &dhcp_universe) {
2723: name = u -> name;
2724: dot = ".";
2725: } else {
2726: name = "";
2727: dot = "";
2728: }
2729: if (evaluate_option_cache (&ds, packet, lease, client_state,
2730: in_options, cfg_options, scope, oc, MDL)) {
2731: /* The option name */
2732: fprintf(leaseFile, "%soption %s%s%s", preamble,
2733: name, dot, oc->option->name);
2734:
2735: /* The option value if there is one */
2736: if ((oc->option->format == NULL) ||
2737: (oc->option->format[0] != 'Z')) {
2738: fprintf(leaseFile, " %s",
2739: pretty_print_option(oc->option, ds.data,
2740: ds.len, 1, 1));
2741: }
2742:
2743: /* The closing semi-colon and newline */
2744: fprintf(leaseFile, ";\n");
2745:
2746: data_string_forget (&ds, MDL);
2747: }
2748: }
2749:
2750: /* Write an option cache to the lease store. */
2751: static void
2752: write_options(struct client_state *client, struct option_state *options,
2753: const char *preamble)
2754: {
2755: int i;
2756:
2757: for (i = 0; i < options->universe_count; i++) {
2758: option_space_foreach(NULL, NULL, client, NULL, options,
2759: &global_scope, universes[i],
2760: (char *)preamble, write_lease_option);
2761: }
2762: }
2763:
2764: /* Write the default DUID to the lease store. */
2765: static isc_result_t
2766: write_duid(struct data_string *duid)
2767: {
2768: char *str;
2769: int stat;
2770:
2771: if ((duid == NULL) || (duid->len <= 2))
2772: return ISC_R_INVALIDARG;
2773:
2774: if (leaseFile == NULL) { /* XXX? */
2775: leaseFile = fopen(path_dhclient_db, "w");
2776: if (leaseFile == NULL) {
2777: log_error("can't create %s: %m", path_dhclient_db);
2778: return ISC_R_IOERROR;
2779: }
2780: }
2781:
2782: /* It would make more sense to write this as a hex string,
2783: * but our function to do that (print_hex_n) uses a fixed
2784: * length buffer...and we can't guarantee a duid would be
2785: * less than the fixed length.
2786: */
2787: str = quotify_buf(duid->data, duid->len, MDL);
2788: if (str == NULL)
2789: return ISC_R_NOMEMORY;
2790:
2791: stat = fprintf(leaseFile, "default-duid \"%s\";\n", str);
2792: dfree(str, MDL);
2793: if (stat <= 0)
2794: return ISC_R_IOERROR;
2795:
2796: if (fflush(leaseFile) != 0)
2797: return ISC_R_IOERROR;
2798:
2799: return ISC_R_SUCCESS;
2800: }
2801:
2802: /* Write a DHCPv6 lease to the store. */
2803: isc_result_t
2804: write_client6_lease(struct client_state *client, struct dhc6_lease *lease,
2805: int rewrite, int sync)
2806: {
2807: struct dhc6_ia *ia;
2808: struct dhc6_addr *addr;
2809: int stat;
2810: const char *ianame;
2811:
2812: /* This should include the current lease. */
2813: if (!rewrite && (leases_written++ > 20)) {
2814: rewrite_client_leases();
2815: leases_written = 0;
2816: return ISC_R_SUCCESS;
2817: }
2818:
2819: if (client == NULL || lease == NULL)
2820: return ISC_R_INVALIDARG;
2821:
2822: if (leaseFile == NULL) { /* XXX? */
2823: leaseFile = fopen(path_dhclient_db, "w");
2824: if (leaseFile == NULL) {
2825: log_error("can't create %s: %m", path_dhclient_db);
2826: return ISC_R_IOERROR;
2827: }
2828: }
2829:
2830: stat = fprintf(leaseFile, "lease6 {\n");
2831: if (stat <= 0)
2832: return ISC_R_IOERROR;
2833:
2834: stat = fprintf(leaseFile, " interface \"%s\";\n",
2835: client->interface->name);
2836: if (stat <= 0)
2837: return ISC_R_IOERROR;
2838:
2839: for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
2840: switch (ia->ia_type) {
2841: case D6O_IA_NA:
2842: default:
2843: ianame = "ia-na";
2844: break;
2845: case D6O_IA_TA:
2846: ianame = "ia-ta";
2847: break;
2848: case D6O_IA_PD:
2849: ianame = "ia-pd";
2850: break;
2851: }
2852: stat = fprintf(leaseFile, " %s %s {\n",
2853: ianame, print_hex_1(4, ia->iaid, 12));
2854: if (stat <= 0)
2855: return ISC_R_IOERROR;
2856:
2857: if (ia->ia_type != D6O_IA_TA)
2858: stat = fprintf(leaseFile, " starts %d;\n"
2859: " renew %u;\n"
2860: " rebind %u;\n",
2861: (int)ia->starts, ia->renew, ia->rebind);
2862: else
2863: stat = fprintf(leaseFile, " starts %d;\n",
2864: (int)ia->starts);
2865: if (stat <= 0)
2866: return ISC_R_IOERROR;
2867:
2868: for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
2869: if (ia->ia_type != D6O_IA_PD)
2870: stat = fprintf(leaseFile,
2871: " iaaddr %s {\n",
2872: piaddr(addr->address));
2873: else
2874: stat = fprintf(leaseFile,
2875: " iaprefix %s/%d {\n",
2876: piaddr(addr->address),
2877: (int)addr->plen);
2878: if (stat <= 0)
2879: return ISC_R_IOERROR;
2880:
2881: stat = fprintf(leaseFile, " starts %d;\n"
2882: " preferred-life %u;\n"
2883: " max-life %u;\n",
2884: (int)addr->starts, addr->preferred_life,
2885: addr->max_life);
2886: if (stat <= 0)
2887: return ISC_R_IOERROR;
2888:
2889: if (addr->options != NULL)
2890: write_options(client, addr->options, " ");
2891:
2892: stat = fprintf(leaseFile, " }\n");
2893: if (stat <= 0)
2894: return ISC_R_IOERROR;
2895: }
2896:
2897: if (ia->options != NULL)
2898: write_options(client, ia->options, " ");
2899:
2900: stat = fprintf(leaseFile, " }\n");
2901: if (stat <= 0)
2902: return ISC_R_IOERROR;
2903: }
2904:
2905: if (lease->released) {
2906: stat = fprintf(leaseFile, " released;\n");
2907: if (stat <= 0)
2908: return ISC_R_IOERROR;
2909: }
2910:
2911: if (lease->options != NULL)
2912: write_options(client, lease->options, " ");
2913:
2914: stat = fprintf(leaseFile, "}\n");
2915: if (stat <= 0)
2916: return ISC_R_IOERROR;
2917:
2918: if (fflush(leaseFile) != 0)
2919: return ISC_R_IOERROR;
2920:
2921: if (sync) {
2922: if (fsync(fileno(leaseFile)) < 0) {
2923: log_error("write_client_lease: fsync(): %m");
2924: return ISC_R_IOERROR;
2925: }
2926: }
2927:
2928: return ISC_R_SUCCESS;
2929: }
2930:
2931: int write_client_lease (client, lease, rewrite, makesure)
2932: struct client_state *client;
2933: struct client_lease *lease;
2934: int rewrite;
2935: int makesure;
2936: {
2937: struct data_string ds;
2938: int errors = 0;
2939: char *s;
2940: const char *tval;
2941:
2942: if (!rewrite) {
2943: if (leases_written++ > 20) {
2944: rewrite_client_leases ();
2945: leases_written = 0;
2946: }
2947: }
2948:
2949: /* If the lease came from the config file, we don't need to stash
2950: a copy in the lease database. */
2951: if (lease -> is_static)
2952: return 1;
2953:
2954: if (leaseFile == NULL) { /* XXX */
2955: leaseFile = fopen (path_dhclient_db, "w");
2956: if (leaseFile == NULL) {
2957: log_error ("can't create %s: %m", path_dhclient_db);
2958: return 0;
2959: }
2960: }
2961:
2962: errno = 0;
2963: fprintf (leaseFile, "lease {\n");
2964: if (lease -> is_bootp) {
2965: fprintf (leaseFile, " bootp;\n");
2966: if (errno) {
2967: ++errors;
2968: errno = 0;
2969: }
2970: }
2971: fprintf (leaseFile, " interface \"%s\";\n",
2972: client -> interface -> name);
2973: if (errno) {
2974: ++errors;
2975: errno = 0;
2976: }
2977: if (client -> name) {
2978: fprintf (leaseFile, " name \"%s\";\n", client -> name);
2979: if (errno) {
2980: ++errors;
2981: errno = 0;
2982: }
2983: }
2984: fprintf (leaseFile, " fixed-address %s;\n",
2985: piaddr (lease -> address));
2986: if (errno) {
2987: ++errors;
2988: errno = 0;
2989: }
2990: if (lease -> filename) {
2991: s = quotify_string (lease -> filename, MDL);
2992: if (s) {
2993: fprintf (leaseFile, " filename \"%s\";\n", s);
2994: if (errno) {
2995: ++errors;
2996: errno = 0;
2997: }
2998: dfree (s, MDL);
2999: } else
3000: errors++;
3001:
3002: }
3003: if (lease->server_name != NULL) {
3004: s = quotify_string(lease->server_name, MDL);
3005: if (s != NULL) {
3006: fprintf(leaseFile, " server-name \"%s\";\n", s);
3007: if (errno) {
3008: ++errors;
3009: errno = 0;
3010: }
3011: dfree(s, MDL);
3012: } else
3013: ++errors;
3014: }
3015: if (lease -> medium) {
3016: s = quotify_string (lease -> medium -> string, MDL);
3017: if (s) {
3018: fprintf (leaseFile, " medium \"%s\";\n", s);
3019: if (errno) {
3020: ++errors;
3021: errno = 0;
3022: }
3023: dfree (s, MDL);
3024: } else
3025: errors++;
3026: }
3027: if (errno != 0) {
3028: errors++;
3029: errno = 0;
3030: }
3031:
3032: memset (&ds, 0, sizeof ds);
3033:
3034: write_options(client, lease->options, " ");
3035:
3036: tval = print_time(lease->renewal);
3037: if (tval == NULL ||
3038: fprintf(leaseFile, " renew %s\n", tval) < 0)
3039: errors++;
3040:
3041: tval = print_time(lease->rebind);
3042: if (tval == NULL ||
3043: fprintf(leaseFile, " rebind %s\n", tval) < 0)
3044: errors++;
3045:
3046: tval = print_time(lease->expiry);
3047: if (tval == NULL ||
3048: fprintf(leaseFile, " expire %s\n", tval) < 0)
3049: errors++;
3050:
3051: if (fprintf(leaseFile, "}\n") < 0)
3052: errors++;
3053:
3054: if (fflush(leaseFile) != 0)
3055: errors++;
3056:
3057: client->last_write = cur_time;
3058:
3059: if (!errors && makesure) {
3060: if (fsync (fileno (leaseFile)) < 0) {
3061: log_info ("write_client_lease: %m");
3062: return 0;
3063: }
3064: }
3065:
3066: return errors ? 0 : 1;
3067: }
3068:
3069: /* Variables holding name of script and file pointer for writing to
3070: script. Needless to say, this is not reentrant - only one script
3071: can be invoked at a time. */
3072: char scriptName [256];
3073: FILE *scriptFile;
3074:
3075: void script_init (client, reason, medium)
3076: struct client_state *client;
3077: const char *reason;
3078: struct string_list *medium;
3079: {
3080: struct string_list *sl, *next;
3081:
3082: if (client) {
3083: for (sl = client -> env; sl; sl = next) {
3084: next = sl -> next;
3085: dfree (sl, MDL);
3086: }
3087: client -> env = (struct string_list *)0;
3088: client -> envc = 0;
3089:
3090: if (client -> interface) {
3091: client_envadd (client, "", "interface", "%s",
3092: client -> interface -> name);
3093: }
3094: if (client -> name)
3095: client_envadd (client,
3096: "", "client", "%s", client -> name);
3097: if (medium)
3098: client_envadd (client,
3099: "", "medium", "%s", medium -> string);
3100:
3101: client_envadd (client, "", "reason", "%s", reason);
3102: client_envadd (client, "", "pid", "%ld", (long int)getpid ());
3103: }
3104: }
3105:
3106: void client_option_envadd (struct option_cache *oc,
3107: struct packet *packet, struct lease *lease,
3108: struct client_state *client_state,
3109: struct option_state *in_options,
3110: struct option_state *cfg_options,
3111: struct binding_scope **scope,
3112: struct universe *u, void *stuff)
3113: {
3114: struct envadd_state *es = stuff;
3115: struct data_string data;
3116: memset (&data, 0, sizeof data);
3117:
3118: if (evaluate_option_cache (&data, packet, lease, client_state,
3119: in_options, cfg_options, scope, oc, MDL)) {
3120: if (data.len) {
3121: char name [256];
3122: if (dhcp_option_ev_name (name, sizeof name,
3123: oc->option)) {
3124: const char *value;
3125: value = pretty_print_option(oc->option,
3126: data.data,
3127: data.len, 0, 0);
3128: size_t length = strlen(value);
3129:
3130: if (check_option_values(oc->option->universe,
3131: oc->option->code,
3132: value, length) == 0) {
3133: client_envadd(es->client, es->prefix,
3134: name, "%s", value);
3135: } else {
3136: log_error("suspect value in %s "
3137: "option - discarded",
3138: name);
3139: }
3140: data_string_forget (&data, MDL);
3141: }
3142: }
3143: }
3144: }
3145:
3146: void script_write_params (client, prefix, lease)
3147: struct client_state *client;
3148: const char *prefix;
3149: struct client_lease *lease;
3150: {
3151: int i;
3152: struct data_string data;
3153: struct option_cache *oc;
3154: struct envadd_state es;
3155:
3156: es.client = client;
3157: es.prefix = prefix;
3158:
3159: client_envadd (client,
3160: prefix, "ip_address", "%s", piaddr (lease -> address));
3161:
3162: /* For the benefit of Linux (and operating systems which may
3163: have similar needs), compute the network address based on
3164: the supplied ip address and netmask, if provided. Also
3165: compute the broadcast address (the host address all ones
3166: broadcast address, not the host address all zeroes
3167: broadcast address). */
3168:
3169: memset (&data, 0, sizeof data);
3170: oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
3171: if (oc && evaluate_option_cache (&data, (struct packet *)0,
3172: (struct lease *)0, client,
3173: (struct option_state *)0,
3174: lease -> options,
3175: &global_scope, oc, MDL)) {
3176: if (data.len > 3) {
3177: struct iaddr netmask, subnet, broadcast;
3178:
3179: /*
3180: * No matter the length of the subnet-mask option,
3181: * use only the first four octets. Note that
3182: * subnet-mask options longer than 4 octets are not
3183: * in conformance with RFC 2132, but servers with this
3184: * flaw do exist.
3185: */
3186: memcpy(netmask.iabuf, data.data, 4);
3187: netmask.len = 4;
3188: data_string_forget (&data, MDL);
3189:
3190: subnet = subnet_number (lease -> address, netmask);
3191: if (subnet.len) {
3192: client_envadd (client, prefix, "network_number",
3193: "%s", piaddr (subnet));
3194:
3195: oc = lookup_option (&dhcp_universe,
3196: lease -> options,
3197: DHO_BROADCAST_ADDRESS);
3198: if (!oc ||
3199: !(evaluate_option_cache
3200: (&data, (struct packet *)0,
3201: (struct lease *)0, client,
3202: (struct option_state *)0,
3203: lease -> options,
3204: &global_scope, oc, MDL))) {
3205: broadcast = broadcast_addr (subnet, netmask);
3206: if (broadcast.len) {
3207: client_envadd (client,
3208: prefix, "broadcast_address",
3209: "%s", piaddr (broadcast));
3210: }
3211: }
3212: }
3213: }
3214: data_string_forget (&data, MDL);
3215: }
3216:
3217: if (lease->filename) {
3218: if (check_option_values(NULL, DHO_ROOT_PATH,
3219: lease->filename,
3220: strlen(lease->filename)) == 0) {
3221: client_envadd(client, prefix, "filename",
3222: "%s", lease->filename);
3223: } else {
3224: log_error("suspect value in %s "
3225: "option - discarded",
3226: lease->filename);
3227: }
3228: }
3229:
3230: if (lease->server_name) {
3231: if (check_option_values(NULL, DHO_HOST_NAME,
3232: lease->server_name,
3233: strlen(lease->server_name)) == 0 ) {
3234: client_envadd (client, prefix, "server_name",
3235: "%s", lease->server_name);
3236: } else {
3237: log_error("suspect value in %s "
3238: "option - discarded",
3239: lease->server_name);
3240: }
3241: }
3242:
3243: for (i = 0; i < lease -> options -> universe_count; i++) {
3244: option_space_foreach ((struct packet *)0, (struct lease *)0,
3245: client, (struct option_state *)0,
3246: lease -> options, &global_scope,
3247: universes [i],
3248: &es, client_option_envadd);
3249: }
3250: client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry));
3251: }
3252:
3253: int script_go (client)
3254: struct client_state *client;
3255: {
3256: char *scriptName;
3257: char *argv [2];
3258: char **envp;
3259: char reason [] = "REASON=NBI";
3260: static char client_path [] = CLIENT_PATH;
3261: int i;
3262: struct string_list *sp, *next;
3263: int pid, wpid, wstatus;
3264:
3265: if (client)
3266: scriptName = client -> config -> script_name;
3267: else
3268: scriptName = top_level_config.script_name;
3269:
3270: envp = dmalloc (((client ? client -> envc : 2) +
3271: client_env_count + 2) * sizeof (char *), MDL);
3272: if (!envp) {
3273: log_error ("No memory for client script environment.");
3274: return 0;
3275: }
3276: i = 0;
3277: /* Copy out the environment specified on the command line,
3278: if any. */
3279: for (sp = client_env; sp; sp = sp -> next) {
3280: envp [i++] = sp -> string;
3281: }
3282: /* Copy out the environment specified by dhclient. */
3283: if (client) {
3284: for (sp = client -> env; sp; sp = sp -> next) {
3285: envp [i++] = sp -> string;
3286: }
3287: } else {
3288: envp [i++] = reason;
3289: }
3290: /* Set $PATH. */
3291: envp [i++] = client_path;
3292: envp [i] = (char *)0;
3293:
3294: argv [0] = scriptName;
3295: argv [1] = (char *)0;
3296:
3297: pid = fork ();
3298: if (pid < 0) {
3299: log_error ("fork: %m");
3300: wstatus = 0;
3301: } else if (pid) {
3302: do {
3303: wpid = wait (&wstatus);
3304: } while (wpid != pid && wpid > 0);
3305: if (wpid < 0) {
3306: log_error ("wait: %m");
3307: wstatus = 0;
3308: }
3309: } else {
3310: /* We don't want to pass an open file descriptor for
3311: * dhclient.leases when executing dhclient-script.
3312: */
3313: if (leaseFile != NULL)
3314: fclose(leaseFile);
3315: execve (scriptName, argv, envp);
3316: log_error ("execve (%s, ...): %m", scriptName);
3317: exit (0);
3318: }
3319:
3320: if (client) {
3321: for (sp = client -> env; sp; sp = next) {
3322: next = sp -> next;
3323: dfree (sp, MDL);
3324: }
3325: client -> env = (struct string_list *)0;
3326: client -> envc = 0;
3327: }
3328: dfree (envp, MDL);
3329: gettimeofday(&cur_tv, NULL);
3330: return (WIFEXITED (wstatus) ?
3331: WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
3332: }
3333:
3334: void client_envadd (struct client_state *client,
3335: const char *prefix, const char *name, const char *fmt, ...)
3336: {
3337: char spbuf [1024];
3338: char *s;
3339: unsigned len;
3340: struct string_list *val;
3341: va_list list;
3342:
3343: va_start (list, fmt);
3344: len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
3345: va_end (list);
3346:
3347: val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
3348: len + sizeof *val, MDL);
3349: if (!val)
3350: return;
3351: s = val -> string;
3352: strcpy (s, prefix);
3353: strcat (s, name);
3354: s += strlen (s);
3355: *s++ = '=';
3356: if (len >= sizeof spbuf) {
3357: va_start (list, fmt);
3358: vsnprintf (s, len + 1, fmt, list);
3359: va_end (list);
3360: } else
3361: strcpy (s, spbuf);
3362: val -> next = client -> env;
3363: client -> env = val;
3364: client -> envc++;
3365: }
3366:
3367: int dhcp_option_ev_name (buf, buflen, option)
3368: char *buf;
3369: size_t buflen;
3370: struct option *option;
3371: {
3372: int i, j;
3373: const char *s;
3374:
3375: j = 0;
3376: if (option -> universe != &dhcp_universe) {
3377: s = option -> universe -> name;
3378: i = 0;
3379: } else {
3380: s = option -> name;
3381: i = 1;
3382: }
3383:
3384: do {
3385: while (*s) {
3386: if (j + 1 == buflen)
3387: return 0;
3388: if (*s == '-')
3389: buf [j++] = '_';
3390: else
3391: buf [j++] = *s;
3392: ++s;
3393: }
3394: if (!i) {
3395: s = option -> name;
3396: if (j + 1 == buflen)
3397: return 0;
3398: buf [j++] = '_';
3399: }
3400: ++i;
3401: } while (i != 2);
3402:
3403: buf [j] = 0;
3404: return 1;
3405: }
3406:
3407: void go_daemon ()
3408: {
3409: static int state = 0;
3410: int pid;
3411:
3412: /* Don't become a daemon if the user requested otherwise. */
3413: if (no_daemon) {
3414: write_client_pid_file ();
3415: return;
3416: }
3417:
3418: /* Only do it once. */
3419: if (state)
3420: return;
3421: state = 1;
3422:
3423: /* Stop logging to stderr... */
3424: log_perror = 0;
3425:
3426: /* Become a daemon... */
3427: if ((pid = fork ()) < 0)
3428: log_fatal ("Can't fork daemon: %m");
3429: else if (pid)
3430: exit (0);
3431: /* Become session leader and get pid... */
3432: pid = setsid ();
3433:
3434: /* Close standard I/O descriptors. */
3435: close(0);
3436: close(1);
3437: close(2);
3438:
3439: /* Reopen them on /dev/null. */
3440: open("/dev/null", O_RDWR);
3441: open("/dev/null", O_RDWR);
3442: open("/dev/null", O_RDWR);
3443:
3444: write_client_pid_file ();
3445:
3446: IGNORE_RET (chdir("/"));
3447: }
3448:
3449: void write_client_pid_file ()
3450: {
3451: FILE *pf;
3452: int pfdesc;
3453:
3454: /* nothing to do if the user doesn't want a pid file */
3455: if (no_pid_file == ISC_TRUE) {
3456: return;
3457: }
3458:
3459: pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
3460:
3461: if (pfdesc < 0) {
3462: log_error ("Can't create %s: %m", path_dhclient_pid);
3463: return;
3464: }
3465:
3466: pf = fdopen (pfdesc, "w");
3467: if (!pf) {
3468: close(pfdesc);
3469: log_error ("Can't fdopen %s: %m", path_dhclient_pid);
3470: } else {
3471: fprintf (pf, "%ld\n", (long)getpid ());
3472: fclose (pf);
3473: }
3474: }
3475:
3476: void client_location_changed ()
3477: {
3478: struct interface_info *ip;
3479: struct client_state *client;
3480:
3481: for (ip = interfaces; ip; ip = ip -> next) {
3482: for (client = ip -> client; client; client = client -> next) {
3483: switch (client -> state) {
3484: case S_SELECTING:
3485: cancel_timeout (send_discover, client);
3486: break;
3487:
3488: case S_BOUND:
3489: cancel_timeout (state_bound, client);
3490: break;
3491:
3492: case S_REBOOTING:
3493: case S_REQUESTING:
3494: case S_RENEWING:
3495: cancel_timeout (send_request, client);
3496: break;
3497:
3498: case S_INIT:
3499: case S_REBINDING:
3500: case S_STOPPED:
3501: break;
3502: }
3503: client -> state = S_INIT;
3504: state_reboot (client);
3505: }
3506: }
3507: }
3508:
3509: void do_release(client)
3510: struct client_state *client;
3511: {
3512: struct data_string ds;
3513: struct option_cache *oc;
3514:
3515: /* Pick a random xid. */
3516: client -> xid = random ();
3517:
3518: /* is there even a lease to release? */
3519: if (client -> active) {
3520: /* Make a DHCPRELEASE packet, and set appropriate per-interface
3521: flags. */
3522: make_release (client, client -> active);
3523:
3524: memset (&ds, 0, sizeof ds);
3525: oc = lookup_option (&dhcp_universe,
3526: client -> active -> options,
3527: DHO_DHCP_SERVER_IDENTIFIER);
3528: if (oc &&
3529: evaluate_option_cache (&ds, (struct packet *)0,
3530: (struct lease *)0, client,
3531: (struct option_state *)0,
3532: client -> active -> options,
3533: &global_scope, oc, MDL)) {
3534: if (ds.len > 3) {
3535: memcpy (client -> destination.iabuf,
3536: ds.data, 4);
3537: client -> destination.len = 4;
3538: } else
3539: client -> destination = iaddr_broadcast;
3540:
3541: data_string_forget (&ds, MDL);
3542: } else
3543: client -> destination = iaddr_broadcast;
3544: client -> first_sending = cur_time;
3545: client -> interval = client -> config -> initial_interval;
3546:
3547: /* Zap the medium list... */
3548: client -> medium = (struct string_list *)0;
3549:
3550: /* Send out the first and only DHCPRELEASE packet. */
3551: send_release (client);
3552:
3553: /* Do the client script RELEASE operation. */
3554: script_init (client,
3555: "RELEASE", (struct string_list *)0);
3556: if (client -> alias)
3557: script_write_params (client, "alias_",
3558: client -> alias);
3559: script_write_params (client, "old_", client -> active);
3560: script_go (client);
3561: }
3562:
3563: /* Cancel any timeouts. */
3564: cancel_timeout (state_bound, client);
3565: cancel_timeout (send_discover, client);
3566: cancel_timeout (state_init, client);
3567: cancel_timeout (send_request, client);
3568: cancel_timeout (state_reboot, client);
3569: client -> state = S_STOPPED;
3570: }
3571:
3572: int dhclient_interface_shutdown_hook (struct interface_info *interface)
3573: {
3574: do_release (interface -> client);
3575:
3576: return 1;
3577: }
3578:
3579: int dhclient_interface_discovery_hook (struct interface_info *tmp)
3580: {
3581: struct interface_info *last, *ip;
3582: /* See if we can find the client from dummy_interfaces */
3583: last = 0;
3584: for (ip = dummy_interfaces; ip; ip = ip -> next) {
3585: if (!strcmp (ip -> name, tmp -> name)) {
3586: /* Remove from dummy_interfaces */
3587: if (last) {
3588: ip = (struct interface_info *)0;
3589: interface_reference (&ip, last -> next, MDL);
3590: interface_dereference (&last -> next, MDL);
3591: if (ip -> next) {
3592: interface_reference (&last -> next,
3593: ip -> next, MDL);
3594: interface_dereference (&ip -> next,
3595: MDL);
3596: }
3597: } else {
3598: ip = (struct interface_info *)0;
3599: interface_reference (&ip,
3600: dummy_interfaces, MDL);
3601: interface_dereference (&dummy_interfaces, MDL);
3602: if (ip -> next) {
3603: interface_reference (&dummy_interfaces,
3604: ip -> next, MDL);
3605: interface_dereference (&ip -> next,
3606: MDL);
3607: }
3608: }
3609: /* Copy "client" to tmp */
3610: if (ip -> client) {
3611: tmp -> client = ip -> client;
3612: tmp -> client -> interface = tmp;
3613: }
3614: interface_dereference (&ip, MDL);
3615: break;
3616: }
3617: last = ip;
3618: }
3619: return 1;
3620: }
3621:
3622: isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
3623: {
3624: struct interface_info *ip;
3625: struct client_state *client;
3626:
3627: /* This code needs some rethinking. It doesn't test against
3628: a signal name, and it just kind of bulls into doing something
3629: that may or may not be appropriate. */
3630:
3631: if (interfaces) {
3632: interface_reference (&interface -> next, interfaces, MDL);
3633: interface_dereference (&interfaces, MDL);
3634: }
3635: interface_reference (&interfaces, interface, MDL);
3636:
3637: discover_interfaces (DISCOVER_UNCONFIGURED);
3638:
3639: for (ip = interfaces; ip; ip = ip -> next) {
3640: /* If interfaces were specified, don't configure
3641: interfaces that weren't specified! */
3642: if (ip -> flags & INTERFACE_RUNNING ||
3643: (ip -> flags & (INTERFACE_REQUESTED |
3644: INTERFACE_AUTOMATIC)) !=
3645: INTERFACE_REQUESTED)
3646: continue;
3647: script_init (ip -> client,
3648: "PREINIT", (struct string_list *)0);
3649: if (ip -> client -> alias)
3650: script_write_params (ip -> client, "alias_",
3651: ip -> client -> alias);
3652: script_go (ip -> client);
3653: }
3654:
3655: discover_interfaces (interfaces_requested != 0
3656: ? DISCOVER_REQUESTED
3657: : DISCOVER_RUNNING);
3658:
3659: for (ip = interfaces; ip; ip = ip -> next) {
3660: if (ip -> flags & INTERFACE_RUNNING)
3661: continue;
3662: ip -> flags |= INTERFACE_RUNNING;
3663: for (client = ip->client ; client ; client = client->next) {
3664: client->state = S_INIT;
3665: state_reboot(client);
3666: }
3667: }
3668: return ISC_R_SUCCESS;
3669: }
3670:
3671: /* The client should never receive a relay agent information option,
3672: so if it does, log it and discard it. */
3673:
3674: int parse_agent_information_option (packet, len, data)
3675: struct packet *packet;
3676: int len;
3677: u_int8_t *data;
3678: {
3679: return 1;
3680: }
3681:
3682: /* The client never sends relay agent information options. */
3683:
3684: unsigned cons_agent_information_options (cfg_options, outpacket,
3685: agentix, length)
3686: struct option_state *cfg_options;
3687: struct dhcp_packet *outpacket;
3688: unsigned agentix;
3689: unsigned length;
3690: {
3691: return length;
3692: }
3693:
3694: static void shutdown_exit (void *foo)
3695: {
3696: exit (0);
3697: }
3698:
3699: isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
3700: control_object_state_t newstate)
3701: {
3702: struct interface_info *ip;
3703: struct client_state *client;
3704: struct timeval tv;
3705:
3706: /* Do the right thing for each interface. */
3707: for (ip = interfaces; ip; ip = ip -> next) {
3708: for (client = ip -> client; client; client = client -> next) {
3709: switch (newstate) {
3710: case server_startup:
3711: return ISC_R_SUCCESS;
3712:
3713: case server_running:
3714: return ISC_R_SUCCESS;
3715:
3716: case server_shutdown:
3717: if (client -> active &&
3718: client -> active -> expiry > cur_time) {
3719: if (client -> config -> do_forward_update)
3720: client_dns_update(client, 0, 0,
3721: &client->active->address);
3722: do_release (client);
3723: }
3724: break;
3725:
3726: case server_hibernate:
3727: state_stop (client);
3728: break;
3729:
3730: case server_awaken:
3731: state_reboot (client);
3732: break;
3733: }
3734: }
3735: }
3736:
3737: if (newstate == server_shutdown) {
3738: tv.tv_sec = cur_tv.tv_sec;
3739: tv.tv_usec = cur_tv.tv_usec + 1;
3740: add_timeout(&tv, shutdown_exit, 0, 0, 0);
3741: }
3742: return ISC_R_SUCCESS;
3743: }
3744:
3745: /* Schedule updates to retry occasionally until it no longer times out.
3746: */
3747: void
3748: dhclient_schedule_updates(struct client_state *client, struct iaddr *addr,
3749: int offset)
3750: {
3751: struct dns_update_state *ustate;
3752: struct timeval tv;
3753:
3754: if (!client->config->do_forward_update)
3755: return;
3756:
3757: ustate = dmalloc(sizeof(*ustate), MDL);
3758:
3759: if (ustate != NULL) {
3760: ustate->client = client;
3761: ustate->address = *addr;
3762: ustate->dns_update_timeout = 1;
3763:
3764: tv.tv_sec = cur_tv.tv_sec + offset;
3765: tv.tv_usec = cur_tv.tv_usec;
3766: add_timeout(&tv, client_dns_update_timeout,
3767: ustate, NULL, NULL);
3768: } else {
3769: log_error("Unable to allocate dns update state for %s.",
3770: piaddr(*addr));
3771: }
3772: }
3773:
3774: /* Called after a timeout if the DNS update failed on the previous try.
3775: Retries the update, and if it times out, schedules a retry after
3776: ten times as long of a wait. */
3777:
3778: void client_dns_update_timeout (void *cp)
3779: {
3780: struct dns_update_state *ustate = cp;
3781: isc_result_t status = ISC_R_FAILURE;
3782: struct timeval tv;
3783:
3784: /* XXX: DNS TTL is a problem we need to solve properly. Until
3785: * that time, 300 is a placeholder default for something that is
3786: * less insane than a value scaled by lease timeout.
3787: */
3788: if ((ustate->client->active != NULL) ||
3789: (ustate->client->active_lease != NULL))
3790: status = client_dns_update(ustate->client, 1, 300,
3791: &ustate->address);
3792:
3793: if (status == ISC_R_TIMEDOUT) {
3794: if (ustate->dns_update_timeout < 3600)
3795: ustate->dns_update_timeout *= 10;
3796: tv.tv_sec = cur_tv.tv_sec + ustate->dns_update_timeout;
3797: tv.tv_usec = cur_tv.tv_usec;
3798: add_timeout(&tv, client_dns_update_timeout,
3799: ustate, NULL, NULL);
3800: } else
3801: dfree(ustate, MDL);
3802: }
3803:
3804: /* See if we should do a DNS update, and if so, do it. */
3805:
3806: isc_result_t client_dns_update (struct client_state *client, int addp,
3807: int ttl, struct iaddr *address)
3808: {
3809: struct data_string ddns_fwd_name, ddns_dhcid, client_identifier;
3810: struct option_cache *oc;
3811: int ignorep;
3812: int result;
3813: isc_result_t rcode;
3814:
3815: /* If we didn't send an FQDN option, we certainly aren't going to
3816: be doing an update. */
3817: if (!client -> sent_options)
3818: return ISC_R_SUCCESS;
3819:
3820: /* If we don't have a lease, we can't do an update. */
3821: if ((client->active == NULL) && (client->active_lease == NULL))
3822: return ISC_R_SUCCESS;
3823:
3824: /* If we set the no client update flag, don't do the update. */
3825: if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
3826: FQDN_NO_CLIENT_UPDATE)) &&
3827: evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
3828: (struct lease *)0, client,
3829: client -> sent_options,
3830: (struct option_state *)0,
3831: &global_scope, oc, MDL))
3832: return ISC_R_SUCCESS;
3833:
3834: /* If we set the "server, please update" flag, or didn't set it
3835: to false, don't do the update. */
3836: if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
3837: FQDN_SERVER_UPDATE)) ||
3838: evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
3839: (struct lease *)0, client,
3840: client -> sent_options,
3841: (struct option_state *)0,
3842: &global_scope, oc, MDL))
3843: return ISC_R_SUCCESS;
3844:
3845: /* If no FQDN option was supplied, don't do the update. */
3846: memset (&ddns_fwd_name, 0, sizeof ddns_fwd_name);
3847: if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
3848: FQDN_FQDN)) ||
3849: !evaluate_option_cache (&ddns_fwd_name, (struct packet *)0,
3850: (struct lease *)0, client,
3851: client -> sent_options,
3852: (struct option_state *)0,
3853: &global_scope, oc, MDL))
3854: return ISC_R_SUCCESS;
3855:
3856: /* If this is a DHCPv6 client update, make a dhcid string out of
3857: * the DUID. If this is a DHCPv4 client update, choose either
3858: * the client identifier, if there is one, or the interface's
3859: * MAC address.
3860: */
3861: memset (&ddns_dhcid, 0, sizeof ddns_dhcid);
3862:
3863: result = 0;
3864: memset(&client_identifier, 0, sizeof(client_identifier));
3865: if (client->active_lease != NULL) {
3866: if (((oc =
3867: lookup_option(&dhcpv6_universe, client->sent_options,
3868: D6O_CLIENTID)) != NULL) &&
3869: evaluate_option_cache(&client_identifier, NULL, NULL,
3870: client, client->sent_options, NULL,
3871: &global_scope, oc, MDL)) {
3872: /* RFC4701 defines type '2' as being for the DUID
3873: * field. We aren't using RFC4701 DHCID RR's yet,
3874: * but this is as good a value as any.
3875: */
3876: result = get_dhcid(&ddns_dhcid, 2,
3877: client_identifier.data,
3878: client_identifier.len);
3879: data_string_forget(&client_identifier, MDL);
3880: } else
3881: log_fatal("Impossible condition at %s:%d.", MDL);
3882: } else {
3883: if (((oc =
3884: lookup_option(&dhcp_universe, client->sent_options,
3885: DHO_DHCP_CLIENT_IDENTIFIER)) != NULL) &&
3886: evaluate_option_cache(&client_identifier, NULL, NULL,
3887: client, client->sent_options, NULL,
3888: &global_scope, oc, MDL)) {
3889: result = get_dhcid(&ddns_dhcid,
3890: DHO_DHCP_CLIENT_IDENTIFIER,
3891: client_identifier.data,
3892: client_identifier.len);
3893: data_string_forget(&client_identifier, MDL);
3894: } else
3895: result = get_dhcid(&ddns_dhcid, 0,
3896: client->interface->hw_address.hbuf,
3897: client->interface->hw_address.hlen);
3898: }
3899: if (!result) {
3900: data_string_forget(&ddns_fwd_name, MDL);
3901: return ISC_R_SUCCESS;
3902: }
3903:
3904: /* Start the resolver, if necessary. */
3905: if (!resolver_inited) {
3906: minires_ninit (&resolver_state);
3907: resolver_inited = 1;
3908: resolver_state.retrans = 1;
3909: resolver_state.retry = 1;
3910: }
3911:
3912: /*
3913: * Perform updates.
3914: */
3915: if (ddns_fwd_name.len && ddns_dhcid.len) {
3916: if (addp)
3917: rcode = ddns_update_fwd(&ddns_fwd_name, *address,
3918: &ddns_dhcid, ttl, 1, 1);
3919: else
3920: rcode = ddns_remove_fwd(&ddns_fwd_name, *address,
3921: &ddns_dhcid);
3922: } else
3923: rcode = ISC_R_FAILURE;
3924:
3925: data_string_forget (&ddns_fwd_name, MDL);
3926: data_string_forget (&ddns_dhcid, MDL);
3927: return rcode;
3928: }
3929:
3930: void
3931: dhcpv4_client_assignments(void)
3932: {
3933: struct servent *ent;
3934:
3935: if (path_dhclient_pid == NULL)
3936: path_dhclient_pid = _PATH_DHCLIENT_PID;
3937: if (path_dhclient_db == NULL)
3938: path_dhclient_db = _PATH_DHCLIENT_DB;
3939:
3940: /* Default to the DHCP/BOOTP port. */
3941: if (!local_port) {
3942: /* If we're faking a relay agent, and we're not using loopback,
3943: use the server port, not the client port. */
3944: if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
3945: local_port = htons(67);
3946: } else {
3947: ent = getservbyname ("dhcpc", "udp");
3948: if (!ent)
3949: local_port = htons (68);
3950: else
3951: local_port = ent -> s_port;
3952: #ifndef __CYGWIN32__
3953: endservent ();
3954: #endif
3955: }
3956: }
3957:
3958: /* If we're faking a relay agent, and we're not using loopback,
3959: we're using the server port, not the client port. */
3960: if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
3961: remote_port = local_port;
3962: } else
3963: remote_port = htons (ntohs (local_port) - 1); /* XXX */
3964: }
3965:
3966: /*
3967: * The following routines are used to check that certain
3968: * strings are reasonable before we pass them to the scripts.
3969: * This avoids some problems with scripts treating the strings
3970: * as commands - see ticket 23722
3971: * The domain checking code should be done as part of assembling
3972: * the string but we are doing it here for now due to time
3973: * constraints.
3974: */
3975:
3976: static int check_domain_name(const char *ptr, size_t len, int dots)
3977: {
3978: const char *p;
3979:
3980: /* not empty or complete length not over 255 characters */
3981: if ((len == 0) || (len > 256))
3982: return(-1);
3983:
3984: /* consists of [[:alnum:]-]+ labels separated by [.] */
3985: /* a [_] is against RFC but seems to be "widely used"... */
3986: for (p=ptr; (*p != 0) && (len-- > 0); p++) {
3987: if ((*p == '-') || (*p == '_')) {
3988: /* not allowed at begin or end of a label */
3989: if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
3990: return(-1);
3991: } else if (*p == '.') {
3992: /* each label has to be 1-63 characters;
3993: we allow [.] at the end ('foo.bar.') */
3994: size_t d = p - ptr;
3995: if ((d <= 0) || (d >= 64))
3996: return(-1);
3997: ptr = p + 1; /* jump to the next label */
3998: if ((dots > 0) && (len > 0))
3999: dots--;
4000: } else if (isalnum((unsigned char)*p) == 0) {
4001: /* also numbers at the begin are fine */
4002: return(-1);
4003: }
4004: }
4005: return(dots ? -1 : 0);
4006: }
4007:
4008: static int check_domain_name_list(const char *ptr, size_t len, int dots)
4009: {
4010: const char *p;
4011: int ret = -1; /* at least one needed */
4012:
4013: if ((ptr == NULL) || (len == 0))
4014: return(-1);
4015:
4016: for (p=ptr; (*p != 0) && (len > 0); p++, len--) {
4017: if (*p != ' ')
4018: continue;
4019: if (p > ptr) {
4020: if (check_domain_name(ptr, p - ptr, dots) != 0)
4021: return(-1);
4022: ret = 0;
4023: }
4024: ptr = p + 1;
4025: }
4026: if (p > ptr)
4027: return(check_domain_name(ptr, p - ptr, dots));
4028: else
4029: return(ret);
4030: }
4031:
4032: static int check_option_values(struct universe *universe,
4033: unsigned int opt,
4034: const char *ptr,
4035: size_t len)
4036: {
4037: if (ptr == NULL)
4038: return(-1);
4039:
4040: /* just reject options we want to protect, will be escaped anyway */
4041: if ((universe == NULL) || (universe == &dhcp_universe)) {
4042: switch(opt) {
4043: case DHO_DOMAIN_NAME:
4044: #ifdef ACCEPT_LIST_IN_DOMAIN_NAME
4045: return check_domain_name_list(ptr, len, 0);
4046: #else
4047: return check_domain_name(ptr, len, 0);
4048: #endif
4049: case DHO_HOST_NAME:
4050: case DHO_NIS_DOMAIN:
4051: case DHO_NETBIOS_SCOPE:
4052: return check_domain_name(ptr, len, 0);
4053: break;
4054: case DHO_DOMAIN_SEARCH:
4055: return check_domain_name_list(ptr, len, 0);
4056: break;
4057: case DHO_ROOT_PATH:
4058: if (len == 0)
4059: return(-1);
4060: for (; (*ptr != 0) && (len-- > 0); ptr++) {
4061: if(!(isalnum((unsigned char)*ptr) ||
4062: *ptr == '#' || *ptr == '%' ||
4063: *ptr == '+' || *ptr == '-' ||
4064: *ptr == '_' || *ptr == ':' ||
4065: *ptr == '.' || *ptr == ',' ||
4066: *ptr == '@' || *ptr == '~' ||
4067: *ptr == '\\' || *ptr == '/' ||
4068: *ptr == '[' || *ptr == ']' ||
4069: *ptr == '=' || *ptr == ' '))
4070: return(-1);
4071: }
4072: return(0);
4073: break;
4074: }
4075: }
4076:
4077: #ifdef DHCPv6
4078: if (universe == &dhcpv6_universe) {
4079: switch(opt) {
4080: case D6O_SIP_SERVERS_DNS:
4081: case D6O_DOMAIN_SEARCH:
4082: case D6O_NIS_DOMAIN_NAME:
4083: case D6O_NISP_DOMAIN_NAME:
4084: return check_domain_name_list(ptr, len, 0);
4085: break;
4086: }
4087: }
4088: #endif
4089:
4090: return(0);
4091: }
4092:
4093: static void
4094: add_reject(struct packet *packet) {
4095: struct iaddrmatchlist *list;
4096:
4097: list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
4098: if (!list)
4099: log_fatal ("no memory for reject list!");
4100:
4101: /*
4102: * client_addr is misleading - it is set to source address in common
4103: * code.
4104: */
4105: list->match.addr = packet->client_addr;
4106: /* Set mask to indicate host address. */
4107: list->match.mask.len = list->match.addr.len;
4108: memset(list->match.mask.iabuf, 0xff, sizeof(list->match.mask.iabuf));
4109:
4110: /* Append to reject list for the source interface. */
4111: list->next = packet->interface->client->config->reject_list;
4112: packet->interface->client->config->reject_list = list;
4113:
4114: /*
4115: * We should inform user that we won't be accepting this server
4116: * anymore.
4117: */
4118: log_info("Server added to list of rejected servers.");
4119: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>