6 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
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/.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
25 * https://www.isc.org/
27 * This code is based on the original client state machine that was
28 * written by Elliot Poger. The code has been extensively hacked on
29 * by Ted Lemon since then, so any mistakes you find are probably his
30 * fault and not Elliot's.
36 #include <dns/result.h>
44 TIME default_lease_time
= 43200; /* 12 hours... */
45 TIME max_lease_time
= 86400; /* 24 hours... */
47 const char *path_dhclient_conf
= _PATH_DHCLIENT_CONF
;
48 const char *path_dhclient_db
= NULL
;
49 const char *path_dhclient_pid
= NULL
;
50 static char path_dhclient_script_array
[] = _PATH_DHCLIENT_SCRIPT
;
51 char *path_dhclient_script
= path_dhclient_script_array
;
52 const char *path_dhclient_duid
= NULL
;
54 /* False (default) => we write and use a pid file */
55 isc_boolean_t no_pid_file
= ISC_FALSE
;
57 int dhcp_max_agent_option_packet_length
= 0;
59 int interfaces_requested
= 0;
61 struct iaddr iaddr_broadcast
= { 4, { 255, 255, 255, 255 } };
62 struct iaddr iaddr_any
= { 4, { 0, 0, 0, 0 } };
63 struct in_addr inaddr_any
;
64 struct sockaddr_in sockaddr_broadcast
;
65 struct in_addr giaddr
;
66 struct data_string default_duid
;
71 int decline_wait_time
= 10; /* Default to 10 secs per, RFC 2131, 3.1.5 */
73 /* ASSERT_STATE() does nothing now; it used to be
74 assert (state_is == state_shouldbe). */
75 #define ASSERT_STATE(state_is, state_shouldbe) {}
78 static const char copyright
[] = "Copyright 2004-2017 Internet Systems Consortium.";
79 static const char arr
[] = "All rights reserved.";
80 static const char message
[] = "Internet Systems Consortium DHCP Client";
81 static const char url
[] = "For info, please visit https://www.isc.org/software/dhcp/";
82 #endif /* UNIT_TEST */
84 u_int16_t local_port
= 0;
85 u_int16_t remote_port
= 0;
86 #if defined(DHCPv6) && defined(DHCP4o6)
87 int dhcp4o6_state
= -1; /* -1 = stopped, 0 = polling, 1 = started */
90 int dfd
[2] = { -1, -1 };
91 struct string_list
*client_env
= NULL
;
92 int client_env_count
= 0;
97 int wanted_ia_na
= -1; /* the absolute value is the real one. */
100 int require_all_ias
= 0; /* If the user requires all of the IAs to
101 be available before accepting a lease
102 0 = no, 1 = requries */
104 int dad_wait_time
= 0;
105 int prefix_len_hint
= 0;
108 char *mockup_relay
= NULL
;
110 char *progname
= NULL
;
112 void run_stateless(int exit_mode
, u_int16_t port
);
114 static isc_result_t
write_duid(struct data_string
*duid
);
115 static void add_reject(struct packet
*packet
);
117 static int check_domain_name(const char *ptr
, size_t len
, int dots
);
118 static int check_domain_name_list(const char *ptr
, size_t len
, int dots
);
119 static int check_option_values(struct universe
*universe
, unsigned int opt
,
120 const char *ptr
, size_t len
);
122 static void dhclient_ddns_cb_free(dhcp_ddns_cb_t
*ddns_cb
,
123 char* file
, int line
);
127 * \brief Print the generic usage message
129 * If the user has provided an incorrect command line print out
130 * the description of the command line. The arguments provide
131 * a way for the caller to request more specific information about
132 * the error be printed as well. Mostly this will be that some
133 * comamnd doesn't include its argument.
135 * \param sfmt - The basic string and format for the specific error
136 * \param sarg - Generally the offending argument from the comamnd line.
141 #if defined(DHCPv6) && defined(DHCP4o6)
142 static void dhcp4o6_poll(void *dummy
);
143 static void dhcp4o6_resume(void);
144 static void recv_dhcpv4_response(struct data_string
*raw
);
145 static int send_dhcpv4_query(struct client_state
*client
, int broadcast
);
147 static void dhcp4o6_stop(void);
148 static void forw_dhcpv4_response(struct packet
*packet
);
149 static void forw_dhcpv4_query(struct data_string
*raw
);
153 /* These are only used when we call usage() from the main routine
154 * which isn't compiled when building for unit tests
156 static const char use_noarg
[] = "No argument for command: %s";
158 static const char use_v6command
[] = "Command not used for DHCPv4: %s";
163 #define DHCLIENT_USAGE0 \
164 "[-4|-6] [-SNTPRI1dvrxi] [-nw] -4o6 <port>] [-p <port>] [-D LL|LLT]\n" \
165 " [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
166 " [--decline-wait-time <seconds>]\n"
168 #define DHCLIENT_USAGE0 \
169 "[-4|-6] [-SNTPRI1dvrxi] [-nw] [-p <port>] [-D LL|LLT]\n" \
170 " [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
171 " [--decline-wait-time <seconds>]\n"
174 #define DHCLIENT_USAGE0 \
175 "[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n" \
176 " [--decline-wait-time <seconds>]\n"
179 #define DHCLIENT_USAGEC \
180 " [-s server-addr] [-cf config-file]\n" \
181 " [-df duid-file] [-lf lease-file]\n" \
182 " [-pf pid-file] [--no-pid] [-e VAR=val]\n" \
183 " [-sf script-file] [interface]*"
185 #define DHCLIENT_USAGEH "{--version|--help|-h}"
188 usage(const char *sfmt
, const char *sarg
)
190 log_info("%s %s", message
, PACKAGE_VERSION
);
195 /* If desired print out the specific error message */
196 #ifdef PRINT_SPECIFIC_CL_ERRORS
198 log_error(sfmt
, sarg
);
201 log_fatal("Usage: %s %s%s\n %s %s",
202 isc_file_basename(progname
),
205 isc_file_basename(progname
),
209 extern void initialize_client_option_spaces();
212 main(int argc
, char **argv
) {
215 struct interface_info
*ip
;
216 struct client_state
*client
;
221 int release_mode
= 0;
223 omapi_object_t
*listener
;
226 int no_dhclient_conf
= 0;
227 int no_dhclient_db
= 0;
228 int no_dhclient_pid
= 0;
229 int no_dhclient_script
= 0;
231 int local_family_set
= 0;
233 u_int16_t dhcp4o6_port
= 0;
239 progname
= "dhclient";
243 /* Initialize client globals. */
244 memset(&default_duid
, 0, sizeof(default_duid
));
246 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
247 2 (stderr) are open. To do this, we assume that when we
248 open a file the lowest available file descriptor is used. */
249 fd
= open("/dev/null", O_RDWR
);
251 fd
= open("/dev/null", O_RDWR
);
253 fd
= open("/dev/null", O_RDWR
);
255 log_perror
= 0; /* No sense logging to /dev/null. */
259 openlog(isc_file_basename(progname
), DHCP_LOG_OPTIONS
, LOG_DAEMON
);
261 #if !(defined(DEBUG) || defined(__CYGWIN32__))
262 setlogmask(LOG_UPTO(LOG_INFO
));
265 /* Parse arguments changing no_daemon */
266 for (i
= 1; i
< argc
; i
++) {
267 if (!strcmp(argv
[i
], "-r")) {
269 } else if (!strcmp(argv
[i
], "-x")) {
271 } else if (!strcmp(argv
[i
], "-d")) {
273 } else if (!strcmp(argv
[i
], "--version")) {
274 const char vstring
[] = "isc-dhclient-";
275 IGNORE_RET(write(STDERR_FILENO
, vstring
,
277 IGNORE_RET(write(STDERR_FILENO
,
279 strlen(PACKAGE_VERSION
)));
280 IGNORE_RET(write(STDERR_FILENO
, "\n", 1));
282 } else if (!strcmp(argv
[i
], "--help") ||
283 !strcmp(argv
[i
], "-h")) {
284 const char *pname
= isc_file_basename(progname
);
285 IGNORE_RET(write(STDERR_FILENO
, "Usage: ", 7));
286 IGNORE_RET(write(STDERR_FILENO
, pname
, strlen(pname
)));
287 IGNORE_RET(write(STDERR_FILENO
, " ", 1));
288 IGNORE_RET(write(STDERR_FILENO
, DHCLIENT_USAGE0
,
289 strlen(DHCLIENT_USAGE0
)));
290 IGNORE_RET(write(STDERR_FILENO
, DHCLIENT_USAGEC
,
291 strlen(DHCLIENT_USAGEC
)));
292 IGNORE_RET(write(STDERR_FILENO
, "\n", 1));
293 IGNORE_RET(write(STDERR_FILENO
, " ", 7));
294 IGNORE_RET(write(STDERR_FILENO
, pname
, strlen(pname
)));
295 IGNORE_RET(write(STDERR_FILENO
, " ", 1));
296 IGNORE_RET(write(STDERR_FILENO
, DHCLIENT_USAGEH
,
297 strlen(DHCLIENT_USAGEH
)));
298 IGNORE_RET(write(STDERR_FILENO
, "\n", 1));
302 /* When not forbidden prepare to become a daemon */
307 log_fatal("Can't get pipe: %m");
308 if ((pid
= fork ()) < 0)
309 log_fatal("Can't fork daemon: %m");
311 /* Parent: wait for the child to start */
314 (void) close(dfd
[1]);
318 n
= read(dfd
[0], &buf
, 1);
321 } while (n
== -1 && errno
== EINTR
);
325 (void) close(dfd
[0]);
328 /* Set up the isc and dns library managers */
329 status
= dhcp_context_create(DHCP_CONTEXT_PRE_DB
| DHCP_CONTEXT_POST_DB
330 | DHCP_DNS_CLIENT_LAZY_INIT
, NULL
, NULL
);
331 if (status
!= ISC_R_SUCCESS
)
332 log_fatal("Can't initialize context: %s",
333 isc_result_totext(status
));
335 /* Set up the OMAPI. */
336 status
= omapi_init();
337 if (status
!= ISC_R_SUCCESS
)
338 log_fatal("Can't initialize OMAPI: %s",
339 isc_result_totext(status
));
341 /* Set up the OMAPI wrappers for various server database internal
343 dhcp_common_objects_setup();
345 dhcp_interface_discovery_hook
= dhclient_interface_discovery_hook
;
346 dhcp_interface_shutdown_hook
= dhclient_interface_shutdown_hook
;
347 dhcp_interface_startup_hook
= dhclient_interface_startup_hook
;
349 for (i
= 1; i
< argc
; i
++) {
350 if (!strcmp(argv
[i
], "-r")) {
354 } else if (!strcmp(argv
[i
], "-4")) {
355 if (local_family_set
&& local_family
!= AF_INET
)
356 log_fatal("Client can only do v4 or v6, not "
358 local_family_set
= 1;
359 local_family
= AF_INET
;
360 } else if (!strcmp(argv
[i
], "-6")) {
361 if (local_family_set
&& local_family
!= AF_INET6
)
362 log_fatal("Client can only do v4 or v6, not "
364 local_family_set
= 1;
365 local_family
= AF_INET6
;
367 } else if (!strcmp(argv
[i
], "-4o6")) {
369 usage(use_noarg
, argv
[i
-1]);
370 dhcp4o6_port
= validate_port_pair(argv
[i
]);
372 log_debug("DHCPv4 over DHCPv6 over ::1 port %d and %d",
374 ntohs(dhcp4o6_port
) + 1);
375 dhcpv4_over_dhcpv6
= 1;
378 } else if (!strcmp(argv
[i
], "-x")) { /* eXit, no release */
382 } else if (!strcmp(argv
[i
], "-p")) {
384 usage(use_noarg
, argv
[i
-1]);
385 local_port
= validate_port(argv
[i
]);
386 log_debug("binding to user-specified port %d",
388 } else if (!strcmp(argv
[i
], "-d")) {
391 } else if (!strcmp(argv
[i
], "-pf")) {
393 usage(use_noarg
, argv
[i
-1]);
394 path_dhclient_pid
= argv
[i
];
396 } else if (!strcmp(argv
[i
], "--no-pid")) {
397 no_pid_file
= ISC_TRUE
;
398 } else if (!strcmp(argv
[i
], "-cf")) {
400 usage(use_noarg
, argv
[i
-1]);
401 path_dhclient_conf
= argv
[i
];
402 no_dhclient_conf
= 1;
403 } else if (!strcmp(argv
[i
], "-df")) {
405 usage(use_noarg
, argv
[i
-1]);
406 path_dhclient_duid
= argv
[i
];
407 } else if (!strcmp(argv
[i
], "-lf")) {
409 usage(use_noarg
, argv
[i
-1]);
410 path_dhclient_db
= argv
[i
];
412 } else if (!strcmp(argv
[i
], "-sf")) {
414 usage(use_noarg
, argv
[i
-1]);
415 path_dhclient_script
= argv
[i
];
416 no_dhclient_script
= 1;
417 } else if (!strcmp(argv
[i
], "-1")) {
419 } else if (!strcmp(argv
[i
], "-q")) {
421 } else if (!strcmp(argv
[i
], "-s")) {
423 usage(use_noarg
, argv
[i
-1]);
425 } else if (!strcmp(argv
[i
], "-g")) {
427 usage(use_noarg
, argv
[i
-1]);
428 mockup_relay
= argv
[i
];
429 } else if (!strcmp(argv
[i
], "-nw")) {
431 } else if (!strcmp(argv
[i
], "-n")) {
432 /* do not start up any interfaces */
433 interfaces_requested
= -1;
434 } else if (!strcmp(argv
[i
], "-w")) {
435 /* do not exit if there are no broadcast interfaces. */
437 } else if (!strcmp(argv
[i
], "-e")) {
438 struct string_list
*tmp
;
440 usage(use_noarg
, argv
[i
-1]);
441 tmp
= dmalloc(strlen(argv
[i
]) + sizeof *tmp
, MDL
);
443 log_fatal("No memory for %s", argv
[i
]);
444 strcpy(tmp
->string
, argv
[i
]);
445 tmp
->next
= client_env
;
449 } else if (!strcmp(argv
[i
], "-S")) {
450 if (local_family_set
&& (local_family
== AF_INET
)) {
451 usage(use_v6command
, argv
[i
]);
453 local_family_set
= 1;
454 local_family
= AF_INET6
;
457 } else if (!strcmp(argv
[i
], "-N")) {
458 if (local_family_set
&& (local_family
== AF_INET
)) {
459 usage(use_v6command
, argv
[i
]);
461 local_family_set
= 1;
462 local_family
= AF_INET6
;
463 if (wanted_ia_na
< 0) {
467 } else if (!strcmp(argv
[i
], "-T")) {
468 if (local_family_set
&& (local_family
== AF_INET
)) {
469 usage(use_v6command
, argv
[i
]);
471 local_family_set
= 1;
472 local_family
= AF_INET6
;
473 if (wanted_ia_na
< 0) {
477 } else if (!strcmp(argv
[i
], "-P")) {
478 if (local_family_set
&& (local_family
== AF_INET
)) {
479 usage(use_v6command
, argv
[i
]);
481 local_family_set
= 1;
482 local_family
= AF_INET6
;
483 if (wanted_ia_na
< 0) {
487 } else if (!strcmp(argv
[i
], "-R")) {
488 if (local_family_set
&& (local_family
== AF_INET
)) {
489 usage(use_v6command
, argv
[i
]);
491 local_family_set
= 1;
492 local_family
= AF_INET6
;
494 } else if (!strcmp(argv
[i
], "--dad-wait-time")) {
496 usage(use_noarg
, argv
[i
-1]);
500 dad_wait_time
= (int)strtol(argv
[i
], &s
, 10);
501 if (errno
|| (*s
!= '\0') || (dad_wait_time
< 0)) {
502 usage("Invalid value for --dad-wait-time: %s",
505 } else if (!strcmp(argv
[i
], "--prefix-len-hint")) {
507 usage(use_noarg
, argv
[i
-1]);
511 prefix_len_hint
= (int)strtol(argv
[i
], &s
, 10);
512 if (errno
|| (*s
!= '\0') || (prefix_len_hint
< 0)) {
513 usage("Invalid value for --prefix-len-hint: %s",
517 } else if (!strcmp(argv
[i
], "--decline-wait-time")) {
519 usage(use_noarg
, argv
[i
-1]);
523 decline_wait_time
= (int)strtol(argv
[i
], &s
, 10);
524 if (errno
|| (*s
!= '\0') ||
525 (decline_wait_time
< 0)) {
526 usage("Invalid value for "
527 "--decline-wait-time: %s", argv
[i
]);
529 } else if (!strcmp(argv
[i
], "-D")) {
532 usage(use_noarg
, argv
[i
-1]);
533 if (!strcasecmp(argv
[i
], "LL")) {
535 } else if (!strcasecmp(argv
[i
], "LLT")) {
536 duid_type
= DUID_LLT
;
538 usage("Unknown argument to -D: %s", argv
[i
]);
540 } else if (!strcmp(argv
[i
], "-i")) {
541 /* enable DUID support for DHCPv4 clients */
543 } else if (!strcmp(argv
[i
], "-I")) {
544 /* enable standard DHCID support for DDNS updates */
546 } else if (!strcmp(argv
[i
], "-v")) {
548 } else if (argv
[i
][0] == '-') {
549 usage("Unknown command: %s", argv
[i
]);
550 } else if (interfaces_requested
< 0) {
551 usage("No interfaces comamnd -n and "
552 " requested interface %s", argv
[i
]);
554 struct interface_info
*tmp
= NULL
;
556 status
= interface_allocate(&tmp
, MDL
);
557 if (status
!= ISC_R_SUCCESS
)
558 log_fatal("Can't record interface %s:%s",
559 argv
[i
], isc_result_totext(status
));
560 if (strlen(argv
[i
]) >= sizeof(tmp
->name
))
561 log_fatal("%s: interface name too long (is %ld)",
562 argv
[i
], (long)strlen(argv
[i
]));
563 strcpy(tmp
->name
, argv
[i
]);
565 interface_reference(&tmp
->next
,
567 interface_dereference(&interfaces
, MDL
);
569 interface_reference(&interfaces
, tmp
, MDL
);
570 tmp
->flags
= INTERFACE_REQUESTED
;
571 interfaces_requested
++;
575 if (wanted_ia_na
< 0) {
579 /* Support only one (requested) interface for Prefix Delegation. */
580 if (wanted_ia_pd
&& (interfaces_requested
!= 1)) {
581 usage("PD %s only supports one requested interface", "-P");
584 #if defined(DHCPv6) && defined(DHCP4o6)
585 if ((local_family
== AF_INET6
) && dhcpv4_over_dhcpv6
&&
586 (exit_mode
|| release_mode
))
587 log_error("Can't relay DHCPv4-over-DHCPv6 "
588 "without a persistent DHCPv6 client");
589 if ((local_family
== AF_INET
) && dhcpv4_over_dhcpv6
&&
590 (interfaces_requested
!= 1))
591 log_fatal("DHCPv4-over-DHCPv6 requires an explicit "
592 "interface on which to be applied");
595 if (!no_dhclient_conf
&& (s
= getenv("PATH_DHCLIENT_CONF"))) {
596 path_dhclient_conf
= s
;
598 if (!no_dhclient_db
&& (s
= getenv("PATH_DHCLIENT_DB"))) {
599 path_dhclient_db
= s
;
601 if (!no_dhclient_pid
&& (s
= getenv("PATH_DHCLIENT_PID"))) {
602 path_dhclient_pid
= s
;
604 if (!no_dhclient_script
&& (s
= getenv("PATH_DHCLIENT_SCRIPT"))) {
605 path_dhclient_script
= s
;
608 /* Set up the initial dhcp option universe. */
609 initialize_common_option_spaces();
611 /* Set up the initial client option universe. */
612 initialize_client_option_spaces();
614 /* Assign v4 or v6 specific running parameters. */
615 if (local_family
== AF_INET
)
616 dhcpv4_client_assignments();
618 else if (local_family
== AF_INET6
)
619 dhcpv6_client_assignments();
622 log_fatal("Impossible condition at %s:%d.", MDL
);
625 * convert relative path names to absolute, for files that need
626 * to be reopened after chdir() has been called
628 if (path_dhclient_db
[0] != '/') {
629 const char *old_path
= path_dhclient_db
;
630 path_dhclient_db
= realpath(path_dhclient_db
, NULL
);
631 if (path_dhclient_db
== NULL
)
632 log_fatal("Failed to get realpath for %s: %s", old_path
, strerror(errno
));
635 if (path_dhclient_script
[0] != '/') {
636 const char *old_path
= path_dhclient_script
;
637 path_dhclient_script
= realpath(path_dhclient_script
, NULL
);
638 if (path_dhclient_script
== NULL
)
639 log_fatal("Failed to get realpath for %s: %s", old_path
, strerror(errno
));
643 * See if we should kill off any currently running client
644 * we don't try to kill it off if the user told us not
645 * to write a pid file - we assume they are controlling
646 * the process in some other fashion.
648 if ((release_mode
|| exit_mode
) && (no_pid_file
== ISC_FALSE
)) {
654 if ((pidfd
= fopen(path_dhclient_pid
, "r")) != NULL
) {
655 e
= fscanf(pidfd
, "%ld\n", &temp
);
656 oldpid
= (pid_t
)temp
;
658 if (e
!= 0 && e
!= EOF
&& oldpid
) {
659 if (kill(oldpid
, SIGTERM
) == 0) {
660 log_info("Killed old client process");
661 (void) unlink(path_dhclient_pid
);
663 * wait for the old process to
665 * Note kill() with sig=0 could
666 * detect termination but only
667 * the parent can be signaled...
670 } else if (errno
== ESRCH
) {
671 log_info("Removed stale PID file");
672 (void) unlink(path_dhclient_pid
);
680 log_info("%s %s", message
, PACKAGE_VERSION
);
687 quiet_interface_discovery
= 1;
690 /* If we're given a relay agent address to insert, for testing
691 purposes, figure out what it is. */
693 if (!inet_aton(mockup_relay
, &giaddr
)) {
695 he
= gethostbyname(mockup_relay
);
697 memcpy(&giaddr
, he
->h_addr_list
[0],
700 log_fatal("%s: no such host", mockup_relay
);
705 /* Get the current time... */
706 gettimeofday(&cur_tv
, NULL
);
708 sockaddr_broadcast
.sin_family
= AF_INET
;
709 sockaddr_broadcast
.sin_port
= remote_port
;
711 if (!inet_aton(server
, &sockaddr_broadcast
.sin_addr
)) {
713 he
= gethostbyname(server
);
715 memcpy(&sockaddr_broadcast
.sin_addr
,
717 sizeof sockaddr_broadcast
.sin_addr
);
719 sockaddr_broadcast
.sin_addr
.s_addr
=
723 sockaddr_broadcast
.sin_addr
.s_addr
= INADDR_BROADCAST
;
726 inaddr_any
.s_addr
= INADDR_ANY
;
728 /* Stateless special case. */
730 if (release_mode
|| (wanted_ia_na
> 0) ||
731 wanted_ia_ta
|| wanted_ia_pd
||
732 (interfaces_requested
!= 1)) {
733 usage("Stateless command: %s incompatibile with "
734 "other commands", "-S");
736 #if defined(DHCPv6) && defined(DHCP4o6)
737 run_stateless(exit_mode
, dhcp4o6_port
);
739 run_stateless(exit_mode
, 0);
744 /* Discover all the network interfaces. */
745 discover_interfaces(DISCOVER_UNCONFIGURED
);
747 /* Parse the dhclient.conf file. */
750 /* Parse the lease database. */
751 read_client_leases();
753 /* If desired parse the secondary lease database for a DUID */
754 if ((default_duid
.len
== 0) && (path_dhclient_duid
!= NULL
)) {
758 /* Rewrite the lease database... */
759 rewrite_client_leases();
762 /* config_counter(&snd_counter, &rcv_counter); */
765 * If no broadcast interfaces were discovered, call the script
770 * Call dhclient-script with the NBI flag,
771 * in case somebody cares.
773 script_init(NULL
, "NBI", NULL
);
777 * If we haven't been asked to persist, waiting for new
778 * interfaces, then just exit.
781 /* Nothing more to do. */
782 log_info("No broadcast interfaces found - exiting.");
785 } else if (!release_mode
&& !exit_mode
) {
786 /* Call the script with the list of interfaces. */
787 for (ip
= interfaces
; ip
; ip
= ip
->next
) {
789 * If interfaces were specified, don't configure
790 * interfaces that weren't specified!
792 if ((interfaces_requested
> 0) &&
793 ((ip
->flags
& (INTERFACE_REQUESTED
|
794 INTERFACE_AUTOMATIC
)) !=
795 INTERFACE_REQUESTED
))
798 if (local_family
== AF_INET6
) {
799 script_init(ip
->client
, "PREINIT6", NULL
);
801 script_init(ip
->client
, "PREINIT", NULL
);
802 if (ip
->client
->alias
!= NULL
)
803 script_write_params(ip
->client
,
807 script_go(ip
->client
);
811 /* At this point, all the interfaces that the script thinks
812 are relevant should be running, so now we once again call
813 discover_interfaces(), and this time ask it to actually set
814 up the interfaces. */
815 discover_interfaces(interfaces_requested
!= 0
819 /* Make up a seed for the random number generator from current
820 time plus the sum of the last four bytes of each
821 interface's hardware address interpreted as an integer.
822 Not much entropy, but we're booting, so we're not likely to
823 find anything better. */
825 for (ip
= interfaces
; ip
; ip
= ip
->next
) {
828 &ip
->hw_address
.hbuf
[ip
->hw_address
.hlen
-
829 sizeof seed
], sizeof seed
);
832 srandom(seed
+ cur_time
+ (unsigned)getpid());
836 * Establish a default DUID. We always do so for v6 and
837 * do so if desired for v4 via the -D or -i options
839 if ((local_family
== AF_INET6
) ||
840 ((local_family
== AF_INET
) && (duid_v4
== 1))) {
841 if (default_duid
.len
== 0) {
842 if (default_duid
.buffer
!= NULL
)
843 data_string_forget(&default_duid
, MDL
);
845 form_duid(&default_duid
, MDL
);
846 write_duid(&default_duid
);
850 #if defined(DHCPv6) && defined(DHCP4o6)
851 if (dhcpv4_over_dhcpv6
&& !exit_mode
)
852 dhcp4o6_setup(dhcp4o6_port
);
855 /* Start a configuration state machine for each interface. */
857 if (local_family
== AF_INET6
) {
858 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
859 for (client
= ip
->client
; client
!= NULL
;
860 client
= client
->next
) {
862 start_release6(client
);
864 } else if (exit_mode
) {
865 unconfigure6(client
, "STOP6");
869 /* If we have a previous binding, Confirm
870 * that we can (or can't) still use it.
872 if ((client
->active_lease
!= NULL
) &&
873 !client
->active_lease
->released
)
874 start_confirm6(client
);
882 for (ip
= interfaces
; ip
; ip
= ip
->next
) {
883 ip
->flags
|= INTERFACE_RUNNING
;
884 for (client
= ip
->client
; client
;
885 client
= client
->next
) {
891 client
->state
= S_INIT
;
893 if (top_level_config
.initial_delay
>0)
896 if (top_level_config
.
902 tv
.tv_usec
= random()
906 * distribution than just
909 add_timeout(&tv
, state_reboot
,
912 state_reboot(client
);
925 if ((local_family
== AF_INET6
) || dhcpv4_over_dhcpv6
) {
933 /* Start up a listener for the object management API protocol. */
934 if (top_level_config
.omapi_port
!= -1) {
936 result
= omapi_generic_new(&listener
, MDL
);
937 if (result
!= ISC_R_SUCCESS
)
938 log_fatal("Can't allocate new generic object: %s\n",
939 isc_result_totext(result
));
940 result
= omapi_protocol_listen(listener
,
942 top_level_config
.omapi_port
,
944 if (result
!= ISC_R_SUCCESS
)
945 log_fatal("Can't start OMAPI protocol: %s",
946 isc_result_totext (result
));
949 /* Set up the bootp packet handler... */
950 bootp_packet_handler
= do_packet
;
952 dhcpv6_packet_handler
= do_packet6
;
955 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
956 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
957 dmalloc_cutoff_generation
= dmalloc_generation
;
958 dmalloc_longterm
= dmalloc_outstanding
;
959 dmalloc_outstanding
= 0;
962 #if defined(ENABLE_GENTLE_SHUTDOWN)
963 /* no signal handlers until we deal with the side effects */
964 /* install signal handlers */
965 signal(SIGINT
, dhcp_signal_handler
); /* control-c */
966 signal(SIGTERM
, dhcp_signal_handler
); /* kill */
969 /* If we're not supposed to wait before getting the address,
974 /* If we're not going to daemonize, write the pid file
976 if (no_daemon
|| nowait
)
977 write_client_pid_file();
979 /* Start dispatching packets and timeouts... */
982 /* In fact dispatch() never returns. */
987 * \brief Run the DHCPv6 stateless client (dhclient -6 -S)
989 * \param exist_mode set to 1 when dhclient was called with -x
990 * \param port DHCPv4-over-DHCPv6 client inter-process communication
991 * UDP port pair (port,port+1 with port in network byte order)
994 void run_stateless(int exit_mode
, u_int16_t port
)
997 struct client_state
*client
;
998 omapi_object_t
*listener
;
1002 IGNORE_UNUSED(port
);
1005 /* Discover the network interface. */
1006 discover_interfaces(DISCOVER_REQUESTED
);
1009 usage("No interfaces available for stateless command: %s", "-S");
1011 /* Parse the dhclient.conf file. */
1013 if (dhcpv4_over_dhcpv6
) {
1014 /* Mark we want to request IRT too! */
1015 dhcpv4_over_dhcpv6
++;
1020 /* Parse the lease database. */
1021 read_client_leases();
1023 /* If desired parse the secondary lease database for a DUID */
1024 if ((default_duid
.len
== 0) && (path_dhclient_duid
!= NULL
)) {
1028 /* Establish a default DUID. */
1029 if (default_duid
.len
== 0) {
1030 if (default_duid
.buffer
!= NULL
)
1031 data_string_forget(&default_duid
, MDL
);
1033 form_duid(&default_duid
, MDL
);
1037 if (dhcpv4_over_dhcpv6
&& !exit_mode
)
1038 dhcp4o6_setup(port
);
1041 /* Start a configuration state machine. */
1042 for (client
= interfaces
->client
;
1044 client
= client
->next
) {
1046 unconfigure6(client
, "STOP6");
1049 start_info_request6(client
);
1054 /* Start up a listener for the object management API protocol. */
1055 if (top_level_config
.omapi_port
!= -1) {
1057 result
= omapi_generic_new(&listener
, MDL
);
1058 if (result
!= ISC_R_SUCCESS
)
1059 log_fatal("Can't allocate new generic object: %s\n",
1060 isc_result_totext(result
));
1061 result
= omapi_protocol_listen(listener
,
1063 top_level_config
.omapi_port
,
1065 if (result
!= ISC_R_SUCCESS
)
1066 log_fatal("Can't start OMAPI protocol: %s",
1067 isc_result_totext(result
));
1070 /* Set up the packet handler... */
1071 dhcpv6_packet_handler
= do_packet6
;
1073 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
1074 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1075 dmalloc_cutoff_generation
= dmalloc_generation
;
1076 dmalloc_longterm
= dmalloc_outstanding
;
1077 dmalloc_outstanding
= 0;
1080 /* If we're not supposed to wait before getting the address,
1085 /* If we're not going to daemonize, write the pid file
1087 if (no_daemon
|| nowait
)
1088 write_client_pid_file();
1090 /* Start dispatching packets and timeouts... */
1096 #endif /* !UNIT_TEST */
1098 isc_result_t
find_class (struct class **c
,
1099 const char *s
, const char *file
, int line
)
1104 int check_collection (packet
, lease
, collection
)
1105 struct packet
*packet
;
1106 struct lease
*lease
;
1107 struct collection
*collection
;
1112 void classify (packet
, class)
1113 struct packet
*packet
;
1114 struct class *class;
1118 void unbill_class (lease
)
1119 struct lease
*lease
;
1123 int find_subnet (struct subnet
**sp
,
1124 struct iaddr addr
, const char *file
, int line
)
1129 /* Individual States:
1131 * Each routine is called from the dhclient_state_machine() in one of
1133 * -> entering INIT state
1134 * -> recvpacket_flag == 0: timeout in this state
1135 * -> otherwise: received a packet in this state
1137 * Return conditions as handled by dhclient_state_machine():
1138 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
1139 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
1140 * Returns 0: finish the nap which was interrupted for no good reason.
1142 * Several per-interface variables are used to keep track of the process:
1143 * active_lease: the lease that is being used on the interface
1144 * (null pointer if not configured yet).
1145 * offered_leases: leases corresponding to DHCPOFFER messages that have
1146 * been sent to us by DHCP servers.
1147 * acked_leases: leases corresponding to DHCPACK messages that have been
1148 * sent to us by DHCP servers.
1149 * sendpacket: DHCP packet we're trying to send.
1150 * destination: IP address to send sendpacket to
1151 * In addition, there are several relevant per-lease variables.
1152 * T1_expiry, T2_expiry, lease_expiry: lease milestones
1153 * In the active lease, these control the process of renewing the lease;
1154 * In leases on the acked_leases list, this simply determines when we
1155 * can no longer legitimately use the lease.
1158 void state_reboot (cpp
)
1161 struct client_state
*client
= cpp
;
1163 #if defined(DHCPv6) && defined(DHCP4o6)
1164 if (dhcpv4_over_dhcpv6
&& (dhcp4o6_state
<= 0)) {
1165 if (dhcp4o6_state
< 0)
1167 client
->pending
= P_REBOOT
;
1172 client
->pending
= P_NONE
;
1174 /* If we don't remember an active lease, go straight to INIT. */
1175 if (!client
-> active
||
1176 client
-> active
-> is_bootp
||
1177 client
-> active
-> expiry
<= cur_time
) {
1178 state_init (client
);
1182 /* We are in the rebooting state. */
1183 client
-> state
= S_REBOOTING
;
1186 * make_request doesn't initialize xid because it normally comes
1187 * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
1188 * so pick an xid now.
1190 client
-> xid
= random ();
1193 * Make a DHCPREQUEST packet, and set
1194 * appropriate per-interface flags.
1196 make_request (client
, client
-> active
);
1197 client
-> destination
= iaddr_broadcast
;
1198 client
-> first_sending
= cur_time
;
1199 client
-> interval
= client
-> config
-> initial_interval
;
1201 /* Zap the medium list... */
1202 client
-> medium
= NULL
;
1204 /* Send out the first DHCPREQUEST packet. */
1205 send_request (client
);
1208 /* Called when a lease has completely expired and we've been unable to
1211 void state_init (cpp
)
1214 struct client_state
*client
= cpp
;
1216 ASSERT_STATE(state
, S_INIT
);
1218 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
1220 make_discover (client
, client
-> active
);
1221 client
-> xid
= client
-> packet
.xid
;
1222 client
-> destination
= iaddr_broadcast
;
1223 client
-> state
= S_SELECTING
;
1224 client
-> first_sending
= cur_time
;
1225 client
-> interval
= client
-> config
-> initial_interval
;
1227 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
1229 send_discover (client
);
1233 * state_selecting is called when one or more DHCPOFFER packets have been
1234 * received and a configurable period of time has passed.
1237 void state_selecting (cpp
)
1240 struct client_state
*client
= cpp
;
1241 struct client_lease
*lp
, *next
, *picked
;
1244 ASSERT_STATE(state
, S_SELECTING
);
1247 * Cancel state_selecting and send_discover timeouts, since either
1248 * one could have got us here.
1250 cancel_timeout (state_selecting
, client
);
1251 cancel_timeout (send_discover
, client
);
1254 * We have received one or more DHCPOFFER packets. Currently,
1255 * the only criterion by which we judge leases is whether or
1256 * not we get a response when we arp for them.
1259 for (lp
= client
-> offered_leases
; lp
; lp
= next
) {
1263 * Check to see if we got an ARPREPLY for the address
1264 * in this particular lease.
1268 picked
-> next
= NULL
;
1270 destroy_client_lease (lp
);
1273 client
-> offered_leases
= NULL
;
1276 * If we just tossed all the leases we were offered, go back
1280 client
-> state
= S_INIT
;
1281 state_init (client
);
1285 /* If it was a BOOTREPLY, we can just take the address right now. */
1286 if (picked
-> is_bootp
) {
1287 client
-> new = picked
;
1289 /* Make up some lease expiry times
1290 XXX these should be configurable. */
1291 client
-> new -> expiry
= cur_time
+ 12000;
1292 client
-> new -> renewal
+= cur_time
+ 8000;
1293 client
-> new -> rebind
+= cur_time
+ 10000;
1295 client
-> state
= S_REQUESTING
;
1297 /* Bind to the address we received. */
1298 bind_lease (client
);
1302 /* Go to the REQUESTING state. */
1303 client
-> destination
= iaddr_broadcast
;
1304 client
-> state
= S_REQUESTING
;
1305 client
-> first_sending
= cur_time
;
1306 client
-> interval
= client
-> config
-> initial_interval
;
1308 /* Make a DHCPREQUEST packet from the lease we picked. */
1309 make_request (client
, picked
);
1310 client
-> xid
= client
-> packet
.xid
;
1312 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
1313 destroy_client_lease (picked
);
1315 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
1316 send_request (client
);
1319 /* state_requesting is called when we receive a DHCPACK message after
1320 having sent out one or more DHCPREQUEST packets. */
1322 void dhcpack (packet
)
1323 struct packet
*packet
;
1325 struct interface_info
*ip
= packet
-> interface
;
1326 struct client_state
*client
;
1327 struct client_lease
*lease
;
1328 struct option_cache
*oc
;
1329 struct data_string ds
;
1331 /* If we're not receptive to an offer right now, or if the offer
1332 has an unrecognizable transaction id, then just drop it. */
1333 for (client
= ip
-> client
; client
; client
= client
-> next
) {
1334 if (client
-> xid
== packet
-> raw
-> xid
)
1338 (packet
-> interface
-> hw_address
.hlen
- 1 !=
1339 packet
-> raw
-> hlen
) ||
1340 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
1341 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
1343 log_debug ("DHCPACK in wrong transaction.");
1348 if (client
-> state
!= S_REBOOTING
&&
1349 client
-> state
!= S_REQUESTING
&&
1350 client
-> state
!= S_RENEWING
&&
1351 client
-> state
!= S_REBINDING
) {
1353 log_debug ("DHCPACK in wrong state.");
1358 log_info ("DHCPACK of %s from %s",
1359 inet_ntoa(packet
->raw
->yiaddr
),
1360 piaddr (packet
->client_addr
));
1362 lease
= packet_to_lease (packet
, client
);
1364 log_info ("packet_to_lease failed.");
1368 client
-> new = lease
;
1370 /* Stop resending DHCPREQUEST. */
1371 cancel_timeout (send_request
, client
);
1373 /* Figure out the lease time. */
1374 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1375 DHO_DHCP_LEASE_TIME
);
1376 memset (&ds
, 0, sizeof ds
);
1378 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1379 packet
-> options
, client
-> new -> options
,
1380 &global_scope
, oc
, MDL
)) {
1382 client
-> new -> expiry
= getULong (ds
.data
);
1384 client
-> new -> expiry
= 0;
1385 data_string_forget (&ds
, MDL
);
1387 client
-> new -> expiry
= 0;
1389 if (client
->new->expiry
== 0) {
1392 log_error ("no expiry time on offered lease.");
1394 /* Quench this (broken) server. Return to INIT to reselect. */
1397 /* 1/2 second delay to restart at INIT. */
1398 tv
.tv_sec
= cur_tv
.tv_sec
;
1399 tv
.tv_usec
= cur_tv
.tv_usec
+ 500000;
1401 if (tv
.tv_usec
>= 1000000) {
1403 tv
.tv_usec
-= 1000000;
1406 add_timeout(&tv
, state_init
, client
, 0, 0);
1411 * A number that looks negative here is really just very large,
1412 * because the lease expiry offset is unsigned.
1414 if (client
->new->expiry
< 0)
1415 client
->new->expiry
= TIME_MAX
;
1417 /* Take the server-provided renewal time if there is one. */
1418 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1419 DHO_DHCP_RENEWAL_TIME
);
1421 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1422 packet
-> options
, client
-> new -> options
,
1423 &global_scope
, oc
, MDL
)) {
1425 client
-> new -> renewal
= getULong (ds
.data
);
1427 client
-> new -> renewal
= 0;
1428 data_string_forget (&ds
, MDL
);
1430 client
-> new -> renewal
= 0;
1432 /* If it wasn't specified by the server, calculate it. */
1433 if (!client
-> new -> renewal
)
1434 client
-> new -> renewal
= client
-> new -> expiry
/ 2 + 1;
1436 if (client
-> new -> renewal
<= 0)
1437 client
-> new -> renewal
= TIME_MAX
;
1439 /* Now introduce some randomness to the renewal time: */
1440 if (client
->new->renewal
<= ((TIME_MAX
/ 3) - 3))
1441 client
->new->renewal
= (((client
->new->renewal
* 3) + 3) / 4) +
1442 (((random() % client
->new->renewal
) + 3) / 4);
1444 /* Same deal with the rebind time. */
1445 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1446 DHO_DHCP_REBINDING_TIME
);
1448 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1449 packet
-> options
, client
-> new -> options
,
1450 &global_scope
, oc
, MDL
)) {
1452 client
-> new -> rebind
= getULong (ds
.data
);
1454 client
-> new -> rebind
= 0;
1455 data_string_forget (&ds
, MDL
);
1457 client
-> new -> rebind
= 0;
1459 if (client
-> new -> rebind
<= 0) {
1460 if (client
-> new -> expiry
<= TIME_MAX
/ 7)
1461 client
-> new -> rebind
=
1462 client
-> new -> expiry
* 7 / 8;
1464 client
-> new -> rebind
=
1465 client
-> new -> expiry
/ 8 * 7;
1468 /* Make sure our randomness didn't run the renewal time past the
1470 if (client
-> new -> renewal
> client
-> new -> rebind
) {
1471 if (client
-> new -> rebind
<= TIME_MAX
/ 3)
1472 client
-> new -> renewal
=
1473 client
-> new -> rebind
* 3 / 4;
1475 client
-> new -> renewal
=
1476 client
-> new -> rebind
/ 4 * 3;
1479 client
-> new -> expiry
+= cur_time
;
1480 /* Lease lengths can never be negative. */
1481 if (client
-> new -> expiry
< cur_time
)
1482 client
-> new -> expiry
= TIME_MAX
;
1483 client
-> new -> renewal
+= cur_time
;
1484 if (client
-> new -> renewal
< cur_time
)
1485 client
-> new -> renewal
= TIME_MAX
;
1486 client
-> new -> rebind
+= cur_time
;
1487 if (client
-> new -> rebind
< cur_time
)
1488 client
-> new -> rebind
= TIME_MAX
;
1490 bind_lease (client
);
1493 void bind_lease (client
)
1494 struct client_state
*client
;
1498 /* Remember the medium. */
1499 client
->new->medium
= client
->medium
;
1501 /* Run the client script with the new parameters. */
1502 script_init(client
, (client
->state
== S_REQUESTING
? "BOUND" :
1503 (client
->state
== S_RENEWING
? "RENEW" :
1504 (client
->state
== S_REBOOTING
? "REBOOT" :
1506 client
->new->medium
);
1507 if (client
->active
&& client
->state
!= S_REBOOTING
)
1508 script_write_params(client
, "old_", client
->active
);
1509 script_write_params(client
, "new_", client
->new);
1510 script_write_requested(client
);
1512 script_write_params(client
, "alias_", client
->alias
);
1514 /* If the BOUND/RENEW code detects another machine using the
1515 offered address, it exits nonzero. We need to send a
1516 DHCPDECLINE and toss the lease. */
1517 if (script_go(client
)) {
1518 make_decline(client
, client
->new);
1519 send_decline(client
);
1520 destroy_client_lease(client
->new);
1524 log_info("Unable to obtain a lease on first "
1525 "try (declined). Exiting.");
1528 #if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
1529 /* Let's call a script and we're done */
1530 script_init(client
, "FAIL", (struct string_list
*)0);
1536 tv
.tv_sec
= cur_tv
.tv_sec
+ decline_wait_time
;
1537 tv
.tv_usec
= cur_tv
.tv_usec
;
1538 add_timeout(&tv
, state_init
, client
, 0, 0);
1543 /* Write out the new lease if it has been long enough. */
1544 if (!client
->last_write
||
1545 (cur_time
- client
->last_write
) >= MIN_LEASE_WRITE
)
1546 write_client_lease(client
, client
->new, 0, 1);
1548 /* Replace the old active lease with the new one. */
1550 destroy_client_lease(client
->active
);
1551 client
->active
= client
->new;
1554 /* Set up a timeout to start the renewal process. */
1555 tv
.tv_sec
= client
->active
->renewal
;
1556 tv
.tv_usec
= ((client
->active
->renewal
- cur_tv
.tv_sec
) > 1) ?
1557 random() % 1000000 : cur_tv
.tv_usec
;
1558 add_timeout(&tv
, state_bound
, client
, 0, 0);
1560 log_info("bound to %s -- renewal in %ld seconds.",
1561 piaddr(client
->active
->address
),
1562 (long)(client
->active
->renewal
- cur_time
));
1563 client
->state
= S_BOUND
;
1564 reinitialize_interfaces();
1566 #if defined (NSUPDATE)
1567 if (client
->config
->do_forward_update
)
1568 dhclient_schedule_updates(client
, &client
->active
->address
, 1);
1572 /* state_bound is called when we've successfully bound to a particular
1573 lease, but the renewal time on that lease has expired. We are
1574 expected to unicast a DHCPREQUEST to the server that gave us our
1577 void state_bound (cpp
)
1580 struct client_state
*client
= cpp
;
1581 struct option_cache
*oc
;
1582 struct data_string ds
;
1584 ASSERT_STATE(state
, S_BOUND
);
1586 /* T1 has expired. */
1587 make_request (client
, client
-> active
);
1588 client
-> xid
= client
-> packet
.xid
;
1590 memset (&ds
, 0, sizeof ds
);
1591 oc
= lookup_option (&dhcp_universe
, client
-> active
-> options
,
1592 DHO_DHCP_SERVER_IDENTIFIER
);
1594 evaluate_option_cache (&ds
, (struct packet
*)0, (struct lease
*)0,
1595 client
, (struct option_state
*)0,
1596 client
-> active
-> options
,
1597 &global_scope
, oc
, MDL
)) {
1599 memcpy (client
-> destination
.iabuf
, ds
.data
, 4);
1600 client
-> destination
.len
= 4;
1602 client
-> destination
= iaddr_broadcast
;
1604 data_string_forget (&ds
, MDL
);
1606 client
-> destination
= iaddr_broadcast
;
1608 client
-> first_sending
= cur_time
;
1609 client
-> interval
= client
-> config
-> initial_interval
;
1610 client
-> state
= S_RENEWING
;
1612 /* Send the first packet immediately. */
1613 send_request (client
);
1616 /* state_stop is called when we've been told to shut down. We unconfigure
1617 the interfaces, and then stop operating until told otherwise. */
1619 void state_stop (cpp
)
1622 struct client_state
*client
= cpp
;
1624 client
->pending
= P_NONE
;
1626 /* Cancel all timeouts. */
1627 cancel_timeout(state_selecting
, client
);
1628 cancel_timeout(send_discover
, client
);
1629 cancel_timeout(send_request
, client
);
1630 cancel_timeout(state_bound
, client
);
1632 /* If we have an address, unconfigure it. */
1633 if (client
->active
) {
1634 script_init(client
, "STOP", client
->active
->medium
);
1635 script_write_params(client
, "old_", client
->active
);
1636 script_write_requested(client
);
1638 script_write_params(client
, "alias_", client
->alias
);
1643 int commit_leases ()
1648 int write_lease (lease
)
1649 struct lease
*lease
;
1654 int write_host (host
)
1655 struct host_decl
*host
;
1660 void db_startup (testp
)
1666 struct packet
*packet
;
1668 struct iaddrmatchlist
*ap
;
1672 if (packet
-> raw
-> op
!= BOOTREPLY
)
1675 /* If there's a reject list, make sure this packet's sender isn't
1677 for (ap
= packet
-> interface
-> client
-> config
-> reject_list
;
1678 ap
; ap
= ap
-> next
) {
1679 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1681 /* piaddr() returns its result in a static
1682 buffer sized 4*16 (see common/inet.c). */
1684 strcpy(addrbuf
, piaddr(ap
->match
.addr
));
1685 strcpy(maskbuf
, piaddr(ap
->match
.mask
));
1687 log_info("BOOTREPLY from %s rejected by rule %s "
1688 "mask %s.", piaddr(packet
->client_addr
),
1699 struct packet
*packet
;
1701 struct iaddrmatchlist
*ap
;
1702 void (*handler
) (struct packet
*);
1707 switch (packet
-> packet_type
) {
1709 handler
= dhcpoffer
;
1727 /* If there's a reject list, make sure this packet's sender isn't
1729 for (ap
= packet
-> interface
-> client
-> config
-> reject_list
;
1730 ap
; ap
= ap
-> next
) {
1731 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1733 /* piaddr() returns its result in a static
1734 buffer sized 4*16 (see common/inet.c). */
1736 strcpy(addrbuf
, piaddr(ap
->match
.addr
));
1737 strcpy(maskbuf
, piaddr(ap
->match
.mask
));
1739 log_info("%s from %s rejected by rule %s mask %s.",
1740 type
, piaddr(packet
->client_addr
),
1745 (*handler
) (packet
);
1750 dhcpv6(struct packet
*packet
) {
1751 struct iaddrmatchlist
*ap
;
1752 struct client_state
*client
;
1753 char addrbuf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
1755 /* Silently drop bogus messages. */
1756 if (packet
->dhcpv6_msg_type
>= dhcpv6_type_name_max
)
1759 /* Discard, with log, packets from quenched sources. */
1760 for (ap
= packet
->interface
->client
->config
->reject_list
;
1761 ap
; ap
= ap
->next
) {
1762 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1763 strcpy(addrbuf
, piaddr(packet
->client_addr
));
1764 log_info("%s from %s rejected by rule %s",
1765 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1767 piaddrmask(&ap
->match
.addr
, &ap
->match
.mask
));
1772 /* Screen out nonsensical messages. */
1773 switch(packet
->dhcpv6_msg_type
) {
1775 case DHCPV6_DHCPV4_RESPONSE
:
1776 if (dhcpv4_over_dhcpv6
) {
1777 log_info("RCV: %s message on %s from %s.",
1778 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1779 packet
->interface
->name
,
1780 piaddr(packet
->client_addr
));
1781 forw_dhcpv4_response(packet
);
1785 case DHCPV6_ADVERTISE
:
1786 case DHCPV6_RECONFIGURE
:
1791 log_info("RCV: %s message on %s from %s.",
1792 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1793 packet
->interface
->name
, piaddr(packet
->client_addr
));
1800 /* Find a client state that matches the incoming XID. */
1801 for (client
= packet
->interface
->client
; client
;
1802 client
= client
->next
) {
1803 if (memcmp(&client
->dhcpv6_transaction_id
,
1804 packet
->dhcpv6_transaction_id
, 3) == 0) {
1805 client
->v6_handler(packet
, client
);
1810 /* XXX: temporary log for debugging */
1811 log_info("Packet received, but nothing done with it.");
1816 * \brief Forward a DHCPv4-response to the DHCPv4 client.
1817 * (DHCPv6 client function)
1819 * The DHCPv6 client receives a DHCPv4-response which is forwarded
1820 * to the DHCPv4 client.
1821 * Format: address:16 + DHCPv4 message content
1822 * (we have no state to keep the address so it is transported in
1823 * DHCPv6 <-> DHCPv6 inter-process messages)
1825 * \param packet the DHCPv4-response packet
1827 static void forw_dhcpv4_response(struct packet
*packet
)
1829 struct option_cache
*oc
;
1830 struct data_string enc_opt_data
;
1831 struct data_string ds
;
1835 * Discard if relay is not ready.
1837 if (dhcp4o6_state
== -1) {
1838 log_info("forw_dhcpv4_response: not ready.");
1842 if (packet
->client_addr
.len
!= 16) {
1843 log_error("forw_dhcpv4_response: bad address");
1848 * Get our encapsulated DHCPv4 message.
1850 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_DHCPV4_MSG
);
1852 log_info("DHCPv4-response from %s missing "
1853 "DHCPv4 Message option.",
1854 piaddr(packet
->client_addr
));
1858 memset(&enc_opt_data
, 0, sizeof(enc_opt_data
));
1859 if (!evaluate_option_cache(&enc_opt_data
, NULL
, NULL
, NULL
,
1860 NULL
, NULL
, &global_scope
, oc
, MDL
)) {
1861 log_error("forw_dhcpv4_response: error evaluating "
1863 data_string_forget(&enc_opt_data
, MDL
);
1867 if (enc_opt_data
.len
< DHCP_FIXED_NON_UDP
) {
1868 log_error("forw_dhcpv4_response: "
1869 "no memory for encapsulated packet.");
1870 data_string_forget(&enc_opt_data
, MDL
);
1877 memset(&ds
, 0, sizeof(ds
));
1878 if (!buffer_allocate(&ds
.buffer
, enc_opt_data
.len
+ 16, MDL
)) {
1879 log_error("forw_dhcpv4_response: no memory buffer.");
1880 data_string_forget(&enc_opt_data
, MDL
);
1883 ds
.data
= ds
.buffer
->data
;
1884 ds
.len
= enc_opt_data
.len
+ 16;
1885 memcpy(ds
.buffer
->data
, enc_opt_data
.data
, enc_opt_data
.len
);
1886 memcpy(ds
.buffer
->data
+ enc_opt_data
.len
,
1887 packet
->client_addr
.iabuf
, 16);
1888 data_string_forget(&enc_opt_data
, MDL
);
1893 cc
= send(dhcp4o6_fd
, ds
.data
, ds
.len
, 0);
1895 log_error("forw_dhcpv4_response: send(): %m");
1897 data_string_forget(&ds
, MDL
);
1901 * \brief Receive a DHCPv4-response from the DHCPv6 client.
1902 * (DHCPv4 client function)
1904 * The DHCPv4 client receives a DHCPv4-response forwarded
1905 * by the DHCPv6 client (using \ref forw_dhcpv4_response())
1907 * \param raw the DHCPv4-response raw packet
1909 static void recv_dhcpv4_response(struct data_string
*raw
)
1911 struct packet
*packet
;
1914 if (interfaces
== NULL
) {
1915 log_error("recv_dhcpv4_response: no interfaces.");
1920 memcpy(from
.iabuf
, raw
->data
+ (raw
->len
- 16), 16);
1923 * Build a packet structure.
1926 if (!packet_allocate(&packet
, MDL
)) {
1927 log_error("recv_dhcpv4_response: no memory for packet.");
1931 packet
->raw
= (struct dhcp_packet
*) raw
->data
;
1932 packet
->packet_length
= raw
->len
- 16;
1933 packet
->client_port
= remote_port
;
1934 packet
->client_addr
= from
;
1935 interface_reference(&packet
->interface
, interfaces
, MDL
);
1937 /* Allocate packet->options now so it is non-null for all packets */
1938 if (!option_state_allocate (&packet
->options
, MDL
)) {
1939 log_error("recv_dhcpv4_response: no memory for options.");
1940 packet_dereference (&packet
, MDL
);
1944 /* If there's an option buffer, try to parse it. */
1945 if (packet
->packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
1946 struct option_cache
*op
;
1947 if (!parse_options(packet
)) {
1948 if (packet
->options
)
1949 option_state_dereference
1950 (&packet
->options
, MDL
);
1951 packet_dereference (&packet
, MDL
);
1955 if (packet
->options_valid
&&
1956 (op
= lookup_option(&dhcp_universe
,
1958 DHO_DHCP_MESSAGE_TYPE
))) {
1959 struct data_string dp
;
1960 memset(&dp
, 0, sizeof dp
);
1961 evaluate_option_cache(&dp
, packet
, NULL
, NULL
,
1962 packet
->options
, NULL
,
1965 packet
->packet_type
= dp
.data
[0];
1967 packet
->packet_type
= 0;
1968 data_string_forget(&dp
, MDL
);
1972 if (validate_packet(packet
) != 0) {
1973 if (packet
->packet_type
)
1979 /* If the caller kept the packet, they'll have upped the refcnt. */
1980 packet_dereference(&packet
, MDL
);
1982 #endif /* DHCP4o6 */
1985 void dhcpoffer (packet
)
1986 struct packet
*packet
;
1988 struct interface_info
*ip
= packet
-> interface
;
1989 struct client_state
*client
;
1990 struct client_lease
*lease
, *lp
;
1991 struct option
**req
;
1994 const char *name
= packet
-> packet_type
? "DHCPOFFER" : "BOOTREPLY";
1999 dump_packet (packet
);
2002 /* Find a client state that matches the xid... */
2003 for (client
= ip
-> client
; client
; client
= client
-> next
)
2004 if (client
-> xid
== packet
-> raw
-> xid
)
2007 /* If we're not receptive to an offer right now, or if the offer
2008 has an unrecognizable transaction id, then just drop it. */
2010 client
-> state
!= S_SELECTING
||
2011 (packet
-> interface
-> hw_address
.hlen
- 1 !=
2012 packet
-> raw
-> hlen
) ||
2013 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
2014 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
2016 log_debug ("%s in wrong transaction.", name
);
2021 sprintf (obuf
, "%s of %s from %s", name
,
2022 inet_ntoa(packet
->raw
->yiaddr
),
2023 piaddr(packet
->client_addr
));
2025 /* If this lease doesn't supply the minimum required DHCPv4 parameters,
2028 req
= client
->config
->required_options
;
2030 for (i
= 0 ; req
[i
] != NULL
; i
++) {
2031 if ((req
[i
]->universe
== &dhcp_universe
) &&
2032 !lookup_option(&dhcp_universe
, packet
->options
,
2034 struct option
*option
= NULL
;
2035 unsigned code
= req
[i
]->code
;
2037 option_code_hash_lookup(&option
,
2038 dhcp_universe
.code_hash
,
2042 log_info("%s: no %s option.", obuf
,
2045 log_info("%s: no unknown-%u option.",
2048 option_dereference(&option
, MDL
);
2055 /* If we've already seen this lease, don't record it again. */
2056 for (lease
= client
-> offered_leases
; lease
; lease
= lease
-> next
) {
2057 if (lease
-> address
.len
== sizeof packet
-> raw
-> yiaddr
&&
2058 !memcmp (lease
-> address
.iabuf
,
2059 &packet
-> raw
-> yiaddr
, lease
-> address
.len
)) {
2060 log_debug ("%s: already seen.", obuf
);
2065 lease
= packet_to_lease (packet
, client
);
2067 log_info ("%s: packet_to_lease failed.", obuf
);
2071 /* log it now, so it emits before the request goes out */
2072 log_info("%s", obuf
);
2074 /* If this lease was acquired through a BOOTREPLY, record that
2076 if (!packet
-> options_valid
|| !packet
-> packet_type
)
2077 lease
-> is_bootp
= 1;
2079 /* Record the medium under which this lease was offered. */
2080 lease
-> medium
= client
-> medium
;
2082 /* Figure out when we're supposed to stop selecting. */
2083 stop_selecting
= (client
-> first_sending
+
2084 client
-> config
-> select_interval
);
2086 /* If this is the lease we asked for, put it at the head of the
2087 list, and don't mess with the arp request timeout. */
2088 if (lease
-> address
.len
== client
-> requested_address
.len
&&
2089 !memcmp (lease
-> address
.iabuf
,
2090 client
-> requested_address
.iabuf
,
2091 client
-> requested_address
.len
)) {
2092 lease
-> next
= client
-> offered_leases
;
2093 client
-> offered_leases
= lease
;
2095 /* Put the lease at the end of the list. */
2096 lease
-> next
= (struct client_lease
*)0;
2097 if (!client
-> offered_leases
)
2098 client
-> offered_leases
= lease
;
2100 for (lp
= client
-> offered_leases
; lp
-> next
;
2107 /* If the selecting interval has expired, go immediately to
2108 state_selecting(). Otherwise, time out into
2109 state_selecting at the select interval. */
2110 if (stop_selecting
<= cur_tv
.tv_sec
)
2111 state_selecting (client
);
2113 tv
.tv_sec
= stop_selecting
;
2114 tv
.tv_usec
= cur_tv
.tv_usec
;
2115 add_timeout(&tv
, state_selecting
, client
, 0, 0);
2116 cancel_timeout(send_discover
, client
);
2120 /* Allocate a client_lease structure and initialize it from the parameters
2121 in the specified packet. */
2123 struct client_lease
*packet_to_lease (packet
, client
)
2124 struct packet
*packet
;
2125 struct client_state
*client
;
2127 struct client_lease
*lease
;
2129 struct option_cache
*oc
;
2130 struct option
*option
= NULL
;
2131 struct data_string data
;
2133 lease
= (struct client_lease
*)new_client_lease (MDL
);
2136 log_error("packet_to_lease: no memory to record lease.\n");
2140 memset(lease
, 0, sizeof(*lease
));
2142 /* Copy the lease options. */
2143 option_state_reference(&lease
->options
, packet
->options
, MDL
);
2145 lease
->address
.len
= sizeof(packet
->raw
->yiaddr
);
2146 memcpy(lease
->address
.iabuf
, &packet
->raw
->yiaddr
,
2147 lease
->address
.len
);
2149 lease
->next_srv_addr
.len
= sizeof(packet
->raw
->siaddr
);
2150 memcpy(lease
->next_srv_addr
.iabuf
, &packet
->raw
->siaddr
,
2151 lease
->next_srv_addr
.len
);
2153 memset(&data
, 0, sizeof(data
));
2155 if (client
-> config
-> vendor_space_name
) {
2156 i
= DHO_VENDOR_ENCAPSULATED_OPTIONS
;
2158 /* See if there was a vendor encapsulation option. */
2159 oc
= lookup_option (&dhcp_universe
, lease
-> options
, i
);
2161 client
-> config
-> vendor_space_name
&&
2162 evaluate_option_cache (&data
, packet
,
2163 (struct lease
*)0, client
,
2164 packet
-> options
, lease
-> options
,
2165 &global_scope
, oc
, MDL
)) {
2167 if (!option_code_hash_lookup(&option
,
2168 dhcp_universe
.code_hash
,
2170 log_fatal("Unable to find VENDOR "
2171 "option (%s:%d).", MDL
);
2172 parse_encapsulated_suboptions
2173 (packet
-> options
, option
,
2174 data
.data
, data
.len
, &dhcp_universe
,
2175 client
-> config
-> vendor_space_name
2178 option_dereference(&option
, MDL
);
2180 data_string_forget (&data
, MDL
);
2185 /* Figure out the overload flag. */
2186 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
2187 DHO_DHCP_OPTION_OVERLOAD
);
2189 evaluate_option_cache (&data
, packet
, (struct lease
*)0, client
,
2190 packet
-> options
, lease
-> options
,
2191 &global_scope
, oc
, MDL
)) {
2196 data_string_forget (&data
, MDL
);
2200 /* If the server name was filled out, copy it. */
2201 if (!(i
& 2) && packet
-> raw
-> sname
[0]) {
2203 /* Don't count on the NUL terminator. */
2204 for (len
= 0; len
< DHCP_SNAME_LEN
; len
++)
2205 if (!packet
-> raw
-> sname
[len
])
2207 lease
-> server_name
= dmalloc (len
+ 1, MDL
);
2208 if (!lease
-> server_name
) {
2209 log_error ("dhcpoffer: no memory for server name.\n");
2210 destroy_client_lease (lease
);
2211 return (struct client_lease
*)0;
2213 memcpy (lease
-> server_name
,
2214 packet
-> raw
-> sname
, len
);
2215 lease
-> server_name
[len
] = 0;
2219 /* Ditto for the filename. */
2220 if (!(i
& 1) && packet
-> raw
-> file
[0]) {
2222 /* Don't count on the NUL terminator. */
2223 for (len
= 0; len
< DHCP_FILE_LEN
; len
++)
2224 if (!packet
-> raw
-> file
[len
])
2226 lease
-> filename
= dmalloc (len
+ 1, MDL
);
2227 if (!lease
-> filename
) {
2228 log_error ("dhcpoffer: no memory for filename.\n");
2229 destroy_client_lease (lease
);
2230 return (struct client_lease
*)0;
2232 memcpy (lease
-> filename
,
2233 packet
-> raw
-> file
, len
);
2234 lease
-> filename
[len
] = 0;
2238 execute_statements_in_scope(NULL
, (struct packet
*)packet
, NULL
,
2239 client
, lease
->options
, lease
->options
,
2240 &global_scope
, client
->config
->on_receipt
,
2246 void dhcpnak (packet
)
2247 struct packet
*packet
;
2249 struct interface_info
*ip
= packet
-> interface
;
2250 struct client_state
*client
;
2252 /* Find a client state that matches the xid... */
2253 for (client
= ip
-> client
; client
; client
= client
-> next
)
2254 if (client
-> xid
== packet
-> raw
-> xid
)
2257 /* If we're not receptive to an offer right now, or if the offer
2258 has an unrecognizable transaction id, then just drop it. */
2260 (packet
-> interface
-> hw_address
.hlen
- 1 !=
2261 packet
-> raw
-> hlen
) ||
2262 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
2263 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
2265 log_debug ("DHCPNAK in wrong transaction.");
2270 if (client
-> state
!= S_REBOOTING
&&
2271 client
-> state
!= S_REQUESTING
&&
2272 client
-> state
!= S_RENEWING
&&
2273 client
-> state
!= S_REBINDING
) {
2275 log_debug ("DHCPNAK in wrong state.");
2280 log_info ("DHCPNAK from %s", piaddr (packet
-> client_addr
));
2282 if (!client
-> active
) {
2284 log_info ("DHCPNAK with no active lease.\n");
2289 /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
2290 * to indicate that we want all old bindings to be removed. (It
2291 * is possible that we may get a NAK while in the RENEW state,
2292 * so we might have bindings active at that time)
2294 script_init(client
, "EXPIRE", NULL
);
2295 script_write_params(client
, "old_", client
->active
);
2296 script_write_requested(client
);
2298 script_write_params(client
, "alias_", client
->alias
);
2301 destroy_client_lease (client
-> active
);
2302 client
-> active
= (struct client_lease
*)0;
2304 /* Stop sending DHCPREQUEST packets... */
2305 cancel_timeout (send_request
, client
);
2307 /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
2308 * down (this expunges any routes and arp cache). This makes the
2309 * interface unusable by state_init(), which we call next. So, we
2310 * need to 'PREINIT' the interface to bring it back up.
2312 script_init(client
, "PREINIT", NULL
);
2314 script_write_params(client
, "alias_", client
->alias
);
2317 client
-> state
= S_INIT
;
2318 state_init (client
);
2321 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
2322 one after the right interval has expired. If we don't get an offer by
2323 the time we reach the panic interval, call the panic function. */
2325 void send_discover (cpp
)
2328 struct client_state
*client
= cpp
;
2335 /* Figure out how long it's been since we started transmitting. */
2336 interval
= cur_time
- client
-> first_sending
;
2338 /* If we're past the panic timeout, call the script and tell it
2339 we haven't found anything for this interface yet. */
2340 if (interval
> client
-> config
-> timeout
) {
2341 state_panic (client
);
2345 /* If we're selecting media, try the whole list before doing
2346 the exponential backoff, but if we've already received an
2347 offer, stop looping, because we obviously have it right. */
2348 if (!client
-> offered_leases
&&
2349 client
-> config
-> media
) {
2352 if (client
-> medium
) {
2353 client
-> medium
= client
-> medium
-> next
;
2356 if (!client
-> medium
) {
2358 log_fatal ("No valid media types for %s!",
2359 client
-> interface
-> name
);
2361 client
-> config
-> media
;
2365 log_info ("Trying medium \"%s\" %d",
2366 client
-> medium
-> string
, increase
);
2367 script_init(client
, "MEDIUM", client
-> medium
);
2368 if (script_go(client
)) {
2374 /* If we're supposed to increase the interval, do so. If it's
2375 currently zero (i.e., we haven't sent any packets yet), set
2376 it to initial_interval; otherwise, add to it a random number
2377 between zero and two times itself. On average, this means
2378 that it will double with every transmission. */
2380 if (!client
->interval
)
2381 client
->interval
= client
->config
->initial_interval
;
2383 client
->interval
+= random() % (2 * client
->interval
);
2385 /* Don't backoff past cutoff. */
2386 if (client
->interval
> client
->config
->backoff_cutoff
)
2387 client
->interval
= (client
->config
->backoff_cutoff
/ 2)
2388 + (random() % client
->config
->backoff_cutoff
);
2389 } else if (!client
->interval
)
2390 client
->interval
= client
->config
->initial_interval
;
2392 /* If the backoff would take us to the panic timeout, just use that
2394 if (cur_time
+ client
-> interval
>
2395 client
-> first_sending
+ client
-> config
-> timeout
)
2396 client
-> interval
=
2397 (client
-> first_sending
+
2398 client
-> config
-> timeout
) - cur_time
+ 1;
2400 /* Record the number of seconds since we started sending. */
2401 if (interval
< 65536)
2402 client
-> packet
.secs
= htons (interval
);
2404 client
-> packet
.secs
= htons (65535);
2405 client
-> secs
= client
-> packet
.secs
;
2407 #if defined(DHCPv6) && defined(DHCP4o6)
2408 if (dhcpv4_over_dhcpv6
) {
2409 log_info ("DHCPDISCOVER interval %ld",
2410 (long)(client
-> interval
));
2413 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
2414 client
-> name
? client
-> name
: client
-> interface
-> name
,
2415 inet_ntoa (sockaddr_broadcast
.sin_addr
),
2416 ntohs (sockaddr_broadcast
.sin_port
), (long)(client
-> interval
));
2418 /* Send out a packet. */
2419 #if defined(DHCPv6) && defined(DHCP4o6)
2420 if (dhcpv4_over_dhcpv6
) {
2421 result
= send_dhcpv4_query(client
, 1);
2424 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
2425 client
->packet_length
, inaddr_any
,
2426 &sockaddr_broadcast
, NULL
);
2428 #if defined(DHCPv6) && defined(DHCP4o6)
2429 if (dhcpv4_over_dhcpv6
) {
2430 log_error("%s:%d: Failed to send %d byte long packet.",
2431 MDL
, client
->packet_length
);
2434 log_error("%s:%d: Failed to send %d byte long packet over %s "
2435 "interface.", MDL
, client
->packet_length
,
2436 client
->interface
->name
);
2440 * If we used 0 microseconds here, and there were other clients on the
2441 * same network with a synchronized local clock (ntp), and a similar
2442 * zero-microsecond-scheduler behavior, then we could be participating
2443 * in a sub-second DOS ttck.
2445 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->interval
;
2446 tv
.tv_usec
= client
->interval
> 1 ? random() % 1000000 : cur_tv
.tv_usec
;
2447 add_timeout(&tv
, send_discover
, client
, 0, 0);
2450 /* state_panic gets called if we haven't received any offers in a preset
2451 amount of time. When this happens, we try to use existing leases that
2452 haven't yet expired, and failing that, we call the client script and
2453 hope it can do something. */
2455 void state_panic (cpp
)
2458 struct client_state
*client
= cpp
;
2459 struct client_lease
*loop
;
2460 struct client_lease
*lp
;
2463 loop
= lp
= client
-> active
;
2465 log_info ("No DHCPOFFERS received.");
2467 /* We may not have an active lease, but we may have some
2468 predefined leases that we can try. */
2469 if (!client
-> active
&& client
-> leases
)
2472 /* Run through the list of leases and see if one can be used. */
2473 while (client
-> active
) {
2474 if (client
-> active
-> expiry
> cur_time
) {
2475 log_info ("Trying recorded lease %s",
2476 piaddr (client
-> active
-> address
));
2477 /* Run the client script with the existing
2479 script_init(client
, "TIMEOUT",
2480 client
-> active
-> medium
);
2481 script_write_params(client
, "new_", client
-> active
);
2482 script_write_requested(client
);
2483 if (client
-> alias
)
2484 script_write_params(client
, "alias_",
2487 /* If the old lease is still good and doesn't
2488 yet need renewal, go into BOUND state and
2489 timeout at the renewal time. */
2490 if (!script_go(client
)) {
2491 if (cur_time
< client
-> active
-> renewal
) {
2492 client
-> state
= S_BOUND
;
2493 log_info ("bound: renewal in %ld %s.",
2494 (long)(client
-> active
-> renewal
-
2495 cur_time
), "seconds");
2496 tv
.tv_sec
= client
->active
->renewal
;
2497 tv
.tv_usec
= ((client
->active
->renewal
-
2499 random() % 1000000 :
2501 add_timeout(&tv
, state_bound
, client
, 0, 0);
2503 client
-> state
= S_BOUND
;
2504 log_info ("bound: immediate renewal.");
2505 state_bound (client
);
2507 reinitialize_interfaces ();
2513 /* If there are no other leases, give up. */
2514 if (!client
-> leases
) {
2515 client
-> leases
= client
-> active
;
2516 client
-> active
= (struct client_lease
*)0;
2521 /* Otherwise, put the active lease at the end of the
2522 lease list, and try another lease.. */
2523 for (lp
= client
-> leases
; lp
-> next
; lp
= lp
-> next
)
2525 lp
-> next
= client
-> active
;
2527 lp
-> next
-> next
= (struct client_lease
*)0;
2529 client
-> active
= client
-> leases
;
2530 client
-> leases
= client
-> leases
-> next
;
2532 /* If we already tried this lease, we've exhausted the
2533 set of leases, so we might as well give up for
2535 if (client
-> active
== loop
)
2538 loop
= client
-> active
;
2541 /* No leases were available, or what was available didn't work, so
2542 tell the shell script that we failed to allocate an address,
2543 and try again later. */
2546 log_info ("Unable to obtain a lease on first try.%s",
2550 #if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
2551 /* Let's call a script and we're done */
2552 script_init(client
, "FAIL", (struct string_list
*)0);
2558 log_info ("No working leases in persistent database - sleeping.");
2559 script_init(client
, "FAIL", (struct string_list
*)0);
2560 if (client
-> alias
)
2561 script_write_params(client
, "alias_", client
-> alias
);
2563 client
-> state
= S_INIT
;
2564 tv
.tv_sec
= cur_tv
.tv_sec
+ ((client
->config
->retry_interval
+ 1) / 2 +
2565 (random() % client
->config
->retry_interval
));
2566 tv
.tv_usec
= ((tv
.tv_sec
- cur_tv
.tv_sec
) > 1) ?
2567 random() % 1000000 : cur_tv
.tv_usec
;
2568 add_timeout(&tv
, state_init
, client
, 0, 0);
2572 void send_request (cpp
)
2575 struct client_state
*client
= cpp
;
2579 struct sockaddr_in destination
;
2580 struct in_addr from
;
2583 const char* rip_str
= "";
2585 /* Figure out how long it's been since we started transmitting. */
2586 interval
= cur_time
- client
-> first_sending
;
2588 /* If we're in the INIT-REBOOT or REQUESTING state and we're
2589 past the reboot timeout, go to INIT and see if we can
2590 DISCOVER an address... */
2591 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
2592 means either that we're on a network with no DHCP server,
2593 or that our server is down. In the latter case, assuming
2594 that there is a backup DHCP server, DHCPDISCOVER will get
2595 us a new address, but we could also have successfully
2596 reused our old address. In the former case, we're hosed
2597 anyway. This is not a win-prone situation. */
2598 if ((client
-> state
== S_REBOOTING
||
2599 client
-> state
== S_REQUESTING
) &&
2600 interval
> client
-> config
-> reboot_timeout
) {
2602 client
-> state
= S_INIT
;
2603 cancel_timeout (send_request
, client
);
2604 state_init (client
);
2608 /* If we're in the reboot state, make sure the media is set up
2610 if (client
-> state
== S_REBOOTING
&&
2611 !client
-> medium
&&
2612 client
-> active
-> medium
) {
2613 script_init(client
, "MEDIUM", client
-> active
-> medium
);
2615 /* If the medium we chose won't fly, go to INIT state. */
2616 if (script_go(client
))
2619 /* Record the medium. */
2620 client
-> medium
= client
-> active
-> medium
;
2623 /* If the lease has expired, relinquish the address and go back
2624 to the INIT state. */
2625 if (client
-> state
!= S_REQUESTING
&&
2626 cur_time
> client
-> active
-> expiry
) {
2627 /* Run the client script with the new parameters. */
2628 script_init(client
, "EXPIRE", (struct string_list
*)0);
2629 script_write_params(client
, "old_", client
-> active
);
2630 script_write_requested(client
);
2631 if (client
-> alias
)
2632 script_write_params(client
, "alias_",
2636 /* Now do a preinit on the interface so that we can
2637 discover a new address. */
2638 script_init(client
, "PREINIT", (struct string_list
*)0);
2639 if (client
-> alias
)
2640 script_write_params(client
, "alias_",
2644 client
-> state
= S_INIT
;
2645 state_init (client
);
2649 /* Do the exponential backoff... */
2650 if (!client
-> interval
)
2651 client
-> interval
= client
-> config
-> initial_interval
;
2653 client
-> interval
+= ((random () >> 2) %
2654 (2 * client
-> interval
));
2657 /* Don't backoff past cutoff. */
2658 if (client
-> interval
>
2659 client
-> config
-> backoff_cutoff
)
2660 client
-> interval
=
2661 ((client
-> config
-> backoff_cutoff
/ 2)
2662 + ((random () >> 2) %
2663 client
-> config
-> backoff_cutoff
));
2665 /* If the backoff would take us to the expiry time, just set the
2666 timeout to the expiry time. */
2667 if (client
-> state
!= S_REQUESTING
&&
2668 cur_time
+ client
-> interval
> client
-> active
-> expiry
)
2669 client
-> interval
=
2670 client
-> active
-> expiry
- cur_time
+ 1;
2672 /* If the lease T2 time has elapsed, or if we're not yet bound,
2673 broadcast the DHCPREQUEST rather than unicasting. */
2674 if (client
-> state
== S_REQUESTING
||
2675 client
-> state
== S_REBOOTING
||
2676 cur_time
> client
-> active
-> rebind
)
2677 destination
.sin_addr
= sockaddr_broadcast
.sin_addr
;
2679 memcpy (&destination
.sin_addr
.s_addr
,
2680 client
-> destination
.iabuf
,
2681 sizeof destination
.sin_addr
.s_addr
);
2682 destination
.sin_port
= remote_port
;
2683 destination
.sin_family
= AF_INET
;
2685 destination
.sin_len
= sizeof destination
;
2688 if (client
-> state
== S_RENEWING
||
2689 client
-> state
== S_REBINDING
)
2690 memcpy (&from
, client
-> active
-> address
.iabuf
,
2693 from
.s_addr
= INADDR_ANY
;
2695 /* Record the number of seconds since we started sending. */
2696 if (client
-> state
== S_REQUESTING
)
2697 client
-> packet
.secs
= client
-> secs
;
2699 if (interval
< 65536)
2700 client
-> packet
.secs
= htons (interval
);
2702 client
-> packet
.secs
= htons (65535);
2705 #if defined(DHCPv6) && defined(DHCP4o6)
2706 if (dhcpv4_over_dhcpv6
) {
2707 log_info ("DHCPREQUEST");
2710 memset(rip_buf
, 0x0, sizeof(rip_buf
));
2711 if (client
->state
== S_BOUND
|| client
->state
== S_RENEWING
||
2712 client
->state
== S_REBINDING
) {
2713 rip_str
= inet_ntoa(client
->packet
.ciaddr
);
2715 rip_str
= piaddr(client
->requested_address
);
2718 strncpy(rip_buf
, rip_str
, sizeof(rip_buf
)-1);
2719 log_info ("DHCPREQUEST for %s on %s to %s port %d", rip_buf
,
2720 client
->name
? client
->name
: client
->interface
->name
,
2721 inet_ntoa(destination
.sin_addr
),
2722 ntohs (destination
.sin_port
));
2724 #if defined(DHCPv6) && defined(DHCP4o6)
2725 if (dhcpv4_over_dhcpv6
) {
2727 if (destination
.sin_addr
.s_addr
== INADDR_BROADCAST
)
2729 result
= send_dhcpv4_query(client
, broadcast
);
2731 log_error("%s:%d: Failed to send %d byte long packet.",
2732 MDL
, client
->packet_length
);
2736 if (destination
.sin_addr
.s_addr
!= INADDR_BROADCAST
&&
2737 fallback_interface
) {
2738 result
= send_packet(fallback_interface
, NULL
, &client
->packet
,
2739 client
->packet_length
, from
, &destination
,
2742 log_error("%s:%d: Failed to send %d byte long packet "
2743 "over %s interface.", MDL
,
2744 client
->packet_length
,
2745 fallback_interface
->name
);
2749 /* Send out a packet. */
2750 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
2751 client
->packet_length
, from
, &destination
,
2754 log_error("%s:%d: Failed to send %d byte long packet"
2755 " over %s interface.", MDL
,
2756 client
->packet_length
,
2757 client
->interface
->name
);
2761 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->interval
;
2762 tv
.tv_usec
= ((tv
.tv_sec
- cur_tv
.tv_sec
) > 1) ?
2763 random() % 1000000 : cur_tv
.tv_usec
;
2764 add_timeout(&tv
, send_request
, client
, 0, 0);
2767 void send_decline (cpp
)
2770 struct client_state
*client
= cpp
;
2774 #if defined(DHCPv6) && defined(DHCP4o6)
2775 if (dhcpv4_over_dhcpv6
) {
2776 log_info ("DHCPDECLINE");
2779 log_info ("DHCPDECLINE of %s on %s to %s port %d",
2780 piaddr(client
->requested_address
),
2781 (client
->name
? client
->name
: client
->interface
->name
),
2782 inet_ntoa(sockaddr_broadcast
.sin_addr
),
2783 ntohs(sockaddr_broadcast
.sin_port
));
2785 /* Send out a packet. */
2786 #if defined(DHCPv6) && defined(DHCP4o6)
2787 if (dhcpv4_over_dhcpv6
) {
2788 result
= send_dhcpv4_query(client
, 1);
2791 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
2792 client
->packet_length
, inaddr_any
,
2793 &sockaddr_broadcast
, NULL
);
2795 #if defined(DHCPv6) && defined(DHCP4o6)
2796 if (dhcpv4_over_dhcpv6
) {
2797 log_error("%s:%d: Failed to send %d byte long packet.",
2798 MDL
, client
->packet_length
);
2801 log_error("%s:%d: Failed to send %d byte long packet over %s"
2802 " interface.", MDL
, client
->packet_length
,
2803 client
->interface
->name
);
2807 void send_release (cpp
)
2810 struct client_state
*client
= cpp
;
2813 struct sockaddr_in destination
;
2814 struct in_addr from
;
2816 memcpy (&from
, client
-> active
-> address
.iabuf
,
2818 memcpy (&destination
.sin_addr
.s_addr
,
2819 client
-> destination
.iabuf
,
2820 sizeof destination
.sin_addr
.s_addr
);
2821 destination
.sin_port
= remote_port
;
2822 destination
.sin_family
= AF_INET
;
2824 destination
.sin_len
= sizeof destination
;
2827 /* Set the lease to end now, so that we don't accidentally
2828 reuse it if we restart before the old expiry time. */
2829 client
-> active
-> expiry
=
2830 client
-> active
-> renewal
=
2831 client
-> active
-> rebind
= cur_time
;
2832 if (!write_client_lease (client
, client
-> active
, 1, 1)) {
2833 log_error ("Can't release lease: lease write failed.");
2837 #if defined(DHCPv6) && defined(DHCP4o6)
2838 if (dhcpv4_over_dhcpv6
) {
2839 log_info ("DHCPRELEASE");
2842 log_info ("DHCPRELEASE of %s on %s to %s port %d",
2843 piaddr(client
->active
->address
),
2844 client
->name
? client
->name
: client
->interface
->name
,
2845 inet_ntoa (destination
.sin_addr
),
2846 ntohs (destination
.sin_port
));
2848 #if defined(DHCPv6) && defined(DHCP4o6)
2849 if (dhcpv4_over_dhcpv6
) {
2851 if (destination
.sin_addr
.s_addr
== INADDR_BROADCAST
)
2853 result
= send_dhcpv4_query(client
, broadcast
);
2855 log_error("%s:%d: Failed to send %d byte long packet.",
2856 MDL
, client
->packet_length
);
2860 if (fallback_interface
) {
2861 result
= send_packet(fallback_interface
, NULL
, &client
->packet
,
2862 client
->packet_length
, from
, &destination
,
2865 log_error("%s:%d: Failed to send %d byte long packet"
2866 " over %s interface.", MDL
,
2867 client
->packet_length
,
2868 fallback_interface
->name
);
2871 /* Send out a packet. */
2872 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
2873 client
->packet_length
, from
, &destination
,
2876 log_error ("%s:%d: Failed to send %d byte long packet"
2877 " over %s interface.", MDL
,
2878 client
->packet_length
,
2879 client
->interface
->name
);
2885 #if defined(DHCPv6) && defined(DHCP4o6)
2887 * \brief Send a DHCPv4-query to the DHCPv6 client
2888 * (DHCPv4 client function)
2890 * The DHCPv4 client sends a DHCPv4-query to the DHCPv6 client over
2891 * the inter-process communication socket.
2893 * \param client the DHCPv4 client state
2894 * \param broadcast the broadcast flag
2895 * \return the sent byte count (-1 on error)
2897 static int send_dhcpv4_query(struct client_state
*client
, int broadcast
) {
2898 struct data_string ds
;
2899 struct dhcpv4_over_dhcpv6_packet
*query
;
2902 if (dhcp4o6_state
<= 0) {
2903 log_info("send_dhcpv4_query: not ready.");
2908 * Compute buffer length and allocate it.
2910 len
= ofs
= (int)(offsetof(struct dhcpv4_over_dhcpv6_packet
, options
));
2911 len
+= dhcpv6_universe
.tag_size
+ dhcpv6_universe
.length_size
;
2912 len
+= client
->packet_length
;
2913 memset(&ds
, 0, sizeof(ds
));
2914 if (!buffer_allocate(&ds
.buffer
, len
, MDL
)) {
2915 log_error("Unable to allocate memory for DHCPv4-query.");
2918 ds
.data
= ds
.buffer
->data
;
2924 query
= (struct dhcpv4_over_dhcpv6_packet
*)ds
.data
;
2925 query
->msg_type
= DHCPV6_DHCPV4_QUERY
;
2926 query
->flags
[0] = query
->flags
[1] = query
->flags
[2] = 0;
2928 query
->flags
[0] |= DHCP4O6_QUERY_UNICAST
;
2931 * Append DHCPv4 message.
2933 dhcpv6_universe
.store_tag(ds
.buffer
->data
+ ofs
, D6O_DHCPV4_MSG
);
2934 ofs
+= dhcpv6_universe
.tag_size
;
2935 dhcpv6_universe
.store_length(ds
.buffer
->data
+ ofs
,
2936 client
->packet_length
);
2937 ofs
+= dhcpv6_universe
.length_size
;
2938 memcpy(ds
.buffer
->data
+ ofs
, &client
->packet
, client
->packet_length
);
2941 * Send DHCPv6 message.
2943 cc
= send(dhcp4o6_fd
, ds
.data
, ds
.len
, 0);
2945 log_error("send_dhcpv4_query: send(): %m");
2947 data_string_forget(&ds
, MDL
);
2953 * \brief Forward a DHCPv4-query to all DHCPv4 over DHCPv6 server addresses.
2954 * (DHCPv6 client function)
2956 * \param raw the DHCPv6 DHCPv4-query message raw content
2958 static void forw_dhcpv4_query(struct data_string
*raw
) {
2959 struct interface_info
*ip
;
2960 struct client_state
*client
;
2961 struct dhc6_lease
*lease
;
2962 struct option_cache
*oc
;
2963 struct data_string addrs
;
2964 struct sockaddr_in6 sin6
;
2965 int i
, send_ret
, attempt
, success
;
2967 attempt
= success
= 0;
2968 memset(&sin6
, 0, sizeof(sin6
));
2969 sin6
.sin6_family
= AF_INET6
;
2970 sin6
.sin6_port
= remote_port
;
2972 sin6
.sin6_len
= sizeof(sin6
);
2974 memset(&addrs
, 0, sizeof(addrs
));
2975 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
2976 for (client
= ip
->client
; client
!= NULL
;
2977 client
= client
->next
) {
2978 if ((client
->state
!= S_BOUND
) &&
2979 (client
->state
!= S_RENEWING
) &&
2980 (client
->state
!= S_REBINDING
))
2982 lease
= client
->active_lease
;
2983 if ((lease
== NULL
) || lease
->released
)
2985 oc
= lookup_option(&dhcpv6_universe
,
2987 D6O_DHCP4_O_DHCP6_SERVER
);
2989 !evaluate_option_cache(&addrs
, NULL
, NULL
, NULL
,
2990 lease
->options
, NULL
,
2991 &global_scope
, oc
, MDL
) ||
2992 ((addrs
.len
% sizeof(sin6
.sin6_addr
)) != 0)) {
2993 data_string_forget(&addrs
, MDL
);
2996 if (addrs
.len
== 0) {
2997 /* note there is nothing to forget */
2999 All_DHCP_Relay_Agents_and_Servers
,
3002 send_ret
= send_packet6(ip
, raw
->data
,
3004 if (send_ret
== raw
->len
)
3008 for (i
= 0; i
< addrs
.len
;
3009 i
+= sizeof(sin6
.sin6_addr
)) {
3010 memcpy(&sin6
.sin6_addr
, addrs
.data
+ i
,
3011 sizeof(sin6
.sin6_addr
));
3013 send_ret
= send_packet6(ip
, raw
->data
,
3015 if (send_ret
== raw
->len
)
3018 data_string_forget(&addrs
, MDL
);
3022 log_info("forw_dhcpv4_query: sent(%d): %d/%d",
3023 raw
->len
, success
, attempt
);
3031 make_client_options(struct client_state
*client
, struct client_lease
*lease
,
3032 u_int8_t
*type
, struct option_cache
*sid
,
3033 struct iaddr
*rip
, struct option
**prl
,
3034 struct option_state
**op
)
3037 struct option_cache
*oc
;
3038 struct option
*option
= NULL
;
3039 struct buffer
*bp
= NULL
;
3041 /* If there are any leftover options, get rid of them. */
3043 option_state_dereference(op
, MDL
);
3045 /* Allocate space for options. */
3046 option_state_allocate(op
, MDL
);
3048 /* Send the server identifier if provided. */
3050 save_option(&dhcp_universe
, *op
, sid
);
3054 /* Send the requested address if provided. */
3056 client
->requested_address
= *rip
;
3057 i
= DHO_DHCP_REQUESTED_ADDRESS
;
3058 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
3060 make_const_option_cache(&oc
, NULL
, rip
->iabuf
, rip
->len
,
3062 log_error ("can't make requested address cache.");
3064 save_option(&dhcp_universe
, *op
, oc
);
3065 option_cache_dereference(&oc
, MDL
);
3067 option_dereference(&option
, MDL
);
3069 client
->requested_address
.len
= 0;
3072 i
= DHO_DHCP_MESSAGE_TYPE
;
3073 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
, &i
, 0,
3075 make_const_option_cache(&oc
, NULL
, type
, 1, option
, MDL
)))
3076 log_error("can't make message type.");
3078 save_option(&dhcp_universe
, *op
, oc
);
3079 option_cache_dereference(&oc
, MDL
);
3081 option_dereference(&option
, MDL
);
3086 /* Probe the length of the list. */
3088 for (i
= 0 ; prl
[i
] != NULL
; i
++)
3089 if (prl
[i
]->universe
== &dhcp_universe
)
3092 if (!buffer_allocate(&bp
, len
, MDL
))
3093 log_error("can't make parameter list buffer.");
3095 unsigned code
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
3098 for (i
= 0 ; prl
[i
] != NULL
; i
++)
3099 if (prl
[i
]->universe
== &dhcp_universe
)
3100 bp
->data
[len
++] = prl
[i
]->code
;
3102 if (!(option_code_hash_lookup(&option
,
3103 dhcp_universe
.code_hash
,
3105 make_const_option_cache(&oc
, &bp
, NULL
, len
,
3108 buffer_dereference(&bp
, MDL
);
3109 log_error ("can't make option cache");
3111 save_option(&dhcp_universe
, *op
, oc
);
3112 option_cache_dereference(&oc
, MDL
);
3114 option_dereference(&option
, MDL
);
3119 * If requested (duid_v4 == 1) add an RFC4361 compliant client-identifier
3120 * This can be overridden by including a client id in the configuration
3124 struct data_string client_identifier
;
3127 memset(&client_identifier
, 0, sizeof(client_identifier
));
3128 client_identifier
.len
= 1 + 4 + default_duid
.len
;
3129 if (!buffer_allocate(&client_identifier
.buffer
,
3130 client_identifier
.len
, MDL
))
3131 log_fatal("no memory for default DUID!");
3132 client_identifier
.data
= client_identifier
.buffer
->data
;
3134 i
= DHO_DHCP_CLIENT_IDENTIFIER
;
3136 /* Client-identifier type : 1 byte */
3137 *client_identifier
.buffer
->data
= 255;
3140 * we use the low 4 bytes from the interface address
3142 if (client
->interface
->hw_address
.hlen
> 4) {
3143 hw_idx
= client
->interface
->hw_address
.hlen
- 4;
3147 hw_len
= client
->interface
->hw_address
.hlen
;
3149 memcpy(&client_identifier
.buffer
->data
+ 5 - hw_len
,
3150 client
->interface
->hw_address
.hbuf
+ hw_idx
,
3153 /* Add the default duid */
3154 memcpy(&client_identifier
.buffer
->data
+(1+4),
3155 default_duid
.data
, default_duid
.len
);
3157 /* And save the option */
3158 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
3160 make_const_option_cache(&oc
, NULL
,
3161 (u_int8_t
*)client_identifier
.data
,
3162 client_identifier
.len
,
3164 log_error ("can't make requested client id cache..");
3166 save_option (&dhcp_universe
, *op
, oc
);
3167 option_cache_dereference (&oc
, MDL
);
3169 option_dereference(&option
, MDL
);
3172 /* Run statements that need to be run on transmission. */
3173 if (client
->config
->on_transmission
)
3174 execute_statements_in_scope(NULL
, NULL
, NULL
, client
,
3175 (lease
? lease
->options
: NULL
),
3177 client
->config
->on_transmission
,
3181 void make_discover (client
, lease
)
3182 struct client_state
*client
;
3183 struct client_lease
*lease
;
3185 unsigned char discover
= DHCPDISCOVER
;
3186 struct option_state
*options
= (struct option_state
*)0;
3188 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3190 make_client_options (client
,
3191 lease
, &discover
, (struct option_cache
*)0,
3192 lease
? &lease
-> address
: (struct iaddr
*)0,
3193 client
-> config
-> requested_options
,
3196 /* Set up the option buffer... */
3197 client
-> packet_length
=
3198 cons_options ((struct packet
*)0, &client
-> packet
,
3199 (struct lease
*)0, client
,
3200 /* maximum packet size */1500,
3201 (struct option_state
*)0,
3203 /* scope */ &global_scope
,
3207 (struct data_string
*)0,
3208 client
-> config
-> vendor_space_name
);
3210 option_state_dereference (&options
, MDL
);
3211 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3212 client
-> packet_length
= BOOTP_MIN_LEN
;
3214 client
-> packet
.op
= BOOTREQUEST
;
3215 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3216 /* Assumes hw_address is known, otherwise a random value may result */
3217 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3218 client
-> packet
.hops
= 0;
3219 client
-> packet
.xid
= random ();
3220 client
-> packet
.secs
= 0; /* filled in by send_discover. */
3222 if (can_receive_unicast_unconfigured (client
-> interface
))
3223 client
-> packet
.flags
= 0;
3225 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3227 memset (&(client
-> packet
.ciaddr
),
3228 0, sizeof client
-> packet
.ciaddr
);
3229 memset (&(client
-> packet
.yiaddr
),
3230 0, sizeof client
-> packet
.yiaddr
);
3231 memset (&(client
-> packet
.siaddr
),
3232 0, sizeof client
-> packet
.siaddr
);
3233 client
-> packet
.giaddr
= giaddr
;
3234 if (client
-> interface
-> hw_address
.hlen
> 0)
3235 memcpy (client
-> packet
.chaddr
,
3236 &client
-> interface
-> hw_address
.hbuf
[1],
3237 (unsigned)(client
-> interface
-> hw_address
.hlen
- 1));
3240 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3245 void make_request (client
, lease
)
3246 struct client_state
*client
;
3247 struct client_lease
*lease
;
3249 unsigned char request
= DHCPREQUEST
;
3250 struct option_cache
*oc
;
3252 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3254 if (client
-> state
== S_REQUESTING
)
3255 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3256 DHO_DHCP_SERVER_IDENTIFIER
);
3258 oc
= (struct option_cache
*)0;
3260 if (client
-> sent_options
)
3261 option_state_dereference (&client
-> sent_options
, MDL
);
3263 make_client_options (client
, lease
, &request
, oc
,
3264 ((client
-> state
== S_REQUESTING
||
3265 client
-> state
== S_REBOOTING
)
3267 : (struct iaddr
*)0),
3268 client
-> config
-> requested_options
,
3269 &client
-> sent_options
);
3271 /* Set up the option buffer... */
3272 client
-> packet_length
=
3273 cons_options ((struct packet
*)0, &client
-> packet
,
3274 (struct lease
*)0, client
,
3275 /* maximum packet size */1500,
3276 (struct option_state
*)0,
3277 client
-> sent_options
,
3278 /* scope */ &global_scope
,
3282 (struct data_string
*)0,
3283 client
-> config
-> vendor_space_name
);
3285 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3286 client
-> packet_length
= BOOTP_MIN_LEN
;
3288 client
-> packet
.op
= BOOTREQUEST
;
3289 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3290 /* Assumes hw_address is known, otherwise a random value may result */
3291 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3292 client
-> packet
.hops
= 0;
3293 client
-> packet
.xid
= client
-> xid
;
3294 client
-> packet
.secs
= 0; /* Filled in by send_request. */
3296 /* If we own the address we're requesting, put it in ciaddr;
3297 otherwise set ciaddr to zero. */
3298 if (client
-> state
== S_BOUND
||
3299 client
-> state
== S_RENEWING
||
3300 client
-> state
== S_REBINDING
) {
3301 memcpy (&client
-> packet
.ciaddr
,
3302 lease
-> address
.iabuf
, lease
-> address
.len
);
3303 client
-> packet
.flags
= 0;
3305 memset (&client
-> packet
.ciaddr
, 0,
3306 sizeof client
-> packet
.ciaddr
);
3307 if (can_receive_unicast_unconfigured (client
-> interface
))
3308 client
-> packet
.flags
= 0;
3310 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3313 memset (&client
-> packet
.yiaddr
, 0,
3314 sizeof client
-> packet
.yiaddr
);
3315 memset (&client
-> packet
.siaddr
, 0,
3316 sizeof client
-> packet
.siaddr
);
3317 if (client
-> state
!= S_BOUND
&&
3318 client
-> state
!= S_RENEWING
)
3319 client
-> packet
.giaddr
= giaddr
;
3321 memset (&client
-> packet
.giaddr
, 0,
3322 sizeof client
-> packet
.giaddr
);
3323 if (client
-> interface
-> hw_address
.hlen
> 0)
3324 memcpy (client
-> packet
.chaddr
,
3325 &client
-> interface
-> hw_address
.hbuf
[1],
3326 (unsigned)(client
-> interface
-> hw_address
.hlen
- 1));
3329 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3333 void make_decline (client
, lease
)
3334 struct client_state
*client
;
3335 struct client_lease
*lease
;
3337 unsigned char decline
= DHCPDECLINE
;
3338 struct option_cache
*oc
;
3340 struct option_state
*options
= (struct option_state
*)0;
3342 /* Create the options cache. */
3343 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3344 DHO_DHCP_SERVER_IDENTIFIER
);
3345 make_client_options(client
, lease
, &decline
, oc
, &lease
->address
,
3348 /* Consume the options cache into the option buffer. */
3349 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3350 client
-> packet_length
=
3351 cons_options ((struct packet
*)0, &client
-> packet
,
3352 (struct lease
*)0, client
, 0,
3353 (struct option_state
*)0, options
,
3354 &global_scope
, 0, 0, 0, (struct data_string
*)0,
3355 client
-> config
-> vendor_space_name
);
3357 /* Destroy the options cache. */
3358 option_state_dereference (&options
, MDL
);
3360 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3361 client
-> packet_length
= BOOTP_MIN_LEN
;
3363 client
-> packet
.op
= BOOTREQUEST
;
3364 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3365 /* Assumes hw_address is known, otherwise a random value may result */
3366 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3367 client
-> packet
.hops
= 0;
3368 client
-> packet
.xid
= client
-> xid
;
3369 client
-> packet
.secs
= 0; /* Filled in by send_request. */
3370 if (can_receive_unicast_unconfigured (client
-> interface
))
3371 client
-> packet
.flags
= 0;
3373 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3375 /* ciaddr must always be zero. */
3376 memset (&client
-> packet
.ciaddr
, 0,
3377 sizeof client
-> packet
.ciaddr
);
3378 memset (&client
-> packet
.yiaddr
, 0,
3379 sizeof client
-> packet
.yiaddr
);
3380 memset (&client
-> packet
.siaddr
, 0,
3381 sizeof client
-> packet
.siaddr
);
3382 client
-> packet
.giaddr
= giaddr
;
3383 memcpy (client
-> packet
.chaddr
,
3384 &client
-> interface
-> hw_address
.hbuf
[1],
3385 client
-> interface
-> hw_address
.hlen
);
3388 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3392 void make_release (client
, lease
)
3393 struct client_state
*client
;
3394 struct client_lease
*lease
;
3396 unsigned char request
= DHCPRELEASE
;
3397 struct option_cache
*oc
;
3399 struct option_state
*options
= (struct option_state
*)0;
3401 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3403 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3404 DHO_DHCP_SERVER_IDENTIFIER
);
3405 make_client_options(client
, lease
, &request
, oc
, NULL
, NULL
, &options
);
3407 /* Set up the option buffer... */
3408 client
-> packet_length
=
3409 cons_options ((struct packet
*)0, &client
-> packet
,
3410 (struct lease
*)0, client
,
3411 /* maximum packet size */1500,
3412 (struct option_state
*)0,
3414 /* scope */ &global_scope
,
3418 (struct data_string
*)0,
3419 client
-> config
-> vendor_space_name
);
3421 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3422 client
-> packet_length
= BOOTP_MIN_LEN
;
3423 option_state_dereference (&options
, MDL
);
3425 client
-> packet
.op
= BOOTREQUEST
;
3426 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3427 /* Assumes hw_address is known, otherwise a random value may result */
3428 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3429 client
-> packet
.hops
= 0;
3430 client
-> packet
.xid
= random ();
3431 client
-> packet
.secs
= 0;
3432 client
-> packet
.flags
= 0;
3433 memcpy (&client
-> packet
.ciaddr
,
3434 lease
-> address
.iabuf
, lease
-> address
.len
);
3435 memset (&client
-> packet
.yiaddr
, 0,
3436 sizeof client
-> packet
.yiaddr
);
3437 memset (&client
-> packet
.siaddr
, 0,
3438 sizeof client
-> packet
.siaddr
);
3439 client
-> packet
.giaddr
= giaddr
;
3440 memcpy (client
-> packet
.chaddr
,
3441 &client
-> interface
-> hw_address
.hbuf
[1],
3442 client
-> interface
-> hw_address
.hlen
);
3445 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3449 void destroy_client_lease (lease
)
3450 struct client_lease
*lease
;
3452 if (lease
-> server_name
)
3453 dfree (lease
-> server_name
, MDL
);
3454 if (lease
-> filename
)
3455 dfree (lease
-> filename
, MDL
);
3456 option_state_dereference (&lease
-> options
, MDL
);
3457 free_client_lease (lease
, MDL
);
3460 FILE *leaseFile
= NULL
;
3461 int leases_written
= 0;
3463 void rewrite_client_leases ()
3465 struct interface_info
*ip
;
3466 struct client_state
*client
;
3467 struct client_lease
*lp
;
3469 if (leaseFile
!= NULL
)
3471 leaseFile
= fopen (path_dhclient_db
, "w");
3472 if (leaseFile
== NULL
) {
3473 log_error ("can't create %s: %m", path_dhclient_db
);
3477 /* If there is a default duid, write it out. */
3478 if (default_duid
.len
!= 0)
3479 write_duid(&default_duid
);
3481 /* Write out all the leases attached to configured interfaces that
3483 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
3484 for (client
= ip
-> client
; client
; client
= client
-> next
) {
3485 for (lp
= client
-> leases
; lp
; lp
= lp
-> next
) {
3486 write_client_lease (client
, lp
, 1, 0);
3488 if (client
-> active
)
3489 write_client_lease (client
,
3490 client
-> active
, 1, 0);
3492 if (client
->active_lease
!= NULL
)
3493 write_client6_lease(client
,
3494 client
->active_lease
,
3497 /* Reset last_write after rewrites. */
3498 client
->last_write
= 0;
3502 /* Write out any leases that are attached to interfaces that aren't
3503 currently configured. */
3504 for (ip
= dummy_interfaces
; ip
; ip
= ip
-> next
) {
3505 for (client
= ip
-> client
; client
; client
= client
-> next
) {
3506 for (lp
= client
-> leases
; lp
; lp
= lp
-> next
) {
3507 write_client_lease (client
, lp
, 1, 0);
3509 if (client
-> active
)
3510 write_client_lease (client
,
3511 client
-> active
, 1, 0);
3513 if (client
->active_lease
!= NULL
)
3514 write_client6_lease(client
,
3515 client
->active_lease
,
3518 /* Reset last_write after rewrites. */
3519 client
->last_write
= 0;
3525 void write_lease_option (struct option_cache
*oc
,
3526 struct packet
*packet
, struct lease
*lease
,
3527 struct client_state
*client_state
,
3528 struct option_state
*in_options
,
3529 struct option_state
*cfg_options
,
3530 struct binding_scope
**scope
,
3531 struct universe
*u
, void *stuff
)
3533 const char *name
, *dot
;
3534 struct data_string ds
;
3535 char *preamble
= stuff
;
3537 memset (&ds
, 0, sizeof ds
);
3539 if (u
!= &dhcp_universe
) {
3546 if (evaluate_option_cache (&ds
, packet
, lease
, client_state
,
3547 in_options
, cfg_options
, scope
, oc
, MDL
)) {
3548 /* The option name */
3549 fprintf(leaseFile
, "%soption %s%s%s", preamble
,
3550 name
, dot
, oc
->option
->name
);
3552 /* The option value if there is one */
3553 if ((oc
->option
->format
== NULL
) ||
3554 (oc
->option
->format
[0] != 'Z')) {
3555 fprintf(leaseFile
, " %s",
3556 pretty_print_option(oc
->option
, ds
.data
,
3560 /* The closing semi-colon and newline */
3561 fprintf(leaseFile
, ";\n");
3563 data_string_forget (&ds
, MDL
);
3567 /* Write an option cache to the lease store. */
3569 write_options(struct client_state
*client
, struct option_state
*options
,
3570 const char *preamble
)
3574 for (i
= 0; i
< options
->universe_count
; i
++) {
3575 option_space_foreach(NULL
, NULL
, client
, NULL
, options
,
3576 &global_scope
, universes
[i
],
3577 (char *)preamble
, write_lease_option
);
3582 * The "best" default DUID, since we cannot predict any information
3583 * about the system (such as whether or not the hardware addresses are
3584 * integrated into the motherboard or similar), is the "LLT", link local
3585 * plus time, DUID. For real stateless "LL" is better.
3587 * Once generated, this duid is stored into the state database, and
3588 * retained across restarts.
3590 * For the time being, there is probably a different state database for
3591 * every daemon, so this winds up being a per-interface identifier...which
3592 * is not how it is intended. Upcoming rearchitecting the client should
3593 * address this "one daemon model."
3596 form_duid(struct data_string
*duid
, const char *file
, int line
)
3598 struct interface_info
*ip
;
3602 /* For now, just use the first interface on the list. */
3606 log_fatal("Impossible condition at %s:%d.", MDL
);
3608 if ((ip
->hw_address
.hlen
== 0) ||
3609 (ip
->hw_address
.hlen
> sizeof(ip
->hw_address
.hbuf
)))
3610 log_fatal("Impossible hardware address length at %s:%d.", MDL
);
3613 duid_type
= stateless
? DUID_LL
: DUID_LLT
;
3616 * 2 bytes for the 'duid type' field.
3617 * 2 bytes for the 'htype' field.
3618 * (DUID_LLT) 4 bytes for the 'current time'.
3619 * enough bytes for the hardware address (note that hw_address has
3620 * the 'htype' on byte zero).
3622 len
= 4 + (ip
->hw_address
.hlen
- 1);
3623 if (duid_type
== DUID_LLT
)
3625 if (!buffer_allocate(&duid
->buffer
, len
, MDL
))
3626 log_fatal("no memory for default DUID!");
3627 duid
->data
= duid
->buffer
->data
;
3630 /* Basic Link Local Address type of DUID. */
3631 if (duid_type
== DUID_LLT
) {
3632 putUShort(duid
->buffer
->data
, DUID_LLT
);
3633 putUShort(duid
->buffer
->data
+ 2, ip
->hw_address
.hbuf
[0]);
3634 putULong(duid
->buffer
->data
+ 4, cur_time
- DUID_TIME_EPOCH
);
3635 memcpy(duid
->buffer
->data
+ 8, ip
->hw_address
.hbuf
+ 1,
3636 ip
->hw_address
.hlen
- 1);
3638 putUShort(duid
->buffer
->data
, DUID_LL
);
3639 putUShort(duid
->buffer
->data
+ 2, ip
->hw_address
.hbuf
[0]);
3640 memcpy(duid
->buffer
->data
+ 4, ip
->hw_address
.hbuf
+ 1,
3641 ip
->hw_address
.hlen
- 1);
3644 /* Now format the output based on lease-id-format */
3645 str
= format_lease_id(duid
->data
, duid
->len
,
3646 top_level_config
.lease_id_format
, MDL
);
3648 log_info("form_duid: Couldn't allocate memory to log duid!");
3650 log_info("Created duid %s.", str
);
3655 /* Write the default DUID to the lease store. */
3657 write_duid(struct data_string
*duid
)
3662 if ((duid
== NULL
) || (duid
->len
<= 2))
3663 return DHCP_R_INVALIDARG
;
3665 if (leaseFile
== NULL
) { /* XXX? */
3666 leaseFile
= fopen(path_dhclient_db
, "w");
3667 if (leaseFile
== NULL
) {
3668 log_error("can't create %s: %m", path_dhclient_db
);
3669 return ISC_R_IOERROR
;
3673 /* Generate a formatted duid string per lease-id-format */
3674 str
= format_lease_id(duid
->data
, duid
->len
,
3675 top_level_config
.lease_id_format
, MDL
);
3677 return ISC_R_NOMEMORY
;
3679 stat
= fprintf(leaseFile
, "default-duid %s;\n", str
);
3682 return ISC_R_IOERROR
;
3684 if (fflush(leaseFile
) != 0)
3685 return ISC_R_IOERROR
;
3687 return ISC_R_SUCCESS
;
3690 /* Write a DHCPv6 lease to the store. */
3692 write_client6_lease(struct client_state
*client
, struct dhc6_lease
*lease
,
3693 int rewrite
, int sync
)
3696 struct dhc6_addr
*addr
;
3700 /* This should include the current lease. */
3701 if (!rewrite
&& (leases_written
++ > 20)) {
3702 rewrite_client_leases();
3704 return ISC_R_SUCCESS
;
3707 if (client
== NULL
|| lease
== NULL
)
3708 return DHCP_R_INVALIDARG
;
3710 if (leaseFile
== NULL
) { /* XXX? */
3711 leaseFile
= fopen(path_dhclient_db
, "w");
3712 if (leaseFile
== NULL
) {
3713 log_error("can't create %s: %m", path_dhclient_db
);
3714 return ISC_R_IOERROR
;
3718 stat
= fprintf(leaseFile
, "lease6 {\n");
3720 return ISC_R_IOERROR
;
3722 stat
= fprintf(leaseFile
, " interface \"%s\";\n",
3723 client
->interface
->name
);
3725 return ISC_R_IOERROR
;
3727 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
3728 switch (ia
->ia_type
) {
3741 /* For some reason IAID was never octal or hex, but string or
3742 * hex. Go figure. So for compatibilty's sake we will either
3743 * do hex or "legacy" i.e string rather than octal. What a
3745 switch(top_level_config
.lease_id_format
) {
3747 char* iaid_str
= format_lease_id(
3748 (const unsigned char *) &ia
->iaid
, 4,
3749 top_level_config
.lease_id_format
, MDL
);
3752 log_error("Can't format iaid");
3753 return ISC_R_IOERROR
;
3756 stat
= fprintf(leaseFile
, " %s %s {\n",
3758 dfree(iaid_str
, MDL
);
3764 stat
= fprintf(leaseFile
, " %s %s {\n", ianame
,
3765 print_hex_1(4, ia
->iaid
, 12));
3770 return ISC_R_IOERROR
;
3772 if (ia
->ia_type
!= D6O_IA_TA
)
3773 stat
= fprintf(leaseFile
, " starts %d;\n"
3776 (int)ia
->starts
, ia
->renew
, ia
->rebind
);
3778 stat
= fprintf(leaseFile
, " starts %d;\n",
3781 return ISC_R_IOERROR
;
3783 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
3784 if (ia
->ia_type
!= D6O_IA_PD
)
3785 stat
= fprintf(leaseFile
,
3787 piaddr(addr
->address
));
3789 stat
= fprintf(leaseFile
,
3790 " iaprefix %s/%d {\n",
3791 piaddr(addr
->address
),
3794 return ISC_R_IOERROR
;
3796 stat
= fprintf(leaseFile
, " starts %d;\n"
3797 " preferred-life %u;\n"
3799 (int)addr
->starts
, addr
->preferred_life
,
3802 return ISC_R_IOERROR
;
3804 if (addr
->options
!= NULL
)
3805 write_options(client
, addr
->options
, " ");
3807 stat
= fprintf(leaseFile
, " }\n");
3809 return ISC_R_IOERROR
;
3812 if (ia
->options
!= NULL
)
3813 write_options(client
, ia
->options
, " ");
3815 stat
= fprintf(leaseFile
, " }\n");
3817 return ISC_R_IOERROR
;
3820 if (lease
->released
) {
3821 stat
= fprintf(leaseFile
, " released;\n");
3823 return ISC_R_IOERROR
;
3826 if (lease
->options
!= NULL
)
3827 write_options(client
, lease
->options
, " ");
3829 stat
= fprintf(leaseFile
, "}\n");
3831 return ISC_R_IOERROR
;
3833 if (fflush(leaseFile
) != 0)
3834 return ISC_R_IOERROR
;
3837 if (fsync(fileno(leaseFile
)) < 0) {
3838 log_error("write_client_lease: fsync(): %m");
3839 return ISC_R_IOERROR
;
3843 return ISC_R_SUCCESS
;
3846 int write_client_lease (client
, lease
, rewrite
, makesure
)
3847 struct client_state
*client
;
3848 struct client_lease
*lease
;
3852 struct data_string ds
;
3858 if (leases_written
++ > 20) {
3859 rewrite_client_leases ();
3864 /* If the lease came from the config file, we don't need to stash
3865 a copy in the lease database. */
3866 if (lease
-> is_static
)
3869 if (leaseFile
== NULL
) { /* XXX */
3870 leaseFile
= fopen (path_dhclient_db
, "w");
3871 if (leaseFile
== NULL
) {
3872 log_error ("can't create %s: %m", path_dhclient_db
);
3878 fprintf (leaseFile
, "lease {\n");
3879 if (lease
-> is_bootp
) {
3880 fprintf (leaseFile
, " bootp;\n");
3886 fprintf (leaseFile
, " interface \"%s\";\n",
3887 client
-> interface
-> name
);
3892 if (client
-> name
) {
3893 fprintf (leaseFile
, " name \"%s\";\n", client
-> name
);
3899 fprintf (leaseFile
, " fixed-address %s;\n",
3900 piaddr (lease
-> address
));
3905 if (lease
-> filename
) {
3906 s
= quotify_string (lease
-> filename
, MDL
);
3908 fprintf (leaseFile
, " filename \"%s\";\n", s
);
3918 if (lease
->server_name
!= NULL
) {
3919 s
= quotify_string(lease
->server_name
, MDL
);
3921 fprintf(leaseFile
, " server-name \"%s\";\n", s
);
3930 if (lease
-> medium
) {
3931 s
= quotify_string (lease
-> medium
-> string
, MDL
);
3933 fprintf (leaseFile
, " medium \"%s\";\n", s
);
3947 memset (&ds
, 0, sizeof ds
);
3949 write_options(client
, lease
->options
, " ");
3951 tval
= print_time(lease
->renewal
);
3953 fprintf(leaseFile
, " renew %s\n", tval
) < 0)
3956 tval
= print_time(lease
->rebind
);
3958 fprintf(leaseFile
, " rebind %s\n", tval
) < 0)
3961 tval
= print_time(lease
->expiry
);
3963 fprintf(leaseFile
, " expire %s\n", tval
) < 0)
3966 if (fprintf(leaseFile
, "}\n") < 0)
3969 if (fflush(leaseFile
) != 0)
3972 client
->last_write
= cur_time
;
3974 if (!errors
&& makesure
) {
3975 if (fsync (fileno (leaseFile
)) < 0) {
3976 log_info ("write_client_lease: %m");
3981 return errors
? 0 : 1;
3984 /* Variables holding name of script and file pointer for writing to
3985 script. Needless to say, this is not reentrant - only one script
3986 can be invoked at a time. */
3987 char scriptName
[256];
3991 * @brief Initializes basic variables for a script
3993 * This function is called as an initial preparation for calling a script.
3994 * It sets up a number of common env. variables that will be passed to
3995 * the script. For actual script calling, see @ref script_go .
3997 * @param client variables will be stored here (if null, the whole function
3999 * @param reason specified the reason for calling a script (must be non-null)
4000 * @param medium if specified, defines medium type (may be null)
4002 void script_init(struct client_state
*client
, const char *reason
,
4003 struct string_list
*medium
)
4005 struct string_list
*sl
, *next
;
4008 for (sl
= client
-> env
; sl
; sl
= next
) {
4012 client
-> env
= (struct string_list
*)0;
4015 if (client
-> interface
) {
4016 client_envadd (client
, "", "interface", "%s",
4017 client
-> interface
-> name
);
4020 client_envadd (client
,
4021 "", "client", "%s", client
-> name
);
4023 client_envadd (client
,
4024 "", "medium", "%s", medium
-> string
);
4026 client_envadd (client
, "", "reason", "%s", reason
);
4027 client_envadd (client
, "", "pid", "%ld", (long int)getpid ());
4029 client_envadd (client
, "", "dad_wait_time", "%ld",
4030 (long int)dad_wait_time
);
4035 void client_option_envadd (struct option_cache
*oc
,
4036 struct packet
*packet
, struct lease
*lease
,
4037 struct client_state
*client_state
,
4038 struct option_state
*in_options
,
4039 struct option_state
*cfg_options
,
4040 struct binding_scope
**scope
,
4041 struct universe
*u
, void *stuff
)
4043 struct envadd_state
*es
= stuff
;
4044 struct data_string data
;
4045 memset (&data
, 0, sizeof data
);
4047 if (evaluate_option_cache (&data
, packet
, lease
, client_state
,
4048 in_options
, cfg_options
, scope
, oc
, MDL
)) {
4051 if (dhcp_option_ev_name (name
, sizeof name
,
4055 value
= pretty_print_option(oc
->option
,
4058 length
= strlen(value
);
4060 if (check_option_values(oc
->option
->universe
,
4062 value
, length
) == 0) {
4063 client_envadd(es
->client
, es
->prefix
,
4066 log_error("suspect value in %s "
4067 "option - discarded",
4070 data_string_forget (&data
, MDL
);
4077 * @brief Adds parameters to environment variables for a script
4079 * This function add details of specified lease to a list of env. variables
4080 * to be passed to a script. The lease details will be prepended with
4081 * specified prefix (e.g. "old_") and added to the list stored in client.
4082 * Following variables may be set:
4086 * - broadcast_address
4091 * @param client env. variables will be stored here
4092 * @param prefix textual prefix to be added to each variable (e.g. "old_")
4093 * @param lease lease details will be extracted from here
4095 void script_write_params(struct client_state
*client
, const char *prefix
,
4096 struct client_lease
*lease
)
4099 struct data_string data
;
4100 struct option_cache
*oc
;
4101 struct envadd_state es
;
4106 client_envadd (client
,
4107 prefix
, "ip_address", "%s", piaddr (lease
-> address
));
4109 /* If we've set the next server address in the lease structure
4110 put it into an environment variable for the script */
4111 if (lease
->next_srv_addr
.len
!= 0) {
4112 client_envadd(client
, prefix
, "next_server", "%s",
4113 piaddr(lease
->next_srv_addr
));
4116 /* For the benefit of Linux (and operating systems which may
4117 have similar needs), compute the network address based on
4118 the supplied ip address and netmask, if provided. Also
4119 compute the broadcast address (the host address all ones
4120 broadcast address, not the host address all zeroes
4121 broadcast address). */
4123 memset (&data
, 0, sizeof data
);
4124 oc
= lookup_option (&dhcp_universe
, lease
-> options
, DHO_SUBNET_MASK
);
4125 if (oc
&& evaluate_option_cache (&data
, (struct packet
*)0,
4126 (struct lease
*)0, client
,
4127 (struct option_state
*)0,
4129 &global_scope
, oc
, MDL
)) {
4131 struct iaddr netmask
, subnet
, broadcast
;
4134 * No matter the length of the subnet-mask option,
4135 * use only the first four octets. Note that
4136 * subnet-mask options longer than 4 octets are not
4137 * in conformance with RFC 2132, but servers with this
4140 memcpy(netmask
.iabuf
, data
.data
, 4);
4142 data_string_forget (&data
, MDL
);
4144 subnet
= subnet_number (lease
-> address
, netmask
);
4146 client_envadd (client
, prefix
, "network_number",
4147 "%s", piaddr (subnet
));
4149 oc
= lookup_option (&dhcp_universe
,
4151 DHO_BROADCAST_ADDRESS
);
4153 !(evaluate_option_cache
4154 (&data
, (struct packet
*)0,
4155 (struct lease
*)0, client
,
4156 (struct option_state
*)0,
4158 &global_scope
, oc
, MDL
))) {
4159 broadcast
= broadcast_addr (subnet
, netmask
);
4160 if (broadcast
.len
) {
4161 client_envadd (client
,
4162 prefix
, "broadcast_address",
4163 "%s", piaddr (broadcast
));
4168 data_string_forget (&data
, MDL
);
4171 if (lease
->filename
) {
4172 if (check_option_values(NULL
, DHO_ROOT_PATH
,
4174 strlen(lease
->filename
)) == 0) {
4175 client_envadd(client
, prefix
, "filename",
4176 "%s", lease
->filename
);
4178 log_error("suspect value in %s "
4179 "option - discarded",
4184 if (lease
->server_name
) {
4185 if (check_option_values(NULL
, DHO_HOST_NAME
,
4187 strlen(lease
->server_name
)) == 0 ) {
4188 client_envadd (client
, prefix
, "server_name",
4189 "%s", lease
->server_name
);
4191 log_error("suspect value in %s "
4192 "option - discarded",
4193 lease
->server_name
);
4197 for (i
= 0; i
< lease
-> options
-> universe_count
; i
++) {
4198 option_space_foreach ((struct packet
*)0, (struct lease
*)0,
4199 client
, (struct option_state
*)0,
4200 lease
-> options
, &global_scope
,
4202 &es
, client_option_envadd
);
4205 client_envadd (client
, prefix
, "expiry", "%lu",
4206 (unsigned long)(lease
-> expiry
));
4210 * @brief Write out the environent variable the client requested.
4211 * Write out the environment variables for the objects that the
4212 * client requested. If the object was requested the variable will be:
4213 * requested_<option_name>=1
4214 * If it wasn't requested there won't be a variable.
4216 * @param client client structure
4218 void script_write_requested(struct client_state
*client
)
4221 struct option
**req
;
4223 req
= client
->config
->requested_options
;
4228 for (i
= 0 ; req
[i
] != NULL
; i
++) {
4229 if ((req
[i
]->universe
== &dhcp_universe
) &&
4230 dhcp_option_ev_name(name
, sizeof(name
), req
[i
])) {
4231 client_envadd(client
, "requested_", name
, "%d", 1);
4237 * @brief Calls external script.
4239 * External script is specified either using -sf command line or
4240 * script parameter in the configuration file.
4242 * @param client specifies client information (environment variables,
4243 * and other parameters will be extracted and passed to the script.
4244 * @return If positive, it contains exit code of the process running script.
4245 * If negative, returns the signal number that cause the script process
4248 int script_go(struct client_state
*client
)
4253 char reason
[] = "REASON=NBI";
4254 static char client_path
[] = CLIENT_PATH
;
4256 struct string_list
*sp
, *next
;
4257 int pid
, wpid
, wstatus
;
4260 scriptName
= client
-> config
-> script_name
;
4262 scriptName
= top_level_config
.script_name
;
4264 envp
= dmalloc (((client
? client
-> envc
: 2) +
4265 client_env_count
+ 2) * sizeof (char *), MDL
);
4267 log_error ("No memory for client script environment.");
4271 /* Copy out the environment specified on the command line,
4273 for (sp
= client_env
; sp
; sp
= sp
-> next
) {
4274 envp
[i
++] = sp
-> string
;
4276 /* Copy out the environment specified by dhclient. */
4278 for (sp
= client
-> env
; sp
; sp
= sp
-> next
) {
4279 envp
[i
++] = sp
-> string
;
4282 envp
[i
++] = reason
;
4285 envp
[i
++] = client_path
;
4286 envp
[i
] = (char *)0;
4288 argv
[0] = scriptName
;
4289 argv
[1] = (char *)0;
4293 log_error ("fork: %m");
4297 wpid
= wait (&wstatus
);
4298 } while (wpid
!= pid
&& wpid
> 0);
4300 log_error ("wait: %m");
4304 /* We don't want to pass an open file descriptor for
4305 * dhclient.leases when executing dhclient-script.
4307 if (leaseFile
!= NULL
)
4309 execve (scriptName
, argv
, envp
);
4310 log_error ("execve (%s, ...): %m", scriptName
);
4315 for (sp
= client
-> env
; sp
; sp
= next
) {
4319 client
-> env
= (struct string_list
*)0;
4323 gettimeofday(&cur_tv
, NULL
);
4324 return (WIFEXITED (wstatus
) ?
4325 WEXITSTATUS (wstatus
) : -WTERMSIG (wstatus
));
4328 void client_envadd (struct client_state
*client
,
4329 const char *prefix
, const char *name
, const char *fmt
, ...)
4334 struct string_list
*val
;
4337 va_start (list
, fmt
);
4338 len
= vsnprintf (spbuf
, sizeof spbuf
, fmt
, list
);
4341 val
= dmalloc (strlen (prefix
) + strlen (name
) + 1 /* = */ +
4342 len
+ sizeof *val
, MDL
);
4344 log_error ("client_envadd: cannot allocate space for variable");
4353 if (len
>= sizeof spbuf
) {
4354 va_start (list
, fmt
);
4355 vsnprintf (s
, len
+ 1, fmt
, list
);
4361 val
-> next
= client
-> env
;
4362 client
-> env
= val
;
4366 int dhcp_option_ev_name (buf
, buflen
, option
)
4369 struct option
*option
;
4375 if (option
-> universe
!= &dhcp_universe
) {
4376 s
= option
-> universe
-> name
;
4385 if (j
+ 1 == buflen
)
4395 if (j
+ 1 == buflen
)
4406 void finish (char ret
)
4408 if (no_daemon
|| dfd
[0] == -1 || dfd
[1] == -1)
4410 if (write(dfd
[1], &ret
, 1) != 1)
4411 log_fatal("write to parent: %m");
4412 (void) close(dfd
[1]);
4413 dfd
[0] = dfd
[1] = -1;
4421 /* Don't become a daemon if the user requested otherwise. */
4423 write_client_pid_file ();
4427 /* Only do it once. */
4428 if (dfd
[0] == -1 || dfd
[1] == -1)
4431 /* Signal parent we started successfully. */
4432 if (write(dfd
[1], &buf
, 1) != 1)
4433 log_fatal("write to parent: %m");
4434 (void) close(dfd
[1]);
4435 dfd
[0] = dfd
[1] = -1;
4437 /* Stop logging to stderr... */
4440 /* Become session leader and get pid... */
4443 /* Close standard I/O descriptors. */
4448 /* Reopen them on /dev/null. */
4449 (void) open("/dev/null", O_RDWR
);
4450 (void) open("/dev/null", O_RDWR
);
4451 (void) open("/dev/null", O_RDWR
);
4453 write_client_pid_file ();
4455 IGNORE_RET (chdir("/"));
4459 void write_client_pid_file ()
4464 /* nothing to do if the user doesn't want a pid file */
4465 if (no_pid_file
== ISC_TRUE
) {
4469 pfdesc
= open (path_dhclient_pid
, O_CREAT
| O_TRUNC
| O_WRONLY
, 0644);
4472 log_error ("Can't create %s: %m", path_dhclient_pid
);
4476 pf
= fdopen (pfdesc
, "w");
4479 log_error ("Can't fdopen %s: %m", path_dhclient_pid
);
4481 fprintf (pf
, "%ld\n", (long)getpid ());
4486 void client_location_changed ()
4488 struct interface_info
*ip
;
4489 struct client_state
*client
;
4491 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4492 for (client
= ip
-> client
; client
; client
= client
-> next
) {
4493 switch (client
-> state
) {
4495 cancel_timeout (send_discover
, client
);
4499 cancel_timeout (state_bound
, client
);
4505 cancel_timeout (send_request
, client
);
4513 client
-> state
= S_INIT
;
4514 state_reboot (client
);
4519 void do_release(client
)
4520 struct client_state
*client
;
4522 struct data_string ds
;
4523 struct option_cache
*oc
;
4525 #if defined(DHCPv6) && defined(DHCP4o6)
4526 if (dhcpv4_over_dhcpv6
&& (dhcp4o6_state
<= 0)) {
4527 if (dhcp4o6_state
< 0)
4529 client
->pending
= P_RELEASE
;
4534 /* Pick a random xid. */
4535 client
-> xid
= random ();
4537 /* is there even a lease to release? */
4538 if (client
-> active
) {
4539 /* Make a DHCPRELEASE packet, and set appropriate per-interface
4541 make_release (client
, client
-> active
);
4543 memset (&ds
, 0, sizeof ds
);
4544 oc
= lookup_option (&dhcp_universe
,
4545 client
-> active
-> options
,
4546 DHO_DHCP_SERVER_IDENTIFIER
);
4548 evaluate_option_cache (&ds
, (struct packet
*)0,
4549 (struct lease
*)0, client
,
4550 (struct option_state
*)0,
4551 client
-> active
-> options
,
4552 &global_scope
, oc
, MDL
)) {
4554 memcpy (client
-> destination
.iabuf
,
4556 client
-> destination
.len
= 4;
4558 client
-> destination
= iaddr_broadcast
;
4560 data_string_forget (&ds
, MDL
);
4562 client
-> destination
= iaddr_broadcast
;
4563 client
-> first_sending
= cur_time
;
4564 client
-> interval
= client
-> config
-> initial_interval
;
4566 /* Zap the medium list... */
4567 client
-> medium
= (struct string_list
*)0;
4569 /* Send out the first and only DHCPRELEASE packet. */
4570 send_release (client
);
4572 /* Do the client script RELEASE operation. */
4573 script_init (client
,
4574 "RELEASE", (struct string_list
*)0);
4575 if (client
-> alias
)
4576 script_write_params(client
, "alias_",
4578 script_write_params(client
, "old_", client
-> active
);
4579 script_write_requested(client
);
4583 /* Cancel any timeouts. */
4584 cancel_timeout (state_bound
, client
);
4585 cancel_timeout (send_discover
, client
);
4586 cancel_timeout (state_init
, client
);
4587 cancel_timeout (send_request
, client
);
4588 cancel_timeout (state_reboot
, client
);
4589 client
-> state
= S_STOPPED
;
4591 #if defined(DHCPv6) && defined(DHCP4o6)
4592 if (dhcpv4_over_dhcpv6
)
4597 int dhclient_interface_shutdown_hook (struct interface_info
*interface
)
4599 do_release (interface
-> client
);
4604 int dhclient_interface_discovery_hook (struct interface_info
*tmp
)
4606 struct interface_info
*last
, *ip
;
4607 /* See if we can find the client from dummy_interfaces */
4609 for (ip
= dummy_interfaces
; ip
; ip
= ip
-> next
) {
4610 if (!strcmp (ip
-> name
, tmp
-> name
)) {
4611 /* Remove from dummy_interfaces */
4613 ip
= (struct interface_info
*)0;
4614 interface_reference (&ip
, last
-> next
, MDL
);
4615 interface_dereference (&last
-> next
, MDL
);
4617 interface_reference (&last
-> next
,
4619 interface_dereference (&ip
-> next
,
4623 ip
= (struct interface_info
*)0;
4624 interface_reference (&ip
,
4625 dummy_interfaces
, MDL
);
4626 interface_dereference (&dummy_interfaces
, MDL
);
4628 interface_reference (&dummy_interfaces
,
4630 interface_dereference (&ip
-> next
,
4634 /* Copy "client" to tmp */
4636 tmp
-> client
= ip
-> client
;
4637 tmp
-> client
-> interface
= tmp
;
4639 interface_dereference (&ip
, MDL
);
4647 isc_result_t
dhclient_interface_startup_hook (struct interface_info
*interface
)
4649 struct interface_info
*ip
;
4650 struct client_state
*client
;
4652 /* This code needs some rethinking. It doesn't test against
4653 a signal name, and it just kind of bulls into doing something
4654 that may or may not be appropriate. */
4657 interface_reference (&interface
-> next
, interfaces
, MDL
);
4658 interface_dereference (&interfaces
, MDL
);
4660 interface_reference (&interfaces
, interface
, MDL
);
4662 discover_interfaces (DISCOVER_UNCONFIGURED
);
4664 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4665 /* If interfaces were specified, don't configure
4666 interfaces that weren't specified! */
4667 if (ip
-> flags
& INTERFACE_RUNNING
||
4668 (ip
-> flags
& (INTERFACE_REQUESTED
|
4669 INTERFACE_AUTOMATIC
)) !=
4670 INTERFACE_REQUESTED
)
4672 script_init (ip
-> client
,
4673 "PREINIT", (struct string_list
*)0);
4674 if (ip
-> client
-> alias
)
4675 script_write_params(ip
-> client
, "alias_",
4676 ip
-> client
-> alias
);
4677 script_go(ip
-> client
);
4680 discover_interfaces (interfaces_requested
!= 0
4681 ? DISCOVER_REQUESTED
4682 : DISCOVER_RUNNING
);
4684 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4685 if (ip
-> flags
& INTERFACE_RUNNING
)
4687 ip
-> flags
|= INTERFACE_RUNNING
;
4688 for (client
= ip
->client
; client
; client
= client
->next
) {
4689 client
->state
= S_INIT
;
4690 state_reboot(client
);
4693 return ISC_R_SUCCESS
;
4696 /* The client should never receive a relay agent information option,
4697 so if it does, log it and discard it. */
4699 int parse_agent_information_option (packet
, len
, data
)
4700 struct packet
*packet
;
4707 /* The client never sends relay agent information options. */
4709 unsigned cons_agent_information_options (cfg_options
, outpacket
,
4711 struct option_state
*cfg_options
;
4712 struct dhcp_packet
*outpacket
;
4719 static void shutdown_exit (void *foo
)
4721 /* get rid of the pid if we can */
4722 if (no_pid_file
== ISC_FALSE
)
4723 (void) unlink(path_dhclient_pid
);
4727 #if defined (NSUPDATE)
4729 * If the first query fails, the updater MUST NOT delete the DNS name. It
4730 * may be that the host whose lease on the server has expired has moved
4731 * to another network and obtained a lease from a different server,
4732 * which has caused the client's A RR to be replaced. It may also be
4733 * that some other client has been configured with a name that matches
4734 * the name of the DHCP client, and the policy was that the last client
4735 * to specify the name would get the name. In this case, the DHCID RR
4736 * will no longer match the updater's notion of the client-identity of
4737 * the host pointed to by the DNS name.
4738 * -- "Interaction between DHCP and DNS"
4741 /* The first and second stages are pretty similar so we combine them */
4743 client_dns_remove_action(dhcp_ddns_cb_t
*ddns_cb
,
4744 isc_result_t eresult
)
4747 isc_result_t result
;
4749 if ((eresult
== ISC_R_SUCCESS
) &&
4750 (ddns_cb
->state
== DDNS_STATE_REM_FW_YXDHCID
)) {
4751 /* Do the second stage of the FWD removal */
4752 ddns_cb
->state
= DDNS_STATE_REM_FW_NXRR
;
4754 result
= ddns_modify_fwd(ddns_cb
, MDL
);
4755 if (result
== ISC_R_SUCCESS
) {
4760 /* If we are done or have an error clean up */
4761 dhclient_ddns_cb_free(ddns_cb
, MDL
);
4766 client_dns_remove(struct client_state
*client
,
4769 dhcp_ddns_cb_t
*ddns_cb
;
4770 isc_result_t result
;
4772 /* if we have an old ddns request for this client, cancel it */
4773 if (client
->ddns_cb
!= NULL
) {
4774 ddns_cancel(client
->ddns_cb
, MDL
);
4775 client
->ddns_cb
= NULL
;
4778 ddns_cb
= ddns_cb_alloc(MDL
);
4779 if (ddns_cb
!= NULL
) {
4780 ddns_cb
->address
= *addr
;
4781 ddns_cb
->timeout
= 0;
4783 ddns_cb
->state
= DDNS_STATE_REM_FW_YXDHCID
;
4784 ddns_cb
->flags
= DDNS_UPDATE_ADDR
;
4785 ddns_cb
->cur_func
= client_dns_remove_action
;
4787 result
= client_dns_update(client
, ddns_cb
);
4789 if (result
!= ISC_R_TIMEDOUT
) {
4790 dhclient_ddns_cb_free(ddns_cb
, MDL
);
4796 isc_result_t
dhcp_set_control_state (control_object_state_t oldstate
,
4797 control_object_state_t newstate
)
4799 struct interface_info
*ip
;
4800 struct client_state
*client
;
4803 if (newstate
== server_shutdown
) {
4805 if (shutdown_signal
== SIGUSR1
)
4806 return ISC_R_SUCCESS
;
4807 /* Log shutdown on signal. */
4808 if ((shutdown_signal
== SIGINT
) ||
4809 (shutdown_signal
== SIGTERM
)) {
4810 log_info("Received signal %d, initiating shutdown.",
4813 /* Mark it was called. */
4814 shutdown_signal
= SIGUSR1
;
4817 /* Do the right thing for each interface. */
4818 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4819 for (client
= ip
-> client
; client
; client
= client
-> next
) {
4821 case server_startup
:
4822 return ISC_R_SUCCESS
;
4824 case server_running
:
4825 return ISC_R_SUCCESS
;
4827 case server_shutdown
:
4828 if (client
-> active
&&
4829 client
-> active
-> expiry
> cur_time
) {
4830 #if defined (NSUPDATE)
4831 if (client
->config
->do_forward_update
) {
4832 client_dns_remove(client
,
4833 &client
->active
->address
);
4836 do_release (client
);
4840 case server_hibernate
:
4841 state_stop (client
);
4845 state_reboot (client
);
4851 if (newstate
== server_shutdown
) {
4852 tv
.tv_sec
= cur_tv
.tv_sec
;
4853 tv
.tv_usec
= cur_tv
.tv_usec
+ 1;
4854 add_timeout(&tv
, shutdown_exit
, 0, 0, 0);
4856 return ISC_R_SUCCESS
;
4859 #if defined (NSUPDATE)
4861 * Called after a timeout if the DNS update failed on the previous try.
4862 * Starts the retry process. If the retry times out it will schedule
4863 * this routine to run again after a 10x wait.
4866 client_dns_update_timeout (void *cp
)
4868 dhcp_ddns_cb_t
*ddns_cb
= (dhcp_ddns_cb_t
*)cp
;
4869 struct client_state
*client
= (struct client_state
*)ddns_cb
->lease
;
4870 isc_result_t status
= ISC_R_FAILURE
;
4872 if ((client
!= NULL
) &&
4873 ((client
->active
!= NULL
) ||
4874 (client
->active_lease
!= NULL
)))
4875 status
= client_dns_update(client
, ddns_cb
);
4878 * A status of timedout indicates that we started the update and
4879 * have released control of the control block. Any other status
4880 * indicates that we should clean up the control block. We either
4881 * got a success which indicates that we didn't really need to
4882 * send an update or some other error in which case we weren't able
4883 * to start the update process. In both cases we still own
4884 * the control block and should free it.
4886 if (status
!= ISC_R_TIMEDOUT
) {
4887 dhclient_ddns_cb_free(ddns_cb
, MDL
);
4892 * If the first query succeeds, the updater can conclude that it
4893 * has added a new name whose only RRs are the A and DHCID RR records.
4894 * The A RR update is now complete (and a client updater is finished,
4895 * while a server might proceed to perform a PTR RR update).
4896 * -- "Interaction between DHCP and DNS"
4898 * If the second query succeeds, the updater can conclude that the current
4899 * client was the last client associated with the domain name, and that
4900 * the name now contains the updated A RR. The A RR update is now
4901 * complete (and a client updater is finished, while a server would
4902 * then proceed to perform a PTR RR update).
4903 * -- "Interaction between DHCP and DNS"
4905 * If the second query fails with NXRRSET, the updater must conclude
4906 * that the client's desired name is in use by another host. At this
4907 * juncture, the updater can decide (based on some administrative
4908 * configuration outside of the scope of this document) whether to let
4909 * the existing owner of the name keep that name, and to (possibly)
4910 * perform some name disambiguation operation on behalf of the current
4911 * client, or to replace the RRs on the name with RRs that represent
4912 * the current client. If the configured policy allows replacement of
4913 * existing records, the updater submits a query that deletes the
4914 * existing A RR and the existing DHCID RR, adding A and DHCID RRs that
4915 * represent the IP address and client-identity of the new client.
4916 * -- "Interaction between DHCP and DNS"
4919 /* The first and second stages are pretty similar so we combine them */
4921 client_dns_update_action(dhcp_ddns_cb_t
*ddns_cb
,
4922 isc_result_t eresult
)
4924 isc_result_t result
;
4930 /* Either we succeeded or broke in a bad way, clean up */
4935 * This is the only difference between the two stages,
4936 * check to see if it is the first stage, in which case
4937 * start the second stage
4939 if (ddns_cb
->state
== DDNS_STATE_ADD_FW_NXDOMAIN
) {
4940 ddns_cb
->state
= DDNS_STATE_ADD_FW_YXDHCID
;
4941 ddns_cb
->cur_func
= client_dns_update_action
;
4943 result
= ddns_modify_fwd(ddns_cb
, MDL
);
4944 if (result
== ISC_R_SUCCESS
) {
4950 case ISC_R_TIMEDOUT
:
4952 * We got a timeout response from the DNS module. Schedule
4953 * another attempt for later. We forget the name, dhcid and
4954 * zone so if it gets changed we will get the new information.
4956 data_string_forget(&ddns_cb
->fwd_name
, MDL
);
4957 data_string_forget(&ddns_cb
->dhcid
, MDL
);
4958 if (ddns_cb
->zone
!= NULL
) {
4959 forget_zone((struct dns_zone
**)&ddns_cb
->zone
);
4962 /* Reset to doing the first stage */
4963 ddns_cb
->state
= DDNS_STATE_ADD_FW_NXDOMAIN
;
4964 ddns_cb
->cur_func
= client_dns_update_action
;
4966 /* and update our timer */
4967 if (ddns_cb
->timeout
< 3600)
4968 ddns_cb
->timeout
*= 10;
4969 tv
.tv_sec
= cur_tv
.tv_sec
+ ddns_cb
->timeout
;
4970 tv
.tv_usec
= cur_tv
.tv_usec
;
4971 add_timeout(&tv
, client_dns_update_timeout
,
4972 ddns_cb
, NULL
, NULL
);
4976 dhclient_ddns_cb_free(ddns_cb
, MDL
);
4980 /* See if we should do a DNS update, and if so, do it. */
4983 client_dns_update(struct client_state
*client
, dhcp_ddns_cb_t
*ddns_cb
)
4985 struct data_string client_identifier
;
4986 struct option_cache
*oc
;
4992 /* If we didn't send an FQDN option, we certainly aren't going to
4993 be doing an update. */
4994 if (!client
-> sent_options
)
4995 return ISC_R_SUCCESS
;
4997 /* If we don't have a lease, we can't do an update. */
4998 if ((client
->active
== NULL
) && (client
->active_lease
== NULL
))
4999 return ISC_R_SUCCESS
;
5001 /* If we set the no client update flag, don't do the update. */
5002 if ((oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5003 FQDN_NO_CLIENT_UPDATE
)) &&
5004 evaluate_boolean_option_cache (&ignorep
, (struct packet
*)0,
5005 (struct lease
*)0, client
,
5006 client
-> sent_options
,
5007 (struct option_state
*)0,
5008 &global_scope
, oc
, MDL
))
5009 return ISC_R_SUCCESS
;
5011 /* If we set the "server, please update" flag, or didn't set it
5012 to false, don't do the update. */
5013 if (!(oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5014 FQDN_SERVER_UPDATE
)) ||
5015 evaluate_boolean_option_cache (&ignorep
, (struct packet
*)0,
5016 (struct lease
*)0, client
,
5017 client
-> sent_options
,
5018 (struct option_state
*)0,
5019 &global_scope
, oc
, MDL
))
5020 return ISC_R_SUCCESS
;
5022 /* If no FQDN option was supplied, don't do the update. */
5023 if (!(oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5025 !evaluate_option_cache (&ddns_cb
->fwd_name
, (struct packet
*)0,
5026 (struct lease
*)0, client
,
5027 client
-> sent_options
,
5028 (struct option_state
*)0,
5029 &global_scope
, oc
, MDL
))
5030 return ISC_R_SUCCESS
;
5033 * Construct the DHCID value for use in the DDNS update process
5034 * We have the newer standard version and the older interim version
5035 * chosen by the '-I' option. The interim version is left as is
5036 * for backwards compatibility. The standard version is based on
5037 * RFC 4701 section 3.3
5042 memset(&client_identifier
, 0, sizeof(client_identifier
));
5044 if (std_dhcid
== 1) {
5045 /* standard style */
5046 ddns_cb
->dhcid_class
= dns_rdatatype_dhcid
;
5050 ddns_cb
->dhcid_class
= dns_rdatatype_txt
;
5051 /* for backwards compatibility */
5052 ddns_v4_type
= DHO_DHCP_CLIENT_IDENTIFIER
;
5054 if (client
->active_lease
!= NULL
) {
5055 /* V6 request, get the client identifier, then
5056 * construct the dhcid for either standard
5058 if (((oc
= lookup_option(&dhcpv6_universe
,
5059 client
->sent_options
,
5060 D6O_CLIENTID
)) != NULL
) &&
5061 evaluate_option_cache(&client_identifier
, NULL
,
5063 client
->sent_options
, NULL
,
5064 &global_scope
, oc
, MDL
)) {
5065 result
= get_dhcid(ddns_cb
, 2,
5066 client_identifier
.data
,
5067 client_identifier
.len
);
5068 data_string_forget(&client_identifier
, MDL
);
5070 log_fatal("Impossible condition at %s:%d.", MDL
);
5073 * V4 request, use the client id if there is one or the
5074 * mac address if there isn't. If we have a client id
5075 * we check to see if it is an embedded DUID.
5077 if (((oc
= lookup_option(&dhcp_universe
,
5078 client
->sent_options
,
5079 DHO_DHCP_CLIENT_IDENTIFIER
)) != NULL
) &&
5080 evaluate_option_cache(&client_identifier
, NULL
,
5082 client
->sent_options
, NULL
,
5083 &global_scope
, oc
, MDL
)) {
5084 if ((std_dhcid
== 1) && (duid_v4
== 1) &&
5085 (client_identifier
.data
[0] == 255)) {
5087 * This appears to be an embedded DUID,
5088 * extract it and treat it as such
5090 if (client_identifier
.len
<= 5)
5091 log_fatal("Impossible condition at %s:%d.",
5093 result
= get_dhcid(ddns_cb
, 2,
5094 client_identifier
.data
+ 5,
5095 client_identifier
.len
- 5);
5097 result
= get_dhcid(ddns_cb
, ddns_v4_type
,
5098 client_identifier
.data
,
5099 client_identifier
.len
);
5101 data_string_forget(&client_identifier
, MDL
);
5103 result
= get_dhcid(ddns_cb
, 0,
5104 client
->interface
->hw_address
.hbuf
,
5105 client
->interface
->hw_address
.hlen
);
5109 return ISC_R_SUCCESS
;
5115 if (ddns_cb
->fwd_name
.len
&& ddns_cb
->dhcid
.len
) {
5116 rcode
= ddns_modify_fwd(ddns_cb
, MDL
);
5118 rcode
= ISC_R_FAILURE
;
5121 * A success from the modify routine means we are performing
5122 * async processing, for which we use the timedout error message.
5124 if (rcode
== ISC_R_SUCCESS
) {
5125 rcode
= ISC_R_TIMEDOUT
;
5133 * Schedule the first update. They will continue to retry occasionally
5134 * until they no longer time out (or fail).
5137 dhclient_schedule_updates(struct client_state
*client
,
5141 dhcp_ddns_cb_t
*ddns_cb
;
5144 if (!client
->config
->do_forward_update
)
5147 /* cancel any outstanding ddns requests */
5148 if (client
->ddns_cb
!= NULL
) {
5149 ddns_cancel(client
->ddns_cb
, MDL
);
5150 client
->ddns_cb
= NULL
;
5153 ddns_cb
= ddns_cb_alloc(MDL
);
5155 if (ddns_cb
!= NULL
) {
5156 ddns_cb
->lease
= (void *)client
;
5157 ddns_cb
->address
= *addr
;
5158 ddns_cb
->timeout
= 1;
5161 * XXX: DNS TTL is a problem we need to solve properly.
5162 * Until that time, 300 is a placeholder default for
5163 * something that is less insane than a value scaled
5168 ddns_cb
->state
= DDNS_STATE_ADD_FW_NXDOMAIN
;
5169 ddns_cb
->cur_func
= client_dns_update_action
;
5170 ddns_cb
->flags
= DDNS_UPDATE_ADDR
| DDNS_INCLUDE_RRSET
;
5172 client
->ddns_cb
= ddns_cb
;
5173 tv
.tv_sec
= cur_tv
.tv_sec
+ offset
;
5174 tv
.tv_usec
= cur_tv
.tv_usec
;
5175 add_timeout(&tv
, client_dns_update_timeout
,
5176 ddns_cb
, NULL
, NULL
);
5178 log_error("Unable to allocate dns update state for %s",
5185 dhcpv4_client_assignments(void)
5187 struct servent
*ent
;
5189 if (path_dhclient_pid
== NULL
)
5190 path_dhclient_pid
= _PATH_DHCLIENT_PID
;
5191 if (path_dhclient_db
== NULL
)
5192 path_dhclient_db
= _PATH_DHCLIENT_DB
;
5194 /* Default to the DHCP/BOOTP port. */
5196 /* If we're faking a relay agent, and we're not using loopback,
5197 use the server port, not the client port. */
5198 if (mockup_relay
&& giaddr
.s_addr
!= htonl(INADDR_LOOPBACK
)) {
5199 local_port
= htons(67);
5201 ent
= getservbyname("dhcpc", "udp");
5203 ent
= getservbyname("bootpc", "udp");
5205 local_port
= htons(68);
5207 local_port
= ent
->s_port
;
5208 #ifndef __CYGWIN32__
5214 /* If we're faking a relay agent, and we're not using loopback,
5215 we're using the server port, not the client port. */
5216 if (mockup_relay
&& giaddr
.s_addr
!= htonl(INADDR_LOOPBACK
)) {
5217 remote_port
= local_port
;
5219 remote_port
= htons(ntohs(local_port
) - 1); /* XXX */
5223 * The following routines are used to check that certain
5224 * strings are reasonable before we pass them to the scripts.
5225 * This avoids some problems with scripts treating the strings
5226 * as commands - see ticket 23722
5227 * The domain checking code should be done as part of assembling
5228 * the string but we are doing it here for now due to time
5232 static int check_domain_name(const char *ptr
, size_t len
, int dots
)
5236 /* not empty or complete length not over 255 characters */
5237 if ((len
== 0) || (len
> 256))
5240 /* consists of [[:alnum:]-]+ labels separated by [.] */
5241 /* a [_] is against RFC but seems to be "widely used"... */
5242 for (p
=ptr
; (*p
!= 0) && (len
-- > 0); p
++) {
5243 if ((*p
== '-') || (*p
== '_')) {
5244 /* not allowed at begin or end of a label */
5245 if (((p
- ptr
) == 0) || (len
== 0) || (p
[1] == '.'))
5247 } else if (*p
== '.') {
5248 /* each label has to be 1-63 characters;
5249 we allow [.] at the end ('foo.bar.') */
5251 if ((d
<= 0) || (d
>= 64))
5253 ptr
= p
+ 1; /* jump to the next label */
5254 if ((dots
> 0) && (len
> 0))
5256 } else if (isalnum((unsigned char)*p
) == 0) {
5257 /* also numbers at the begin are fine */
5261 return(dots
? -1 : 0);
5264 static int check_domain_name_list(const char *ptr
, size_t len
, int dots
)
5267 int ret
= -1; /* at least one needed */
5269 if ((ptr
== NULL
) || (len
== 0))
5272 for (p
=ptr
; (*p
!= 0) && (len
> 0); p
++, len
--) {
5276 if (check_domain_name(ptr
, p
- ptr
, dots
) != 0)
5283 return(check_domain_name(ptr
, p
- ptr
, dots
));
5288 static int check_option_values(struct universe
*universe
,
5296 /* just reject options we want to protect, will be escaped anyway */
5297 if ((universe
== NULL
) || (universe
== &dhcp_universe
)) {
5299 case DHO_DOMAIN_NAME
:
5300 #ifdef ACCEPT_LIST_IN_DOMAIN_NAME
5301 return check_domain_name_list(ptr
, len
, 0);
5303 return check_domain_name(ptr
, len
, 0);
5306 case DHO_NIS_DOMAIN
:
5307 case DHO_NETBIOS_SCOPE
:
5308 return check_domain_name(ptr
, len
, 0);
5310 case DHO_DOMAIN_SEARCH
:
5311 return check_domain_name_list(ptr
, len
, 0);
5316 for (; (*ptr
!= 0) && (len
-- > 0); ptr
++) {
5317 if(!(isalnum((unsigned char)*ptr
) ||
5318 *ptr
== '#' || *ptr
== '%' ||
5319 *ptr
== '+' || *ptr
== '-' ||
5320 *ptr
== '_' || *ptr
== ':' ||
5321 *ptr
== '.' || *ptr
== ',' ||
5322 *ptr
== '@' || *ptr
== '~' ||
5323 *ptr
== '\\' || *ptr
== '/' ||
5324 *ptr
== '[' || *ptr
== ']' ||
5325 *ptr
== '=' || *ptr
== ' '))
5334 if (universe
== &dhcpv6_universe
) {
5336 case D6O_SIP_SERVERS_DNS
:
5337 case D6O_DOMAIN_SEARCH
:
5338 case D6O_NIS_DOMAIN_NAME
:
5339 case D6O_NISP_DOMAIN_NAME
:
5340 return check_domain_name_list(ptr
, len
, 0);
5350 add_reject(struct packet
*packet
) {
5351 struct iaddrmatchlist
*list
;
5353 list
= dmalloc(sizeof(struct iaddrmatchlist
), MDL
);
5355 log_fatal ("no memory for reject list!");
5358 * client_addr is misleading - it is set to source address in common
5361 list
->match
.addr
= packet
->client_addr
;
5362 /* Set mask to indicate host address. */
5363 list
->match
.mask
.len
= list
->match
.addr
.len
;
5364 memset(list
->match
.mask
.iabuf
, 0xff, sizeof(list
->match
.mask
.iabuf
));
5366 /* Append to reject list for the source interface. */
5367 list
->next
= packet
->interface
->client
->config
->reject_list
;
5368 packet
->interface
->client
->config
->reject_list
= list
;
5371 * We should inform user that we won't be accepting this server
5374 log_info("Server added to list of rejected servers.");
5377 /* Wrapper function around common ddns_cb_free function that ensures
5378 * we set the client_state pointer to the control block to NULL. */
5380 dhclient_ddns_cb_free(dhcp_ddns_cb_t
*ddns_cb
, char* file
, int line
) {
5382 struct client_state
*client
= (struct client_state
*)ddns_cb
->lease
;
5383 if (client
!= NULL
) {
5384 client
->ddns_cb
= NULL
;
5387 ddns_cb_free(ddns_cb
, file
, line
);
5391 #if defined(DHCPv6) && defined(DHCP4o6)
5393 * \brief Omapi I/O handler
5395 * The inter-process communication receive handler.
5397 * On the DHCPv6 side, the message is either a POLL (which is answered
5398 * by a START or a STOP) or a DHCPv4-QUERY (which is forwarded to
5399 * DHCPv4 over DHCPv6 servers by forw_dhcpv4_query()).
5401 * On the DHCPv4 side, the message is either a START, a STOP
5402 * (both for the DHCP4 over DHCPv6 state machine) or a DHCPv4-RESPONSE
5403 * (which is processed by recv_dhcpv4_response()).
5405 * \param h the OMAPI object
5406 * \return a result for I/O success or error (used by the I/O subsystem)
5408 isc_result_t
dhcpv4o6_handler(omapi_object_t
*h
) {
5410 char start_msg
[5] = { 'S', 'T', 'A', 'R', 'T' };
5411 char stop_msg
[4] = { 'S', 'T', 'O', 'P' };
5412 char poll_msg
[4] = { 'P', 'O', 'L', 'L' };
5413 struct data_string raw
;
5416 if (h
->type
!= dhcp4o6_type
)
5417 return DHCP_R_INVALIDARG
;
5419 cc
= recv(dhcp4o6_fd
, buf
, sizeof(buf
), 0);
5421 return ISC_R_UNEXPECTED
;
5423 if (local_family
== AF_INET6
) {
5425 (memcmp(buf
, poll_msg
, sizeof(poll_msg
)) == 0)) {
5426 log_info("RCV: POLL");
5427 if (dhcp4o6_state
< 0)
5428 cc
= send(dhcp4o6_fd
, stop_msg
,
5429 sizeof(stop_msg
), 0);
5431 cc
= send(dhcp4o6_fd
, start_msg
,
5432 sizeof(start_msg
), 0);
5434 log_error("dhcpv4o6_handler: send(): %m");
5435 return ISC_R_IOERROR
;
5438 if (cc
< DHCP_FIXED_NON_UDP
+ 8)
5439 return ISC_R_UNEXPECTED
;
5440 memset(&raw
, 0, sizeof(raw
));
5441 if (!buffer_allocate(&raw
.buffer
, cc
, MDL
)) {
5442 log_error("dhcpv4o6_handler: "
5443 "no memory buffer.");
5444 return ISC_R_NOMEMORY
;
5446 raw
.data
= raw
.buffer
->data
;
5448 memcpy(raw
.buffer
->data
, buf
, cc
);
5450 forw_dhcpv4_query(&raw
);
5452 data_string_forget(&raw
, MDL
);
5456 (memcmp(buf
, stop_msg
, sizeof(stop_msg
)) == 0)) {
5457 log_info("RCV: STOP");
5458 if (dhcp4o6_state
> 0) {
5462 } else if ((cc
== 5) &&
5463 (memcmp(buf
, start_msg
, sizeof(start_msg
)) == 0)) {
5464 log_info("RCV: START");
5465 if (dhcp4o6_state
== 0)
5466 cancel_timeout(dhcp4o6_poll
, NULL
);
5470 if (cc
< DHCP_FIXED_NON_UDP
+ 16)
5471 return ISC_R_UNEXPECTED
;
5472 memset(&raw
, 0, sizeof(raw
));
5473 if (!buffer_allocate(&raw
.buffer
, cc
, MDL
)) {
5474 log_error("dhcpv4o6_handler: "
5475 "no memory buffer.");
5476 return ISC_R_NOMEMORY
;
5478 raw
.data
= raw
.buffer
->data
;
5480 memcpy(raw
.buffer
->data
, buf
, cc
);
5482 recv_dhcpv4_response(&raw
);
5484 data_string_forget(&raw
, MDL
);
5488 return ISC_R_SUCCESS
;
5492 * \brief Poll the DHCPv6 client
5493 * (DHCPv4 client function)
5495 * A POLL message is sent to the DHCPv6 client periodically to check
5496 * if the DHCPv6 is ready (i.e., has a valid DHCPv4-over-DHCPv6 server
5499 static void dhcp4o6_poll(void *dummy
) {
5500 char msg
[4] = { 'P', 'O', 'L', 'L' };
5504 IGNORE_UNUSED(dummy
);
5506 if (dhcp4o6_state
< 0)
5511 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5513 log_error("dhcp4o6_poll: send(): %m");
5515 tv
.tv_sec
= cur_time
+ 60;
5516 tv
.tv_usec
= random() % 1000000;
5518 add_timeout(&tv
, dhcp4o6_poll
, NULL
, 0, 0);
5522 * \brief Resume pending operations
5523 * (DHCPv4 client function)
5525 * A START message was received from the DHCPv6 client so pending
5526 * operations (RELEASE or REBOOT) must be resumed.
5528 static void dhcp4o6_resume() {
5529 struct interface_info
*ip
;
5530 struct client_state
*client
;
5532 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
5533 for (client
= ip
->client
; client
!= NULL
;
5534 client
= client
->next
) {
5535 if (client
->pending
== P_RELEASE
)
5537 else if (client
->pending
== P_REBOOT
)
5538 state_reboot(client
);
5544 * \brief Send a START to the DHCPv4 client
5545 * (DHCPv6 client function)
5547 * First check if there is a valid DHCPv4-over-DHCPv6 server address option,
5548 * and when found go UP and on a transition from another state send
5549 * a START message to the DHCPv4 client.
5551 void dhcp4o6_start() {
5552 struct interface_info
*ip
;
5553 struct client_state
*client
;
5554 struct dhc6_lease
*lease
;
5555 struct option_cache
*oc
;
5556 struct data_string addrs
;
5557 char msg
[5] = { 'S', 'T', 'A', 'R', 'T' };
5560 memset(&addrs
, 0, sizeof(addrs
));
5561 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
5562 for (client
= ip
->client
; client
!= NULL
;
5563 client
= client
->next
) {
5564 if ((client
->state
!= S_BOUND
) &&
5565 (client
->state
!= S_RENEWING
) &&
5566 (client
->state
!= S_REBINDING
))
5568 lease
= client
->active_lease
;
5569 if ((lease
== NULL
) || lease
->released
)
5571 oc
= lookup_option(&dhcpv6_universe
,
5573 D6O_DHCP4_O_DHCP6_SERVER
);
5575 !evaluate_option_cache(&addrs
, NULL
, NULL
, NULL
,
5576 lease
->options
, NULL
,
5577 &global_scope
, oc
, MDL
))
5579 if ((addrs
.len
% 16) != 0) {
5580 data_string_forget(&addrs
, MDL
);
5583 data_string_forget(&addrs
, MDL
);
5587 log_info("dhcp4o6_start: failed");
5592 if (dhcp4o6_state
== 1)
5594 log_info("dhcp4o6_start: go to UP");
5597 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5599 log_info("dhcp4o6_start: send(): %m");
5603 * Send a STOP to the DHCPv4 client
5604 * (DHCPv6 client function)
5606 * Go DOWN and on a transition from another state send a STOP message
5607 * to the DHCPv4 client.
5609 static void dhcp4o6_stop() {
5610 char msg
[4] = { 'S', 'T', 'O', 'P' };
5613 if (dhcp4o6_state
== -1)
5616 log_info("dhcp4o6_stop: go to DOWN");
5619 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5621 log_error("dhcp4o6_stop: send(): %m");
5623 #endif /* DHCPv6 && DHCP4o6 */