ISC DHCP 4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
 
Loading...
Searching...
No Matches
dhclient.c
Go to the documentation of this file.
1/* dhclient.c
2
3 DHCP Client. */
4
5/*
6 * Copyright (c) 2004-2022 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
8 *
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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 * PO Box 360
23 * Newmarket, NH 03857 USA
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 <isc/util.h>
35#include <isc/file.h>
36#include <dns/result.h>
37#include <syslog.h>
38#include <signal.h>
39#include <errno.h>
40#include <sys/time.h>
41#include <sys/wait.h>
42#include <limits.h>
43
44#ifdef HAVE_LIBCAP_NG
45#include <cap-ng.h>
46#endif
47
48/*
49 * Defined in stdio.h when _GNU_SOURCE is set, but we don't want to define
50 * that when building ISC code.
51 */
52extern int asprintf(char **strp, const char *fmt, ...);
53
54TIME default_lease_time = 43200; /* 12 hours... */
55TIME max_lease_time = 86400; /* 24 hours... */
56
58const char *path_dhclient_db = NULL;
59const char *path_dhclient_pid = NULL;
60static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
61char *path_dhclient_script = path_dhclient_script_array;
62const char *path_dhclient_duid = NULL;
63
64static void add_to_tail(struct client_lease** lease_list, struct client_lease* lease);
65
66/* False (default) => we write and use a pid file */
68
70
72
73struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
74struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
75struct in_addr inaddr_any;
76struct sockaddr_in sockaddr_broadcast;
77struct in_addr giaddr;
79int duid_type = 0;
80int duid_v4 = 0;
81int std_dhcid = 0;
82
83int decline_wait_time = 10; /* Default to 10 secs per, RFC 2131, 3.1.5 */
84
85/* ASSERT_STATE() does nothing now; it used to be
86 assert (state_is == state_shouldbe). */
87#define ASSERT_STATE(state_is, state_shouldbe) {}
88
89#ifndef UNIT_TEST
90static const char copyright[] = "Copyright 2004-2022 Internet Systems Consortium.";
91static const char arr [] = "All rights reserved.";
92static const char message [] = "Internet Systems Consortium DHCP Client";
93static const char url [] = "For info, please visit https://www.isc.org/software/dhcp/";
94#endif /* UNIT_TEST */
95
96extern u_int16_t local_port;
97extern u_int16_t remote_port;
98
99#if defined(DHCPv6) && defined(DHCP4o6)
100int dhcp4o6_state = -1; /* -1 = stopped, 0 = polling, 1 = started */
101#endif
102int no_daemon = 0;
103int dfd[2] = { -1, -1 };
104struct string_list *client_env = NULL;
106int onetry = 0;
107int quiet = 1;
108int nowait = 0;
109int stateless = 0;
110int wanted_ia_na = -1; /* the absolute value is the real one. */
113int require_all_ias = 0; /* If the user requires all of the IAs to
114 be available before accepting a lease
115 0 = no, 1 = requries */
116#if defined(DHCPv6)
117int dad_wait_time = 0;
118int prefix_len_hint = 0;
119#endif
120
122char *mockup_relay = NULL;
123
124char *progname = NULL;
125
127
128extern struct option *default_requested_options[];
129
130void run_stateless(int exit_mode, u_int16_t port);
131
132static isc_result_t write_duid(struct data_string *duid);
133static void add_reject(struct packet *packet);
134
135static int check_domain_name(const char *ptr, size_t len, int dots);
136static int check_domain_name_list(const char *ptr, size_t len, int dots);
137static int check_option_values(struct universe *universe, unsigned int opt,
138 const char *ptr, size_t len);
139
140#if defined(NSUPDATE)
141static void dhclient_ddns_cb_free(dhcp_ddns_cb_t *ddns_cb,
142 char* file, int line);
143#endif /* defined NSUPDATE */
144
145
161
162#if defined(DHCPv6) && defined(DHCP4o6)
163static void dhcp4o6_poll(void *dummy);
164static void dhcp4o6_resume(void);
165static void recv_dhcpv4_response(struct data_string *raw);
166static int send_dhcpv4_query(struct client_state *client, int broadcast);
167
168static void dhcp4o6_stop(void);
169static void forw_dhcpv4_response(struct packet *packet);
170static void forw_dhcpv4_query(struct data_string *raw);
171#endif
172
173#ifndef UNIT_TEST
174/* These are only used when we call usage() from the main routine
175 * which isn't compiled when building for unit tests
176 */
177static const char use_noarg[] = "No argument for command: %s";
178#ifdef DHCPv6
179static const char use_v6command[] = "Command not used for DHCPv4: %s";
180#endif
181
182#ifdef DHCPv6
183#ifdef DHCP4o6
184#define DHCLIENT_USAGE0 \
185"[-4|-6] [-SNTPRI1dvrxi] [-nw] -4o6 <port>] [-p <port>] [-D LL|LLT]\n" \
186" [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
187" [--decline-wait-time <seconds>]\n" \
188" [--address-prefix-len <length>]\n"
189#else /* DHCP4o6 */
190#define DHCLIENT_USAGE0 \
191"[-4|-6] [-SNTPRI1dvrxi] [-nw] [-p <port>] [-D LL|LLT]\n" \
192" [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
193" [--decline-wait-time <seconds>]\n" \
194" [--address-prefix-len <length>]\n"
195#endif
196#else /* DHCPv6 */
197#define DHCLIENT_USAGE0 \
198"[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n" \
199" [--decline-wait-time <seconds>]\n"
200#endif
201
202#define DHCLIENT_USAGEC \
203" [-s server-addr] [-cf config-file]\n" \
204" [-df duid-file] [-lf lease-file]\n" \
205" [-pf pid-file] [--no-pid] [-e VAR=val]\n" \
206" [-sf script-file] [interface]*\n" \
207" [-C <dhcp-client-identifier>] [-B]\n" \
208" [-H <host-name> | -F <fqdn.fqdn>] [--timeout <timeout>]\n" \
209" [-V <vendor-class-identifier>]\n" \
210" [--request-options <request option list>]"
211
212#define DHCLIENT_USAGEH "{--version|--help|-h}"
213
214static void setup_ib_interface(struct interface_info *ip);
215
216static void
217usage(const char *sfmt, const char *sarg)
218{
219 log_info("%s %s", message, PACKAGE_VERSION);
220 log_info(copyright);
221 log_info(arr);
222 log_info(url);
223
224 /* If desired print out the specific error message */
225#ifdef PRINT_SPECIFIC_CL_ERRORS
226 if (sfmt != NULL)
227 log_error(sfmt, sarg);
228#endif
229
230 log_fatal("Usage: %s %s%s\n %s %s",
231 isc_file_basename(progname),
234 isc_file_basename(progname),
236}
237
239
240int
241main(int argc, char **argv) {
242 int fd;
243 int i;
244 struct interface_info *ip;
245 struct client_state *client;
246 unsigned seed;
247 char *server = NULL;
248 isc_result_t status;
249 int exit_mode = 0;
250 int release_mode = 0;
251 struct timeval tv;
252 omapi_object_t *listener;
253 isc_result_t result;
254 int persist = 0;
255 int no_dhclient_conf = 0;
256 int no_dhclient_db = 0;
257 int no_dhclient_pid = 0;
258 int no_dhclient_script = 0;
259#ifdef DHCPv6
260 int local_family_set = 0;
261#ifdef DHCP4o6
262 u_int16_t dhcp4o6_port = 0;
263#endif /* DHCP4o6 */
264#endif /* DHCPv6 */
265 char *s;
266
267#ifdef OLD_LOG_NAME
268 progname = "dhclient";
269#else
270 progname = argv[0];
271#endif
272 char *dhcp_client_identifier_arg = NULL;
273 char *dhcp_host_name_arg = NULL;
274 char *dhcp_fqdn_arg = NULL;
275 char *dhcp_vendor_class_identifier_arg = NULL;
276 char *dhclient_request_options = NULL;
277
278 int timeout_arg = 0;
279 char *arg_conf = NULL;
280 int arg_conf_len = 0;
281#ifdef HAVE_LIBCAP_NG
282 int keep_capabilities = 0;
283#endif
284
285 /* Initialize client globals. */
286 memset(&default_duid, 0, sizeof(default_duid));
287
288 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
289 2 (stderr) are open. To do this, we assume that when we
290 open a file the lowest available file descriptor is used. */
291 fd = open("/dev/null", O_RDWR | O_CLOEXEC);
292 if (fd == 0)
293 fd = open("/dev/null", O_RDWR | O_CLOEXEC);
294 if (fd == 1)
295 fd = open("/dev/null", O_RDWR | O_CLOEXEC);
296 if (fd == 2)
297 log_perror = 0; /* No sense logging to /dev/null. */
298 else if (fd != -1)
299 close(fd);
300
301 openlog(isc_file_basename(progname), DHCP_LOG_OPTIONS, LOG_DAEMON);
302
303#if !(defined(DEBUG) || defined(__CYGWIN32__))
304 setlogmask(LOG_UPTO(LOG_INFO));
305#endif
306
307 /* Parse arguments changing no_daemon */
308 for (i = 1; i < argc; i++) {
309 if (!strcmp(argv[i], "-r")) {
310 no_daemon = 1;
311 } else if (!strcmp(argv[i], "-x")) {
312 no_daemon = 0;
313 } else if (!strcmp(argv[i], "-d")) {
314 no_daemon = 1;
315 } else if (!strcmp(argv[i], "--version")) {
316 const char vstring[] = "isc-dhclient-";
317 IGNORE_RET(write(STDERR_FILENO, vstring,
318 strlen(vstring)));
321 strlen(PACKAGE_VERSION)));
322 IGNORE_RET(write(STDERR_FILENO, "\n", 1));
323 exit(0);
324 } else if (!strcmp(argv[i], "--help") ||
325 !strcmp(argv[i], "-h")) {
326 const char *pname = isc_file_basename(progname);
327 IGNORE_RET(write(STDERR_FILENO, "Usage: ", 7));
328 IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname)));
329 IGNORE_RET(write(STDERR_FILENO, " ", 1));
331 strlen(DHCLIENT_USAGE0)));
333 strlen(DHCLIENT_USAGEC)));
334 IGNORE_RET(write(STDERR_FILENO, "\n", 1));
335 IGNORE_RET(write(STDERR_FILENO, " ", 7));
336 IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname)));
337 IGNORE_RET(write(STDERR_FILENO, " ", 1));
339 strlen(DHCLIENT_USAGEH)));
340 IGNORE_RET(write(STDERR_FILENO, "\n", 1));
341 exit(0);
342 }
343 }
344 /* When not forbidden prepare to become a daemon */
345 if (!no_daemon) {
346 int pid;
347
348 if (pipe(dfd) == -1)
349 log_fatal("Can't get pipe: %m");
350 if ((pid = fork ()) < 0)
351 log_fatal("Can't fork daemon: %m");
352 if (pid != 0) {
353 /* Parent: wait for the child to start */
354 int n;
355
356 (void) close(dfd[1]);
357 do {
358 char buf;
359
360 n = read(dfd[0], &buf, 1);
361 if (n == 1)
362 _exit((int)buf);
363 } while (n == -1 && errno == EINTR);
364 _exit(1);
365 }
366 /* Child */
367 (void) close(dfd[0]);
368 }
369
370 /* Set up the isc and dns library managers */
372 | DHCP_DNS_CLIENT_LAZY_INIT, NULL, NULL);
373 if (status != ISC_R_SUCCESS)
374 log_fatal("Can't initialize context: %s",
375 isc_result_totext(status));
376
377 /* Set up the OMAPI. */
378 status = omapi_init();
379 if (status != ISC_R_SUCCESS)
380 log_fatal("Can't initialize OMAPI: %s",
381 isc_result_totext(status));
382
383 /* Set up the OMAPI wrappers for various server database internal
384 objects. */
386
390
391 for (i = 1; i < argc; i++) {
392 if (!strcmp(argv[i], "-r")) {
393 release_mode = 1;
394 /* no_daemon = 1; */
395#ifdef DHCPv6
396 } else if (!strcmp(argv[i], "-4")) {
397 if (local_family_set && local_family != AF_INET)
398 log_fatal("Client can only do v4 or v6, not "
399 "both.");
400 local_family_set = 1;
401 local_family = AF_INET;
402 } else if (!strcmp(argv[i], "-6")) {
403 if (local_family_set && local_family != AF_INET6)
404 log_fatal("Client can only do v4 or v6, not "
405 "both.");
406 local_family_set = 1;
407 local_family = AF_INET6;
408#ifdef DHCP4o6
409 } else if (!strcmp(argv[i], "-4o6")) {
410 if (++i == argc)
411 usage(use_noarg, argv[i-1]);
412 dhcp4o6_port = validate_port_pair(argv[i]);
413
414 log_debug("DHCPv4 over DHCPv6 over ::1 port %d and %d",
415 ntohs(dhcp4o6_port),
416 ntohs(dhcp4o6_port) + 1);
418#endif /* DHCP4o6 */
419#endif /* DHCPv6 */
420 } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */
421 release_mode = 0;
422 /* no_daemon = 0; */
423 exit_mode = 1;
424 } else if (!strcmp(argv[i], "-p")) {
425 if (++i == argc)
426 usage(use_noarg, argv[i-1]);
427 local_port = validate_port(argv[i]);
428 log_debug("binding to user-specified port %d",
429 ntohs(local_port));
430 } else if (!strcmp(argv[i], "-d")) {
431 /* no_daemon = 1; */
432 quiet = 0;
433 } else if (!strcmp(argv[i], "-pf")) {
434 if (++i == argc)
435 usage(use_noarg, argv[i-1]);
436 path_dhclient_pid = argv[i];
437 no_dhclient_pid = 1;
438 } else if (!strcmp(argv[i], "--no-pid")) {
440 } else if (!strcmp(argv[i], "-cf")) {
441 if (++i == argc)
442 usage(use_noarg, argv[i-1]);
443 path_dhclient_conf = argv[i];
444 no_dhclient_conf = 1;
445 } else if (!strcmp(argv[i], "-df")) {
446 if (++i == argc)
447 usage(use_noarg, argv[i-1]);
448 path_dhclient_duid = argv[i];
449 } else if (!strcmp(argv[i], "-lf")) {
450 if (++i == argc)
451 usage(use_noarg, argv[i-1]);
452 path_dhclient_db = argv[i];
453 no_dhclient_db = 1;
454 } else if (!strcmp(argv[i], "-sf")) {
455 if (++i == argc)
456 usage(use_noarg, argv[i-1]);
457 path_dhclient_script = argv[i];
458 no_dhclient_script = 1;
459 } else if (!strcmp(argv[i], "-1")) {
460 onetry = 1;
461 } else if (!strcmp(argv[i], "-q")) {
462 quiet = 1;
463 } else if (!strcmp(argv[i], "-s")) {
464 if (++i == argc)
465 usage(use_noarg, argv[i-1]);
466 server = argv[i];
467 } else if (!strcmp(argv[i], "-g")) {
468 if (++i == argc)
469 usage(use_noarg, argv[i-1]);
470 mockup_relay = argv[i];
471 } else if (!strcmp(argv[i], "-nw")) {
472 nowait = 1;
473 } else if (!strcmp(argv[i], "-n")) {
474 /* do not start up any interfaces */
476 } else if (!strcmp(argv[i], "-w")) {
477 /* do not exit if there are no broadcast interfaces. */
478 persist = 1;
479 } else if (!strcmp(argv[i], "-e")) {
480 struct string_list *tmp;
481 if (++i == argc)
482 usage(use_noarg, argv[i-1]);
483 tmp = dmalloc(strlen(argv[i]) + sizeof *tmp, MDL);
484 if (!tmp)
485 log_fatal("No memory for %s", argv[i]);
486 strcpy(tmp->string, argv[i]);
487 tmp->next = client_env;
488 client_env = tmp;
490#ifdef DHCPv6
491 } else if (!strcmp(argv[i], "-S")) {
492 if (local_family_set && (local_family == AF_INET)) {
493 usage(use_v6command, argv[i]);
494 }
495 local_family_set = 1;
496 local_family = AF_INET6;
497 wanted_ia_na = 0;
498 stateless = 1;
499 } else if (!strcmp(argv[i], "-N")) {
500 if (local_family_set && (local_family == AF_INET)) {
501 usage(use_v6command, argv[i]);
502 }
503 local_family_set = 1;
504 local_family = AF_INET6;
505 if (wanted_ia_na < 0) {
506 wanted_ia_na = 0;
507 }
508 wanted_ia_na++;
509 } else if (!strcmp(argv[i], "-T")) {
510 if (local_family_set && (local_family == AF_INET)) {
511 usage(use_v6command, argv[i]);
512 }
513 local_family_set = 1;
514 local_family = AF_INET6;
515 if (wanted_ia_na < 0) {
516 wanted_ia_na = 0;
517 }
518 wanted_ia_ta++;
519 } else if (!strcmp(argv[i], "-P")) {
520 if (local_family_set && (local_family == AF_INET)) {
521 usage(use_v6command, argv[i]);
522 }
523 local_family_set = 1;
524 local_family = AF_INET6;
525 if (wanted_ia_na < 0) {
526 wanted_ia_na = 0;
527 }
528 wanted_ia_pd++;
529 } else if (!strcmp(argv[i], "-R")) {
530 if (local_family_set && (local_family == AF_INET)) {
531 usage(use_v6command, argv[i]);
532 }
533 local_family_set = 1;
534 local_family = AF_INET6;
535 require_all_ias = 1;
536 } else if (!strcmp(argv[i], "--dad-wait-time")) {
537 if (++i == argc) {
538 usage(use_noarg, argv[i-1]);
539 }
540 errno = 0;
541 dad_wait_time = (int)strtol(argv[i], &s, 10);
542 if (errno || (*s != '\0') || (dad_wait_time < 0)) {
543 usage("Invalid value for --dad-wait-time: %s",
544 argv[i]);
545 }
546 } else if (!strcmp(argv[i], "--prefix-len-hint")) {
547 if (++i == argc) {
548 usage(use_noarg, argv[i-1]);
549 }
550
551 errno = 0;
552 prefix_len_hint = (int)strtol(argv[i], &s, 10);
553 if (errno || (*s != '\0') || (prefix_len_hint < 0)) {
554 usage("Invalid value for --prefix-len-hint: %s",
555 argv[i]);
556 }
557 } else if (!strcmp(argv[i], "--address-prefix-len")) {
558 if (++i == argc) {
559 usage(use_noarg, argv[i-1]);
560 }
561 errno = 0;
562 address_prefix_len = (int)strtol(argv[i], &s, 10);
563 if (errno || (*s != '\0') ||
564 (address_prefix_len < 0)) {
565 usage("Invalid value for"
566 " --address-prefix-len: %s", argv[i]);
567 }
568#endif /* DHCPv6 */
569 } else if (!strcmp(argv[i], "--decline-wait-time")) {
570 if (++i == argc) {
571 usage(use_noarg, argv[i-1]);
572 }
573
574 errno = 0;
575 decline_wait_time = (int)strtol(argv[i], &s, 10);
576 if (errno || (*s != '\0') ||
577 (decline_wait_time < 0)) {
578 usage("Invalid value for "
579 "--decline-wait-time: %s", argv[i]);
580 }
581 } else if (!strcmp(argv[i], "-D")) {
582 duid_v4 = 1;
583 if (++i == argc)
584 usage(use_noarg, argv[i-1]);
585 if (!strcasecmp(argv[i], "LL")) {
587 } else if (!strcasecmp(argv[i], "LLT")) {
589 } else {
590 usage("Unknown argument to -D: %s", argv[i]);
591 }
592 } else if (!strcmp(argv[i], "-i")) {
593 /* enable DUID support for DHCPv4 clients */
594 duid_v4 = 1;
595 } else if (!strcmp(argv[i], "-I")) {
596 /* enable standard DHCID support for DDNS updates */
597 std_dhcid = 1;
598 } else if (!strcmp(argv[i], "-v")) {
599 quiet = 0;
600 } else if (!strcmp(argv[i], "-C")) {
601 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
602 usage(use_noarg, argv[i-1]);
603 exit(1);
604 }
605
606 if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
607 log_error("-C option dhcp-client-identifier string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
608 exit(1);
609 }
610
611 dhcp_client_identifier_arg = argv[i];
612 } else if (!strcmp(argv[i], "-B")) {
614 } else if (!strcmp(argv[i], "-H")) {
615 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
616 usage(use_noarg, argv[i-1]);
617 exit(1);
618 }
619
620 if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
621 log_error("-H option host-name string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
622 exit(1);
623 }
624
625 if (dhcp_host_name_arg != NULL) {
626 log_error("The -H <host-name> and -F <fqdn> arguments are mutually exclusive");
627 exit(1);
628 }
629
630 dhcp_host_name_arg = argv[i];
631 } else if (!strcmp(argv[i], "-F")) {
632 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
633 usage(use_noarg, argv[i-1]);
634 exit(1);
635 }
636
637 if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
638 log_error("-F option fqdn.fqdn string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
639 exit(1);
640 }
641
642 if (dhcp_fqdn_arg != NULL) {
643 log_error("Only one -F <fqdn> argument can be specified");
644 exit(1);
645 }
646
647 if (dhcp_host_name_arg != NULL) {
648 log_error("The -F <fqdn> and -H <host-name> arguments are mutually exclusive");
649 exit(1);
650 }
651
652 dhcp_fqdn_arg = argv[i];
653 } else if (!strcmp(argv[i], "--timeout")) {
654 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
655 usage(use_noarg, argv[i-1]);
656 exit(1);
657 }
658
659 if ((timeout_arg = atoi(argv[i])) <= 0) {
660 log_error("timeout option must be > 0 - bad value: %s",argv[i]);
661 exit(1);
662 }
663 } else if (!strcmp(argv[i], "-V")) {
664 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
665 usage(use_noarg, argv[i-1]);
666 exit(1);
667 }
668
669 if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
670 log_error("-V option vendor-class-identifier string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
671 exit(1);
672 }
673
674 dhcp_vendor_class_identifier_arg = argv[i];
675 } else if (!strcmp(argv[i], "--request-options")) {
676 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
677 usage(use_noarg, argv[i-1]);
678 exit(1);
679 }
680
681 dhclient_request_options = argv[i];
682
683 } else if (!strcmp(argv[i], "-nc")) {
684#ifdef HAVE_LIBCAP_NG
685 keep_capabilities = 1;
686#endif
687 } else if (argv[i][0] == '-') {
688 usage("Unknown command: %s", argv[i]);
689 } else if (interfaces_requested < 0) {
690 usage("No interfaces command -n and "
691 " requested interface %s", argv[i]);
692 } else {
693 struct interface_info *tmp = NULL;
694
695 status = interface_allocate(&tmp, MDL);
696 if (status != ISC_R_SUCCESS)
697 log_fatal("Can't record interface %s:%s",
698 argv[i], isc_result_totext(status));
699 if (strlen(argv[i]) >= sizeof(tmp->name))
700 log_fatal("%s: interface name too long (is %ld)",
701 argv[i], (long)strlen(argv[i]));
702 strcpy(tmp->name, argv[i]);
703 if (interfaces) {
704 interface_reference(&tmp->next,
705 interfaces, MDL);
706 interface_dereference(&interfaces, MDL);
707 }
708 interface_reference(&interfaces, tmp, MDL);
711 }
712 }
713
714 if (wanted_ia_na < 0) {
715 wanted_ia_na = 1;
716 }
717
718 /* Support only one (requested) interface for Prefix Delegation. */
719 if (wanted_ia_pd && (interfaces_requested != 1)) {
720 usage("PD %s only supports one requested interface", "-P");
721 }
722
723#if defined(DHCPv6) && defined(DHCP4o6)
724 if ((local_family == AF_INET6) && dhcpv4_over_dhcpv6 &&
725 (exit_mode || release_mode))
726 log_error("Can't relay DHCPv4-over-DHCPv6 "
727 "without a persistent DHCPv6 client");
728 if ((local_family == AF_INET) && dhcpv4_over_dhcpv6 &&
730 log_fatal("DHCPv4-over-DHCPv6 requires an explicit "
731 "interface on which to be applied");
732#endif
733
734 if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
736 }
737 if (!no_dhclient_db && (s = getenv("PATH_DHCLIENT_DB"))) {
739 }
740 if (!no_dhclient_pid && (s = getenv("PATH_DHCLIENT_PID"))) {
742 }
743 if (!no_dhclient_script && (s = getenv("PATH_DHCLIENT_SCRIPT"))) {
745 }
746
747#ifdef HAVE_LIBCAP_NG
748 /* Drop capabilities */
749 if (!keep_capabilities) {
750 capng_clear(CAPNG_SELECT_CAPS);
751 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
752 CAP_DAC_OVERRIDE); // Drop this someday
753 capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
754 CAP_NET_ADMIN, CAP_NET_RAW,
755 CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, -1);
756 capng_apply(CAPNG_SELECT_CAPS);
757 }
758#endif
759
760 /* Set up the initial dhcp option universe. */
762
763 /* Set up the initial client option universe. */
765
766 /* Assign v4 or v6 specific running parameters. */
767 if (local_family == AF_INET)
769#ifdef DHCPv6
770 else if (local_family == AF_INET6)
772#endif /* DHCPv6 */
773 else
774 log_fatal("Impossible condition at %s:%d.", MDL);
775
776 /*
777 * convert relative path names to absolute, for files that need
778 * to be reopened after chdir() has been called
779 */
780 if (path_dhclient_db[0] != '/') {
782 }
783
784 if (path_dhclient_script[0] != '/') {
786 }
787
788 /*
789 * See if we should kill off any currently running client
790 * we don't try to kill it off if the user told us not
791 * to write a pid file - we assume they are controlling
792 * the process in some other fashion.
793 */
794 if ((release_mode || exit_mode) && (no_pid_file == ISC_FALSE)) {
795 FILE *pidfd;
796 pid_t oldpid;
797 long temp;
798 int e;
799
800 if ((pidfd = fopen(path_dhclient_pid, "re")) != NULL) {
801 e = fscanf(pidfd, "%ld\n", &temp);
802 oldpid = (pid_t)temp;
803
804 if (e != 0 && e != EOF && oldpid) {
805 if (kill(oldpid, SIGTERM) == 0) {
806 log_info("Killed old client process");
807 (void) unlink(path_dhclient_pid);
808 /*
809 * wait for the old process to
810 * cleanly terminate.
811 * Note kill() with sig=0 could
812 * detect termination but only
813 * the parent can be signaled...
814 */
815 sleep(1);
816 } else if (errno == ESRCH) {
817 log_info("Removed stale PID file");
818 (void) unlink(path_dhclient_pid);
819 }
820 }
821 fclose(pidfd);
822 } else {
823 /* handle release for interfaces requested with Red Hat
824 * /sbin/ifup - pidfile will be /var/run/dhclient-$interface.pid
825 */
826
827 if ((path_dhclient_pid == NULL) || (*path_dhclient_pid == '\0'))
828 path_dhclient_pid = "/var/run/dhclient.pid";
829
830 char *new_path_dhclient_pid;
831 struct interface_info *ip;
832 int pdp_len = strlen(path_dhclient_pid), pfx, dpfx;
833
834 /* find append point: beginning of any trailing '.pid'
835 * or '-$IF.pid' */
836 for (pfx=pdp_len; (pfx >= 0) && (path_dhclient_pid[pfx] != '.') && (path_dhclient_pid[pfx] != '/'); pfx--);
837 if (pfx == -1)
838 pfx = pdp_len;
839
840 if (path_dhclient_pid[pfx] == '/')
841 pfx += 1;
842
843 for (dpfx=pfx; (dpfx >= 0) && (path_dhclient_pid[dpfx] != '-') && (path_dhclient_pid[dpfx] != '/'); dpfx--);
844 if ((dpfx > -1) && (path_dhclient_pid[dpfx] != '/'))
845 pfx = dpfx;
846
847 for (ip = interfaces; ip; ip = ip->next) {
848 if (interfaces_requested && (ip->flags & (INTERFACE_REQUESTED))) {
849 int n_len = strlen(ip->name);
850
851 new_path_dhclient_pid = (char*) malloc(pfx + n_len + 6);
852 strncpy(new_path_dhclient_pid, path_dhclient_pid, pfx);
853 sprintf(new_path_dhclient_pid + pfx, "-%s.pid", ip->name);
854
855 if ((pidfd = fopen(new_path_dhclient_pid, "re")) != NULL) {
856 e = fscanf(pidfd, "%ld\n", &temp);
857 oldpid = (pid_t)temp;
858
859 if (e != 0 && e != EOF) {
860 if (oldpid) {
861 if (kill(oldpid, SIGTERM) == 0)
862 unlink(path_dhclient_pid);
863 }
864 }
865
866 fclose(pidfd);
867 }
868
869 free(new_path_dhclient_pid);
870 }
871 }
872 }
873 } else {
874 FILE *pidfp = NULL;
875 long temp = 0;
876 pid_t dhcpid = 0;
877 int dhc_running = 0;
878 char procfn[256] = "";
879
880 if ((pidfp = fopen(path_dhclient_pid, "re")) != NULL) {
881 if ((fscanf(pidfp, "%ld", &temp)==1) && ((dhcpid=(pid_t)temp) > 0)) {
882 snprintf(procfn,256,"/proc/%u",dhcpid);
883 dhc_running = (access(procfn, F_OK) == 0);
884 }
885
886 fclose(pidfp);
887 }
888
889 if (dhc_running) {
890 log_fatal("dhclient(%u) is already running - exiting. ", dhcpid);
891 return(1);
892 }
893 }
894
896
897 if (!quiet) {
898 log_info("%s %s", message, PACKAGE_VERSION);
899 log_info(copyright);
900 log_info(arr);
901 log_info(url);
902 log_info("%s", "");
903 } else {
904 log_perror = 0;
906 }
907
908 /* If we're given a relay agent address to insert, for testing
909 purposes, figure out what it is. */
910 if (mockup_relay) {
911 if (!inet_aton(mockup_relay, &giaddr)) {
912 struct hostent *he;
913 he = gethostbyname(mockup_relay);
914 if (he) {
915 memcpy(&giaddr, he->h_addr_list[0],
916 sizeof giaddr);
917 } else {
918 log_fatal("%s: no such host", mockup_relay);
919 }
920 }
921 }
922
923 /* Get the current time... */
924 gettimeofday(&cur_tv, NULL);
925
926 sockaddr_broadcast.sin_family = AF_INET;
928 if (server) {
929 if (!inet_aton(server, &sockaddr_broadcast.sin_addr)) {
930 struct hostent *he;
931 he = gethostbyname(server);
932 if (he) {
933 memcpy(&sockaddr_broadcast.sin_addr,
934 he->h_addr_list[0],
935 sizeof sockaddr_broadcast.sin_addr);
936 } else
937 sockaddr_broadcast.sin_addr.s_addr =
938 INADDR_BROADCAST;
939 }
940 } else {
941 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
942 }
943
944 inaddr_any.s_addr = INADDR_ANY;
945
946 /* Discover all the network interfaces. */
948
949 /* Parse the dhclient.conf file. */
951
952 /* Stateless special case. */
953 if (stateless) {
954 if (release_mode || (wanted_ia_na > 0) ||
956 (interfaces_requested != 1)) {
957 usage("Stateless command: %s incompatibile with "
958 "other commands", "-S");
959 }
960#if defined(DHCPv6) && defined(DHCP4o6)
961 run_stateless(exit_mode, dhcp4o6_port);
962#else
963 run_stateless(exit_mode, 0);
964#endif
965 finish(0);
966 }
967
968 /* Parse any extra command line configuration arguments: */
969 if ((dhcp_client_identifier_arg != NULL) && (*dhcp_client_identifier_arg != '\0')) {
970 arg_conf_len = asprintf(&arg_conf, "send dhcp-client-identifier \"%s\";", dhcp_client_identifier_arg);
971
972 if ((arg_conf == 0) || (arg_conf_len <= 0))
973 log_fatal("Unable to send -C option dhcp-client-identifier");
974 }
975
976 if ((dhcp_host_name_arg != NULL) && (*dhcp_host_name_arg != '\0')) {
977 if (arg_conf == 0) {
978 arg_conf_len = asprintf(&arg_conf, "send host-name \"%s\";", dhcp_host_name_arg);
979
980 if ((arg_conf == 0) || (arg_conf_len <= 0))
981 log_fatal("Unable to send -H option host-name");
982 } else {
983 char *last_arg_conf = arg_conf;
984 arg_conf = NULL;
985 arg_conf_len = asprintf(&arg_conf, "%s\nsend host-name \"%s\";", last_arg_conf, dhcp_host_name_arg);
986
987 if ((arg_conf == 0) || (arg_conf_len <= 0))
988 log_fatal("Unable to send -H option host-name");
989
990 free(last_arg_conf);
991 }
992 }
993
994 if ((dhcp_fqdn_arg != NULL) && (*dhcp_fqdn_arg != '\0')) {
995 if (arg_conf == 0) {
996 arg_conf_len = asprintf(&arg_conf, "send fqdn.fqdn \"%s\";", dhcp_fqdn_arg);
997
998 if ((arg_conf == 0) || (arg_conf_len <= 0))
999 log_fatal("Unable to send -F option fqdn.fqdn");
1000 } else {
1001 char *last_arg_conf = arg_conf;
1002 arg_conf = NULL;
1003 arg_conf_len = asprintf(&arg_conf, "%s\nsend fqdn.fqdn \"%s\";", last_arg_conf, dhcp_fqdn_arg);
1004
1005 if ((arg_conf == 0) || (arg_conf_len <= 0))
1006 log_fatal("Unable to send -F option fqdn.fqdn");
1007
1008 free(last_arg_conf);
1009 }
1010 }
1011
1012 if (timeout_arg) {
1013 if (arg_conf == 0) {
1014 arg_conf_len = asprintf(&arg_conf, "timeout %d;", timeout_arg);
1015
1016 if ((arg_conf == 0) || (arg_conf_len <= 0))
1017 log_fatal("Unable to process --timeout timeout argument");
1018 } else {
1019 char *last_arg_conf = arg_conf;
1020 arg_conf = NULL;
1021 arg_conf_len = asprintf(&arg_conf, "%s\ntimeout %d;", last_arg_conf, timeout_arg);
1022
1023 if ((arg_conf == 0) || (arg_conf_len == 0))
1024 log_fatal("Unable to process --timeout timeout argument");
1025
1026 free(last_arg_conf);
1027 }
1028 }
1029
1030 if ((dhcp_vendor_class_identifier_arg != NULL) && (*dhcp_vendor_class_identifier_arg != '\0')) {
1031 if (arg_conf == 0) {
1032 arg_conf_len = asprintf(&arg_conf, "send vendor-class-identifier \"%s\";", dhcp_vendor_class_identifier_arg);
1033
1034 if ((arg_conf == 0) || (arg_conf_len <= 0))
1035 log_fatal("Unable to send -V option vendor-class-identifier");
1036 } else {
1037 char *last_arg_conf = arg_conf;
1038 arg_conf = NULL;
1039 arg_conf_len = asprintf(&arg_conf, "%s\nsend vendor-class-identifier \"%s\";", last_arg_conf, dhcp_vendor_class_identifier_arg);
1040
1041 if ((arg_conf == 0) || (arg_conf_len <= 0))
1042 log_fatal("Unable to send -V option vendor-class-identifier");
1043
1044 free(last_arg_conf);
1045 }
1046 }
1047
1048 if (dhclient_request_options != NULL) {
1049 if (arg_conf == 0) {
1050 arg_conf_len = asprintf(&arg_conf, "request %s;", dhclient_request_options);
1051
1052 if ((arg_conf == 0) || (arg_conf_len <= 0))
1053 log_fatal("Unable to parse --request-options <request options list> argument");
1054 } else {
1055 char *last_arg_conf = arg_conf;
1056 arg_conf = NULL;
1057 arg_conf_len = asprintf(&arg_conf, "%s\nrequest %s;", last_arg_conf, dhclient_request_options);
1058
1059 if ((arg_conf == 0) || (arg_conf_len <= 0))
1060 log_fatal("Unable to parse --request-options <request options list> argument");
1061
1062 free(last_arg_conf);
1063 }
1064 }
1065
1066 if (arg_conf) {
1067 if (arg_conf_len == 0)
1068 if ((arg_conf_len = strlen(arg_conf)) == 0)
1069 /* huh ? cannot happen ! */
1070 log_fatal("Unable to process -C/-H/-F/--timeout/-V/--request-options configuration arguments");
1071
1072 /* parse the extra dhclient.conf configuration arguments
1073 * into top level config: */
1074 struct parse *cfile = (struct parse *)0;
1075 const char *val = NULL;
1076 int token;
1077
1078 status = new_parse(&cfile, -1, arg_conf, arg_conf_len, "extra dhclient -C/-H/-F/--timeout/-V/--request-options configuration arguments", 0);
1079
1080 if ((status != ISC_R_SUCCESS) || (cfile -> warnings_occurred))
1081 log_fatal("Cannot parse -C/-H/-F/--timeout/-V/--request-options configuration arguments !");
1082 /* more detailed parse failures will be logged */
1083
1084 do {
1085 token = peek_token(&val, (unsigned *)0, cfile);
1086 if (token == END_OF_FILE)
1087 break;
1088
1090 } while (1);
1091
1092 if (cfile -> warnings_occurred)
1093 log_fatal("Cannot parse -C/-H/-F/--timeout/-V/--request-options configuration arguments !");
1094 end_parse(&cfile);
1095
1096 if (timeout_arg) {
1097 /* we just set the toplevel timeout, but per-client
1098 * timeouts may still be at defaults.
1099 */
1100 for (ip=interfaces; ip; ip = ip->next) {
1101 if (ip->client->config->timeout == 60)
1102 ip->client->config->timeout = timeout_arg;
1103 }
1104 }
1105
1106 if ((dhclient_request_options != 0) && (top_level_config.requested_options != default_requested_options)) {
1107 for (ip=interfaces; ip; ip = ip->next) {
1108 if (ip->client->config->requested_options == default_requested_options)
1109 ip->client->config->requested_options = top_level_config.requested_options;
1110 }
1111 }
1112
1113 free(arg_conf);
1114 arg_conf = NULL;
1115 arg_conf_len = 0;
1116 }
1117
1118 /* Parse the lease database. */
1120
1121 /* If desired parse the secondary lease database for a DUID */
1122 if ((default_duid.len == 0) && (path_dhclient_duid != NULL)) {
1124 }
1125
1126 /* Rewrite the lease database... */
1128
1129 /* XXX */
1130/* config_counter(&snd_counter, &rcv_counter); */
1131
1132 /*
1133 * If no broadcast interfaces were discovered, call the script
1134 * and tell it so.
1135 */
1136 if (!interfaces) {
1137 /*
1138 * Call dhclient-script with the NBI flag,
1139 * in case somebody cares.
1140 */
1141 script_init(NULL, "NBI", NULL);
1142 script_go(NULL);
1143
1144 /*
1145 * If we haven't been asked to persist, waiting for new
1146 * interfaces, then just exit.
1147 */
1148 if (!persist) {
1149 /* Nothing more to do. */
1150 log_info("No broadcast interfaces found - exiting.");
1151 finish(0);
1152 }
1153 } else if (!release_mode && !exit_mode) {
1154 /* Call the script with the list of interfaces. */
1155 for (ip = interfaces; ip; ip = ip->next) {
1156 /*
1157 * If interfaces were specified, don't configure
1158 * interfaces that weren't specified!
1159 */
1160 if ((interfaces_requested > 0) &&
1161 ((ip->flags & (INTERFACE_REQUESTED |
1164 continue;
1165
1166 if (local_family == AF_INET6) {
1167 script_init(ip->client, "PREINIT6", NULL);
1168 } else {
1169 script_init(ip->client, "PREINIT", NULL);
1170 if (ip->client->alias != NULL)
1171 script_write_params(ip->client,
1172 "alias_",
1173 ip->client->alias);
1174 }
1175 script_go(ip->client);
1176 }
1177 }
1178
1179 /* We create a backup seed before rediscovering interfaces in order to
1180 have a seed built using all of the available interfaces
1181 It's interesting if required interfaces doesn't let us defined
1182 a really unique seed due to a lack of valid HW addr later
1183 (this is the case with DHCP over IB)
1184 We only use the last device as using a sum could broke the
1185 uniqueness of the seed among multiple nodes
1186 */
1187 unsigned backup_seed = 0;
1188 for (ip = interfaces; ip; ip = ip -> next) {
1189 int junk;
1190 if ( ip -> hw_address.hlen <= sizeof seed )
1191 continue;
1192 memcpy (&junk,
1193 &ip -> hw_address.hbuf [ip -> hw_address.hlen -
1194 sizeof seed], sizeof seed);
1195 backup_seed = junk;
1196 }
1197
1198
1199 /* At this point, all the interfaces that the script thinks
1200 are relevant should be running, so now we once again call
1201 discover_interfaces(), and this time ask it to actually set
1202 up the interfaces. */
1206
1207 /* PLEASE PREFER the random device: not all systems use random
1208 * process identifiers so the alternative can be predictable. */
1209 seed = 0;
1210 size_t nrnd = 0;
1211#ifdef ISC_PATH_RANDOMDEV
1212 FILE *frnd = fopen(ISC_PATH_RANDOMDEV, "r");
1213 if (frnd) {
1214 nrnd = fread(&seed, sizeof(seed), 1, frnd);
1215 fclose(frnd);
1216 }
1217#endif
1218 /* Please leave the compiler to emit a warning about a constant
1219 * condition in the if test. */
1220 if (!nrnd) {
1221 /* Make up a seed for the random number generator from current
1222 time plus the sum of the last four bytes of each
1223 interface's hardware address interpreted as an integer.
1224 Not much entropy, but we're booting, so we're not likely to
1225 find anything better. */
1226
1227 int seed_flag = 0;
1228 for (ip = interfaces; ip; ip = ip->next) {
1229 int junk;
1230 if ( ip -> hw_address.hlen <= sizeof seed )
1231 continue;
1232 memcpy(&junk,
1233 &ip->hw_address.hbuf[ip->hw_address.hlen -
1234 sizeof seed], sizeof seed);
1235 seed += junk;
1236 seed_flag = 1;
1237 }
1238 if ( seed_flag == 0 ) {
1239 if ( backup_seed != 0 ) {
1240 seed = backup_seed;
1241 log_info ("xid: rand init seed (0x%x) built using all"
1242 " available interfaces",seed);
1243 }
1244 else {
1245 seed = cur_time^((unsigned) gethostid()) ;
1246 log_info ("xid: warning: no netdev with useable HWADDR found"
1247 " for seed's uniqueness enforcement");
1248 log_info ("xid: rand init seed (0x%x) built using gethostid",
1249 seed);
1250 }
1251 /* we only use seed and no current time as a broadcast reply */
1252 /* will certainly be used by the hwaddrless interface */
1253 }
1254 seed += ((unsigned)(cur_tv.tv_usec * 1000000)) + (unsigned)getpid();
1255 }
1256 srandom(seed);
1257
1258 /* Setup specific Infiniband options */
1259 for (ip = interfaces; ip; ip = ip->next) {
1260 if (ip->client &&
1261 (ip->hw_address.hbuf[0] == HTYPE_INFINIBAND)) {
1262 setup_ib_interface(ip);
1263 }
1264 }
1265
1266 /*
1267 * Establish a default DUID. We always do so for v6 and
1268 * do so if desired for v4 via the -D or -i options
1269 */
1270 if ((local_family == AF_INET6) ||
1271 ((local_family == AF_INET) && (duid_v4 == 1))) {
1272 if (default_duid.len == 0) {
1273 if (default_duid.buffer != NULL)
1275
1277 write_duid(&default_duid);
1278 }
1279 }
1280
1281#if defined(DHCPv6) && defined(DHCP4o6)
1282 if (dhcpv4_over_dhcpv6 && !exit_mode)
1283 dhcp4o6_setup(dhcp4o6_port);
1284#endif
1285
1286 /* Start a configuration state machine for each interface. */
1287#ifdef DHCPv6
1288 if (local_family == AF_INET6) {
1289 for (ip = interfaces ; ip != NULL ; ip = ip->next) {
1290 for (client = ip->client ; client != NULL ;
1291 client = client->next) {
1292 if (release_mode) {
1293 start_release6(client);
1294 continue;
1295 } else if (exit_mode) {
1296 unconfigure6(client, "STOP6");
1297 continue;
1298 }
1299
1300 /* If we have a previous binding, Confirm
1301 * that we can (or can't) still use it.
1302 */
1303 if ((client->active_lease != NULL) &&
1304 !client->active_lease->released)
1305 start_confirm6(client);
1306 else
1307 start_init6(client);
1308 }
1309 }
1310 } else
1311#endif /* DHCPv6 */
1312 {
1313 for (ip = interfaces ; ip ; ip = ip->next) {
1314 ip->flags |= INTERFACE_RUNNING;
1315 for (client = ip->client ; client ;
1316 client = client->next) {
1317 if (exit_mode)
1318 state_stop(client);
1319 if (release_mode)
1320 do_release(client);
1321 else {
1322 client->state = S_INIT;
1323
1324 if (top_level_config.initial_delay>0)
1325 {
1326 tv.tv_sec = 0;
1327 if (top_level_config.
1328 initial_delay>1)
1329 tv.tv_sec = cur_time
1330 + random()
1332 initial_delay-1);
1333 tv.tv_usec = random()
1334 % 1000000;
1335 /*
1336 * this gives better
1337 * distribution than just
1338 *whole seconds
1339 */
1341 client, 0, 0);
1342 } else {
1343 state_reboot(client);
1344 }
1345 }
1346 }
1347 }
1348 }
1349
1350 if (exit_mode)
1351 finish(0);
1352 if (release_mode) {
1353#ifndef DHCPv6
1354 finish(0);
1355#else
1356 if ((local_family == AF_INET6) || dhcpv4_over_dhcpv6) {
1357 if (onetry)
1358 finish(0);
1359 } else
1360 finish(0);
1361#endif /* DHCPv6 */
1362 }
1363
1364 /* Start up a listener for the object management API protocol. */
1365 if (top_level_config.omapi_port != -1) {
1366 listener = NULL;
1367 result = omapi_generic_new(&listener, MDL);
1368 if (result != ISC_R_SUCCESS)
1369 log_fatal("Can't allocate new generic object: %s\n",
1370 isc_result_totext(result));
1371 result = omapi_protocol_listen(listener,
1372 (unsigned)
1373 top_level_config.omapi_port,
1374 1);
1375 if (result != ISC_R_SUCCESS)
1376 log_fatal("Can't start OMAPI protocol: %s",
1377 isc_result_totext (result));
1378 }
1379
1380 /* Set up the bootp packet handler... */
1382#ifdef DHCPv6
1384#endif /* DHCPv6 */
1385
1386#if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
1387 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1388 dmalloc_cutoff_generation = dmalloc_generation;
1389 dmalloc_longterm = dmalloc_outstanding;
1390 dmalloc_outstanding = 0;
1391#endif
1392
1393#if defined(ENABLE_GENTLE_SHUTDOWN)
1394 /* no signal handlers until we deal with the side effects */
1395 /* install signal handlers */
1396 signal(SIGINT, dhcp_signal_handler); /* control-c */
1397 signal(SIGTERM, dhcp_signal_handler); /* kill */
1398#endif
1399
1400 /* If we're not supposed to wait before getting the address,
1401 don't. */
1402 if (nowait)
1403 detach();
1404
1405 /* If we're not going to daemonize, write the pid file
1406 now. */
1407 if (no_daemon || nowait)
1409
1410 /* Start dispatching packets and timeouts... */
1411 dispatch();
1412
1413 /* In fact dispatch() never returns. */
1414 return 0;
1415}
1416
1417/*
1418 * \brief Run the DHCPv6 stateless client (dhclient -6 -S)
1419 *
1420 * \param exist_mode set to 1 when dhclient was called with -x
1421 * \param port DHCPv4-over-DHCPv6 client inter-process communication
1422 * UDP port pair (port,port+1 with port in network byte order)
1423 */
1424
1425void run_stateless(int exit_mode, u_int16_t port)
1426{
1427#ifdef DHCPv6
1428 struct client_state *client;
1429 omapi_object_t *listener;
1430 isc_result_t result;
1431
1432#ifndef DHCP4o6
1433 IGNORE_UNUSED(port);
1434#endif
1435
1436 struct interface_info *ip;
1437
1438 if (!interfaces)
1439 usage("No interfaces available for stateless command: %s", "-S");
1440
1441#ifdef DHCP4o6
1442 if (dhcpv4_over_dhcpv6) {
1443 /* Mark we want to request IRT too! */
1445 }
1446#endif
1447
1448 for (ip = interfaces; ip; ip = ip->next) {
1449 if ((interfaces_requested > 0) &&
1450 ((ip->flags & (INTERFACE_REQUESTED |
1453 continue;
1454 script_init(ip->client, "PREINIT6", NULL);
1455 script_go(ip->client);
1456 }
1457
1458 /* Discover the network interface. */
1460
1461 /* Parse the lease database. */
1463
1464 /* If desired parse the secondary lease database for a DUID */
1465 if ((default_duid.len == 0) && (path_dhclient_duid != NULL)) {
1467 }
1468
1469 /* Establish a default DUID. */
1470 if (default_duid.len == 0) {
1471 if (default_duid.buffer != NULL)
1473
1477 write_duid(&default_duid);
1478 }
1479
1480#ifdef DHCP4o6
1481 if (dhcpv4_over_dhcpv6 && !exit_mode)
1482 dhcp4o6_setup(port);
1483#endif
1484
1485 /* Start a configuration state machine. */
1486 for (client = interfaces->client ;
1487 client != NULL ;
1488 client = client->next) {
1489 if (exit_mode) {
1490 unconfigure6(client, "STOP6");
1491 continue;
1492 }
1494 }
1495 if (exit_mode)
1496 return;
1497
1498 /* Start up a listener for the object management API protocol. */
1499 if (top_level_config.omapi_port != -1) {
1500 listener = NULL;
1501 result = omapi_generic_new(&listener, MDL);
1502 if (result != ISC_R_SUCCESS)
1503 log_fatal("Can't allocate new generic object: %s\n",
1504 isc_result_totext(result));
1505 result = omapi_protocol_listen(listener,
1506 (unsigned)
1507 top_level_config.omapi_port,
1508 1);
1509 if (result != ISC_R_SUCCESS)
1510 log_fatal("Can't start OMAPI protocol: %s",
1511 isc_result_totext(result));
1512 }
1513
1514 /* Set up the packet handler... */
1516
1517#if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
1518 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1519 dmalloc_cutoff_generation = dmalloc_generation;
1520 dmalloc_longterm = dmalloc_outstanding;
1521 dmalloc_outstanding = 0;
1522#endif
1523
1524 /* If we're not supposed to wait before getting the address,
1525 don't. */
1526 if (nowait)
1527 detach();
1528
1529 /* If we're not going to daemonize, write the pid file
1530 now. */
1531 if (no_daemon || nowait)
1533
1534 /* Start dispatching packets and timeouts... */
1535 dispatch();
1536
1537#endif /* DHCPv6 */
1538 return;
1539}
1540#endif /* !UNIT_TEST */
1541
1542isc_result_t find_class (struct class **c,
1543 const char *s, const char *file, int line)
1544{
1545 return 0;
1546}
1547
1549 struct packet *packet;
1550 struct lease *lease;
1551 struct collection *collection;
1552{
1553 return 0;
1554}
1555
1556void classify (packet, class)
1557 struct packet *packet;
1558 struct class *class;
1559{
1560}
1561
1563 struct lease *lease;
1564{
1565}
1566
1567int find_subnet (struct subnet **sp,
1568 struct iaddr addr, const char *file, int line)
1569{
1570 return 0;
1571}
1572
1573static void setup_ib_interface(struct interface_info *ip)
1574{
1575 struct group *g;
1576
1577 /* Set the broadcast flag */
1578 ip->client->config->bootp_broadcast_always = 1;
1579
1580 /*
1581 * Find out if a dhcp-client-identifier option was specified either
1582 * in the config file or on the command line
1583 */
1584 for (g = ip->client->config->on_transmission; g != NULL; g = g->next) {
1585 if ((g->statements != NULL) &&
1586 (strcmp(g->statements->data.option->option->name,
1587 "dhcp-client-identifier") == 0)) {
1588 return;
1589 }
1590 }
1591
1592 /* No client ID specified */
1593 log_fatal("dhcp-client-identifier must be specified for InfiniBand");
1594}
1595
1596/* Individual States:
1597 *
1598 * Each routine is called from the dhclient_state_machine() in one of
1599 * these conditions:
1600 * -> entering INIT state
1601 * -> recvpacket_flag == 0: timeout in this state
1602 * -> otherwise: received a packet in this state
1603 *
1604 * Return conditions as handled by dhclient_state_machine():
1605 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
1606 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
1607 * Returns 0: finish the nap which was interrupted for no good reason.
1608 *
1609 * Several per-interface variables are used to keep track of the process:
1610 * active_lease: the lease that is being used on the interface
1611 * (null pointer if not configured yet).
1612 * offered_leases: leases corresponding to DHCPOFFER messages that have
1613 * been sent to us by DHCP servers.
1614 * acked_leases: leases corresponding to DHCPACK messages that have been
1615 * sent to us by DHCP servers.
1616 * sendpacket: DHCP packet we're trying to send.
1617 * destination: IP address to send sendpacket to
1618 * In addition, there are several relevant per-lease variables.
1619 * T1_expiry, T2_expiry, lease_expiry: lease milestones
1620 * In the active lease, these control the process of renewing the lease;
1621 * In leases on the acked_leases list, this simply determines when we
1622 * can no longer legitimately use the lease.
1623 */
1624
1626 void *cpp;
1627{
1628 struct client_state *client = cpp;
1629
1630#if defined(DHCPv6) && defined(DHCP4o6)
1631 if (dhcpv4_over_dhcpv6 && (dhcp4o6_state <= 0)) {
1632 if (dhcp4o6_state < 0)
1633 dhcp4o6_poll(NULL);
1634 client->pending = P_REBOOT;
1635 return;
1636 }
1637#endif
1638
1639 client->pending= P_NONE;
1640
1641 /* If we don't remember an active lease, go straight to INIT. */
1642 if (!client -> active ||
1643 client -> active -> is_bootp ||
1644 client -> active -> expiry <= cur_time) {
1645 state_init (client);
1646 return;
1647 }
1648
1649 /* We are in the rebooting state. */
1650 client -> state = S_REBOOTING;
1651
1652 /*
1653 * make_request doesn't initialize xid because it normally comes
1654 * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
1655 * so pick an xid now.
1656 */
1657 client -> xid = random ();
1658
1659 /*
1660 * Make a DHCPREQUEST packet, and set
1661 * appropriate per-interface flags.
1662 */
1663 make_request (client, client -> active);
1664 client -> destination = iaddr_broadcast;
1665 client -> first_sending = cur_time;
1666 client -> interval = client -> config -> initial_interval;
1667
1668 /* Zap the medium list... */
1669 client -> medium = NULL;
1670
1671 /* Send out the first DHCPREQUEST packet. */
1672 send_request (client);
1673}
1674
1675/* Called when a lease has completely expired and we've been unable to
1676 renew it. */
1677
1678void state_init (cpp)
1679 void *cpp;
1680{
1681 struct client_state *client = cpp;
1682
1684
1685 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
1686 flags. */
1687 make_discover (client, client -> active);
1688 client -> xid = client -> packet.xid;
1689 client -> destination = iaddr_broadcast;
1690 client -> state = S_SELECTING;
1691 client -> first_sending = cur_time;
1692 client -> interval = client -> config -> initial_interval;
1693
1694 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
1695 to go out. */
1696 send_discover (client);
1697}
1698
1699/* check_v6only is called by dhcpoffer and dhcpack. It checks if a
1700 * requested v6-only-preferred option is present and returned the
1701 * V6ONLY_WAIT delay to suspend DHCPv4. */
1702
1703uint32_t check_v6only(packet, client)
1704 struct packet *packet;
1705 struct client_state *client;
1706{
1707 int i;
1708 struct option **req;
1709 isc_boolean_t found = ISC_FALSE;
1710 struct option_cache *oc;
1711 struct data_string data;
1712 uint32_t v6only_wait = 0;
1713
1714 /* Check if the v6-only-preferred was requested. */
1715 req = client->config->requested_options;
1716
1717 if (req == NULL)
1718 return 0;
1719
1720 for (i = 0 ; req[i] != NULL ; i++) {
1721 if ((req[i]->universe == &dhcp_universe) &&
1722 (req[i]->code == DHO_V6_ONLY_PREFERRED)) {
1723 found = ISC_TRUE;
1724 break;
1725 }
1726 }
1727
1728 if (found == ISC_FALSE)
1729 return 0;
1730
1731 /* Get the V6ONLY_WAIT timer. */
1734 if (!oc)
1735 return 0;
1736
1737 memset(&data, 0, sizeof(data));
1738
1739 if (evaluate_option_cache(&data, packet, (struct lease *)0, client,
1740 packet->options, (struct option_state *)0,
1741 &global_scope, oc, MDL)) {
1742 if (data.len == 4) {
1743 v6only_wait = getULong(data.data);
1744 if (v6only_wait < MIN_V6ONLY_WAIT)
1745 v6only_wait = MIN_V6ONLY_WAIT;
1746 }
1748 }
1749
1750 return (v6only_wait);
1751}
1752
1753/* finish_v6only is called when the V6ONLY_WAIT timer expired. */
1754
1756 void *cpp;
1757{
1758 struct client_state *client = cpp;
1759
1761 client->state = S_INIT;
1762 state_init(cpp);
1763}
1764
1765/*
1766 * start_v6only is called when a requested v6-only-preferred option was
1767 * returned by the server. */
1768
1769void start_v6only(client, v6only_wait)
1770 struct client_state *client;
1771 uint32_t v6only_wait;
1772{
1773 struct timeval tv;
1774
1775 /* Enter V6ONLY state. */
1776
1777 client->state = S_V6ONLY;
1778
1779 /* Run the client script. */
1780 script_init(client, "V6ONLY", NULL);
1781 if (client->active) {
1782 script_write_params(client, "old_", client->active);
1784 client->active = NULL;
1785 }
1786 script_write_requested(client);
1787 client_envadd(client, "", "v6-only-preferred", "%lu",
1788 (long unsigned)v6only_wait);
1789 script_go(client);
1790
1791 /* Trigger finish_v6only after V6ONLY_WAIT seconds. */
1792 tv.tv_sec = cur_tv.tv_sec + v6only_wait;
1793 tv.tv_usec = cur_tv.tv_usec;
1794
1795 add_timeout(&tv, finish_v6only, client, 0, 0);
1796}
1797
1798/*
1799 * state_selecting is called when one or more DHCPOFFER packets have been
1800 * received and a configurable period of time has passed.
1801 */
1802
1804 void *cpp;
1805{
1806 struct client_state *client = cpp;
1807 struct client_lease *lp, *next, *picked;
1808
1809
1810 ASSERT_STATE(state, S_SELECTING);
1811
1812 /*
1813 * Cancel state_selecting and send_discover timeouts, since either
1814 * one could have got us here.
1815 */
1817 cancel_timeout (send_discover, client);
1818
1819 /*
1820 * We have received one or more DHCPOFFER packets. Currently,
1821 * the only criterion by which we judge leases is whether or
1822 * not we get a response when we arp for them.
1823 */
1824 picked = NULL;
1825 for (lp = client -> offered_leases; lp; lp = next) {
1826 next = lp -> next;
1827
1828 /*
1829 * Check to see if we got an ARPREPLY for the address
1830 * in this particular lease.
1831 */
1832 if (!picked) {
1833 picked = lp;
1834 picked -> next = NULL;
1835 } else {
1837 }
1838 }
1839 client -> offered_leases = NULL;
1840
1841 /*
1842 * If we just tossed all the leases we were offered, go back
1843 * to square one.
1844 */
1845 if (!picked) {
1846 client -> state = S_INIT;
1847 state_init (client);
1848 return;
1849 }
1850
1851 /* If it was a BOOTREPLY, we can just take the address right now. */
1852 if (picked -> is_bootp) {
1853 client -> new = picked;
1854
1855 /* Make up some lease expiry times
1856 XXX these should be configurable. */
1857 client -> new -> expiry = cur_time + 12000;
1858 client -> new -> renewal += cur_time + 8000;
1859 client -> new -> rebind += cur_time + 10000;
1860
1861 client -> state = S_REQUESTING;
1862
1863 /* Bind to the address we received. */
1864 bind_lease (client);
1865 return;
1866 }
1867
1868 /* Go to the REQUESTING state. */
1869 client -> destination = iaddr_broadcast;
1870 client -> state = S_REQUESTING;
1871 client -> first_sending = cur_time;
1872 client -> interval = client -> config -> initial_interval;
1873
1874 /* Make a DHCPREQUEST packet from the lease we picked. */
1875 make_request (client, picked);
1876 client -> xid = client -> packet.xid;
1877
1878 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
1879 destroy_client_lease (picked);
1880
1881 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
1882 send_request (client);
1883}
1884
1885/* state_requesting is called when we receive a DHCPACK message after
1886 having sent out one or more DHCPREQUEST packets. */
1887
1889 struct packet *packet;
1890{
1891 struct interface_info *ip = packet -> interface;
1892 struct client_state *client;
1893 uint32_t v6only_wait;
1894 struct client_lease *lease;
1895 struct option_cache *oc;
1896 struct data_string ds;
1897
1898 /* If we're not receptive to an offer right now, or if the offer
1899 has an unrecognizable transaction id, then just drop it. */
1900 for (client = ip -> client; client; client = client -> next) {
1901 if (client -> xid == packet -> raw -> xid)
1902 break;
1903 }
1904 if (!client ||
1905 (packet -> interface -> hw_address.hlen - 1 !=
1906 packet -> raw -> hlen) ||
1907 (memcmp (&packet -> interface -> hw_address.hbuf [1],
1908 packet -> raw -> chaddr, packet -> raw -> hlen))) {
1909#if defined (DEBUG)
1910 log_debug ("DHCPACK in wrong transaction.");
1911#endif
1912 return;
1913 }
1914
1915 if (client -> state != S_REBOOTING &&
1916 client -> state != S_REQUESTING &&
1917 client -> state != S_RENEWING &&
1918 client -> state != S_REBINDING) {
1919#if defined (DEBUG)
1920 log_debug ("DHCPACK in wrong state.");
1921#endif
1922 return;
1923 }
1924
1925 log_info ("DHCPACK of %s from %s (xid=0x%x)",
1926 inet_ntoa(packet->raw->yiaddr),
1927 piaddr (packet -> client_addr),
1928 ntohl(client -> xid));
1929
1930 /* Check v6only first. */
1931 v6only_wait = check_v6only(packet, client);
1932 if (v6only_wait > 0) {
1933 log_info("v6 only preferred for %lu seconds.",
1934 (long unsigned)v6only_wait);
1936 start_v6only(client, v6only_wait);
1937 return;
1938 }
1939
1940 lease = packet_to_lease (packet, client);
1941 if (!lease) {
1942 log_info ("packet_to_lease failed.");
1943 return;
1944 }
1945
1946 client -> new = lease;
1947
1948 /* Stop resending DHCPREQUEST. */
1949 cancel_timeout (send_request, client);
1950
1951 /* Figure out the lease time. */
1952 oc = lookup_option (&dhcp_universe, client -> new -> options,
1954 memset (&ds, 0, sizeof ds);
1955 if (oc &&
1956 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
1957 packet -> options, client -> new -> options,
1958 &global_scope, oc, MDL)) {
1959 if (ds.len > 3)
1960 client -> new -> expiry = getULong (ds.data);
1961 else
1962 client -> new -> expiry = 0;
1963 data_string_forget (&ds, MDL);
1964 } else
1965 client -> new -> expiry = 0;
1966
1967 if (client->new->expiry == 0) {
1968 struct timeval tv;
1969
1970 log_error ("no expiry time on offered lease.");
1971
1972 /* Quench this (broken) server. Return to INIT to reselect. */
1973 add_reject(packet);
1974
1975 /* 1/2 second delay to restart at INIT. */
1976 tv.tv_sec = cur_tv.tv_sec;
1977 tv.tv_usec = cur_tv.tv_usec + 500000;
1978
1979 if (tv.tv_usec >= 1000000) {
1980 tv.tv_sec++;
1981 tv.tv_usec -= 1000000;
1982 }
1983
1984 add_timeout(&tv, state_init, client, 0, 0);
1985 return;
1986 }
1987
1988 /*
1989 * A number that looks negative here is really just very large,
1990 * because the lease expiry offset is unsigned.
1991 */
1992 if (client->new->expiry < 0)
1993 client->new->expiry = TIME_MAX;
1994
1995 /* Take the server-provided renewal time if there is one. */
1996 oc = lookup_option (&dhcp_universe, client -> new -> options,
1998 if (oc &&
1999 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
2000 packet -> options, client -> new -> options,
2001 &global_scope, oc, MDL)) {
2002 if (ds.len > 3)
2003 client -> new -> renewal = getULong (ds.data);
2004 else
2005 client -> new -> renewal = 0;
2006 data_string_forget (&ds, MDL);
2007 } else
2008 client -> new -> renewal = 0;
2009
2010 /* If it wasn't specified by the server, calculate it. */
2011 if (!client -> new -> renewal)
2012 client -> new -> renewal = client -> new -> expiry / 2 + 1;
2013
2014 if (client -> new -> renewal <= 0)
2015 client -> new -> renewal = TIME_MAX;
2016
2017 /* Now introduce some randomness to the renewal time: */
2018 if (client->new->renewal <= ((TIME_MAX / 3) - 3))
2019 client->new->renewal = (((client->new->renewal * 3) + 3) / 4) +
2020 (((random() % client->new->renewal) + 3) / 4);
2021
2022 /* Same deal with the rebind time. */
2023 oc = lookup_option (&dhcp_universe, client -> new -> options,
2025 if (oc &&
2026 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
2027 packet -> options, client -> new -> options,
2028 &global_scope, oc, MDL)) {
2029 if (ds.len > 3)
2030 client -> new -> rebind = getULong (ds.data);
2031 else
2032 client -> new -> rebind = 0;
2033 data_string_forget (&ds, MDL);
2034 } else
2035 client -> new -> rebind = 0;
2036
2037 if (client -> new -> rebind <= 0) {
2038 if (client -> new -> expiry <= TIME_MAX / 7)
2039 client -> new -> rebind =
2040 client -> new -> expiry * 7 / 8;
2041 else
2042 client -> new -> rebind =
2043 client -> new -> expiry / 8 * 7;
2044 }
2045
2046 /* Make sure our randomness didn't run the renewal time past the
2047 rebind time. */
2048 if (client -> new -> renewal > client -> new -> rebind) {
2049 if (client -> new -> rebind <= TIME_MAX / 3)
2050 client -> new -> renewal =
2051 client -> new -> rebind * 3 / 4;
2052 else
2053 client -> new -> renewal =
2054 client -> new -> rebind / 4 * 3;
2055 }
2056
2057 client -> new -> expiry += cur_time;
2058 /* Lease lengths can never be negative. */
2059 if (client -> new -> expiry < cur_time)
2060 client -> new -> expiry = TIME_MAX;
2061 client -> new -> renewal += cur_time;
2062 if (client -> new -> renewal < cur_time)
2063 client -> new -> renewal = TIME_MAX;
2064 client -> new -> rebind += cur_time;
2065 if (client -> new -> rebind < cur_time)
2066 client -> new -> rebind = TIME_MAX;
2067
2068 bind_lease (client);
2069}
2070
2071void bind_lease (client)
2072 struct client_state *client;
2073{
2074 struct timeval tv;
2075
2076 /* Remember the medium. */
2077 client->new->medium = client->medium;
2078
2079 /* Run the client script with the new parameters. */
2080 script_init(client, (client->state == S_REQUESTING ? "BOUND" :
2081 (client->state == S_RENEWING ? "RENEW" :
2082 (client->state == S_REBOOTING ? "REBOOT" :
2083 "REBIND"))),
2084 client->new->medium);
2085 if (client->active && client->state != S_REBOOTING)
2086 script_write_params(client, "old_", client->active);
2087 script_write_params(client, "new_", client->new);
2088 script_write_requested(client);
2089 if (client->alias)
2090 script_write_params(client, "alias_", client->alias);
2091
2092 /* If the BOUND/RENEW code detects another machine using the
2093 offered address, then per our man page it should exit with
2094 a non-zero status, to which we send a DHCPDECLINE and toss
2095 the lease. A return value of less than zero indicates
2096 the script crashed (e.g. segfault) which script_go will log
2097 but we will ignore here. */
2098 if (script_go(client) > 0) {
2099 make_decline(client, client->new);
2100 send_decline(client);
2101 destroy_client_lease(client->new);
2102 client->new = NULL;
2103 if (onetry) {
2104 if (!quiet) {
2105 log_info("Unable to obtain a lease on first "
2106 "try (declined). Exiting.");
2107 }
2108
2109#if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
2110 /* Let's call a script and we're done */
2111 script_init(client, "FAIL", (struct string_list *)0);
2112 script_go(client);
2113#endif
2114 finish(2);
2115 } else {
2116 struct timeval tv;
2117 tv.tv_sec = cur_tv.tv_sec + decline_wait_time;
2118 tv.tv_usec = cur_tv.tv_usec;
2119 add_timeout(&tv, state_init, client, 0, 0);
2120 return;
2121 }
2122 }
2123
2124 /* Write out the new lease if it has been long enough. */
2125 if (!client->last_write ||
2126 (cur_time - client->last_write) >= MIN_LEASE_WRITE)
2127 write_client_lease(client, client->new, 0, 1);
2128
2129 /* Replace the old active lease with the new one. */
2130 if (client->active) {
2131 if (client->active->is_static) {
2132 // We need to preserve the fallback lease in case
2133 // we lose DHCP service again.
2134 add_to_tail(&client->leases, client->active);
2135 } else {
2137 }
2138 }
2139
2140 client->active = client->new;
2141 client->new = NULL;
2142
2143 /* Set up a timeout to start the renewal process. */
2144 tv.tv_sec = client->active->renewal;
2145 tv.tv_usec = ((client->active->renewal - cur_tv.tv_sec) > 1) ?
2146 random() % 1000000 : cur_tv.tv_usec;
2147 add_timeout(&tv, state_bound, client, 0, 0);
2148
2149 log_info("bound to %s -- renewal in %ld seconds.",
2150 piaddr(client->active->address),
2151 (long)(client->active->renewal - cur_time));
2152 client->state = S_BOUND;
2154 detach();
2155#if defined (NSUPDATE)
2156 if (client->config->do_forward_update)
2157 dhclient_schedule_updates(client, &client->active->address, 1);
2158#endif /* defined NSUPDATE */
2159
2160}
2161
2162/* state_bound is called when we've successfully bound to a particular
2163 lease, but the renewal time on that lease has expired. We are
2164 expected to unicast a DHCPREQUEST to the server that gave us our
2165 original lease. */
2166
2167void state_bound (cpp)
2168 void *cpp;
2169{
2170 struct client_state *client = cpp;
2171 struct option_cache *oc;
2172 struct data_string ds;
2173
2174 ASSERT_STATE(state, S_BOUND);
2175
2176 /* T1 has expired. */
2177 make_request (client, client -> active);
2178 client -> xid = client -> packet.xid;
2179
2180 memset (&ds, 0, sizeof ds);
2181 oc = lookup_option (&dhcp_universe, client -> active -> options,
2183 if (oc &&
2184 evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
2185 client, (struct option_state *)0,
2186 client -> active -> options,
2187 &global_scope, oc, MDL)) {
2188 if (ds.len > 3) {
2189 memcpy (client -> destination.iabuf, ds.data, 4);
2190 client -> destination.len = 4;
2191 } else
2192 client -> destination = iaddr_broadcast;
2193
2194 data_string_forget (&ds, MDL);
2195 } else
2196 client -> destination = iaddr_broadcast;
2197
2198 client -> first_sending = cur_time;
2199 client -> interval = client -> config -> initial_interval;
2200 client -> state = S_RENEWING;
2201
2202 /* Send the first packet immediately. */
2203 send_request (client);
2204}
2205
2206/* state_stop is called when we've been told to shut down. We unconfigure
2207 the interfaces, and then stop operating until told otherwise. */
2208
2209void state_stop (cpp)
2210 void *cpp;
2211{
2212 struct client_state *client = cpp;
2213
2214 client->pending = P_NONE;
2215
2216 /* Cancel all timeouts. */
2220 cancel_timeout(state_bound, client);
2222
2223 /* If we have an address, unconfigure it. */
2224 if (client->active) {
2225 script_init(client, "STOP", client->active->medium);
2226 script_write_params(client, "old_", client->active);
2227 script_write_requested(client);
2228 if (client->alias)
2229 script_write_params(client, "alias_", client->alias);
2230 script_go(client);
2231 }
2232}
2233
2235{
2236 return 0;
2237}
2238
2240 struct lease *lease;
2241{
2242 return 0;
2243}
2244
2246 struct host_decl *host;
2247{
2248 return 0;
2249}
2250
2251void db_startup (testp)
2252 int testp;
2253{
2254}
2255
2257 struct packet *packet;
2258{
2259 struct iaddrmatchlist *ap;
2260 char addrbuf[4*16];
2261 char maskbuf[4*16];
2262
2263 if (packet -> raw -> op != BOOTREPLY)
2264 return;
2265
2266 /* If there's a reject list, make sure this packet's sender isn't
2267 on it. */
2268 for (ap = packet -> interface -> client -> config -> reject_list;
2269 ap; ap = ap -> next) {
2270 if (addr_match(&packet->client_addr, &ap->match)) {
2271
2272 /* piaddr() returns its result in a static
2273 buffer sized 4*16 (see common/inet.c). */
2274
2275 strcpy(addrbuf, piaddr(ap->match.addr));
2276 strcpy(maskbuf, piaddr(ap->match.mask));
2277
2278 log_info("BOOTREPLY from %s rejected by rule %s "
2279 "mask %s.", piaddr(packet->client_addr),
2280 addrbuf, maskbuf);
2281 return;
2282 }
2283 }
2284
2285 dhcpoffer (packet);
2286
2287}
2288
2290 struct packet *packet;
2291{
2292 struct iaddrmatchlist *ap;
2293 void (*handler) (struct packet *);
2294 const char *type;
2295 char addrbuf[4*16];
2296 char maskbuf[4*16];
2297
2298 switch (packet -> packet_type) {
2299 case DHCPOFFER:
2300 handler = dhcpoffer;
2301 type = "DHCPOFFER";
2302 break;
2303
2304 case DHCPNAK:
2305 handler = dhcpnak;
2306 type = "DHCPNACK";
2307 break;
2308
2309 case DHCPACK:
2310 handler = dhcpack;
2311 type = "DHCPACK";
2312 break;
2313
2314 default:
2315 return;
2316 }
2317
2318 /* If there's a reject list, make sure this packet's sender isn't
2319 on it. */
2320 for (ap = packet -> interface -> client -> config -> reject_list;
2321 ap; ap = ap -> next) {
2322 if (addr_match(&packet->client_addr, &ap->match)) {
2323
2324 /* piaddr() returns its result in a static
2325 buffer sized 4*16 (see common/inet.c). */
2326
2327 strcpy(addrbuf, piaddr(ap->match.addr));
2328 strcpy(maskbuf, piaddr(ap->match.mask));
2329
2330 log_info("%s from %s rejected by rule %s mask %s.",
2331 type, piaddr(packet->client_addr),
2332 addrbuf, maskbuf);
2333 return;
2334 }
2335 }
2336 (*handler) (packet);
2337}
2338
2339#ifdef DHCPv6
2340void
2341dhcpv6(struct packet *packet) {
2342 struct iaddrmatchlist *ap;
2343 struct client_state *client;
2344 char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
2345
2346 /* Silently drop bogus messages. */
2348 return;
2349
2350 /* Discard, with log, packets from quenched sources. */
2351 for (ap = packet->interface->client->config->reject_list ;
2352 ap ; ap = ap->next) {
2353 if (addr_match(&packet->client_addr, &ap->match)) {
2354 strcpy(addrbuf, piaddr(packet->client_addr));
2355 log_info("%s from %s rejected by rule %s",
2357 addrbuf,
2358 piaddrmask(&ap->match.addr, &ap->match.mask));
2359 return;
2360 }
2361 }
2362
2363 /* Screen out nonsensical messages. */
2364 switch(packet->dhcpv6_msg_type) {
2365#ifdef DHCP4o6
2367 if (dhcpv4_over_dhcpv6) {
2368 log_info("RCV: %s message on %s from %s.",
2372 forw_dhcpv4_response(packet);
2373 }
2374 return;
2375#endif
2376 case DHCPV6_ADVERTISE:
2377 case DHCPV6_RECONFIGURE:
2378 if (stateless)
2379 return;
2380 /* Falls through */
2381 case DHCPV6_REPLY:
2382 log_info("RCV: %s message on %s from %s.",
2385 break;
2386
2387 default:
2388 return;
2389 }
2390
2391 /* Find a client state that matches the incoming XID. */
2392 for (client = packet->interface->client ; client ;
2393 client = client->next) {
2394 if (memcmp(&client->dhcpv6_transaction_id,
2395 packet->dhcpv6_transaction_id, 3) == 0) {
2396 client->v6_handler(packet, client);
2397 return;
2398 }
2399 }
2400
2401 /* XXX: temporary log for debugging */
2402 log_info("Packet received, but nothing done with it.");
2403}
2404
2405#ifdef DHCP4o6
2406/*
2407 * \brief Forward a DHCPv4-response to the DHCPv4 client.
2408 * (DHCPv6 client function)
2409 *
2410 * The DHCPv6 client receives a DHCPv4-response which is forwarded
2411 * to the DHCPv4 client.
2412 * Format: address:16 + DHCPv4 message content
2413 * (we have no state to keep the address so it is transported in
2414 * DHCPv6 <-> DHCPv6 inter-process messages)
2415 *
2416 * \param packet the DHCPv4-response packet
2417 */
2418static void forw_dhcpv4_response(struct packet *packet)
2419{
2420 struct option_cache *oc;
2421 struct data_string enc_opt_data;
2422 struct data_string ds;
2423 int cc;
2424
2425 /*
2426 * Discard if relay is not ready.
2427 */
2428 if (dhcp4o6_state == -1) {
2429 log_info("forw_dhcpv4_response: not ready.");
2430 return;
2431 }
2432
2433 if (packet->client_addr.len != 16) {
2434 log_error("forw_dhcpv4_response: bad address");
2435 return;
2436 }
2437
2438 /*
2439 * Get our encapsulated DHCPv4 message.
2440 */
2442 if (oc == NULL) {
2443 log_info("DHCPv4-response from %s missing "
2444 "DHCPv4 Message option.",
2446 return;
2447 }
2448
2449 memset(&enc_opt_data, 0, sizeof(enc_opt_data));
2450 if (!evaluate_option_cache(&enc_opt_data, NULL, NULL, NULL,
2451 NULL, NULL, &global_scope, oc, MDL)) {
2452 log_error("forw_dhcpv4_response: error evaluating "
2453 "DHCPv4 message.");
2454 data_string_forget(&enc_opt_data, MDL);
2455 return;
2456 }
2457
2458 if (enc_opt_data.len < DHCP_FIXED_NON_UDP) {
2459 log_error("forw_dhcpv4_response: "
2460 "no memory for encapsulated packet.");
2461 data_string_forget(&enc_opt_data, MDL);
2462 return;
2463 }
2464
2465 /*
2466 * Append address.
2467 */
2468 memset(&ds, 0, sizeof(ds));
2469 if (!buffer_allocate(&ds.buffer, enc_opt_data.len + 16, MDL)) {
2470 log_error("forw_dhcpv4_response: no memory buffer.");
2471 data_string_forget(&enc_opt_data, MDL);
2472 return;
2473 }
2474 ds.data = ds.buffer->data;
2475 ds.len = enc_opt_data.len + 16;
2476 memcpy(ds.buffer->data, enc_opt_data.data, enc_opt_data.len);
2477 memcpy(ds.buffer->data + enc_opt_data.len,
2478 packet->client_addr.iabuf, 16);
2479 data_string_forget(&enc_opt_data, MDL);
2480
2481 /*
2482 * Forward them.
2483 */
2484 cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
2485 if (cc < 0)
2486 log_error("forw_dhcpv4_response: send(): %m");
2487
2488 data_string_forget(&ds, MDL);
2489}
2490
2491/*
2492 * \brief Receive a DHCPv4-response from the DHCPv6 client.
2493 * (DHCPv4 client function)
2494 *
2495 * The DHCPv4 client receives a DHCPv4-response forwarded
2496 * by the DHCPv6 client (using \ref forw_dhcpv4_response())
2497 *
2498 * \param raw the DHCPv4-response raw packet
2499 */
2500static void recv_dhcpv4_response(struct data_string *raw)
2501{
2502 struct packet *packet;
2503 struct iaddr from;
2504
2505 if (interfaces == NULL) {
2506 log_error("recv_dhcpv4_response: no interfaces.");
2507 return;
2508 }
2509
2510 from.len = 16;
2511 memcpy(from.iabuf, raw->data + (raw->len - 16), 16);
2512
2513 /*
2514 * Build a packet structure.
2515 */
2516 packet = NULL;
2517 if (!packet_allocate(&packet, MDL)) {
2518 log_error("recv_dhcpv4_response: no memory for packet.");
2519 return;
2520 }
2521
2522 packet->raw = (struct dhcp_packet *) raw->data;
2523 packet->packet_length = raw->len - 16;
2525 packet->client_addr = from;
2526 interface_reference(&packet->interface, interfaces, MDL);
2527
2528 /* Allocate packet->options now so it is non-null for all packets */
2530 log_error("recv_dhcpv4_response: no memory for options.");
2532 return;
2533 }
2534
2535 /* If there's an option buffer, try to parse it. */
2537 struct option_cache *op;
2538 if (!parse_options(packet)) {
2539 if (packet->options)
2541 (&packet->options, MDL);
2543 return;
2544 }
2545
2546 if (packet->options_valid &&
2548 packet->options,
2550 struct data_string dp;
2551 memset(&dp, 0, sizeof dp);
2552 evaluate_option_cache(&dp, packet, NULL, NULL,
2553 packet->options, NULL,
2554 NULL, op, MDL);
2555 if (dp.len > 0)
2556 packet->packet_type = dp.data[0];
2557 else
2558 packet->packet_type = 0;
2559 data_string_forget(&dp, MDL);
2560 }
2561 }
2562
2563 if (validate_packet(packet) != 0) {
2564 if (packet->packet_type)
2565 dhcp(packet);
2566 else
2567 bootp(packet);
2568 }
2569
2570 /* If the caller kept the packet, they'll have upped the refcnt. */
2572}
2573#endif /* DHCP4o6 */
2574#endif /* DHCPv6 */
2575
2577 struct packet *packet;
2578{
2579 struct interface_info *ip = packet -> interface;
2580 struct client_state *client;
2581 uint32_t v6only_wait;
2582 struct client_lease *lease, *lp;
2583 struct option **req;
2584 int i;
2585 int stop_selecting;
2586 const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
2587 char obuf [1024];
2588 struct timeval tv;
2589
2590#ifdef DEBUG_PACKET
2592#endif
2593
2594 /* Find a client state that matches the xid... */
2595 for (client = ip -> client; client; client = client -> next)
2596 if (client -> xid == packet -> raw -> xid)
2597 break;
2598
2599 /* If we're not receptive to an offer right now, or if the offer
2600 has an unrecognizable transaction id, then just drop it. */
2601 if (!client ||
2602 client -> state != S_SELECTING ||
2603 (packet -> interface -> hw_address.hlen - 1 !=
2604 packet -> raw -> hlen) ||
2605 (memcmp (&packet -> interface -> hw_address.hbuf [1],
2606 packet -> raw -> chaddr, packet -> raw -> hlen))) {
2607#if defined (DEBUG)
2608 log_debug ("%s in wrong transaction.", name);
2609#endif
2610 return;
2611 }
2612
2613 sprintf (obuf, "%s of %s from %s", name,
2614 inet_ntoa(packet->raw->yiaddr),
2616
2617 /* Check v6only first. */
2618 v6only_wait = check_v6only(packet, client);
2619 if (v6only_wait > 0) {
2620 log_info("%s: v6 only preferred for %lu.", obuf,
2621 (long unsigned)v6only_wait);
2623 start_v6only(client, v6only_wait);
2624 return;
2625 }
2626
2627 /* If this lease doesn't supply the minimum required DHCPv4 parameters,
2628 * ignore it.
2629 */
2630 req = client->config->required_options;
2631 if (req != NULL) {
2632 for (i = 0 ; req[i] != NULL ; i++) {
2633 if ((req[i]->universe == &dhcp_universe) &&
2635 req[i]->code)) {
2636 struct option *option = NULL;
2637 unsigned code = req[i]->code;
2638
2639 option_code_hash_lookup(&option,
2640 dhcp_universe.code_hash,
2641 &code, 0, MDL);
2642
2643 if (option)
2644 log_info("%s: no %s option.", obuf,
2645 option->name);
2646 else
2647 log_info("%s: no unknown-%u option.",
2648 obuf, code);
2649
2651
2652 return;
2653 }
2654 }
2655 }
2656
2657 /* If we've already seen this lease, don't record it again. */
2658 for (lease = client -> offered_leases; lease; lease = lease -> next) {
2659 if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
2660 !memcmp (lease -> address.iabuf,
2661 &packet -> raw -> yiaddr, lease -> address.len)) {
2662 log_debug ("%s: already seen.", obuf);
2663 return;
2664 }
2665 }
2666
2667 lease = packet_to_lease (packet, client);
2668 if (!lease) {
2669 log_info ("%s: packet_to_lease failed.", obuf);
2670 return;
2671 }
2672
2673 /* log it now, so it emits before the request goes out */
2674 log_info("%s", obuf);
2675
2676 /* If this lease was acquired through a BOOTREPLY, record that
2677 fact. */
2678 if (!packet -> options_valid || !packet -> packet_type)
2679 lease -> is_bootp = 1;
2680
2681 /* Record the medium under which this lease was offered. */
2682 lease -> medium = client -> medium;
2683
2684 /* Figure out when we're supposed to stop selecting. */
2685 stop_selecting = (client -> first_sending +
2686 client -> config -> select_interval);
2687
2688 /* If this is the lease we asked for, put it at the head of the
2689 list, and don't mess with the arp request timeout. */
2690 if (lease -> address.len == client -> requested_address.len &&
2691 !memcmp (lease -> address.iabuf,
2692 client -> requested_address.iabuf,
2693 client -> requested_address.len)) {
2694 lease -> next = client -> offered_leases;
2695 client -> offered_leases = lease;
2696 } else {
2697 /* Put the lease at the end of the list. */
2698 lease -> next = (struct client_lease *)0;
2699 if (!client -> offered_leases)
2700 client -> offered_leases = lease;
2701 else {
2702 for (lp = client -> offered_leases; lp -> next;
2703 lp = lp -> next)
2704 ;
2705 lp -> next = lease;
2706 }
2707 }
2708
2709 /* If the selecting interval has expired, go immediately to
2710 state_selecting(). Otherwise, time out into
2711 state_selecting at the select interval. */
2712 if (stop_selecting <= cur_tv.tv_sec)
2713 state_selecting (client);
2714 else {
2715 tv.tv_sec = stop_selecting;
2716 tv.tv_usec = cur_tv.tv_usec;
2717 add_timeout(&tv, state_selecting, client, 0, 0);
2719 }
2720}
2721
2722/* Allocate a client_lease structure and initialize it from the parameters
2723 in the specified packet. */
2724
2726 struct packet *packet;
2727 struct client_state *client;
2728{
2729 struct client_lease *lease;
2730 unsigned i;
2731 struct option_cache *oc;
2732 struct option *option = NULL;
2733 struct data_string data;
2734
2735 lease = (struct client_lease *)new_client_lease (MDL);
2736
2737 if (!lease) {
2738 log_error("packet_to_lease: no memory to record lease.\n");
2739 return NULL;
2740 }
2741
2742 memset(lease, 0, sizeof(*lease));
2743
2744 /* Copy the lease options. */
2746
2747 lease->address.len = sizeof(packet->raw->yiaddr);
2748 memcpy(lease->address.iabuf, &packet->raw->yiaddr,
2749 lease->address.len);
2750
2751 lease->next_srv_addr.len = sizeof(packet->raw->siaddr);
2752 memcpy(lease->next_srv_addr.iabuf, &packet->raw->siaddr,
2753 lease->next_srv_addr.len);
2754
2755 memset(&data, 0, sizeof(data));
2756
2757 if (client -> config -> vendor_space_name) {
2759
2760 /* See if there was a vendor encapsulation option. */
2762 if (oc &&
2763 client -> config -> vendor_space_name &&
2765 (struct lease *)0, client,
2766 packet -> options, lease -> options,
2767 &global_scope, oc, MDL)) {
2768 if (data.len) {
2769 if (!option_code_hash_lookup(&option,
2770 dhcp_universe.code_hash,
2771 &i, 0, MDL))
2772 log_fatal("Unable to find VENDOR "
2773 "option (%s:%d).", MDL);
2775 (packet -> options, option,
2776 data.data, data.len, &dhcp_universe,
2777 client -> config -> vendor_space_name
2778 );
2779
2781 }
2782 data_string_forget (&data, MDL);
2783 }
2784 } else
2785 i = 0;
2786
2787 /* Figure out the overload flag. */
2790 if (oc &&
2791 evaluate_option_cache (&data, packet, (struct lease *)0, client,
2792 packet -> options, lease -> options,
2793 &global_scope, oc, MDL)) {
2794 if (data.len > 0)
2795 i = data.data [0];
2796 else
2797 i = 0;
2798 data_string_forget (&data, MDL);
2799 } else
2800 i = 0;
2801
2802 /* If the server name was filled out, copy it. */
2803 if (!(i & 2) && packet -> raw -> sname [0]) {
2804 unsigned len;
2805 /* Don't count on the NUL terminator. */
2806 for (len = 0; len < DHCP_SNAME_LEN; len++)
2807 if (!packet -> raw -> sname [len])
2808 break;
2809 lease -> server_name = dmalloc (len + 1, MDL);
2810 if (!lease -> server_name) {
2811 log_error ("dhcpoffer: no memory for server name.\n");
2813 return (struct client_lease *)0;
2814 } else {
2815 memcpy (lease -> server_name,
2816 packet -> raw -> sname, len);
2817 lease -> server_name [len] = 0;
2818 }
2819 }
2820
2821 /* Ditto for the filename. */
2822 if (!(i & 1) && packet -> raw -> file [0]) {
2823 unsigned len;
2824 /* Don't count on the NUL terminator. */
2825 for (len = 0; len < DHCP_FILE_LEN; len++)
2826 if (!packet -> raw -> file [len])
2827 break;
2828 lease -> filename = dmalloc (len + 1, MDL);
2829 if (!lease -> filename) {
2830 log_error ("dhcpoffer: no memory for filename.\n");
2832 return (struct client_lease *)0;
2833 } else {
2834 memcpy (lease -> filename,
2835 packet -> raw -> file, len);
2836 lease -> filename [len] = 0;
2837 }
2838 }
2839
2840 execute_statements_in_scope(NULL, (struct packet *)packet, NULL,
2841 client, lease->options, lease->options,
2842 &global_scope, client->config->on_receipt,
2843 NULL, NULL);
2844
2845 return lease;
2846}
2847
2849 struct packet *packet;
2850{
2851 struct interface_info *ip = packet -> interface;
2852 struct client_state *client;
2853
2854 /* Find a client state that matches the xid... */
2855 for (client = ip -> client; client; client = client -> next)
2856 if (client -> xid == packet -> raw -> xid)
2857 break;
2858
2859 /* If we're not receptive to an offer right now, or if the offer
2860 has an unrecognizable transaction id, then just drop it. */
2861 if (!client ||
2862 (packet -> interface -> hw_address.hlen - 1 !=
2863 packet -> raw -> hlen) ||
2864 (memcmp (&packet -> interface -> hw_address.hbuf [1],
2865 packet -> raw -> chaddr, packet -> raw -> hlen))) {
2866#if defined (DEBUG)
2867 log_debug ("DHCPNAK in wrong transaction.");
2868#endif
2869 return;
2870 }
2871
2872 if (client -> state != S_REBOOTING &&
2873 client -> state != S_REQUESTING &&
2874 client -> state != S_RENEWING &&
2875 client -> state != S_REBINDING) {
2876#if defined (DEBUG)
2877 log_debug ("DHCPNAK in wrong state.");
2878#endif
2879 return;
2880 }
2881
2882 log_info ("DHCPNAK from %s (xid=0x%x)", piaddr (packet -> client_addr), ntohl(client -> xid));
2883
2884 if (!client -> active) {
2885#if defined (DEBUG)
2886 log_info ("DHCPNAK with no active lease.\n");
2887#endif
2888 return;
2889 }
2890
2891 /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
2892 * to indicate that we want all old bindings to be removed. (It
2893 * is possible that we may get a NAK while in the RENEW state,
2894 * so we might have bindings active at that time)
2895 */
2896 script_init(client, "EXPIRE", NULL);
2897 script_write_params(client, "old_", client->active);
2898 script_write_requested(client);
2899 if (client->alias)
2900 script_write_params(client, "alias_", client->alias);
2901 script_go(client);
2902
2903 destroy_client_lease (client -> active);
2904 client -> active = (struct client_lease *)0;
2905
2906 /* Stop sending DHCPREQUEST packets... */
2907 cancel_timeout (send_request, client);
2908
2909 /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
2910 * down (this expunges any routes and arp cache). This makes the
2911 * interface unusable by state_init(), which we call next. So, we
2912 * need to 'PREINIT' the interface to bring it back up.
2913 */
2914 script_init(client, "PREINIT", NULL);
2915 if (client->alias)
2916 script_write_params(client, "alias_", client->alias);
2917 script_go(client);
2918
2919 client -> state = S_INIT;
2920 state_init (client);
2921}
2922
2923/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
2924 one after the right interval has expired. If we don't get an offer by
2925 the time we reach the panic interval, call the panic function. */
2926
2928 void *cpp;
2929{
2930 struct client_state *client = cpp;
2931
2932 int result;
2933 int interval;
2934 int increase = 1;
2935 struct timeval tv;
2936
2937 /* Figure out how long it's been since we started transmitting. */
2938 interval = cur_time - client -> first_sending;
2939
2940 /* If we're past the panic timeout, call the script and tell it
2941 we haven't found anything for this interface yet. */
2942 if (interval > client -> config -> timeout) {
2943 state_panic (client);
2944 return;
2945 }
2946
2947 /* If we're selecting media, try the whole list before doing
2948 the exponential backoff, but if we've already received an
2949 offer, stop looping, because we obviously have it right. */
2950 if (!client -> offered_leases &&
2951 client -> config -> media) {
2952 int fail = 0;
2953 again:
2954 if (client -> medium) {
2955 client -> medium = client -> medium -> next;
2956 increase = 0;
2957 }
2958 if (!client -> medium) {
2959 if (fail)
2960 log_fatal ("No valid media types for %s!",
2961 client -> interface -> name);
2962 client -> medium =
2963 client -> config -> media;
2964 increase = 1;
2965 }
2966
2967 log_info ("Trying medium \"%s\" %d",
2968 client -> medium -> string, increase);
2969 script_init(client, "MEDIUM", client -> medium);
2970 if (script_go(client)) {
2971 fail = 1;
2972 goto again;
2973 }
2974 }
2975
2976 /* If we're supposed to increase the interval, do so. If it's
2977 currently zero (i.e., we haven't sent any packets yet), set
2978 it to initial_interval; otherwise, add to it a random number
2979 between zero and two times itself. On average, this means
2980 that it will double with every transmission. */
2981 if (increase) {
2982 if (!client->interval)
2983 client->interval = client->config->initial_interval;
2984 else
2985 client->interval += random() % (2 * client->interval);
2986
2987 /* Don't backoff past cutoff. */
2988 if (client->interval > client->config->backoff_cutoff)
2989 client->interval = (client->config->backoff_cutoff / 2)
2990 + (random() % client->config->backoff_cutoff);
2991 } else if (!client->interval)
2992 client->interval = client->config->initial_interval;
2993
2994 /* If the backoff would take us to the panic timeout, just use that
2995 as the interval. */
2996 if (cur_time + client -> interval >
2997 client -> first_sending + client -> config -> timeout)
2998 client -> interval =
2999 (client -> first_sending +
3000 client -> config -> timeout) - cur_time + 1;
3001
3002 /* Record the number of seconds since we started sending. */
3003 if (interval < 65536)
3004 client -> packet.secs = htons (interval);
3005 else
3006 client -> packet.secs = htons (65535);
3007 client -> secs = client -> packet.secs;
3008
3009#if defined(DHCPv6) && defined(DHCP4o6)
3010 if (dhcpv4_over_dhcpv6) {
3011 log_info ("DHCPDISCOVER interval %ld",
3012 (long)(client -> interval));
3013 } else
3014#endif
3015 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld (xid=0x%x)",
3016 client -> name ? client -> name : client -> interface -> name,
3017 inet_ntoa (sockaddr_broadcast.sin_addr),
3018 ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval), ntohl(client -> xid));
3019
3020 /* Send out a packet. */
3021#if defined(DHCPv6) && defined(DHCP4o6)
3022 if (dhcpv4_over_dhcpv6) {
3023 result = send_dhcpv4_query(client, 1);
3024 } else
3025#endif
3026 result = send_packet(client->interface, NULL, &client->packet,
3027 client->packet_length, inaddr_any,
3028 &sockaddr_broadcast, NULL);
3029 if (result < 0) {
3030#if defined(DHCPv6) && defined(DHCP4o6)
3031 if (dhcpv4_over_dhcpv6) {
3032 log_error("%s:%d: Failed to send %d byte long packet.",
3033 MDL, client->packet_length);
3034 } else
3035#endif
3036 log_error("%s:%d: Failed to send %d byte long packet over %s "
3037 "interface.", MDL, client->packet_length,
3038 client->interface->name);
3039 }
3040
3041 /*
3042 * If we used 0 microseconds here, and there were other clients on the
3043 * same network with a synchronized local clock (ntp), and a similar
3044 * zero-microsecond-scheduler behavior, then we could be participating
3045 * in a sub-second DOS ttck.
3046 */
3047 tv.tv_sec = cur_tv.tv_sec + client->interval;
3048 tv.tv_usec = client->interval > 1 ? random() % 1000000 : cur_tv.tv_usec;
3049 add_timeout(&tv, send_discover, client, 0, 0);
3050}
3051
3052
3053/*
3054 * \brief Remove leases from a list of leases which duplicate a given lease
3055 *
3056 * Searches through a linked-list of leases, remove the first one matches the
3057 * given lease's address and value of is_static. The latter test is done
3058 * so we only remove leases that are from the same source (i.e server/lease file
3059 * vs config file). This ensures we do not discard "fallback" config file leases
3060 * that happen to match non-config file leases.
3061 *
3062 * \param lease_list list of leases to clean
3063 * \param lease lease for which duplicates should be removed
3064 */
3065void discard_duplicate (struct client_lease** lease_list, struct client_lease* lease) {
3066 struct client_lease *cur, *prev, *next;
3067
3068 if (!lease_list || !lease) {
3069 return;
3070 }
3071
3072 prev = (struct client_lease *)0;
3073 for (cur = *lease_list; cur; cur = next) {
3074 next = cur->next;
3075 if ((cur->is_static == lease->is_static) &&
3076 (cur->address.len == lease->address.len &&
3077 !memcmp (cur->address.iabuf, lease->address.iabuf,
3078 lease->address.len))) {
3079 if (prev)
3080 prev->next = next;
3081 else
3082 *lease_list = next;
3083
3085 break;
3086 } else {
3087 prev = cur;
3088 }
3089 }
3090}
3091
3092/*
3093 * \brief Add a given lease to the end of list of leases
3094 *
3095 * Searches through a linked-list of leases, removing any that match the
3096 * given lease's address and value of is_static. The latter test is done
3097 * so we only remove leases that are from the same source (i.e server/lease file
3098 * vs config file). This ensures we do not discard "fallback" config file leases
3099 * that happen to match non-config file leases.
3100 *
3101 * \param lease_list list of leases to clean
3102 * \param lease lease for which duplicates should be removed
3103 */
3104void add_to_tail(struct client_lease** lease_list,
3105 struct client_lease* lease)
3106{
3107 if (!lease_list || !lease) {
3108 return;
3109 }
3110
3111 /* If there is already a lease for this address and
3112 * is_static value, toss discard it. This ensures
3113 * we only keep one dynamic and/or one static lease
3114 * for a given address. */
3115 discard_duplicate(lease_list, lease);
3116
3117 /* Find the tail */
3118 struct client_lease* tail;
3119 for (tail = *lease_list; tail && tail->next; tail = tail->next){};
3120
3121 /* Ensure the tail points nowhere. */
3122 lease->next = NULL;
3123
3124 /* Add to the tail. */
3125 if (!tail) {
3126 *lease_list = lease;
3127 } else {
3128 tail->next = lease;
3129 }
3130}
3131
3132#if 0
3133void dbg_print_lease(char *text, struct client_lease* lease) {
3134 if (!lease) {
3135 log_debug("%s, lease is null", text);
3136 } else {
3137 log_debug ("%s: %p addr:%s expires:%ld :is_static? %d",
3138 text, lease, piaddr (lease->address),
3139 (lease->expiry - cur_time),
3140 lease->is_static);
3141 }
3142}
3143#endif
3144
3145/* state_panic gets called if we haven't received any offers in a preset
3146 amount of time. When this happens, we try to use existing leases that
3147 haven't yet expired, and failing that, we call the client script and
3148 hope it can do something. */
3149
3150void state_panic (cpp)
3151 void *cpp;
3152{
3153 struct client_state *client = cpp;
3154 struct client_lease *loop;
3155 struct client_lease *lp;
3156 struct timeval tv;
3157
3158 loop = lp = client -> active;
3159
3160 log_info ("No DHCPOFFERS received.");
3161
3162 /* We may not have an active lease, but we may have some
3163 predefined leases that we can try. */
3164 if (!client -> active && client -> leases)
3165 goto activate_next;
3166
3167 /* Run through the list of leases and see if one can be used. */
3168 while (client -> active) {
3169 if (client -> active -> expiry > cur_time) {
3170 log_info ("Trying %s lease %s",
3171 (client -> active -> is_static
3172 ? "fallback" : "recorded"),
3173 piaddr (client -> active -> address));
3174 /* Run the client script with the existing
3175 parameters. */
3176 script_init(client, "TIMEOUT",
3177 client -> active -> medium);
3178 script_write_params(client, "new_", client -> active);
3179 script_write_requested(client);
3180 if (client -> alias)
3181 script_write_params(client, "alias_",
3182 client -> alias);
3183
3184 /* If the old lease is still good and doesn't
3185 yet need renewal, go into BOUND state and
3186 timeout at the renewal time. */
3187 if (!script_go(client)) {
3188 if (cur_time < client -> active -> renewal) {
3189 client -> state = S_BOUND;
3190 log_info ("bound: renewal in %ld %s.",
3191 (long)(client -> active -> renewal -
3192 cur_time), "seconds");
3193 tv.tv_sec = client->active->renewal;
3194 tv.tv_usec = ((client->active->renewal -
3195 cur_time) > 1) ?
3196 random() % 1000000 :
3197 cur_tv.tv_usec;
3198 add_timeout(&tv, state_bound, client, 0, 0);
3199 } else {
3200 client -> state = S_BOUND;
3201 log_info ("bound: immediate renewal.");
3202 state_bound (client);
3203 }
3205 detach ();
3206 return;
3207 }
3208 }
3209
3210 /* If there are no other leases, give up. */
3211 if (!client -> leases) {
3212 client -> leases = client -> active;
3213 client -> active = (struct client_lease *)0;
3214 break;
3215 }
3216
3217 activate_next:
3218 /* Otherwise, put the active lease at the end of the
3219 lease list, and try another lease.. */
3220 add_to_tail(&client->leases, client->active);
3221
3222 client -> active = client -> leases;
3223 client -> leases = client -> leases -> next;
3224
3225 /* If we already tried this lease, we've exhausted the
3226 set of leases, so we might as well give up for
3227 now. */
3228 if (client -> active == loop)
3229 break;
3230 else if (!loop)
3231 loop = client -> active;
3232 }
3233
3234 /* No leases were available, or what was available didn't work, so
3235 tell the shell script that we failed to allocate an address,
3236 and try again later. */
3237 if (onetry) {
3238 if (!quiet) {
3239 log_info ("Unable to obtain a lease on first try.%s",
3240 " Exiting.");
3241 }
3242
3243#if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
3244 /* Let's call a script and we're done */
3245 script_init(client, "FAIL", (struct string_list *)0);
3246 script_go(client);
3247#endif
3248 finish(2);
3249 }
3250
3251 log_info ("No working leases in persistent database - sleeping.");
3252 script_init(client, "FAIL", (struct string_list *)0);
3253 if (client -> alias)
3254 script_write_params(client, "alias_", client -> alias);
3255 script_go(client);
3256 client -> state = S_INIT;
3257 tv.tv_sec = cur_tv.tv_sec + ((client->config->retry_interval + 1) / 2 +
3258 (random() % client->config->retry_interval));
3259 tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
3260 random() % 1000000 : cur_tv.tv_usec;
3261 add_timeout(&tv, state_init, client, 0, 0);
3262 detach ();
3263}
3264
3266 void *cpp;
3267{
3268 struct client_state *client = cpp;
3269
3270 int result;
3271 int interval;
3272 struct sockaddr_in destination;
3273 struct in_addr from;
3274 struct timeval tv;
3275 char rip_buf[128];
3276 const char* rip_str = "";
3277
3278 /* Figure out how long it's been since we started transmitting. */
3279 interval = cur_time - client -> first_sending;
3280
3281 /* If we're in the INIT-REBOOT or REQUESTING state and we're
3282 past the reboot timeout, go to INIT and see if we can
3283 DISCOVER an address... */
3284 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
3285 means either that we're on a network with no DHCP server,
3286 or that our server is down. In the latter case, assuming
3287 that there is a backup DHCP server, DHCPDISCOVER will get
3288 us a new address, but we could also have successfully
3289 reused our old address. In the former case, we're hosed
3290 anyway. This is not a win-prone situation. */
3291 if ((client -> state == S_REBOOTING ||
3292 client -> state == S_REQUESTING) &&
3293 interval > client -> config -> reboot_timeout) {
3294 cancel:
3295 client -> state = S_INIT;
3296 cancel_timeout (send_request, client);
3297 state_init (client);
3298 return;
3299 }
3300
3301 /* If we're in the reboot state, make sure the media is set up
3302 correctly. */
3303 if (client -> state == S_REBOOTING &&
3304 !client -> medium &&
3305 client -> active -> medium ) {
3306 script_init(client, "MEDIUM", client -> active -> medium);
3307
3308 /* If the medium we chose won't fly, go to INIT state. */
3309 if (script_go(client))
3310 goto cancel;
3311
3312 /* Record the medium. */
3313 client -> medium = client -> active -> medium;
3314 }
3315
3316 /* If the lease has expired, relinquish the address and go back
3317 to the INIT state. */
3318 if (client -> state != S_REQUESTING &&
3319 cur_time > client -> active -> expiry) {
3320 /* Run the client script with the new parameters. */
3321 script_init(client, "EXPIRE", (struct string_list *)0);
3322 script_write_params(client, "old_", client -> active);
3323 script_write_requested(client);
3324 if (client -> alias)
3325 script_write_params(client, "alias_",
3326 client -> alias);
3327 script_go(client);
3328
3329 /* Now do a preinit on the interface so that we can
3330 discover a new address. */
3331 script_init(client, "PREINIT", (struct string_list *)0);
3332 if (client -> alias)
3333 script_write_params(client, "alias_",
3334 client -> alias);
3335 script_go(client);
3336
3337 client -> state = S_INIT;
3338 state_init (client);
3339 return;
3340 }
3341
3342 /* Do the exponential backoff... */
3343 if (!client -> interval)
3344 client -> interval = client -> config -> initial_interval;
3345 else {
3346 client -> interval += ((random () >> 2) %
3347 (2 * client -> interval));
3348 }
3349
3350 /* Don't backoff past cutoff. */
3351 if (client -> interval >
3352 client -> config -> backoff_cutoff)
3353 client -> interval =
3354 ((client -> config -> backoff_cutoff / 2)
3355 + ((random () >> 2) %
3356 client -> config -> backoff_cutoff));
3357
3358 /* If the backoff would take us to the expiry time, just set the
3359 timeout to the expiry time. */
3360 if (client -> state != S_REQUESTING &&
3361 cur_time + client -> interval > client -> active -> expiry)
3362 client -> interval =
3363 client -> active -> expiry - cur_time + 1;
3364
3365 /* If the lease T2 time has elapsed, or if we're not yet bound,
3366 broadcast the DHCPREQUEST rather than unicasting. */
3367 if (client -> state == S_REQUESTING ||
3368 client -> state == S_REBOOTING ||
3369 cur_time > client -> active -> rebind)
3370 destination.sin_addr = sockaddr_broadcast.sin_addr;
3371 else
3372 memcpy (&destination.sin_addr.s_addr,
3373 client -> destination.iabuf,
3374 sizeof destination.sin_addr.s_addr);
3375 destination.sin_port = remote_port;
3376 destination.sin_family = AF_INET;
3377#ifdef HAVE_SA_LEN
3378 destination.sin_len = sizeof destination;
3379#endif
3380
3381 if (client -> state == S_RENEWING ||
3382 client -> state == S_REBINDING)
3383 memcpy (&from, client -> active -> address.iabuf,
3384 sizeof from);
3385 else
3386 from.s_addr = INADDR_ANY;
3387
3388 /* Record the number of seconds since we started sending. */
3389 if (client -> state == S_REQUESTING)
3390 client -> packet.secs = client -> secs;
3391 else {
3392 if (interval < 65536)
3393 client -> packet.secs = htons (interval);
3394 else
3395 client -> packet.secs = htons (65535);
3396 }
3397
3398#if defined(DHCPv6) && defined(DHCP4o6)
3399 if (dhcpv4_over_dhcpv6) {
3400 log_info ("DHCPREQUEST");
3401 } else
3402#endif
3403 memset(rip_buf, 0x0, sizeof(rip_buf));
3404 if (client->state == S_BOUND || client->state == S_RENEWING ||
3405 client->state == S_REBINDING) {
3406 rip_str = inet_ntoa(client->packet.ciaddr);
3407 } else {
3408 rip_str = piaddr(client->requested_address);
3409 }
3410
3411 strncpy(rip_buf, rip_str, sizeof(rip_buf)-1);
3412 log_info ("DHCPREQUEST for %s on %s to %s port %d (xid=0x%x)",
3413 rip_buf,
3414 client->name ? client->name : client->interface->name,
3415 inet_ntoa(destination.sin_addr),
3416 ntohs (destination.sin_port),
3417 ntohl(client -> xid));
3418
3419#if defined(DHCPv6) && defined(DHCP4o6)
3420 if (dhcpv4_over_dhcpv6) {
3421 int broadcast = 0;
3422 if (destination.sin_addr.s_addr == INADDR_BROADCAST)
3423 broadcast = 1;
3424 result = send_dhcpv4_query(client, broadcast);
3425 if (result < 0) {
3426 log_error("%s:%d: Failed to send %d byte long packet.",
3427 MDL, client->packet_length);
3428 }
3429 } else
3430#endif
3431 if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
3433#if defined(SO_BINDTODEVICE)
3434 if (setsockopt(fallback_interface -> wfdesc, SOL_SOCKET,
3435 SO_BINDTODEVICE, client->interface->name,
3436 strlen(client->interface->name)) < 0) {
3437 log_error("%s:%d: Failed to bind fallback interface"
3438 " to %s: %m", MDL, client->interface->name);
3439 }
3440#endif
3441 result = send_packet(fallback_interface, NULL, &client->packet,
3442 client->packet_length, from, &destination,
3443 NULL);
3444 if (result < 0) {
3445 log_error("%s:%d: Failed to send %d byte long packet "
3446 "over %s interface.", MDL,
3447 client->packet_length,
3448 fallback_interface->name);
3449 }
3450#if defined(SO_BINDTODEVICE)
3451 if (setsockopt(fallback_interface -> wfdesc, SOL_SOCKET,
3452 SO_BINDTODEVICE, NULL, 0) < 0) {
3453 log_fatal("%s:%d: Failed to unbind fallback interface:"
3454 " %m", MDL);
3455 }
3456#endif
3457 }
3458 else {
3459 /* Send out a packet. */
3460 result = send_packet(client->interface, NULL, &client->packet,
3461 client->packet_length, from, &destination,
3462 NULL);
3463 if (result < 0) {
3464 log_error("%s:%d: Failed to send %d byte long packet"
3465 " over %s interface.", MDL,
3466 client->packet_length,
3467 client->interface->name);
3468 }
3469 }
3470
3471 tv.tv_sec = cur_tv.tv_sec + client->interval;
3472 tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
3473 random() % 1000000 : cur_tv.tv_usec;
3474 add_timeout(&tv, send_request, client, 0, 0);
3475}
3476
3478 void *cpp;
3479{
3480 struct client_state *client = cpp;
3481
3482 int result;
3483
3484#if defined(DHCPv6) && defined(DHCP4o6)
3485 if (dhcpv4_over_dhcpv6) {
3486 log_info ("DHCPDECLINE");
3487 } else
3488#endif
3489 log_info ("DHCPDECLINE of %s on %s to %s port %d (xid=0x%x)",
3490 piaddr(client->requested_address),
3491 (client->name ? client->name : client->interface->name),
3492 inet_ntoa(sockaddr_broadcast.sin_addr),
3493 ntohs(sockaddr_broadcast.sin_port),
3494 ntohl(client -> xid));
3495
3496
3497 /* Send out a packet. */
3498#if defined(DHCPv6) && defined(DHCP4o6)
3499 if (dhcpv4_over_dhcpv6) {
3500 result = send_dhcpv4_query(client, 1);
3501 } else
3502#endif
3503 result = send_packet(client->interface, NULL, &client->packet,
3504 client->packet_length, inaddr_any,
3505 &sockaddr_broadcast, NULL);
3506 if (result < 0) {
3507#if defined(DHCPv6) && defined(DHCP4o6)
3508 if (dhcpv4_over_dhcpv6) {
3509 log_error("%s:%d: Failed to send %d byte long packet.",
3510 MDL, client->packet_length);
3511 } else
3512#endif
3513 log_error("%s:%d: Failed to send %d byte long packet over %s"
3514 " interface.", MDL, client->packet_length,
3515 client->interface->name);
3516 }
3517}
3518
3520 void *cpp;
3521{
3522 struct client_state *client = cpp;
3523
3524 int result;
3525 struct sockaddr_in destination;
3526 struct in_addr from;
3527
3528 memcpy (&from, client -> active -> address.iabuf,
3529 sizeof from);
3530 memcpy (&destination.sin_addr.s_addr,
3531 client -> destination.iabuf,
3532 sizeof destination.sin_addr.s_addr);
3533 destination.sin_port = remote_port;
3534 destination.sin_family = AF_INET;
3535#ifdef HAVE_SA_LEN
3536 destination.sin_len = sizeof destination;
3537#endif
3538
3539 /* Set the lease to end now, so that we don't accidentally
3540 reuse it if we restart before the old expiry time. */
3541 client -> active -> expiry =
3542 client -> active -> renewal =
3543 client -> active -> rebind = cur_time;
3544 if (!write_client_lease (client, client -> active, 1, 1)) {
3545 log_error ("Can't release lease: lease write failed.");
3546 return;
3547 }
3548
3549#if defined(DHCPv6) && defined(DHCP4o6)
3550 if (dhcpv4_over_dhcpv6) {
3551 log_info ("DHCPRELEASE");
3552 } else
3553#endif
3554 log_info ("DHCPRELEASE of %s on %s to %s port %d (xid=0x%x)",
3555 piaddr(client->active->address),
3556 client->name ? client->name : client->interface->name,
3557 inet_ntoa (destination.sin_addr),
3558 ntohs (destination.sin_port),
3559 ntohl(client -> xid));
3560
3561#if defined(DHCPv6) && defined(DHCP4o6)
3562 if (dhcpv4_over_dhcpv6) {
3563 int broadcast = 0;
3564 if (destination.sin_addr.s_addr == INADDR_BROADCAST)
3565 broadcast = 1;
3566 result = send_dhcpv4_query(client, broadcast);
3567 if (result < 0) {
3568 log_error("%s:%d: Failed to send %d byte long packet.",
3569 MDL, client->packet_length);
3570 }
3571 } else
3572#endif
3573 if (fallback_interface) {
3574#if defined(SO_BINDTODEVICE)
3575 if (setsockopt(fallback_interface -> wfdesc, SOL_SOCKET,
3576 SO_BINDTODEVICE, client->interface->name,
3577 strlen(client->interface->name)) < 0) {
3578 log_error("%s:%d: Failed to bind fallback interface"
3579 " to %s: %m", MDL, client->interface->name);
3580 }
3581#endif
3582 result = send_packet(fallback_interface, NULL, &client->packet,
3583 client->packet_length, from, &destination,
3584 NULL);
3585 if (result < 0) {
3586 log_error("%s:%d: Failed to send %d byte long packet"
3587 " over %s interface.", MDL,
3588 client->packet_length,
3589 fallback_interface->name);
3590 }
3591#if defined(SO_BINDTODEVICE)
3592 if (setsockopt(fallback_interface -> wfdesc, SOL_SOCKET,
3593 SO_BINDTODEVICE, NULL, 0) < 0) {
3594 log_fatal("%s:%d: Failed to unbind fallback interface:"
3595 " %m", MDL);
3596 }
3597#endif
3598 } else {
3599 /* Send out a packet. */
3600 result = send_packet(client->interface, NULL, &client->packet,
3601 client->packet_length, from, &destination,
3602 NULL);
3603 if (result < 0) {
3604 log_error ("%s:%d: Failed to send %d byte long packet"
3605 " over %s interface.", MDL,
3606 client->packet_length,
3607 client->interface->name);
3608 }
3609
3610 }
3611}
3612
3613#if defined(DHCPv6) && defined(DHCP4o6)
3614/*
3615 * \brief Send a DHCPv4-query to the DHCPv6 client
3616 * (DHCPv4 client function)
3617 *
3618 * The DHCPv4 client sends a DHCPv4-query to the DHCPv6 client over
3619 * the inter-process communication socket.
3620 *
3621 * \param client the DHCPv4 client state
3622 * \param broadcast the broadcast flag
3623 * \return the sent byte count (-1 on error)
3624 */
3625static int send_dhcpv4_query(struct client_state *client, int broadcast) {
3626 struct data_string ds;
3627 struct dhcpv4_over_dhcpv6_packet *query;
3628 int ofs, len, cc;
3629
3630 if (dhcp4o6_state <= 0) {
3631 log_info("send_dhcpv4_query: not ready.");
3632 return -1;
3633 }
3634
3635 /*
3636 * Compute buffer length and allocate it.
3637 */
3638 len = ofs = (int)(offsetof(struct dhcpv4_over_dhcpv6_packet, options));
3639 len += dhcpv6_universe.tag_size + dhcpv6_universe.length_size;
3640 len += client->packet_length;
3641 memset(&ds, 0, sizeof(ds));
3642 if (!buffer_allocate(&ds.buffer, len, MDL)) {
3643 log_error("Unable to allocate memory for DHCPv4-query.");
3644 return -1;
3645 }
3646 ds.data = ds.buffer->data;
3647 ds.len = len;
3648
3649 /*
3650 * Fill header.
3651 */
3652 query = (struct dhcpv4_over_dhcpv6_packet *)ds.data;
3654 query->flags[0] = query->flags[1] = query->flags[2] = 0;
3655 if (!broadcast)
3656 query->flags[0] |= DHCP4O6_QUERY_UNICAST;
3657
3658 /*
3659 * Append DHCPv4 message.
3660 */
3661 dhcpv6_universe.store_tag(ds.buffer->data + ofs, D6O_DHCPV4_MSG);
3662 ofs += dhcpv6_universe.tag_size;
3663 dhcpv6_universe.store_length(ds.buffer->data + ofs,
3664 client->packet_length);
3665 ofs += dhcpv6_universe.length_size;
3666 memcpy(ds.buffer->data + ofs, &client->packet, client->packet_length);
3667
3668 /*
3669 * Send DHCPv6 message.
3670 */
3671 cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
3672 if (cc < 0)
3673 log_error("send_dhcpv4_query: send(): %m");
3674
3675 data_string_forget(&ds, MDL);
3676
3677 return cc;
3678}
3679
3680/*
3681 * \brief Forward a DHCPv4-query to all DHCPv4 over DHCPv6 server addresses.
3682 * (DHCPv6 client function)
3683 *
3684 * \param raw the DHCPv6 DHCPv4-query message raw content
3685 */
3686static void forw_dhcpv4_query(struct data_string *raw) {
3687 struct interface_info *ip;
3688 struct client_state *client;
3689 struct dhc6_lease *lease;
3690 struct option_cache *oc;
3691 struct data_string addrs;
3692 struct sockaddr_in6 sin6;
3693 int i, send_ret, attempt, success;
3694
3695 attempt = success = 0;
3696 memset(&sin6, 0, sizeof(sin6));
3697 sin6.sin6_family = AF_INET6;
3698 sin6.sin6_port = remote_port;
3699#ifdef HAVE_SA_LEN
3700 sin6.sin6_len = sizeof(sin6);
3701#endif
3702 memset(&addrs, 0, sizeof(addrs));
3703 for (ip = interfaces; ip != NULL; ip = ip->next) {
3704 for (client = ip->client; client != NULL;
3705 client = client->next) {
3706 if ((client->state != S_BOUND) &&
3707 (client->state != S_RENEWING) &&
3708 (client->state != S_REBINDING))
3709 continue;
3710 lease = client->active_lease;
3711 if ((lease == NULL) || lease->released)
3712 continue;
3714 lease->options,
3716 if ((oc == NULL) ||
3717 !evaluate_option_cache(&addrs, NULL, NULL, NULL,
3718 lease->options, NULL,
3719 &global_scope, oc, MDL) ||
3720 ((addrs.len % sizeof(sin6.sin6_addr)) != 0)) {
3721 data_string_forget(&addrs, MDL);
3722 continue;
3723 }
3724 if (addrs.len == 0) {
3725 /* note there is nothing to forget */
3726 inet_pton(AF_INET6,
3728 &sin6.sin6_addr);
3729 attempt++;
3730 send_ret = send_packet6(ip, raw->data,
3731 raw->len, &sin6);
3732 if (send_ret == raw->len)
3733 success++;
3734 continue;
3735 }
3736 for (i = 0; i < addrs.len;
3737 i += sizeof(sin6.sin6_addr)) {
3738 memcpy(&sin6.sin6_addr, addrs.data + i,
3739 sizeof(sin6.sin6_addr));
3740 attempt++;
3741 send_ret = send_packet6(ip, raw->data,
3742 raw->len, &sin6);
3743 if (send_ret == raw->len)
3744 success++;
3745 }
3746 data_string_forget(&addrs, MDL);
3747 }
3748 }
3749
3750 log_info("forw_dhcpv4_query: sent(%d): %d/%d",
3751 raw->len, success, attempt);
3752
3753 if (attempt == 0)
3754 dhcp4o6_stop();
3755}
3756#endif
3757
3758void
3760 u_int8_t *type, struct option_cache *sid,
3761 struct iaddr *rip, struct option **prl,
3762 struct option_state **op)
3763{
3764 unsigned i;
3765 struct option_cache *oc;
3766 struct option *option = NULL;
3767 struct buffer *bp = NULL;
3768
3769 /* If there are any leftover options, get rid of them. */
3770 if (*op)
3772
3773 /* Allocate space for options. */
3775
3776 /* Send the server identifier if provided. */
3777 if (sid)
3778 save_option(&dhcp_universe, *op, sid);
3779
3780 oc = NULL;
3781
3782 /* Send the requested address if provided. */
3783 if (rip) {
3784 client->requested_address = *rip;
3786 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
3787 &i, 0, MDL) &&
3788 make_const_option_cache(&oc, NULL, rip->iabuf, rip->len,
3789 option, MDL)))
3790 log_error ("can't make requested address cache.");
3791 else {
3792 save_option(&dhcp_universe, *op, oc);
3794 }
3796 } else {
3797 client->requested_address.len = 0;
3798 }
3799
3801 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
3802 MDL) &&
3803 make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
3804 log_error("can't make message type.");
3805 else {
3806 save_option(&dhcp_universe, *op, oc);
3808 }
3810
3811 if (prl) {
3812 int len;
3813
3814 /* Probe the length of the list. */
3815 len = 0;
3816 for (i = 0 ; prl[i] != NULL ; i++)
3817 if (prl[i]->universe == &dhcp_universe)
3818 len++;
3819
3820 if (!buffer_allocate(&bp, len, MDL))
3821 log_error("can't make parameter list buffer.");
3822 else {
3823 unsigned code = DHO_DHCP_PARAMETER_REQUEST_LIST;
3824
3825 len = 0;
3826 for (i = 0 ; prl[i] != NULL ; i++)
3827 if (prl[i]->universe == &dhcp_universe)
3828 bp->data[len++] = prl[i]->code;
3829
3830 if (!(option_code_hash_lookup(&option,
3831 dhcp_universe.code_hash,
3832 &code, 0, MDL) &&
3833 make_const_option_cache(&oc, &bp, NULL, len,
3834 option, MDL))) {
3835 if (bp != NULL)
3836 buffer_dereference(&bp, MDL);
3837 log_error ("can't make option cache");
3838 } else {
3839 save_option(&dhcp_universe, *op, oc);
3841 }
3843 }
3844 }
3845
3846 /*
3847 * If requested (duid_v4 == 1) add an RFC4361 compliant client-identifier
3848 * This can be overridden by including a client id in the configuration
3849 * file.
3850 */
3851 if (duid_v4 == 1) {
3852 struct data_string client_identifier;
3853 int hw_idx, hw_len;
3854
3855 memset(&client_identifier, 0, sizeof(client_identifier));
3856 client_identifier.len = 1 + 4 + default_duid.len;
3857 if (!buffer_allocate(&client_identifier.buffer,
3858 client_identifier.len, MDL))
3859 log_fatal("no memory for default DUID!");
3860 client_identifier.data = client_identifier.buffer->data;
3861
3863
3864 /* Client-identifier type : 1 byte */
3865 *client_identifier.buffer->data = 255;
3866
3867 /* IAID : 4 bytes
3868 * we use the low 4 bytes from the interface address
3869 */
3870 if (client->interface->hw_address.hlen > 4) {
3871 hw_idx = client->interface->hw_address.hlen - 4;
3872 hw_len = 4;
3873 } else {
3874 hw_idx = 0;
3875 hw_len = client->interface->hw_address.hlen;
3876 }
3877 memcpy(client_identifier.buffer->data + 5 - hw_len,
3878 client->interface->hw_address.hbuf + hw_idx,
3879 hw_len);
3880
3881 /* Add the default duid */
3882 memcpy(client_identifier.buffer->data + (1 + 4),
3883 default_duid.data, default_duid.len);
3884
3885 /* And save the option */
3886 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
3887 &i, 0, MDL) &&
3888 make_const_option_cache(&oc, NULL,
3889 (u_int8_t *)client_identifier.data,
3890 client_identifier.len,
3891 option, MDL)))
3892 log_error ("can't make requested client id cache..");
3893 else {
3894 save_option (&dhcp_universe, *op, oc);
3896 }
3898 }
3899
3900 /* Run statements that need to be run on transmission. */
3901 if (client->config->on_transmission)
3902 execute_statements_in_scope(NULL, NULL, NULL, client,
3903 (lease ? lease->options : NULL),
3904 *op, &global_scope,
3905 client->config->on_transmission,
3906 NULL, NULL);
3907}
3908
3909void make_discover (client, lease)
3910 struct client_state *client;
3911 struct client_lease *lease;
3912{
3913 unsigned char discover = DHCPDISCOVER;
3914 struct option_state *options = (struct option_state *)0;
3915
3916 memset (&client -> packet, 0, sizeof (client -> packet));
3917
3918 make_client_options (client,
3919 lease, &discover, (struct option_cache *)0,
3920 lease ? &lease -> address : (struct iaddr *)0,
3921 client -> config -> requested_options,
3922 &options);
3923
3924 /* Set up the option buffer... */
3925 client -> packet_length =
3926 cons_options ((struct packet *)0, &client -> packet,
3927 (struct lease *)0, client,
3928 /* maximum packet size */1500,
3929 (struct option_state *)0,
3930 options,
3931 /* scope */ &global_scope,
3932 /* overload */ 0,
3933 /* terminate */0,
3934 /* bootpp */0,
3935 (struct data_string *)0,
3936 client -> config -> vendor_space_name);
3937
3938 option_state_dereference (&options, MDL);
3939 if (client -> packet_length < BOOTP_MIN_LEN)
3940 client -> packet_length = BOOTP_MIN_LEN;
3941
3942 client -> packet.op = BOOTREQUEST;
3943 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
3944 /* Assumes hw_address is known, otherwise a random value may result */
3945 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
3946 client -> packet.hops = 0;
3947 client -> packet.xid = random ();
3948 client -> packet.secs = 0; /* filled in by send_discover. */
3949
3952 client -> packet.flags = 0;
3953 else
3954 client -> packet.flags = htons (BOOTP_BROADCAST);
3955
3956 memset (&(client -> packet.ciaddr),
3957 0, sizeof client -> packet.ciaddr);
3958 memset (&(client -> packet.yiaddr),
3959 0, sizeof client -> packet.yiaddr);
3960 memset (&(client -> packet.siaddr),
3961 0, sizeof client -> packet.siaddr);
3962 client -> packet.giaddr = giaddr;
3963 if (client -> interface -> hw_address.hlen > 0)
3964 memcpy (client -> packet.chaddr,
3965 &client -> interface -> hw_address.hbuf [1],
3966 (unsigned)(client -> interface -> hw_address.hlen - 1));
3967
3968#ifdef DEBUG_PACKET
3969 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
3970#endif
3971}
3972
3973
3974void make_request (client, lease)
3975 struct client_state *client;
3976 struct client_lease *lease;
3977{
3978 unsigned char request = DHCPREQUEST;
3979 struct option_cache *oc;
3980
3981 memset (&client -> packet, 0, sizeof (client -> packet));
3982
3983 if (client -> state == S_REQUESTING)
3984 oc = lookup_option (&dhcp_universe, lease -> options,
3986 else
3987 oc = (struct option_cache *)0;
3988
3989 if (client -> sent_options)
3990 option_state_dereference (&client -> sent_options, MDL);
3991
3992 make_client_options (client, lease, &request, oc,
3993 ((client -> state == S_REQUESTING ||
3994 client -> state == S_REBOOTING)
3995 ? &lease -> address
3996 : (struct iaddr *)0),
3997 client -> config -> requested_options,
3998 &client -> sent_options);
3999
4000 /* Set up the option buffer... */
4001 client -> packet_length =
4002 cons_options ((struct packet *)0, &client -> packet,
4003 (struct lease *)0, client,
4004 /* maximum packet size */1500,
4005 (struct option_state *)0,
4006 client -> sent_options,
4007 /* scope */ &global_scope,
4008 /* overload */ 0,
4009 /* terminate */0,
4010 /* bootpp */0,
4011 (struct data_string *)0,
4012 client -> config -> vendor_space_name);
4013
4014 if (client -> packet_length < BOOTP_MIN_LEN)
4015 client -> packet_length = BOOTP_MIN_LEN;
4016
4017 client -> packet.op = BOOTREQUEST;
4018 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
4019 /* Assumes hw_address is known, otherwise a random value may result */
4020 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
4021 client -> packet.hops = 0;
4022 client -> packet.xid = client -> xid;
4023 client -> packet.secs = 0; /* Filled in by send_request. */
4024
4025 /* If we own the address we're requesting, put it in ciaddr;
4026 otherwise set ciaddr to zero. */
4027 if (client -> state == S_BOUND ||
4028 client -> state == S_RENEWING ||
4029 client -> state == S_REBINDING) {
4030 memcpy (&client -> packet.ciaddr,
4031 lease -> address.iabuf, lease -> address.len);
4032 client -> packet.flags = 0;
4033 } else {
4034 memset (&client -> packet.ciaddr, 0,
4035 sizeof client -> packet.ciaddr);
4036 if ((!(bootp_broadcast_always ||
4037 client ->config->bootp_broadcast_always)) &&
4038 can_receive_unicast_unconfigured (client -> interface))
4039 client -> packet.flags = 0;
4040 else
4041 client -> packet.flags = htons (BOOTP_BROADCAST);
4042 }
4043
4044 memset (&client -> packet.yiaddr, 0,
4045 sizeof client -> packet.yiaddr);
4046 memset (&client -> packet.siaddr, 0,
4047 sizeof client -> packet.siaddr);
4048 if (client -> state != S_BOUND &&
4049 client -> state != S_RENEWING)
4050 client -> packet.giaddr = giaddr;
4051 else
4052 memset (&client -> packet.giaddr, 0,
4053 sizeof client -> packet.giaddr);
4054 if (client -> interface -> hw_address.hlen > 0)
4055 memcpy (client -> packet.chaddr,
4056 &client -> interface -> hw_address.hbuf [1],
4057 (unsigned)(client -> interface -> hw_address.hlen - 1));
4058
4059#ifdef DEBUG_PACKET
4060 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
4061#endif
4062}
4063
4064void make_decline (client, lease)
4065 struct client_state *client;
4066 struct client_lease *lease;
4067{
4068 unsigned char decline = DHCPDECLINE;
4069 struct option_cache *oc;
4070
4071 struct option_state *options = (struct option_state *)0;
4072
4073 /* Create the options cache. */
4074 oc = lookup_option (&dhcp_universe, lease -> options,
4076 make_client_options(client, lease, &decline, oc, &lease->address,
4077 NULL, &options);
4078
4079 /* Consume the options cache into the option buffer. */
4080 memset (&client -> packet, 0, sizeof (client -> packet));
4081 client -> packet_length =
4082 cons_options ((struct packet *)0, &client -> packet,
4083 (struct lease *)0, client, 0,
4084 (struct option_state *)0, options,
4085 &global_scope, 0, 0, 0, (struct data_string *)0,
4086 client -> config -> vendor_space_name);
4087
4088 /* Destroy the options cache. */
4089 option_state_dereference (&options, MDL);
4090
4091 if (client -> packet_length < BOOTP_MIN_LEN)
4092 client -> packet_length = BOOTP_MIN_LEN;
4093
4094 client -> packet.op = BOOTREQUEST;
4095 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
4096 /* Assumes hw_address is known, otherwise a random value may result */
4097 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
4098 client -> packet.hops = 0;
4099 client -> packet.xid = client -> xid;
4100 client -> packet.secs = 0; /* Filled in by send_request. */
4103 client -> packet.flags = 0;
4104 else
4105 client -> packet.flags = htons (BOOTP_BROADCAST);
4106
4107 /* ciaddr must always be zero. */
4108 memset (&client -> packet.ciaddr, 0,
4109 sizeof client -> packet.ciaddr);
4110 memset (&client -> packet.yiaddr, 0,
4111 sizeof client -> packet.yiaddr);
4112 memset (&client -> packet.siaddr, 0,
4113 sizeof client -> packet.siaddr);
4114 client -> packet.giaddr = giaddr;
4115 memcpy (client -> packet.chaddr,
4116 &client -> interface -> hw_address.hbuf [1],
4117 client -> interface -> hw_address.hlen);
4118
4119#ifdef DEBUG_PACKET
4120 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
4121#endif
4122}
4123
4124void make_release (client, lease)
4125 struct client_state *client;
4126 struct client_lease *lease;
4127{
4128 unsigned char request = DHCPRELEASE;
4129 struct option_cache *oc;
4130
4131 struct option_state *options = (struct option_state *)0;
4132
4133 memset (&client -> packet, 0, sizeof (client -> packet));
4134
4135 oc = lookup_option (&dhcp_universe, lease -> options,
4137 make_client_options(client, lease, &request, oc, NULL, NULL, &options);
4138
4139 /* Set up the option buffer... */
4140 client -> packet_length =
4141 cons_options ((struct packet *)0, &client -> packet,
4142 (struct lease *)0, client,
4143 /* maximum packet size */1500,
4144 (struct option_state *)0,
4145 options,
4146 /* scope */ &global_scope,
4147 /* overload */ 0,
4148 /* terminate */0,
4149 /* bootpp */0,
4150 (struct data_string *)0,
4151 client -> config -> vendor_space_name);
4152
4153 if (client -> packet_length < BOOTP_MIN_LEN)
4154 client -> packet_length = BOOTP_MIN_LEN;
4155 option_state_dereference (&options, MDL);
4156
4157 client -> packet.op = BOOTREQUEST;
4158 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
4159 /* Assumes hw_address is known, otherwise a random value may result */
4160 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
4161 client -> packet.hops = 0;
4162 client -> packet.xid = random ();
4163 client -> packet.secs = 0;
4164 client -> packet.flags = 0;
4165 memcpy (&client -> packet.ciaddr,
4166 lease -> address.iabuf, lease -> address.len);
4167 memset (&client -> packet.yiaddr, 0,
4168 sizeof client -> packet.yiaddr);
4169 memset (&client -> packet.siaddr, 0,
4170 sizeof client -> packet.siaddr);
4171 client -> packet.giaddr = giaddr;
4172 memcpy (client -> packet.chaddr,
4173 &client -> interface -> hw_address.hbuf [1],
4174 client -> interface -> hw_address.hlen);
4175
4176#ifdef DEBUG_PACKET
4177 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
4178#endif
4179}
4180
4182 struct client_lease *lease;
4183{
4184 if (lease -> server_name)
4185 dfree (lease -> server_name, MDL);
4186 if (lease -> filename)
4187 dfree (lease -> filename, MDL);
4190}
4191
4192FILE *leaseFile = NULL;
4194
4196{
4197 struct interface_info *ip;
4198 struct client_state *client;
4199 struct client_lease *lp;
4200
4201 if (leaseFile != NULL)
4202 fclose (leaseFile);
4203 leaseFile = fopen (path_dhclient_db, "we");
4204 if (leaseFile == NULL) {
4205 log_error ("can't create %s: %m", path_dhclient_db);
4206 return;
4207 }
4208
4209 /* If there is a default duid, write it out. */
4210 if (default_duid.len != 0)
4211 write_duid(&default_duid);
4212
4213 /* Write out all the leases attached to configured interfaces that
4214 we know about. */
4215 for (ip = interfaces; ip; ip = ip -> next) {
4216 for (client = ip -> client; client; client = client -> next) {
4217 for (lp = client -> leases; lp; lp = lp -> next) {
4218 write_client_lease (client, lp, 1, 0);
4219 }
4220 if (client -> active)
4221 write_client_lease (client,
4222 client -> active, 1, 0);
4223
4224 if (client->active_lease != NULL)
4225 write_client6_lease(client,
4226 client->active_lease,
4227 1, 0);
4228
4229 /* Reset last_write after rewrites. */
4230 client->last_write = 0;
4231 }
4232 }
4233
4234 /* Write out any leases that are attached to interfaces that aren't
4235 currently configured. */
4236 for (ip = dummy_interfaces; ip; ip = ip -> next) {
4237 for (client = ip -> client; client; client = client -> next) {
4238 for (lp = client -> leases; lp; lp = lp -> next) {
4239 write_client_lease (client, lp, 1, 0);
4240 }
4241 if (client -> active)
4242 write_client_lease (client,
4243 client -> active, 1, 0);
4244
4245 if (client->active_lease != NULL)
4246 write_client6_lease(client,
4247 client->active_lease,
4248 1, 0);
4249
4250 /* Reset last_write after rewrites. */
4251 client->last_write = 0;
4252 }
4253 }
4254 fflush (leaseFile);
4255}
4256
4258 struct packet *packet, struct lease *lease,
4259 struct client_state *client_state,
4260 struct option_state *in_options,
4261 struct option_state *cfg_options,
4262 struct binding_scope **scope,
4263 struct universe *u, void *stuff)
4264{
4265 const char *name, *dot;
4266 struct data_string ds;
4267 char *preamble = stuff;
4268
4269 memset (&ds, 0, sizeof ds);
4270
4271 if (u != &dhcp_universe) {
4272 name = u -> name;
4273 dot = ".";
4274 } else {
4275 name = "";
4276 dot = "";
4277 }
4279 in_options, cfg_options, scope, oc, MDL)) {
4280 /* The option name */
4281 fprintf(leaseFile, "%soption %s%s%s", preamble,
4282 name, dot, oc->option->name);
4283
4284 /* The option value if there is one */
4285 if ((oc->option->format == NULL) ||
4286 (oc->option->format[0] != 'Z')) {
4287 fprintf(leaseFile, " %s",
4289 ds.len, 1, 1));
4290 }
4291
4292 /* The closing semi-colon and newline */
4293 fprintf(leaseFile, ";\n");
4294
4295 data_string_forget (&ds, MDL);
4296 }
4297}
4298
4299/* Write an option cache to the lease store. */
4300static void
4301write_options(struct client_state *client, struct option_state *options,
4302 const char *preamble)
4303{
4304 int i;
4305
4306 for (i = 0; i < options->universe_count; i++) {
4307 option_space_foreach(NULL, NULL, client, NULL, options,
4309 (char *)preamble, write_lease_option);
4310 }
4311}
4312
4313int unhexchar(char c) {
4314
4315 if (c >= '0' && c <= '9')
4316 return c - '0';
4317
4318 if (c >= 'a' && c <= 'f')
4319 return c - 'a' + 10;
4320
4321 if (c >= 'A' && c <= 'F')
4322 return c - 'A' + 10;
4323
4324 return -1;
4325}
4326
4327isc_result_t
4328read_uuid(u_int8_t* uuid) {
4329 const char *id_fname = "/etc/machine-id";
4330 char id[32];
4331 size_t nread;
4332 FILE * file = fopen( id_fname , "r");
4333 if (!file) {
4334 log_debug("Cannot open %s", id_fname);
4335 return ISC_R_IOERROR;
4336 }
4337 nread = fread(id, 1, sizeof id, file);
4338 fclose(file);
4339
4340 if (nread < 32) {
4341 log_debug("Not enough data in %s", id_fname);
4342 return ISC_R_IOERROR;
4343 }
4344 int j;
4345 for (j = 0; j < 16; j++) {
4346 int a, b;
4347
4348 a = unhexchar(id[j*2]);
4349 b = unhexchar(id[j*2+1]);
4350
4351 if (a < 0 || b < 0) {
4352 log_debug("Wrong data in %s", id_fname);
4353 return ISC_R_IOERROR;
4354 }
4355 uuid[j] = a << 4 | b;
4356 }
4357
4358 /* Set UUID version to 4 --- truly random generation */
4359 uuid[6] = (uuid[6] & 0x0F) | 0x40;
4360 /* Set the UUID variant to DCE */
4361 uuid[8] = (uuid[8] & 0x3F) | 0x80;
4362
4363 return ISC_R_SUCCESS;
4364}
4365
4366/*
4367 * The "best" default DUID, since we cannot predict any information
4368 * about the system (such as whether or not the hardware addresses are
4369 * integrated into the motherboard or similar), is the "LLT", link local
4370 * plus time, DUID. For real stateless "LL" is better.
4371 *
4372 * Once generated, this duid is stored into the state database, and
4373 * retained across restarts.
4374 *
4375 * For the time being, there is probably a different state database for
4376 * every daemon, so this winds up being a per-interface identifier...which
4377 * is not how it is intended. Upcoming rearchitecting the client should
4378 * address this "one daemon model."
4379 */
4380isc_result_t
4381form_duid(struct data_string *duid, const char *file, int line)
4382{
4383 struct interface_info *ip;
4384 int len;
4385 char *str;
4386 u_int8_t uuid[16];
4387
4388 /* For now, just use the first interface on the list. */
4389 ip = interfaces;
4390
4391 if (ip == NULL)
4392 log_fatal("Impossible condition at %s:%d.", MDL);
4393
4394 while (ip && ip->hw_address.hbuf[0] == HTYPE_RESERVED) {
4395 /* Try the other interfaces */
4396 log_debug("Cannot form default DUID from interface %s.", ip->name);
4397 ip = ip->next;
4398 }
4399 if (ip == NULL) {
4400 return ISC_R_UNEXPECTED;
4401 }
4402
4403 if ((ip->hw_address.hlen == 0) ||
4404 (ip->hw_address.hlen > sizeof(ip->hw_address.hbuf)))
4405 log_fatal("Impossible hardware address length at %s:%d.", MDL);
4406
4407 if (duid_type == 0) {
4408 if (read_uuid(uuid) == ISC_R_SUCCESS)
4410 else
4412 }
4413
4414 if (duid_type == DUID_UUID)
4415 len = 2 + sizeof (uuid);
4416 else {
4417 /*
4418 * 2 bytes for the 'duid type' field.
4419 * 2 bytes for the 'htype' field.
4420 * (DUID_LLT) 4 bytes for the 'current time'.
4421 * enough bytes for the hardware address (note that hw_address has
4422 * the 'htype' on byte zero).
4423 */
4424 len = 4 + (ip->hw_address.hlen - 1);
4425 if (duid_type == DUID_LLT)
4426 len += 4;
4427 }
4428 if (!buffer_allocate(&duid->buffer, len, MDL))
4429 log_fatal("no memory for default DUID!");
4430 duid->data = duid->buffer->data;
4431 duid->len = len;
4432
4433 if (duid_type == DUID_UUID) {
4434 putUShort(duid->buffer->data, DUID_UUID);
4435 memcpy(duid->buffer->data + 2, uuid, sizeof(uuid));
4436 }
4437 /* Basic Link Local Address type of DUID. */
4438 else if (duid_type == DUID_LLT) {
4439 putUShort(duid->buffer->data, DUID_LLT);
4440 putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
4442 memcpy(duid->buffer->data + 8, ip->hw_address.hbuf + 1,
4443 ip->hw_address.hlen - 1);
4444 } else {
4445 putUShort(duid->buffer->data, DUID_LL);
4446 putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
4447 memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
4448 ip->hw_address.hlen - 1);
4449 }
4450
4451 /* Now format the output based on lease-id-format */
4452 str = format_lease_id(duid->data, duid->len,
4453 top_level_config.lease_id_format, MDL);
4454 if (str == NULL) {
4455 log_info("form_duid: Couldn't allocate memory to log duid!");
4456 } else {
4457 log_info("Created duid %s.", str);
4458 dfree(str, MDL);
4459 }
4460
4461 return ISC_R_SUCCESS;
4462}
4463
4464/* Write the default DUID to the lease store. */
4465static isc_result_t
4466write_duid(struct data_string *duid)
4467{
4468 char *str;
4469 int stat;
4470
4471 if ((duid == NULL) || (duid->len <= 2))
4472 return DHCP_R_INVALIDARG;
4473
4474 if (leaseFile == NULL) { /* XXX? */
4475 leaseFile = fopen(path_dhclient_db, "we");
4476 if (leaseFile == NULL) {
4477 log_error("can't create %s: %m", path_dhclient_db);
4478 return ISC_R_IOERROR;
4479 }
4480 }
4481
4482 /* Generate a formatted duid string per lease-id-format */
4483 str = format_lease_id(duid->data, duid->len,
4484 top_level_config.lease_id_format, MDL);
4485 if (str == NULL)
4486 return ISC_R_NOMEMORY;
4487
4488 stat = fprintf(leaseFile, "default-duid %s;\n", str);
4489 dfree(str, MDL);
4490 if (stat <= 0)
4491 return ISC_R_IOERROR;
4492
4493 if (fflush(leaseFile) != 0)
4494 return ISC_R_IOERROR;
4495
4496 return ISC_R_SUCCESS;
4497}
4498
4499/* Write a DHCPv6 lease to the store. */
4500isc_result_t
4502 int rewrite, int sync)
4503{
4504 struct dhc6_ia *ia;
4505 struct dhc6_addr *addr;
4506 int stat;
4507 const char *ianame;
4508
4509 /* This should include the current lease. */
4510 if (!rewrite && (leases_written++ > 20)) {
4512 leases_written = 0;
4513 return ISC_R_SUCCESS;
4514 }
4515
4516 if (client == NULL || lease == NULL)
4517 return DHCP_R_INVALIDARG;
4518
4519 if (leaseFile == NULL) { /* XXX? */
4520 leaseFile = fopen(path_dhclient_db, "w");
4521 if (leaseFile == NULL) {
4522 log_error("can't create %s: %m", path_dhclient_db);
4523 return ISC_R_IOERROR;
4524 }
4525 }
4526
4527 stat = fprintf(leaseFile, "lease6 {\n");
4528 if (stat <= 0)
4529 return ISC_R_IOERROR;
4530
4531 stat = fprintf(leaseFile, " interface \"%s\";\n",
4532 client->interface->name);
4533 if (stat <= 0)
4534 return ISC_R_IOERROR;
4535
4536 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
4537 switch (ia->ia_type) {
4538 case D6O_IA_NA:
4539 default:
4540 ianame = "ia-na";
4541 break;
4542 case D6O_IA_TA:
4543 ianame = "ia-ta";
4544 break;
4545 case D6O_IA_PD:
4546 ianame = "ia-pd";
4547 break;
4548 }
4549
4550 /* For some reason IAID was never octal or hex, but string or
4551 * hex. Go figure. So for compatibilty's sake we will either
4552 * do hex or "legacy" i.e string rather than octal. What a
4553 * cluster. */
4554 switch(top_level_config.lease_id_format) {
4555 case TOKEN_HEX: {
4556 char* iaid_str = format_lease_id(
4557 (const unsigned char *) &ia->iaid, 4,
4558 top_level_config.lease_id_format, MDL);
4559
4560 if (!iaid_str) {
4561 log_error("Can't format iaid");
4562 return ISC_R_IOERROR;
4563 }
4564
4565 stat = fprintf(leaseFile, " %s %s {\n",
4566 ianame, iaid_str);
4567 dfree(iaid_str, MDL);
4568 break;
4569 }
4570
4571 case TOKEN_OCTAL:
4572 default:
4573 stat = fprintf(leaseFile, " %s %s {\n", ianame,
4574 print_hex_1(4, ia->iaid, 12));
4575 break;
4576 }
4577
4578 if (stat <= 0)
4579 return ISC_R_IOERROR;
4580
4581 if (ia->ia_type != D6O_IA_TA)
4582 stat = fprintf(leaseFile, " starts %d;\n"
4583 " renew %u;\n"
4584 " rebind %u;\n",
4585 (int)ia->starts, ia->renew, ia->rebind);
4586 else
4587 stat = fprintf(leaseFile, " starts %d;\n",
4588 (int)ia->starts);
4589 if (stat <= 0)
4590 return ISC_R_IOERROR;
4591
4592 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
4593 if (ia->ia_type != D6O_IA_PD)
4594 stat = fprintf(leaseFile,
4595 " iaaddr %s {\n",
4596 piaddr(addr->address));
4597 else
4598 stat = fprintf(leaseFile,
4599 " iaprefix %s/%d {\n",
4600 piaddr(addr->address),
4601 (int)addr->plen);
4602 if (stat <= 0)
4603 return ISC_R_IOERROR;
4604
4605 stat = fprintf(leaseFile, " starts %d;\n"
4606 " preferred-life %u;\n"
4607 " max-life %u;\n",
4608 (int)addr->starts, addr->preferred_life,
4609 addr->max_life);
4610 if (stat <= 0)
4611 return ISC_R_IOERROR;
4612
4613 if (addr->options != NULL)
4614 write_options(client, addr->options, " ");
4615
4616 stat = fprintf(leaseFile, " }\n");
4617 if (stat <= 0)
4618 return ISC_R_IOERROR;
4619 }
4620
4621 if (ia->options != NULL)
4622 write_options(client, ia->options, " ");
4623
4624 stat = fprintf(leaseFile, " }\n");
4625 if (stat <= 0)
4626 return ISC_R_IOERROR;
4627 }
4628
4629 if (lease->released) {
4630 stat = fprintf(leaseFile, " released;\n");
4631 if (stat <= 0)
4632 return ISC_R_IOERROR;
4633 }
4634
4635 if (lease->options != NULL)
4636 write_options(client, lease->options, " ");
4637
4638 stat = fprintf(leaseFile, "}\n");
4639 if (stat <= 0)
4640 return ISC_R_IOERROR;
4641
4642 if (fflush(leaseFile) != 0)
4643 return ISC_R_IOERROR;
4644
4645 if (sync) {
4646 if (fsync(fileno(leaseFile)) < 0) {
4647 log_error("write_client_lease: fsync(): %m");
4648 return ISC_R_IOERROR;
4649 }
4650 }
4651
4652 return ISC_R_SUCCESS;
4653}
4654
4655int write_client_lease (client, lease, rewrite, makesure)
4656 struct client_state *client;
4657 struct client_lease *lease;
4658 int rewrite;
4659 int makesure;
4660{
4661 struct data_string ds;
4662 int errors = 0;
4663 char *s;
4664 const char *tval;
4665
4666 if (!rewrite) {
4667 if (leases_written++ > 20) {
4669 leases_written = 0;
4670 }
4671 }
4672
4673 /* If the lease came from the config file, we don't need to stash
4674 a copy in the lease database. */
4675 if (lease -> is_static)
4676 return 1;
4677
4678 if (leaseFile == NULL) { /* XXX */
4679 leaseFile = fopen (path_dhclient_db, "we");
4680 if (leaseFile == NULL) {
4681 log_error ("can't create %s: %m", path_dhclient_db);
4682 return 0;
4683 }
4684 }
4685
4686 errno = 0;
4687 fprintf (leaseFile, "lease {\n");
4688 if (lease -> is_bootp) {
4689 fprintf (leaseFile, " bootp;\n");
4690 if (errno) {
4691 ++errors;
4692 errno = 0;
4693 }
4694 }
4695 fprintf (leaseFile, " interface \"%s\";\n",
4696 client -> interface -> name);
4697 if (errno) {
4698 ++errors;
4699 errno = 0;
4700 }
4701 if (client -> name) {
4702 fprintf (leaseFile, " name \"%s\";\n", client -> name);
4703 if (errno) {
4704 ++errors;
4705 errno = 0;
4706 }
4707 }
4708 fprintf (leaseFile, " fixed-address %s;\n",
4709 piaddr (lease -> address));
4710 if (errno) {
4711 ++errors;
4712 errno = 0;
4713 }
4714 if (lease -> filename) {
4715 s = quotify_string (lease -> filename, MDL);
4716 if (s) {
4717 fprintf (leaseFile, " filename \"%s\";\n", s);
4718 if (errno) {
4719 ++errors;
4720 errno = 0;
4721 }
4722 dfree (s, MDL);
4723 } else
4724 errors++;
4725
4726 }
4727 if (lease->server_name != NULL) {
4728 s = quotify_string(lease->server_name, MDL);
4729 if (s != NULL) {
4730 fprintf(leaseFile, " server-name \"%s\";\n", s);
4731 if (errno) {
4732 ++errors;
4733 errno = 0;
4734 }
4735 dfree(s, MDL);
4736 } else
4737 ++errors;
4738 }
4739 if (lease -> medium) {
4740 s = quotify_string (lease -> medium -> string, MDL);
4741 if (s) {
4742 fprintf (leaseFile, " medium \"%s\";\n", s);
4743 if (errno) {
4744 ++errors;
4745 errno = 0;
4746 }
4747 dfree (s, MDL);
4748 } else
4749 errors++;
4750 }
4751 if (errno != 0) {
4752 errors++;
4753 errno = 0;
4754 }
4755
4756 memset (&ds, 0, sizeof ds);
4757
4758 write_options(client, lease->options, " ");
4759
4760 tval = print_time(lease->renewal);
4761 if (tval == NULL ||
4762 fprintf(leaseFile, " renew %s\n", tval) < 0)
4763 errors++;
4764
4765 tval = print_time(lease->rebind);
4766 if (tval == NULL ||
4767 fprintf(leaseFile, " rebind %s\n", tval) < 0)
4768 errors++;
4769
4770 tval = print_time(lease->expiry);
4771 if (tval == NULL ||
4772 fprintf(leaseFile, " expire %s\n", tval) < 0)
4773 errors++;
4774
4775 if (fprintf(leaseFile, "}\n") < 0)
4776 errors++;
4777
4778 if (fflush(leaseFile) != 0)
4779 errors++;
4780
4781 client->last_write = cur_time;
4782
4783 if (!errors && makesure) {
4784 if (fsync (fileno (leaseFile)) < 0) {
4785 log_info ("write_client_lease: %m");
4786 return 0;
4787 }
4788 }
4789
4790 return errors ? 0 : 1;
4791}
4792
4793/* Variables holding name of script and file pointer for writing to
4794 script. Needless to say, this is not reentrant - only one script
4795 can be invoked at a time. */
4796char scriptName [256];
4798
4811void script_init(struct client_state *client, const char *reason,
4812 struct string_list *medium)
4813{
4814 struct string_list *sl, *next;
4815
4816 if (client) {
4817 for (sl = client -> env; sl; sl = next) {
4818 next = sl -> next;
4819 dfree (sl, MDL);
4820 }
4821 client -> env = (struct string_list *)0;
4822 client -> envc = 0;
4823
4824 if (client -> interface) {
4825 client_envadd (client, "", "interface", "%s",
4826 client -> interface -> name);
4827 }
4828 if (client -> name)
4829 client_envadd (client,
4830 "", "client", "%s", client -> name);
4831 if (medium)
4832 client_envadd (client,
4833 "", "medium", "%s", medium -> string);
4834
4835 client_envadd (client, "", "reason", "%s", reason);
4836 client_envadd (client, "", "pid", "%ld", (long int)getpid ());
4837#if defined(DHCPv6)
4838 client_envadd (client, "", "dad_wait_time", "%ld",
4839 (long int)dad_wait_time);
4840#endif
4841 }
4842}
4843
4845 struct packet *packet, struct lease *lease,
4846 struct client_state *client_state,
4847 struct option_state *in_options,
4848 struct option_state *cfg_options,
4849 struct binding_scope **scope,
4850 struct universe *u, void *stuff)
4851{
4852 struct envadd_state *es = stuff;
4853 struct data_string data;
4854 memset (&data, 0, sizeof data);
4855
4857 in_options, cfg_options, scope, oc, MDL)) {
4858 if (data.len) {
4859 char name [256];
4860 if (dhcp_option_ev_name (name, sizeof name,
4861 oc->option)) {
4862 const char *value;
4863 size_t length;
4865 data.data,
4866 data.len, 0, 0);
4867 length = strlen(value);
4868
4869 if (check_option_values(oc->option->universe,
4870 oc->option->code,
4871 value, length) == 0) {
4872 client_envadd(es->client, es->prefix,
4873 name, "%s", value);
4874 } else {
4875 log_error("suspect value in %s "
4876 "option - discarded",
4877 name);
4878 }
4879 }
4880 }
4881
4883 }
4884}
4885
4905void script_write_params(struct client_state *client, const char *prefix,
4906 struct client_lease *lease)
4907{
4908 int i;
4909 struct data_string data;
4910 struct option_cache *oc;
4911 struct envadd_state es;
4912
4913 es.client = client;
4914 es.prefix = prefix;
4915
4917 prefix, "ip_address", "%s", piaddr (lease -> address));
4918
4919 /* If we've set the next server address in the lease structure
4920 put it into an environment variable for the script */
4921 if (lease->next_srv_addr.len != 0) {
4922 client_envadd(client, prefix, "next_server", "%s",
4923 piaddr(lease->next_srv_addr));
4924 }
4925
4926 /* For the benefit of Linux (and operating systems which may
4927 have similar needs), compute the network address based on
4928 the supplied ip address and netmask, if provided. Also
4929 compute the broadcast address (the host address all ones
4930 broadcast address, not the host address all zeroes
4931 broadcast address). */
4932
4933 memset (&data, 0, sizeof data);
4934 oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
4935 if (oc && evaluate_option_cache (&data, (struct packet *)0,
4936 (struct lease *)0, client,
4937 (struct option_state *)0,
4938 lease -> options,
4939 &global_scope, oc, MDL)) {
4940 if (data.len > 3) {
4941 struct iaddr netmask, subnet, broadcast;
4942
4943 /*
4944 * No matter the length of the subnet-mask option,
4945 * use only the first four octets. Note that
4946 * subnet-mask options longer than 4 octets are not
4947 * in conformance with RFC 2132, but servers with this
4948 * flaw do exist.
4949 */
4950 memcpy(netmask.iabuf, data.data, 4);
4951 netmask.len = 4;
4952 data_string_forget (&data, MDL);
4953
4954 subnet = subnet_number (lease -> address, netmask);
4955 if (subnet.len) {
4956 client_envadd (client, prefix, "network_number",
4957 "%s", piaddr (subnet));
4958
4960 lease -> options,
4962 if (!oc ||
4964 (&data, (struct packet *)0,
4965 (struct lease *)0, client,
4966 (struct option_state *)0,
4967 lease -> options,
4968 &global_scope, oc, MDL))) {
4969 broadcast = broadcast_addr (subnet, netmask);
4970 if (broadcast.len) {
4971 client_envadd (client,
4972 prefix, "broadcast_address",
4973 "%s", piaddr (broadcast));
4974 }
4975 }
4976 }
4977 }
4978 data_string_forget (&data, MDL);
4979 }
4980
4981 if (lease->filename) {
4982 if (check_option_values(NULL, DHO_ROOT_PATH,
4983 lease->filename,
4984 strlen(lease->filename)) == 0) {
4985 client_envadd(client, prefix, "filename",
4986 "%s", lease->filename);
4987 } else {
4988 log_error("suspect value in %s "
4989 "option - discarded",
4990 lease->filename);
4991 }
4992 }
4993
4994 if (lease->server_name) {
4995 if (check_option_values(NULL, DHO_HOST_NAME,
4996 lease->server_name,
4997 strlen(lease->server_name)) == 0 ) {
4998 client_envadd (client, prefix, "server_name",
4999 "%s", lease->server_name);
5000 } else {
5001 log_error("suspect value in %s "
5002 "option - discarded",
5003 lease->server_name);
5004 }
5005 }
5006
5007 for (i = 0; i < lease -> options -> universe_count; i++) {
5008 option_space_foreach ((struct packet *)0, (struct lease *)0,
5009 client, (struct option_state *)0,
5010 lease -> options, &global_scope,
5011 universes [i],
5013 }
5014
5015 client_envadd (client, prefix, "expiry", "%lu",
5016 (unsigned long)(lease -> expiry));
5017}
5018
5029{
5030 int i;
5031 struct option **req;
5032 char name[256];
5033 req = client->config->requested_options;
5034
5035 if (req == NULL)
5036 return;
5037
5038 for (i = 0 ; req[i] != NULL ; i++) {
5039 if ((req[i]->universe == &dhcp_universe) &&
5040 dhcp_option_ev_name(name, sizeof(name), req[i])) {
5041 client_envadd(client, "requested_", name, "%d", 1);
5042 }
5043 }
5044}
5045
5058int script_go(struct client_state *client)
5059{
5060 char *scriptName;
5061 char *argv [2];
5062 char **envp;
5063 char reason [] = "REASON=NBI";
5064 static char client_path [] = CLIENT_PATH;
5065 int i;
5066 struct string_list *sp, *next;
5067 int pid, wpid, wstatus;
5068
5069 if (client)
5070 scriptName = client -> config -> script_name;
5071 else
5072 scriptName = top_level_config.script_name;
5073
5074 envp = dmalloc (((client ? client -> envc : 2) +
5075 client_env_count + 2) * sizeof (char *), MDL);
5076 if (!envp) {
5077 log_error ("No memory for client script environment.");
5078 return 0;
5079 }
5080 i = 0;
5081 /* Copy out the environment specified on the command line,
5082 if any. */
5083 for (sp = client_env; sp; sp = sp -> next) {
5084 envp [i++] = sp -> string;
5085 }
5086 /* Copy out the environment specified by dhclient. */
5087 if (client) {
5088 for (sp = client -> env; sp; sp = sp -> next) {
5089 envp [i++] = sp -> string;
5090 }
5091 } else {
5092 envp [i++] = reason;
5093 }
5094 /* Set $PATH. */
5095 envp [i++] = client_path;
5096 envp [i] = (char *)0;
5097
5098 argv [0] = scriptName;
5099 argv [1] = (char *)0;
5100
5101 pid = fork ();
5102 if (pid < 0) {
5103 log_error ("fork: %m");
5104 wstatus = 0;
5105 } else if (pid) {
5106 do {
5107 wpid = wait (&wstatus);
5108 } while (wpid != pid && wpid > 0);
5109 if (wpid < 0) {
5110 log_error ("wait: %m");
5111 wstatus = 0;
5112 }
5113 } else {
5114 /* We don't want to pass an open file descriptor for
5115 * dhclient.leases when executing dhclient-script.
5116 */
5117 if (leaseFile != NULL)
5118 fclose(leaseFile);
5119 execve (scriptName, argv, envp);
5120 log_error ("execve (%s, ...): %m", scriptName);
5121 exit (0);
5122 }
5123
5124 if (client) {
5125 for (sp = client -> env; sp; sp = next) {
5126 next = sp -> next;
5127 dfree (sp, MDL);
5128 }
5129 client -> env = (struct string_list *)0;
5130 client -> envc = 0;
5131 }
5132 dfree (envp, MDL);
5133 gettimeofday(&cur_tv, NULL);
5134
5135 if (!WIFEXITED(wstatus)) {
5136 int sigval = WTERMSIG(wstatus);
5137 log_error ("script_go script: %s was terminated by signal %d", scriptName, sigval);
5138 return (-sigval);
5139 }
5140
5141 return (WEXITSTATUS(wstatus));
5142}
5143
5144void client_envadd (struct client_state *client,
5145 const char *prefix, const char *name, const char *fmt, ...)
5146{
5147 char spbuf [1024];
5148 char *s;
5149 unsigned len;
5150 struct string_list *val;
5151 va_list list;
5152
5153 va_start (list, fmt);
5154 len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
5155 va_end (list);
5156
5157 val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
5158 len + sizeof *val, MDL);
5159 if (!val) {
5160 log_error ("client_envadd: cannot allocate space for variable");
5161 return;
5162 }
5163
5164 s = val -> string;
5165 strcpy (s, prefix);
5166 strcat (s, name);
5167 s += strlen (s);
5168 *s++ = '=';
5169 if (len >= sizeof spbuf) {
5170 va_start (list, fmt);
5171 vsnprintf (s, len + 1, fmt, list);
5172 va_end (list);
5173 } else {
5174 strcpy (s, spbuf);
5175 }
5176
5177 val -> next = client -> env;
5178 client -> env = val;
5179 client -> envc++;
5180}
5181
5182int dhcp_option_ev_name (buf, buflen, option)
5183 char *buf;
5184 size_t buflen;
5185 struct option *option;
5186{
5187 int i, j;
5188 const char *s;
5189
5190 j = 0;
5191 if (option -> universe != &dhcp_universe) {
5192 s = option -> universe -> name;
5193 i = 0;
5194 } else {
5195 s = option -> name;
5196 i = 1;
5197 }
5198
5199 do {
5200 while (*s) {
5201 if (j + 1 == buflen)
5202 return 0;
5203 if (*s == '-')
5204 buf [j++] = '_';
5205 else
5206 buf [j++] = *s;
5207 ++s;
5208 }
5209 if (!i) {
5210 s = option -> name;
5211 if (j + 1 == buflen)
5212 return 0;
5213 buf [j++] = '_';
5214 }
5215 ++i;
5216 } while (i != 2);
5217
5218 buf [j] = 0;
5219 return 1;
5220}
5221
5222void finish (char ret)
5223{
5224 if (no_daemon || dfd[0] == -1 || dfd[1] == -1)
5225 exit((int)ret);
5226 if (write(dfd[1], &ret, 1) != 1)
5227 log_fatal("write to parent: %m");
5228 (void) close(dfd[1]);
5229 dfd[0] = dfd[1] = -1;
5230 exit((int)ret);
5231}
5232
5233void detach ()
5234{
5235 char buf = 0;
5236
5237 /* Don't become a daemon if the user requested otherwise. */
5238 if (no_daemon) {
5240 return;
5241 }
5242
5243 /* Only do it once. */
5244 if (dfd[0] == -1 || dfd[1] == -1)
5245 return;
5246
5247 /* Signal parent we started successfully. */
5248 if (write(dfd[1], &buf, 1) != 1)
5249 log_fatal("write to parent: %m");
5250 (void) close(dfd[1]);
5251 dfd[0] = dfd[1] = -1;
5252
5253 /* Stop logging to stderr... */
5254 log_perror = 0;
5255
5256 /* Become session leader and get pid... */
5257 (void) setsid ();
5258
5259 /* Close standard I/O descriptors. */
5260 (void) close(0);
5261 (void) close(1);
5262 (void) close(2);
5263
5264 /* Reopen them on /dev/null. */
5265 (void) open("/dev/null", O_RDWR | O_CLOEXEC);
5266 (void) open("/dev/null", O_RDWR | O_CLOEXEC);
5267 (void) open("/dev/null", O_RDWR | O_CLOEXEC);
5268
5270
5271 IGNORE_RET (chdir("/"));
5272
5273}
5274
5276{
5277 FILE *pf;
5278 int pfdesc;
5279
5280 /* nothing to do if the user doesn't want a pid file */
5281 if (no_pid_file == ISC_TRUE) {
5282 return;
5283 }
5284
5285 pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
5286
5287 if (pfdesc < 0) {
5288 log_error ("Can't create %s: %m", path_dhclient_pid);
5289 return;
5290 }
5291
5292 pf = fdopen (pfdesc, "we");
5293 if (!pf) {
5294 close(pfdesc);
5295 log_error ("Can't fdopen %s: %m", path_dhclient_pid);
5296 } else {
5297 fprintf (pf, "%ld\n", (long)getpid ());
5298 fclose (pf);
5299 }
5300}
5301
5303{
5304 struct interface_info *ip;
5305 struct client_state *client;
5306
5307 for (ip = interfaces; ip; ip = ip -> next) {
5308 for (client = ip -> client; client; client = client -> next) {
5309 switch (client -> state) {
5310 case S_SELECTING:
5311 cancel_timeout (send_discover, client);
5312 break;
5313
5314 case S_BOUND:
5315 cancel_timeout (state_bound, client);
5316 break;
5317
5318 case S_REBOOTING:
5319 case S_REQUESTING:
5320 case S_RENEWING:
5321 cancel_timeout (send_request, client);
5322 break;
5323
5324 case S_INIT:
5325 case S_REBINDING:
5326 case S_STOPPED:
5327 case S_DECLINING:
5328 case S_V6ONLY:
5329 break;
5330 }
5331 client -> state = S_INIT;
5332 state_reboot (client);
5333 }
5334 }
5335}
5336
5337void do_release(client)
5338 struct client_state *client;
5339{
5340 struct data_string ds;
5341 struct option_cache *oc;
5342
5343#if defined(DHCPv6) && defined(DHCP4o6)
5344 if (dhcpv4_over_dhcpv6 && (dhcp4o6_state <= 0)) {
5345 if (dhcp4o6_state < 0)
5346 dhcp4o6_poll(NULL);
5347 client->pending = P_RELEASE;
5348 return;
5349 }
5350#endif
5351
5352 /* Pick a random xid. */
5353 client -> xid = random ();
5354
5355 /* is there even a lease to release? */
5356 if (client -> active) {
5357 /* Make a DHCPRELEASE packet, and set appropriate per-interface
5358 flags. */
5359 make_release (client, client -> active);
5360
5361 memset (&ds, 0, sizeof ds);
5363 client -> active -> options,
5365 if (oc &&
5366 evaluate_option_cache (&ds, (struct packet *)0,
5367 (struct lease *)0, client,
5368 (struct option_state *)0,
5369 client -> active -> options,
5370 &global_scope, oc, MDL)) {
5371 if (ds.len > 3) {
5372 memcpy (client -> destination.iabuf,
5373 ds.data, 4);
5374 client -> destination.len = 4;
5375 } else
5376 client -> destination = iaddr_broadcast;
5377
5378 data_string_forget (&ds, MDL);
5379 } else
5380 client -> destination = iaddr_broadcast;
5381 client -> first_sending = cur_time;
5382 client -> interval = client -> config -> initial_interval;
5383
5384 /* Zap the medium list... */
5385 client -> medium = (struct string_list *)0;
5386
5387 /* Send out the first and only DHCPRELEASE packet. */
5388 send_release (client);
5389
5390 /* Do the client script RELEASE operation. */
5391 script_init (client,
5392 "RELEASE", (struct string_list *)0);
5393 if (client -> alias)
5394 script_write_params(client, "alias_",
5395 client -> alias);
5396 script_write_params(client, "old_", client -> active);
5397 script_write_requested(client);
5398 script_go(client);
5399 }
5400
5401 /* Cancel any timeouts. */
5402 cancel_timeout (state_bound, client);
5403 cancel_timeout (send_discover, client);
5404 cancel_timeout (state_init, client);
5405 cancel_timeout (send_request, client);
5406 cancel_timeout (state_reboot, client);
5407 cancel_timeout (finish_v6only, client);
5408 client -> state = S_STOPPED;
5409
5410#if defined(DHCPv6) && defined(DHCP4o6)
5412 finish(0);
5413#endif
5414}
5415
5417{
5418 do_release (interface -> client);
5419
5420 return 1;
5421}
5422
5424{
5425 struct interface_info *last, *ip;
5426 /* See if we can find the client from dummy_interfaces */
5427 last = 0;
5428 for (ip = dummy_interfaces; ip; ip = ip -> next) {
5429 if (!strcmp (ip -> name, tmp -> name)) {
5430 /* Remove from dummy_interfaces */
5431 if (last) {
5432 ip = (struct interface_info *)0;
5433 interface_reference (&ip, last -> next, MDL);
5434 interface_dereference (&last -> next, MDL);
5435 if (ip -> next) {
5436 interface_reference (&last -> next,
5437 ip -> next, MDL);
5438 interface_dereference (&ip -> next,
5439 MDL);
5440 }
5441 } else {
5442 ip = (struct interface_info *)0;
5443 interface_reference (&ip,
5445 interface_dereference (&dummy_interfaces, MDL);
5446 if (ip -> next) {
5447 interface_reference (&dummy_interfaces,
5448 ip -> next, MDL);
5449 interface_dereference (&ip -> next,
5450 MDL);
5451 }
5452 }
5453 /* Copy "client" to tmp */
5454 if (ip -> client) {
5455 tmp -> client = ip -> client;
5456 tmp -> client -> interface = tmp;
5457 }
5458 interface_dereference (&ip, MDL);
5459 break;
5460 }
5461 last = ip;
5462 }
5463 return 1;
5464}
5465
5466isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
5467{
5468 struct interface_info *ip;
5469 struct client_state *client;
5470
5471 /* This code needs some rethinking. It doesn't test against
5472 a signal name, and it just kind of bulls into doing something
5473 that may or may not be appropriate. */
5474
5475 if (interfaces) {
5476 interface_reference (&interface -> next, interfaces, MDL);
5477 interface_dereference (&interfaces, MDL);
5478 }
5479 interface_reference (&interfaces, interface, MDL);
5480
5482
5483 for (ip = interfaces; ip; ip = ip -> next) {
5484 /* If interfaces were specified, don't configure
5485 interfaces that weren't specified! */
5486 if (ip -> flags & INTERFACE_RUNNING ||
5487 (ip -> flags & (INTERFACE_REQUESTED |
5490 continue;
5491 script_init (ip -> client,
5492 "PREINIT", (struct string_list *)0);
5493 if (ip -> client -> alias)
5494 script_write_params(ip -> client, "alias_",
5495 ip -> client -> alias);
5496 script_go(ip -> client);
5497 }
5498
5502
5503 for (ip = interfaces; ip; ip = ip -> next) {
5504 if (ip -> flags & INTERFACE_RUNNING)
5505 continue;
5506 ip -> flags |= INTERFACE_RUNNING;
5507 for (client = ip->client ; client ; client = client->next) {
5508 client->state = S_INIT;
5509 state_reboot(client);
5510 }
5511 }
5512 return ISC_R_SUCCESS;
5513}
5514
5515/* The client should never receive a relay agent information option,
5516 so if it does, log it and discard it. */
5517
5519 struct packet *packet;
5520 int len;
5521 u_int8_t *data;
5522{
5523 return 1;
5524}
5525
5526/* The client never sends relay agent information options. */
5527
5528unsigned cons_agent_information_options (cfg_options, outpacket,
5529 agentix, length)
5530 struct option_state *cfg_options;
5531 struct dhcp_packet *outpacket;
5532 unsigned agentix;
5533 unsigned length;
5534{
5535 return length;
5536}
5537
5538static void shutdown_exit (void *foo)
5539{
5540 /* get rid of the pid if we can */
5541 if (no_pid_file == ISC_FALSE)
5542 (void) unlink(path_dhclient_pid);
5543 finish(0);
5544}
5545
5546#if defined (NSUPDATE)
5547/*
5548 * If the first query fails, the updater MUST NOT delete the DNS name. It
5549 * may be that the host whose lease on the server has expired has moved
5550 * to another network and obtained a lease from a different server,
5551 * which has caused the client's A RR to be replaced. It may also be
5552 * that some other client has been configured with a name that matches
5553 * the name of the DHCP client, and the policy was that the last client
5554 * to specify the name would get the name. In this case, the DHCID RR
5555 * will no longer match the updater's notion of the client-identity of
5556 * the host pointed to by the DNS name.
5557 * -- "Interaction between DHCP and DNS"
5558 */
5559
5560/* The first and second stages are pretty similar so we combine them */
5561void
5562client_dns_remove_action(dhcp_ddns_cb_t *ddns_cb,
5563 isc_result_t eresult)
5564{
5565
5566 isc_result_t result;
5567
5568 if ((eresult == ISC_R_SUCCESS) &&
5569 (ddns_cb->state == DDNS_STATE_REM_FW_YXDHCID)) {
5570 /* Do the second stage of the FWD removal */
5571 ddns_cb->state = DDNS_STATE_REM_FW_NXRR;
5572
5573 result = ddns_modify_fwd(ddns_cb, MDL);
5574 if (result == ISC_R_SUCCESS) {
5575 return;
5576 }
5577 }
5578
5579 /* If we are done or have an error clean up */
5580 dhclient_ddns_cb_free(ddns_cb, MDL);
5581 return;
5582}
5583
5584void
5585client_dns_remove(struct client_state *client,
5586 struct iaddr *addr)
5587{
5588 dhcp_ddns_cb_t *ddns_cb;
5589 isc_result_t result;
5590
5591 /* if we have an old ddns request for this client, cancel it */
5592 if (client->ddns_cb != NULL) {
5593 ddns_cancel(client->ddns_cb, MDL);
5594 client->ddns_cb = NULL;
5595 }
5596
5597 ddns_cb = ddns_cb_alloc(MDL);
5598 if (ddns_cb != NULL) {
5599 ddns_cb->address = *addr;
5600 ddns_cb->timeout = 0;
5601
5603 ddns_cb->flags = DDNS_UPDATE_ADDR;
5604 ddns_cb->cur_func = client_dns_remove_action;
5605
5606 result = client_dns_update(client, ddns_cb);
5607
5608 if (result != ISC_R_TIMEDOUT) {
5609 dhclient_ddns_cb_free(ddns_cb, MDL);
5610 }
5611 }
5612}
5613#endif /* defined NSUPDATE */
5614
5615
5617 control_object_state_t newstate)
5618{
5619 struct interface_info *ip;
5620 struct client_state *client;
5621 struct timeval tv;
5622
5623 if (newstate == server_shutdown) {
5624 /* Re-entry */
5625 if (shutdown_signal == SIGUSR1)
5626 return ISC_R_SUCCESS;
5627 /* Log shutdown on signal. */
5628 if ((shutdown_signal == SIGINT) ||
5629 (shutdown_signal == SIGTERM)) {
5630 log_info("Received signal %d, initiating shutdown.",
5632 }
5633 /* Mark it was called. */
5634 shutdown_signal = SIGUSR1;
5635 }
5636
5637 /* Do the right thing for each interface. */
5638 for (ip = interfaces; ip; ip = ip -> next) {
5639 for (client = ip -> client; client; client = client -> next) {
5640 switch (newstate) {
5641 case server_startup:
5642 return ISC_R_SUCCESS;
5643
5644 case server_running:
5645 return ISC_R_SUCCESS;
5646
5647 case server_shutdown:
5648 if (client -> active &&
5649 client -> active -> expiry > cur_time) {
5650#if defined (NSUPDATE)
5651 if (client->config->do_forward_update) {
5652 client_dns_remove(client,
5653 &client->active->address);
5654 }
5655#endif /* defined NSUPDATE */
5656
5657 do_release (client);
5658 }
5659 break;
5660
5661 case server_hibernate:
5662 state_stop (client);
5663 break;
5664
5665 case server_awaken:
5666 state_reboot (client);
5667 break;
5668
5670 if (client->active){
5671 state_reboot (client);
5672 }
5673 break;
5674 }
5675 }
5676 }
5677
5678 if (newstate == server_shutdown) {
5679 tv.tv_sec = cur_tv.tv_sec;
5680 tv.tv_usec = cur_tv.tv_usec + 1;
5681 add_timeout(&tv, shutdown_exit, 0, 0, 0);
5682 }
5683 return ISC_R_SUCCESS;
5684}
5685
5686#if defined (NSUPDATE)
5687/*
5688 * Called after a timeout if the DNS update failed on the previous try.
5689 * Starts the retry process. If the retry times out it will schedule
5690 * this routine to run again after a 10x wait.
5691 */
5692void
5694{
5695 dhcp_ddns_cb_t *ddns_cb = (dhcp_ddns_cb_t *)cp;
5696 struct client_state *client = (struct client_state *)ddns_cb->lease;
5697 isc_result_t status = ISC_R_FAILURE;
5698
5699 if ((client != NULL) &&
5700 ((client->active != NULL) ||
5701 (client->active_lease != NULL)))
5702 status = client_dns_update(client, ddns_cb);
5703
5704 /*
5705 * A status of timedout indicates that we started the update and
5706 * have released control of the control block. Any other status
5707 * indicates that we should clean up the control block. We either
5708 * got a success which indicates that we didn't really need to
5709 * send an update or some other error in which case we weren't able
5710 * to start the update process. In both cases we still own
5711 * the control block and should free it.
5712 */
5713 if (status != ISC_R_TIMEDOUT) {
5714 dhclient_ddns_cb_free(ddns_cb, MDL);
5715 }
5716}
5717
5718/*
5719 * If the first query succeeds, the updater can conclude that it
5720 * has added a new name whose only RRs are the A and DHCID RR records.
5721 * The A RR update is now complete (and a client updater is finished,
5722 * while a server might proceed to perform a PTR RR update).
5723 * -- "Interaction between DHCP and DNS"
5724 *
5725 * If the second query succeeds, the updater can conclude that the current
5726 * client was the last client associated with the domain name, and that
5727 * the name now contains the updated A RR. The A RR update is now
5728 * complete (and a client updater is finished, while a server would
5729 * then proceed to perform a PTR RR update).
5730 * -- "Interaction between DHCP and DNS"
5731 *
5732 * If the second query fails with NXRRSET, the updater must conclude
5733 * that the client's desired name is in use by another host. At this
5734 * juncture, the updater can decide (based on some administrative
5735 * configuration outside of the scope of this document) whether to let
5736 * the existing owner of the name keep that name, and to (possibly)
5737 * perform some name disambiguation operation on behalf of the current
5738 * client, or to replace the RRs on the name with RRs that represent
5739 * the current client. If the configured policy allows replacement of
5740 * existing records, the updater submits a query that deletes the
5741 * existing A RR and the existing DHCID RR, adding A and DHCID RRs that
5742 * represent the IP address and client-identity of the new client.
5743 * -- "Interaction between DHCP and DNS"
5744 */
5745
5746/* The first and second stages are pretty similar so we combine them */
5747void
5748client_dns_update_action(dhcp_ddns_cb_t *ddns_cb,
5749 isc_result_t eresult)
5750{
5751 isc_result_t result;
5752 struct timeval tv;
5753
5754 switch(eresult) {
5755 case ISC_R_SUCCESS:
5756 default:
5757 /* Either we succeeded or broke in a bad way, clean up */
5758 break;
5759
5760 case DNS_R_YXRRSET:
5761 /*
5762 * This is the only difference between the two stages,
5763 * check to see if it is the first stage, in which case
5764 * start the second stage
5765 */
5766 if (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) {
5768 ddns_cb->cur_func = client_dns_update_action;
5769
5770 result = ddns_modify_fwd(ddns_cb, MDL);
5771 if (result == ISC_R_SUCCESS) {
5772 return;
5773 }
5774 }
5775 break;
5776
5777 case ISC_R_TIMEDOUT:
5778 /*
5779 * We got a timeout response from the DNS module. Schedule
5780 * another attempt for later. We forget the name, dhcid and
5781 * zone so if it gets changed we will get the new information.
5782 */
5783 data_string_forget(&ddns_cb->fwd_name, MDL);
5784 data_string_forget(&ddns_cb->dhcid, MDL);
5785 if (ddns_cb->zone != NULL) {
5786 forget_zone((struct dns_zone **)&ddns_cb->zone);
5787 }
5788
5789 /* Reset to doing the first stage */
5791 ddns_cb->cur_func = client_dns_update_action;
5792
5793 /* and update our timer */
5794 if (ddns_cb->timeout < 3600)
5795 ddns_cb->timeout *= 10;
5796 tv.tv_sec = cur_tv.tv_sec + ddns_cb->timeout;
5797 tv.tv_usec = cur_tv.tv_usec;
5799 ddns_cb, NULL, NULL);
5800 return;
5801 }
5802
5803 dhclient_ddns_cb_free(ddns_cb, MDL);
5804 return;
5805}
5806
5807/* See if we should do a DNS update, and if so, do it. */
5808
5809isc_result_t
5810client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
5811{
5812 struct data_string client_identifier;
5813 struct option_cache *oc;
5814 int ignorep;
5815 int result;
5816 int ddns_v4_type;
5817 isc_result_t rcode;
5818
5819 /* If we didn't send an FQDN option, we certainly aren't going to
5820 be doing an update. */
5821 if (!client -> sent_options)
5822 return ISC_R_SUCCESS;
5823
5824 /* If we don't have a lease, we can't do an update. */
5825 if ((client->active == NULL) && (client->active_lease == NULL))
5826 return ISC_R_SUCCESS;
5827
5828 /* If we set the no client update flag, don't do the update. */
5829 if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
5831 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
5832 (struct lease *)0, client,
5833 client -> sent_options,
5834 (struct option_state *)0,
5835 &global_scope, oc, MDL))
5836 return ISC_R_SUCCESS;
5837
5838 /* If we set the "server, please update" flag, or didn't set it
5839 to false, don't do the update. */
5840 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
5842 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
5843 (struct lease *)0, client,
5844 client -> sent_options,
5845 (struct option_state *)0,
5846 &global_scope, oc, MDL))
5847 return ISC_R_SUCCESS;
5848
5849 /* If no FQDN option was supplied, don't do the update. */
5850 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
5851 FQDN_FQDN)) ||
5852 !evaluate_option_cache (&ddns_cb->fwd_name, (struct packet *)0,
5853 (struct lease *)0, client,
5854 client -> sent_options,
5855 (struct option_state *)0,
5856 &global_scope, oc, MDL))
5857 return ISC_R_SUCCESS;
5858
5859 /*
5860 * Construct the DHCID value for use in the DDNS update process
5861 * We have the newer standard version and the older interim version
5862 * chosen by the '-I' option. The interim version is left as is
5863 * for backwards compatibility. The standard version is based on
5864 * RFC 4701 section 3.3
5865 */
5866
5867 result = 0;
5868 POST(result);
5869 memset(&client_identifier, 0, sizeof(client_identifier));
5870
5871 if (std_dhcid == 1) {
5872 /* standard style */
5873 ddns_cb->dhcid_class = dns_rdatatype_dhcid;
5874 ddns_v4_type = 1;
5875 } else {
5876 /* interim style */
5877 ddns_cb->dhcid_class = dns_rdatatype_txt;
5878 /* for backwards compatibility */
5879 ddns_v4_type = DHO_DHCP_CLIENT_IDENTIFIER;
5880 }
5881 if (client->active_lease != NULL) {
5882 /* V6 request, get the client identifier, then
5883 * construct the dhcid for either standard
5884 * or interim */
5885 if (((oc = lookup_option(&dhcpv6_universe,
5886 client->sent_options,
5887 D6O_CLIENTID)) != NULL) &&
5888 evaluate_option_cache(&client_identifier, NULL,
5889 NULL, client,
5890 client->sent_options, NULL,
5891 &global_scope, oc, MDL)) {
5892 result = get_dhcid(ddns_cb, 2,
5893 client_identifier.data,
5894 client_identifier.len);
5895 data_string_forget(&client_identifier, MDL);
5896 } else
5897 log_fatal("Impossible condition at %s:%d.", MDL);
5898 } else {
5899 /*
5900 * V4 request, use the client id if there is one or the
5901 * mac address if there isn't. If we have a client id
5902 * we check to see if it is an embedded DUID.
5903 */
5904 if (((oc = lookup_option(&dhcp_universe,
5905 client->sent_options,
5906 DHO_DHCP_CLIENT_IDENTIFIER)) != NULL) &&
5907 evaluate_option_cache(&client_identifier, NULL,
5908 NULL, client,
5909 client->sent_options, NULL,
5910 &global_scope, oc, MDL)) {
5911 if ((std_dhcid == 1) && (duid_v4 == 1) &&
5912 (client_identifier.data[0] == 255)) {
5913 /*
5914 * This appears to be an embedded DUID,
5915 * extract it and treat it as such
5916 */
5917 if (client_identifier.len <= 5)
5918 log_fatal("Impossible condition at %s:%d.",
5919 MDL);
5920 result = get_dhcid(ddns_cb, 2,
5921 client_identifier.data + 5,
5922 client_identifier.len - 5);
5923 } else {
5924 result = get_dhcid(ddns_cb, ddns_v4_type,
5925 client_identifier.data,
5926 client_identifier.len);
5927 }
5928 data_string_forget(&client_identifier, MDL);
5929 } else
5930 result = get_dhcid(ddns_cb, 0,
5931 client->interface->hw_address.hbuf,
5932 client->interface->hw_address.hlen);
5933 }
5934
5935 if (!result) {
5936 return ISC_R_SUCCESS;
5937 }
5938
5939 /*
5940 * Perform updates.
5941 */
5942 if (ddns_cb->fwd_name.len && ddns_cb->dhcid.len) {
5943 rcode = ddns_modify_fwd(ddns_cb, MDL);
5944 } else
5945 rcode = ISC_R_FAILURE;
5946
5947 /*
5948 * A success from the modify routine means we are performing
5949 * async processing, for which we use the timedout error message.
5950 */
5951 if (rcode == ISC_R_SUCCESS) {
5952 rcode = ISC_R_TIMEDOUT;
5953 }
5954
5955 return rcode;
5956}
5957
5958
5959/*
5960 * Schedule the first update. They will continue to retry occasionally
5961 * until they no longer time out (or fail).
5962 */
5963void
5965 struct iaddr *addr,
5966 int offset)
5967{
5968 dhcp_ddns_cb_t *ddns_cb;
5969 struct timeval tv;
5970
5971 if (!client->config->do_forward_update)
5972 return;
5973
5974 /* cancel any outstanding ddns requests */
5975 if (client->ddns_cb != NULL) {
5976 ddns_cancel(client->ddns_cb, MDL);
5977 client->ddns_cb = NULL;
5978 }
5979
5980 ddns_cb = ddns_cb_alloc(MDL);
5981
5982 if (ddns_cb != NULL) {
5983 ddns_cb->lease = (void *)client;
5984 ddns_cb->address = *addr;
5985 ddns_cb->timeout = 1;
5986
5987 /*
5988 * XXX: DNS TTL is a problem we need to solve properly.
5989 * Until that time, 300 is a placeholder default for
5990 * something that is less insane than a value scaled
5991 * by lease timeout.
5992 */
5993 ddns_cb->ttl = 300;
5994
5996 ddns_cb->cur_func = client_dns_update_action;
5998
5999 client->ddns_cb = ddns_cb;
6000 tv.tv_sec = cur_tv.tv_sec + offset;
6001 tv.tv_usec = cur_tv.tv_usec;
6003 ddns_cb, NULL, NULL);
6004 } else {
6005 log_error("Unable to allocate dns update state for %s",
6006 piaddr(*addr));
6007 }
6008}
6009#endif /* defined NSUPDATE */
6010
6011void
6013{
6014 struct servent *ent;
6015
6016 if (path_dhclient_pid == NULL)
6018 if (path_dhclient_db == NULL)
6020
6021 /* Default to the DHCP/BOOTP port. */
6022 if (!local_port) {
6023 /* If we're faking a relay agent, and we're not using loopback,
6024 use the server port, not the client port. */
6025 if (mockup_relay && giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
6026 local_port = htons(67);
6027 } else {
6028 ent = getservbyname("dhcpc", "udp");
6029 if (ent == NULL)
6030 ent = getservbyname("bootpc", "udp");
6031 if (ent == NULL)
6032 local_port = htons(68);
6033 else
6034 local_port = ent->s_port;
6035#ifndef __CYGWIN32__
6036 endservent ();
6037#endif
6038 }
6039 }
6040
6041 /* If we're faking a relay agent, and we're not using loopback,
6042 we're using the server port, not the client port. */
6043 if (mockup_relay && giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
6045 } else
6046 remote_port = htons(ntohs(local_port) - 1); /* XXX */
6047}
6048
6049/*
6050 * The following routines are used to check that certain
6051 * strings are reasonable before we pass them to the scripts.
6052 * This avoids some problems with scripts treating the strings
6053 * as commands - see ticket 23722
6054 * The domain checking code should be done as part of assembling
6055 * the string but we are doing it here for now due to time
6056 * constraints.
6057 */
6058
6059static int check_domain_name(const char *ptr, size_t len, int dots)
6060{
6061 const char *p;
6062
6063 /* not empty or complete length not over 255 characters */
6064 if ((len == 0) || (len > 256))
6065 return(-1);
6066
6067 /* consists of [[:alnum:]-]+ labels separated by [.] */
6068 /* a [_] is against RFC but seems to be "widely used"... */
6069 for (p=ptr; (*p != 0) && (len-- > 0); p++) {
6070 if ((*p == '-') || (*p == '_')) {
6071 /* not allowed at begin or end of a label */
6072 if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
6073 return(-1);
6074 } else if (*p == '.') {
6075 /* each label has to be 1-63 characters;
6076 we allow [.] at the end ('foo.bar.') */
6077 size_t d = p - ptr;
6078 if ((d <= 0) || (d >= 64))
6079 return(-1);
6080 ptr = p + 1; /* jump to the next label */
6081 if ((dots > 0) && (len > 0))
6082 dots--;
6083 } else if (isalnum((unsigned char)*p) == 0) {
6084 /* also numbers at the begin are fine */
6085 return(-1);
6086 }
6087 }
6088 return(dots ? -1 : 0);
6089}
6090
6091static int check_domain_name_list(const char *ptr, size_t len, int dots)
6092{
6093 const char *p;
6094 int ret = -1; /* at least one needed */
6095
6096 if ((ptr == NULL) || (len == 0))
6097 return(-1);
6098
6099 for (p=ptr; (*p != 0) && (len > 0); p++, len--) {
6100 if (*p != ' ')
6101 continue;
6102 if (p > ptr) {
6103 if (check_domain_name(ptr, p - ptr, dots) != 0)
6104 return(-1);
6105 ret = 0;
6106 }
6107 ptr = p + 1;
6108 }
6109 if (p > ptr)
6110 return(check_domain_name(ptr, p - ptr, dots));
6111 else
6112 return(ret);
6113}
6114
6115static int check_option_values(struct universe *universe,
6116 unsigned int opt,
6117 const char *ptr,
6118 size_t len)
6119{
6120 if (ptr == NULL)
6121 return(-1);
6122
6123 /* just reject options we want to protect, will be escaped anyway */
6124 if ((universe == NULL) || (universe == &dhcp_universe)) {
6125 switch(opt) {
6126 case DHO_DOMAIN_NAME:
6127#ifdef ACCEPT_LIST_IN_DOMAIN_NAME
6128 return check_domain_name_list(ptr, len, 0);
6129#else
6130 return check_domain_name(ptr, len, 0);
6131#endif
6132 case DHO_HOST_NAME:
6133 case DHO_NIS_DOMAIN:
6134 case DHO_NETBIOS_SCOPE:
6135 return check_domain_name(ptr, len, 0);
6136 break;
6137 case DHO_DOMAIN_SEARCH:
6138 return check_domain_name_list(ptr, len, 0);
6139 break;
6140 case DHO_ROOT_PATH:
6141 if (len == 0)
6142 return(-1);
6143 for (; (*ptr != 0) && (len-- > 0); ptr++) {
6144 if(!(isalnum((unsigned char)*ptr) ||
6145 *ptr == '#' || *ptr == '%' ||
6146 *ptr == '+' || *ptr == '-' ||
6147 *ptr == '_' || *ptr == ':' ||
6148 *ptr == '.' || *ptr == ',' ||
6149 *ptr == '@' || *ptr == '~' ||
6150 *ptr == '\\' || *ptr == '/' ||
6151 *ptr == '[' || *ptr == ']' ||
6152 *ptr == '=' || *ptr == ' '))
6153 return(-1);
6154 }
6155 return(0);
6156 break;
6157 }
6158 }
6159
6160#ifdef DHCPv6
6161 if (universe == &dhcpv6_universe) {
6162 switch(opt) {
6164 case D6O_DOMAIN_SEARCH:
6167 return check_domain_name_list(ptr, len, 0);
6168 break;
6169 }
6170 }
6171#endif
6172
6173 return(0);
6174}
6175
6176static void
6177add_reject(struct packet *packet) {
6178 struct iaddrmatchlist *list;
6179
6180 list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
6181 if (!list)
6182 log_fatal ("no memory for reject list!");
6183
6184 /*
6185 * client_addr is misleading - it is set to source address in common
6186 * code.
6187 */
6188 list->match.addr = packet->client_addr;
6189 /* Set mask to indicate host address. */
6190 list->match.mask.len = list->match.addr.len;
6191 memset(list->match.mask.iabuf, 0xff, sizeof(list->match.mask.iabuf));
6192
6193 /* Append to reject list for the source interface. */
6196
6197 /*
6198 * We should inform user that we won't be accepting this server
6199 * anymore.
6200 */
6201 log_info("Server added to list of rejected servers.");
6202}
6203
6204#if defined(NSUPDATE)
6205/* Wrapper function around common ddns_cb_free function that ensures
6206 * we set the client_state pointer to the control block to NULL. */
6207static void
6208dhclient_ddns_cb_free(dhcp_ddns_cb_t *ddns_cb, char* file, int line) {
6209 if (ddns_cb) {
6210 struct client_state *client = (struct client_state *)ddns_cb->lease;
6211 if (client != NULL) {
6212 client->ddns_cb = NULL;
6213 }
6214
6216 }
6217}
6218#endif /* defined NSUPDATE */
6219
6220#if defined(DHCPv6) && defined(DHCP4o6)
6221/*
6222 * \brief Omapi I/O handler
6223 *
6224 * The inter-process communication receive handler.
6225 *
6226 * On the DHCPv6 side, the message is either a POLL (which is answered
6227 * by a START or a STOP) or a DHCPv4-QUERY (which is forwarded to
6228 * DHCPv4 over DHCPv6 servers by forw_dhcpv4_query()).
6229 *
6230 * On the DHCPv4 side, the message is either a START, a STOP
6231 * (both for the DHCP4 over DHCPv6 state machine) or a DHCPv4-RESPONSE
6232 * (which is processed by recv_dhcpv4_response()).
6233 *
6234 * \param h the OMAPI object
6235 * \return a result for I/O success or error (used by the I/O subsystem)
6236 */
6237isc_result_t dhcpv4o6_handler(omapi_object_t *h) {
6238 char buf[65536];
6239 char start_msg[5] = { 'S', 'T', 'A', 'R', 'T' };
6240 char stop_msg[4] = { 'S', 'T', 'O', 'P' };
6241 char poll_msg[4] = { 'P', 'O', 'L', 'L' };
6242 struct data_string raw;
6243 int cc;
6244
6245 if (h->type != dhcp4o6_type)
6246 return DHCP_R_INVALIDARG;
6247
6248 cc = recv(dhcp4o6_fd, buf, sizeof(buf), 0);
6249 if (cc <= 0)
6250 return ISC_R_UNEXPECTED;
6251
6252 if (local_family == AF_INET6) {
6253 if ((cc == 4) &&
6254 (memcmp(buf, poll_msg, sizeof(poll_msg)) == 0)) {
6255 log_info("RCV: POLL");
6256 if (dhcp4o6_state < 0)
6257 cc = send(dhcp4o6_fd, stop_msg,
6258 sizeof(stop_msg), 0);
6259 else
6260 cc = send(dhcp4o6_fd, start_msg,
6261 sizeof(start_msg), 0);
6262 if (cc < 0) {
6263 log_error("dhcpv4o6_handler: send(): %m");
6264 return ISC_R_IOERROR;
6265 }
6266 } else {
6267 if (cc < DHCP_FIXED_NON_UDP + 8)
6268 return ISC_R_UNEXPECTED;
6269 memset(&raw, 0, sizeof(raw));
6270 if (!buffer_allocate(&raw.buffer, cc, MDL)) {
6271 log_error("dhcpv4o6_handler: "
6272 "no memory buffer.");
6273 return ISC_R_NOMEMORY;
6274 }
6275 raw.data = raw.buffer->data;
6276 raw.len = cc;
6277 memcpy(raw.buffer->data, buf, cc);
6278
6279 forw_dhcpv4_query(&raw);
6280
6281 data_string_forget(&raw, MDL);
6282 }
6283 } else {
6284 if ((cc == 4) &&
6285 (memcmp(buf, stop_msg, sizeof(stop_msg)) == 0)) {
6286 log_info("RCV: STOP");
6287 if (dhcp4o6_state > 0) {
6288 dhcp4o6_state = 0;
6289 dhcp4o6_poll(NULL);
6290 }
6291 } else if ((cc == 5) &&
6292 (memcmp(buf, start_msg, sizeof(start_msg)) == 0)) {
6293 log_info("RCV: START");
6294 if (dhcp4o6_state == 0)
6295 cancel_timeout(dhcp4o6_poll, NULL);
6296 dhcp4o6_state = 1;
6297 dhcp4o6_resume();
6298 } else {
6299 if (cc < DHCP_FIXED_NON_UDP + 16)
6300 return ISC_R_UNEXPECTED;
6301 memset(&raw, 0, sizeof(raw));
6302 if (!buffer_allocate(&raw.buffer, cc, MDL)) {
6303 log_error("dhcpv4o6_handler: "
6304 "no memory buffer.");
6305 return ISC_R_NOMEMORY;
6306 }
6307 raw.data = raw.buffer->data;
6308 raw.len = cc;
6309 memcpy(raw.buffer->data, buf, cc);
6310
6311 recv_dhcpv4_response(&raw);
6312
6313 data_string_forget(&raw, MDL);
6314 }
6315 }
6316
6317 return ISC_R_SUCCESS;
6318}
6319
6320/*
6321 * \brief Poll the DHCPv6 client
6322 * (DHCPv4 client function)
6323 *
6324 * A POLL message is sent to the DHCPv6 client periodically to check
6325 * if the DHCPv6 is ready (i.e., has a valid DHCPv4-over-DHCPv6 server
6326 * address option).
6327 */
6328static void dhcp4o6_poll(void *dummy) {
6329 char msg[4] = { 'P', 'O', 'L', 'L' };
6330 struct timeval tv;
6331 int cc;
6332
6333 IGNORE_UNUSED(dummy);
6334
6335 if (dhcp4o6_state < 0)
6336 dhcp4o6_state = 0;
6337
6338 log_info("POLL");
6339
6340 cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
6341 if (cc < 0)
6342 log_error("dhcp4o6_poll: send(): %m");
6343
6344 tv.tv_sec = cur_time + 60;
6345 tv.tv_usec = random() % 1000000;
6346
6347 add_timeout(&tv, dhcp4o6_poll, NULL, 0, 0);
6348}
6349
6350/*
6351 * \brief Resume pending operations
6352 * (DHCPv4 client function)
6353 *
6354 * A START message was received from the DHCPv6 client so pending
6355 * operations (RELEASE or REBOOT) must be resumed.
6356 */
6357static void dhcp4o6_resume() {
6358 struct interface_info *ip;
6359 struct client_state *client;
6360
6361 for (ip = interfaces; ip != NULL; ip = ip->next) {
6362 for (client = ip->client; client != NULL;
6363 client = client->next) {
6364 if (client->pending == P_RELEASE)
6365 do_release(client);
6366 else if (client->pending == P_REBOOT)
6367 state_reboot(client);
6368 }
6369 }
6370}
6371
6372/*
6373 * \brief Send a START to the DHCPv4 client
6374 * (DHCPv6 client function)
6375 *
6376 * First check if there is a valid DHCPv4-over-DHCPv6 server address option,
6377 * and when found go UP and on a transition from another state send
6378 * a START message to the DHCPv4 client.
6379 */
6380void dhcp4o6_start() {
6381 struct interface_info *ip;
6382 struct client_state *client;
6383 struct dhc6_lease *lease;
6384 struct option_cache *oc;
6385 struct data_string addrs;
6386 char msg[5] = { 'S', 'T', 'A', 'R', 'T' };
6387 int cc;
6388
6389 memset(&addrs, 0, sizeof(addrs));
6390 for (ip = interfaces; ip != NULL; ip = ip->next) {
6391 for (client = ip->client; client != NULL;
6392 client = client->next) {
6393 if ((client->state != S_BOUND) &&
6394 (client->state != S_RENEWING) &&
6395 (client->state != S_REBINDING))
6396 continue;
6397 lease = client->active_lease;
6398 if ((lease == NULL) || lease->released)
6399 continue;
6401 lease->options,
6403 if ((oc == NULL) ||
6404 !evaluate_option_cache(&addrs, NULL, NULL, NULL,
6405 lease->options, NULL,
6406 &global_scope, oc, MDL))
6407 continue;
6408 if ((addrs.len % 16) != 0) {
6409 data_string_forget(&addrs, MDL);
6410 continue;
6411 }
6412 data_string_forget(&addrs, MDL);
6413 goto found;
6414 }
6415 }
6416 log_info("dhcp4o6_start: failed");
6417 dhcp4o6_stop();
6418 return;
6419
6420found:
6421 if (dhcp4o6_state == 1)
6422 return;
6423 log_info("dhcp4o6_start: go to UP");
6424 dhcp4o6_state = 1;
6425
6426 cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
6427 if (cc < 0)
6428 log_info("dhcp4o6_start: send(): %m");
6429}
6430
6431/*
6432 * Send a STOP to the DHCPv4 client
6433 * (DHCPv6 client function)
6434 *
6435 * Go DOWN and on a transition from another state send a STOP message
6436 * to the DHCPv4 client.
6437 */
6438static void dhcp4o6_stop() {
6439 char msg[4] = { 'S', 'T', 'O', 'P' };
6440 int cc;
6441
6442 if (dhcp4o6_state == -1)
6443 return;
6444
6445 log_info("dhcp4o6_stop: go to DOWN");
6446 dhcp4o6_state = -1;
6447
6448 cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
6449 if (cc < 0)
6450 log_error("dhcp4o6_stop: send(): %m");
6451}
6452#endif /* DHCPv6 && DHCP4o6 */
#define IGNORE_UNUSED(x)
Definition cdefs.h:67
#define IGNORE_RET(x)
Definition cdefs.h:54
struct option * default_requested_options[NUM_DEFAULT_REQUESTED_OPTS+2+1]
Definition clparse.c:36
void read_client_leases()
Definition clparse.c:369
isc_result_t read_client_conf()
Definition clparse.c:58
void parse_client_statement(struct parse *cfile, struct interface_info *ip, struct client_config *config)
Definition clparse.c:438
void read_client_duid()
Definition clparse.c:333
struct client_config top_level_config
Definition clparse.c:32
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
Definition alloc.c:679
void data_string_forget(struct data_string *data, const char *file, int line)
Definition alloc.c:1339
int option_state_reference(struct option_state **ptr, struct option_state *bp, const char *file, int line)
Definition alloc.c:883
int option_state_allocate(struct option_state **ptr, const char *file, int line)
Definition alloc.c:846
int option_state_dereference(struct option_state **ptr, const char *file, int line)
Definition alloc.c:911
int packet_dereference(struct packet **ptr, const char *file, int line)
Definition alloc.c:1081
void free_client_lease(struct client_lease *lease, const char *file, int line)
Definition alloc.c:369
struct client_lease * new_client_lease(char *file, int line) const
Definition alloc.c:361
int packet_allocate(struct packet **ptr, const char *file, int line)
Definition alloc.c:1015
int buffer_dereference(struct buffer **ptr, const char *file, int line)
Definition alloc.c:726
enum dhcp_token peek_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition conflex.c:443
isc_result_t end_parse(struct parse **cfile)
Definition conflex.c:103
isc_result_t new_parse(struct parse **cfile, int file, char *inbuf, unsigned buflen, const char *name, int eolp)
Definition conflex.c:41
void add_timeout(struct timeval *when, void *where, void *what, tvref_t ref, tvunref_t unref)
Definition dispatch.c:206
void dispatch(void)
Definition dispatch.c:109
void cancel_timeout(void *where, void *what)
Definition dispatch.c:390
void save_option(struct universe *universe, struct option_state *options, struct option_cache *oc)
Definition options.c:2818
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
Definition options.c:2953
const char * pretty_print_option(struct option *option, const unsigned char *data, unsigned len, int emit_commas, int emit_quotes)
Definition options.c:1793
int parse_encapsulated_suboptions(struct option_state *options, struct option *eopt, const unsigned char *buffer, unsigned len, struct universe *eu, const char *uname)
Definition options.c:337
int parse_options(struct packet *packet)
Definition options.c:49
void option_space_foreach(struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff, void(*func)(struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *))
Definition options.c:3789
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
Definition options.c:2503
void do_packet(struct interface_info *interface, struct dhcp_packet *packet, unsigned len, unsigned int from_port, struct iaddr from, struct hardware *hfrom)
Definition options.c:4045
int cons_options(struct packet *inpacket, struct dhcp_packet *outpacket, struct lease *lease, struct client_state *client_state, int mms, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, int overload_avail, int terminate, int bootpp, struct data_string *prl, const char *vuname)
Definition options.c:538
int validate_packet(struct packet *packet)
Definition options.c:4538
char * format_lease_id(const unsigned char *s, unsigned len, int format, const char *file, int line)
Definition print.c:1427
char * quotify_string(const char *s, const char *file, int line)
Definition print.c:33
char * absolute_path(const char *orgpath)
Definition print.c:1453
const char * print_time(TIME t)
Definition print.c:1312
void dump_raw(unsigned char *buf, unsigned len) const
Definition print.c:293
#define _PATH_DHCLIENT_DB
Definition config.h:316
#define _PATH_DHCLIENT_PID
Definition config.h:319
#define PACKAGE_VERSION
Definition config.h:168
#define ISC_PATH_RANDOMDEV
Definition config.h:135
void putUShort(unsigned char *, u_int32_t)
Definition convert.c:86
u_int32_t getULong(const unsigned char *)
void putULong(unsigned char *, u_int32_t)
Definition convert.c:70
isc_boolean_t
Definition data.h:150
#define ISC_TRUE
Definition data.h:153
#define ISC_FALSE
Definition data.h:152
#define DHCLIENT_USAGEH
Definition dhclient.c:212
void finish_v6only(void *cpp)
Definition dhclient.c:1755
#define DHCLIENT_USAGE0
Definition dhclient.c:197
int script_go(struct client_state *client)
Calls external script.
Definition dhclient.c:5058
int parse_agent_information_option(struct packet *packet, int len, u_int8_t *data)
Definition dhclient.c:5518
TIME default_lease_time
Definition dhclient.c:54
int client_env_count
Definition dhclient.c:105
void bootp(struct packet *packet)
Definition dhclient.c:2256
void dhcpv4_client_assignments(void)
Definition dhclient.c:6012
int asprintf(char **strp, const char *fmt,...)
int wanted_ia_pd
Definition dhclient.c:112
isc_result_t read_uuid(u_int8_t *uuid)
Definition dhclient.c:4328
void bind_lease(struct client_state *client)
Definition dhclient.c:2071
isc_boolean_t no_pid_file
Definition dhclient.c:67
void dhcp(struct packet *packet)
Definition dhclient.c:2289
void state_stop(void *cpp)
Definition dhclient.c:2209
int dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
Definition dhclient.c:5182
unsigned cons_agent_information_options(struct option_state *cfg_options, struct dhcp_packet *outpacket, unsigned agentix, unsigned length)
Definition dhclient.c:5528
#define DHCLIENT_USAGEC
Definition dhclient.c:202
int std_dhcid
Definition dhclient.c:81
int leases_written
Definition dhclient.c:4193
void finish(char ret)
Definition dhclient.c:5222
int interfaces_requested
Definition dhclient.c:71
int dfd[2]
Definition dhclient.c:103
FILE * scriptFile
Definition dhclient.c:4797
void start_v6only(struct client_state *client, uint32_t v6only_wait)
Definition dhclient.c:1769
int address_prefix_len
Definition dhclient.c:121
int dhclient_interface_discovery_hook(struct interface_info *tmp)
Definition dhclient.c:5423
void dhcpnak(struct packet *packet)
Definition dhclient.c:2848
int main(int argc, char **argv)
Definition dhclient.c:241
struct iaddr iaddr_broadcast
Definition dhclient.c:73
struct string_list * client_env
Definition dhclient.c:104
void script_write_params(struct client_state *client, const char *prefix, struct client_lease *lease)
Adds parameters to environment variables for a script.
Definition dhclient.c:4905
struct in_addr inaddr_any
Definition dhclient.c:75
int wanted_ia_ta
Definition dhclient.c:111
int stateless
Definition dhclient.c:109
void make_discover(struct client_state *client, struct client_lease *lease)
Definition dhclient.c:3909
int onetry
Definition dhclient.c:106
int dhcp_max_agent_option_packet_length
Definition dhclient.c:69
void send_discover(void *cpp)
Definition dhclient.c:2927
void make_request(struct client_state *client, struct client_lease *lease)
Definition dhclient.c:3974
void initialize_client_option_spaces()
int write_host(struct host_decl *host)
Definition dhclient.c:2245
int quiet
Definition dhclient.c:107
void state_init(void *cpp)
Definition dhclient.c:1678
uint32_t check_v6only(struct packet *packet, struct client_state *client)
Definition dhclient.c:1703
int require_all_ias
Definition dhclient.c:113
struct iaddr iaddr_any
Definition dhclient.c:74
void make_client_options(struct client_state *client, struct client_lease *lease, u_int8_t *type, struct option_cache *sid, struct iaddr *rip, struct option **prl, struct option_state **op)
Definition dhclient.c:3759
struct sockaddr_in sockaddr_broadcast
Definition dhclient.c:76
int commit_leases()
Definition dhclient.c:2234
int bootp_broadcast_always
Definition dhclient.c:126
isc_result_t dhclient_interface_startup_hook(struct interface_info *interface)
Definition dhclient.c:5466
int no_daemon
Definition dhclient.c:102
void run_stateless(int exit_mode, u_int16_t port)
Definition dhclient.c:1425
void client_location_changed()
Definition dhclient.c:5302
void discard_duplicate(struct client_lease **lease_list, struct client_lease *lease)
Definition dhclient.c:3065
const char * path_dhclient_duid
Definition dhclient.c:62
int duid_v4
Definition dhclient.c:80
isc_result_t write_client6_lease(struct client_state *client, struct dhc6_lease *lease, int rewrite, int sync)
Definition dhclient.c:4501
int check_collection(struct packet *packet, struct lease *lease, struct collection *collection)
Definition dhclient.c:1548
void state_panic(void *cpp)
Definition dhclient.c:3150
char * mockup_relay
Definition dhclient.c:122
u_int16_t remote_port
Definition discover.c:49
struct in_addr giaddr
Definition dhclient.c:77
int write_client_lease(struct client_state *client, struct client_lease *lease, int rewrite, int makesure)
Definition dhclient.c:4655
void send_release(void *cpp)
Definition dhclient.c:3519
void dhcpack(struct packet *packet)
Definition dhclient.c:1888
u_int16_t local_port
Definition discover.c:48
void state_reboot(void *cpp)
Definition dhclient.c:1625
void write_client_pid_file()
Definition dhclient.c:5275
int unhexchar(char c)
Definition dhclient.c:4313
void classify(struct packet *packet, struct class *class)
Definition dhclient.c:1556
FILE * leaseFile
Definition dhclient.c:4192
void do_release(struct client_state *client)
Definition dhclient.c:5337
const char * path_dhclient_db
Definition dhclient.c:58
char scriptName[256]
Definition dhclient.c:4796
void rewrite_client_leases()
Definition dhclient.c:4195
void destroy_client_lease(struct client_lease *lease)
Definition dhclient.c:4181
const char * path_dhclient_conf
Definition dhclient.c:57
isc_result_t find_class(struct class **c, const char *s, const char *file, int line)
Definition dhclient.c:1542
isc_result_t dhcp_set_control_state(control_object_state_t oldstate, control_object_state_t newstate)
Definition dhclient.c:5616
void make_release(struct client_state *client, struct client_lease *lease)
Definition dhclient.c:4124
int nowait
Definition dhclient.c:108
char * progname
Definition dhclient.c:124
int wanted_ia_na
Definition dhclient.c:110
void send_decline(void *cpp)
Definition dhclient.c:3477
int find_subnet(struct subnet **sp, struct iaddr addr, const char *file, int line)
Definition dhclient.c:1567
void detach()
Definition dhclient.c:5233
struct client_lease * packet_to_lease(struct packet *packet, struct client_state *client)
Definition dhclient.c:2725
int dhclient_interface_shutdown_hook(struct interface_info *interface)
Definition dhclient.c:5416
int decline_wait_time
Definition dhclient.c:83
void unbill_class(struct lease *lease)
Definition dhclient.c:1562
void script_write_requested(struct client_state *client)
Write out the environent variable the client requested. Write out the environment variables for the o...
Definition dhclient.c:5028
void client_option_envadd(struct option_cache *oc, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff)
Definition dhclient.c:4844
void write_lease_option(struct option_cache *oc, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff)
Definition dhclient.c:4257
void send_request(void *cpp)
Definition dhclient.c:3265
void db_startup(int testp)
Definition dhclient.c:2251
void make_decline(struct client_state *client, struct client_lease *lease)
Definition dhclient.c:4064
int write_lease(struct lease *lease)
Definition dhclient.c:2239
#define ASSERT_STATE(state_is, state_shouldbe)
Definition dhclient.c:87
TIME max_lease_time
Definition dhclient.c:55
void client_envadd(struct client_state *client, const char *prefix, const char *name, const char *fmt,...)
Definition dhclient.c:5144
struct data_string default_duid
Definition dhclient.c:78
int duid_type
Definition dhclient.c:79
void state_bound(void *cpp)
Definition dhclient.c:2167
isc_result_t form_duid(struct data_string *duid, const char *file, int line)
Definition dhclient.c:4381
void dhcpoffer(struct packet *packet)
Definition dhclient.c:2576
void state_selecting(void *cpp)
Definition dhclient.c:1803
void script_init(struct client_state *client, const char *reason, struct string_list *medium)
Initializes basic variables for a script.
Definition dhclient.c:4811
const char * path_dhclient_pid
Definition dhclient.c:59
char * path_dhclient_script
Definition dhclient.c:61
#define D6O_CLIENTID
Definition dhcp6.h:30
#define D6O_NIS_DOMAIN_NAME
Definition dhcp6.h:58
#define D6O_SIP_SERVERS_DNS
Definition dhcp6.h:50
#define DUID_UUID
Definition dhcp6.h:170
#define DHCP4O6_QUERY_UNICAST
Definition dhcp6.h:256
#define DHCPV6_REPLY
Definition dhcp6.h:146
#define D6O_NISP_DOMAIN_NAME
Definition dhcp6.h:59
#define D6O_DHCP4_O_DHCP6_SERVER
Definition dhcp6.h:117
#define D6O_DHCPV4_MSG
Definition dhcp6.h:116
#define D6O_IA_PD
Definition dhcp6.h:54
#define D6O_DOMAIN_SEARCH
Definition dhcp6.h:53
#define DUID_LL
Definition dhcp6.h:169
#define DHCPV6_DHCPV4_QUERY
Definition dhcp6.h:159
#define All_DHCP_Relay_Agents_and_Servers
Definition dhcp6.h:189
#define DUID_TIME_EPOCH
Definition dhcp6.h:275
#define DUID_LLT
Definition dhcp6.h:167
#define DHCPV6_RECONFIGURE
Definition dhcp6.h:149
#define DHCPV6_ADVERTISE
Definition dhcp6.h:141
#define D6O_IA_TA
Definition dhcp6.h:33
#define D6O_IA_NA
Definition dhcp6.h:32
#define DHCPV6_DHCPV4_RESPONSE
Definition dhcp6.h:160
#define HTYPE_RESERVED
Definition dhcp.h:81
#define DHCPREQUEST
Definition dhcp.h:172
#define DHO_VENDOR_ENCAPSULATED_OPTIONS
Definition dhcp.h:132
#define BOOTP_MIN_LEN
Definition dhcp.h:39
#define DHCPRELEASE
Definition dhcp.h:176
#define FQDN_FQDN
Definition dhcp.h:200
#define DHO_DHCP_PARAMETER_REQUEST_LIST
Definition dhcp.h:144
#define DHO_NETBIOS_SCOPE
Definition dhcp.h:136
#define DHCPNAK
Definition dhcp.h:175
#define DHCP_SNAME_LEN
Definition dhcp.h:34
#define DHCPACK
Definition dhcp.h:174
#define DHCP_FILE_LEN
Definition dhcp.h:35
#define DHO_NIS_DOMAIN
Definition dhcp.h:129
#define BOOTREPLY
Definition dhcp.h:69
#define DHO_HOST_NAME
Definition dhcp.h:101
#define DHO_BROADCAST_ADDRESS
Definition dhcp.h:117
#define DHO_DOMAIN_SEARCH
Definition dhcp.h:162
#define FQDN_SERVER_UPDATE
Definition dhcp.h:194
#define DHCP_FIXED_NON_UDP
Definition dhcp.h:36
#define DHO_DHCP_CLIENT_IDENTIFIER
Definition dhcp.h:150
#define FQDN_NO_CLIENT_UPDATE
Definition dhcp.h:193
#define DHO_DHCP_MESSAGE_TYPE
Definition dhcp.h:142
#define BOOTREQUEST
Definition dhcp.h:68
#define DHCPDISCOVER
Definition dhcp.h:170
#define DHO_DOMAIN_NAME
Definition dhcp.h:104
#define DHO_DHCP_RENEWAL_TIME
Definition dhcp.h:147
#define BOOTP_BROADCAST
Definition dhcp.h:72
#define DHCPOFFER
Definition dhcp.h:171
#define DHO_V6_ONLY_PREFERRED
Definition dhcp.h:160
#define DHO_DHCP_REBINDING_TIME
Definition dhcp.h:148
#define DHO_DHCP_OPTION_OVERLOAD
Definition dhcp.h:141
#define DHO_DHCP_SERVER_IDENTIFIER
Definition dhcp.h:143
#define DHO_ROOT_PATH
Definition dhcp.h:106
#define HTYPE_INFINIBAND
Definition dhcp.h:78
#define DHO_DHCP_REQUESTED_ADDRESS
Definition dhcp.h:139
#define DHO_DHCP_LEASE_TIME
Definition dhcp.h:140
#define DHO_SUBNET_MASK
Definition dhcp.h:90
#define DHCP_MAX_OPTION_LEN
Definition dhcp.h:44
#define DHCPDECLINE
Definition dhcp.h:173
#define DHCP_LOG_OPTIONS
Definition dhcpd.h:1636
#define INTERFACE_RUNNING
Definition dhcpd.h:1426
#define DISCOVER_REQUESTED
Definition dhcpd.h:701
void do_packet6(struct interface_info *, const char *, int, int, const struct iaddr *, isc_boolean_t)
void unconfigure6(struct client_state *client, const char *reason)
#define INTERFACE_REQUESTED
Definition dhcpd.h:1424
control_object_state_t
Definition dhcpd.h:522
@ server_time_changed
Definition dhcpd.h:528
@ server_awaken
Definition dhcpd.h:527
@ server_startup
Definition dhcpd.h:523
@ server_shutdown
Definition dhcpd.h:525
@ server_hibernate
Definition dhcpd.h:526
@ server_running
Definition dhcpd.h:524
@ P_NONE
Definition dhcpd.h:1221
@ P_RELEASE
Definition dhcpd.h:1223
@ P_REBOOT
Definition dhcpd.h:1222
#define DISCOVER_RUNNING
Definition dhcpd.h:696
#define MIN_LEASE_WRITE
Definition dhcpd.h:877
void start_info_request6(struct client_state *client)
#define DDNS_INCLUDE_RRSET
Definition dhcpd.h:1779
time_t TIME
Definition dhcpd.h:85
struct timeval cur_tv
Definition dispatch.c:35
struct dhcp_ddns_cb dhcp_ddns_cb_t
void ddns_cancel(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
#define DDNS_STATE_REM_FW_NXRR
Definition dhcpd.h:1804
#define DDNS_STATE_ADD_FW_YXDHCID
Definition dhcpd.h:1799
void dhcp_common_objects_setup(void)
void dump_packet(struct packet *)
isc_result_t ddns_modify_fwd(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
#define MIN_V6ONLY_WAIT
Definition dhcpd.h:885
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
#define cur_time
Definition dhcpd.h:2126
#define _PATH_DHCLIENT_SCRIPT
Definition dhcpd.h:1595
void start_release6(struct client_state *client)
#define DDNS_STATE_ADD_FW_NXDOMAIN
Definition dhcpd.h:1798
#define DDNS_UPDATE_ADDR
Definition dhcpd.h:1777
void client_dns_remove(struct client_state *client, struct iaddr *addr)
@ S_V6ONLY
Definition dhcpd.h:1216
@ S_STOPPED
Definition dhcpd.h:1215
@ S_DECLINING
Definition dhcpd.h:1214
int can_receive_unicast_unconfigured(struct interface_info *)
void dhclient_schedule_updates(struct client_state *client, struct iaddr *addr, int offset)
void dhcpv6_client_assignments(void)
void dhcp4o6_start(void)
struct universe dhcp_universe
void(* dhcpv6_packet_handler)(struct interface_info *, const char *, int, int, const struct iaddr *, isc_boolean_t)
void start_confirm6(struct client_state *client)
#define DDNS_STATE_REM_FW_YXDHCID
Definition dhcpd.h:1803
#define INTERFACE_AUTOMATIC
Definition dhcpd.h:1425
void forget_zone(struct dns_zone **)
const char int line
Definition dhcpd.h:3802
#define DISCOVER_UNCONFIGURED
Definition dhcpd.h:698
#define _PATH_DHCLIENT_CONF
Definition dhcpd.h:1591
ssize_t send_packet6(struct interface_info *, const unsigned char *, size_t, struct sockaddr_in6 *)
dhcp_ddns_cb_t * ddns_cb_alloc(const char *file, int line)
void client_dns_update_timeout(void *cp)
int get_dhcid(dhcp_ddns_cb_t *, int, const u_int8_t *, unsigned)
isc_result_t client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
void start_init6(struct client_state *client)
void dhcpv6(struct packet *)
void ddns_cb_free(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
const char * file
Definition dhcpd.h:3802
#define print_hex_1(len, data, limit)
Definition dhcpd.h:2638
int local_family
Definition discover.c:59
struct interface_info * interfaces
Definition discover.c:42
struct interface_info * fallback_interface
Definition discover.c:44
void discover_interfaces(int state)
Definition discover.c:571
int dhcpv4_over_dhcpv6
Definition discover.c:51
int(* dhcp_interface_discovery_hook)(struct interface_info *)
Definition discover.c:53
int quiet_interface_discovery
Definition discover.c:47
void reinitialize_interfaces()
Definition discover.c:1078
void(* bootp_packet_handler)(struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *)
Definition discover.c:70
int(* dhcp_interface_shutdown_hook)(struct interface_info *)
Definition discover.c:55
struct interface_info * dummy_interfaces
Definition discover.c:43
isc_result_t(* dhcp_interface_startup_hook)(struct interface_info *)
Definition discover.c:54
void execute_statements_in_scope(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct group *group, struct group *limiting_group, struct on_star *on_star)
Definition execute.c:570
@ TOKEN_OCTAL
Definition dhctoken.h:378
@ END_OF_FILE
Definition dhctoken.h:307
@ TOKEN_HEX
Definition dhctoken.h:377
u_int16_t validate_port(char *port)
Definition inet.c:659
const char * piaddr(const struct iaddr addr)
Definition inet.c:579
struct iaddr broadcast_addr(struct iaddr subnet, struct iaddr mask)
Definition inet.c:112
u_int16_t validate_port_pair(char *port)
Definition inet.c:685
int addr_match(struct iaddr *addr, struct iaddrmatch *match)
Definition inet.c:184
struct iaddr subnet_number(struct iaddr addr, struct iaddr mask)
Definition inet.c:34
char * piaddrmask(struct iaddr *addr, struct iaddr *mask)
Definition inet.c:606
isc_result_t dhcp_context_create(int flags, struct in_addr *local4, struct in6_addr *local6)
Definition isclib.c:167
int shutdown_signal
Definition isclib.c:34
#define DHCP_DNS_CLIENT_LAZY_INIT
Definition isclib.h:136
void dhcp_signal_handler(int signal)
Definition isclib.c:378
#define DHCP_CONTEXT_PRE_DB
Definition isclib.h:134
#define DHCP_CONTEXT_POST_DB
Definition isclib.h:135
#define S_SELECTING
#define ISC_R_SUCCESS
#define S_REBOOTING
#define S_REBINDING
#define S_REQUESTING
#define S_BOUND
#define S_RENEWING
#define S_INIT
#define MDL
Definition omapip.h:567
isc_result_t omapi_generic_new(omapi_object_t **, const char *, int)
isc_result_t omapi_protocol_listen(omapi_object_t *, unsigned, int)
Definition protocol.c:997
const char int
Definition omapip.h:442
struct __omapi_object omapi_object_t
Definition omapip.h:39
isc_result_t omapi_init(void)
Definition support.c:61
void * dmalloc(size_t, const char *, int)
Definition alloc.c:57
void dfree(void *, const char *, int)
Definition alloc.c:145
int log_error(const char *,...) __attribute__((__format__(__printf__
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
int log_perror
Definition errwarn.c:43
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int int log_info(const char *,...) __attribute__((__format__(__printf__
#define TIME_MAX
Definition osdep.h:82
#define STDERR_FILENO
Definition osdep.h:287
#define DHCP_R_INVALIDARG
Definition result.h:49
#define DHCLIENT_DEFAULT_PREFIX_LEN
Definition site.h:288
Definition tree.h:60
unsigned char data[1]
Definition tree.h:62
TIME initial_interval
Definition dhcpd.h:1251
struct option ** required_options
Definition dhcpd.h:1243
int bootp_broadcast_always
Definition dhcpd.h:1292
struct group * on_transmission
Definition dhcpd.h:1241
struct iaddrmatchlist * reject_list
Definition dhcpd.h:1280
struct option ** requested_options
Definition dhcpd.h:1244
TIME backoff_cutoff
Definition dhcpd.h:1263
struct group * on_receipt
Definition dhcpd.h:1236
int do_forward_update
Definition dhcpd.h:1285
TIME retry_interval
Definition dhcpd.h:1253
unsigned int is_static
Definition dhcpd.h:1152
struct string_list * medium
Definition dhcpd.h:1149
TIME renewal
Definition dhcpd.h:1145
struct iaddr address
Definition dhcpd.h:1146
char * filename
Definition dhcpd.h:1148
char * server_name
Definition dhcpd.h:1147
unsigned int is_bootp
Definition dhcpd.h:1153
struct client_lease * next
Definition dhcpd.h:1144
struct option_state * options
Definition dhcpd.h:1155
TIME rebind
Definition dhcpd.h:1145
TIME expiry
Definition dhcpd.h:1145
struct client_lease * alias
Definition dhcpd.h:1317
char * name
Definition dhcpd.h:1301
struct dhc6_lease * active_lease
Definition dhcpd.h:1334
struct client_lease * active
Definition dhcpd.h:1313
void(* v6_handler)(struct packet *, struct client_state *)
Definition dhcpd.h:1357
struct dhcp_packet packet
Definition dhcpd.h:1325
struct client_config * config
Definition dhcpd.h:1304
struct client_lease * leases
Definition dhcpd.h:1316
enum dhcp_state state
Definition dhcpd.h:1308
struct dhcp_ddns_cb * ddns_cb
Definition dhcpd.h:1365
struct interface_info * interface
Definition dhcpd.h:1300
struct iaddr requested_address
Definition dhcpd.h:1328
enum dhcp_pending pending
Definition dhcpd.h:1310
struct client_state * next
Definition dhcpd.h:1299
TIME last_write
Definition dhcpd.h:1309
struct iaddr destination
Definition dhcpd.h:1319
struct option_state * sent_options
Definition dhcpd.h:1307
struct string_list * medium
Definition dhcpd.h:1324
u_int32_t xid
Definition dhcpd.h:1320
struct client_lease * new
Definition dhcpd.h:1314
unsigned packet_length
Definition dhcpd.h:1326
unsigned char dhcpv6_transaction_id[3]
Definition dhcpd.h:1331
TIME interval
Definition dhcpd.h:1323
TIME first_sending
Definition dhcpd.h:1322
struct buffer * buffer
Definition tree.h:77
const unsigned char * data
Definition tree.h:78
unsigned len
Definition tree.h:79
u_int8_t plen
Definition dhcpd.h:1163
u_int32_t preferred_life
Definition dhcpd.h:1172
u_int32_t max_life
Definition dhcpd.h:1173
TIME starts
Definition dhcpd.h:1171
struct dhc6_addr * next
Definition dhcpd.h:1161
struct iaddr address
Definition dhcpd.h:1162
struct option_state * options
Definition dhcpd.h:1175
struct option_state * options
Definition dhcpd.h:1188
struct dhc6_ia * next
Definition dhcpd.h:1179
u_int32_t renew
Definition dhcpd.h:1184
struct dhc6_addr * addrs
Definition dhcpd.h:1186
unsigned char iaid[4]
Definition dhcpd.h:1180
u_int16_t ia_type
Definition dhcpd.h:1181
TIME starts
Definition dhcpd.h:1183
u_int32_t rebind
Definition dhcpd.h:1185
isc_boolean_t released
Definition dhcpd.h:1195
void * lease
Definition dhcpd.h:1842
struct data_string fwd_name
Definition dhcpd.h:1820
TIME timeout
Definition dhcpd.h:1835
u_int16_t flags
Definition dhcpd.h:1834
dns_rdataclass_t dhcid_class
Definition dhcpd.h:1848
struct dns_zone * zone
Definition dhcpd.h:1832
ddns_action_t cur_func
Definition dhcpd.h:1837
struct iaddr address
Definition dhcpd.h:1823
unsigned long ttl
Definition dhcpd.h:1826
struct data_string dhcid
Definition dhcpd.h:1822
struct in_addr siaddr
Definition dhcp.h:57
struct in_addr ciaddr
Definition dhcp.h:55
struct in_addr yiaddr
Definition dhcp.h:56
unsigned char msg_type
Definition dhcp6.h:252
unsigned char flags[3]
Definition dhcp6.h:253
unsigned char options[FLEXIBLE_ARRAY_MEMBER]
Definition dhcp6.h:254
struct client_state * client
Definition dhcpd.h:1369
const char * prefix
Definition dhcpd.h:1370
union executable_statement::@336221350347175166011011356261373334214214051201 data
struct option_cache * option
Definition statement.h:65
Definition dhcpd.h:962
struct group * next
Definition dhcpd.h:963
struct executable_statement * statements
Definition dhcpd.h:970
u_int8_t hlen
Definition dhcpd.h:492
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
Definition dhcpd.h:493
Definition inet.h:31
unsigned char iabuf[16]
Definition inet.h:33
unsigned len
Definition inet.h:32
struct iaddr addr
Definition inet.h:54
struct iaddr mask
Definition inet.h:55
struct iaddrmatch match
Definition inet.h:62
struct iaddrmatchlist * next
Definition inet.h:61
char name[IFNAMSIZ]
Definition dhcpd.h:1408
struct interface_info * next
Definition dhcpd.h:1383
struct client_state * client
Definition dhcpd.h:1432
struct hardware hw_address
Definition dhcpd.h:1386
u_int32_t flags
Definition dhcpd.h:1423
Definition ip.h:47
Definition dhcpd.h:560
struct lease * next
Definition dhcpd.h:562
struct host_decl * host
Definition dhcpd.h:576
struct option * option
Definition dhcpd.h:389
int universe_count
Definition dhcpd.h:398
Definition tree.h:345
const char * format
Definition tree.h:347
unsigned code
Definition tree.h:349
struct universe * universe
Definition tree.h:348
const char * name
Definition tree.h:346
int client_port
Definition dhcpd.h:431
struct dhcp_packet * raw
Definition dhcpd.h:406
unsigned char dhcpv6_msg_type
Definition dhcpd.h:411
struct interface_info * interface
Definition dhcpd.h:433
struct option_state * options
Definition dhcpd.h:449
unsigned packet_length
Definition dhcpd.h:408
int options_valid
Definition dhcpd.h:430
unsigned char dhcpv6_transaction_id[3]
Definition dhcpd.h:414
int packet_type
Definition dhcpd.h:409
struct iaddr client_addr
Definition dhcpd.h:432
Definition dhcpd.h:288
int warnings_occurred
Definition dhcpd.h:326
enum dhcp_token token
Definition dhcpd.h:320
char string[1]
Definition dhcpd.h:349
struct string_list * next
Definition dhcpd.h:348
Definition data.h:171
const int dhcpv6_type_name_max
Definition tables.c:692
struct universe fqdn_universe
Definition tables.c:318
int universe_count
Definition tables.c:976
const char * dhcpv6_type_names[]
Definition tables.c:668
int option_dereference(struct option **dest, const char *file, int line)
Definition tables.c:1014
struct universe dhcpv6_universe
Definition tables.c:351
void initialize_common_option_spaces()
Definition tables.c:1061
struct universe ** universes
Definition tables.c:975
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
Definition tree.c:2699
int evaluate_boolean_option_cache(int *ignorep, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
Definition tree.c:2733
struct binding_scope * global_scope
Definition tree.c:38
int make_const_option_cache(struct option_cache **oc, struct buffer **buffer, u_int8_t *data, unsigned len, struct option *option, const char *file, int line)
Definition tree.c:149
Definition data.h:205