6 * Copyright (c) 2004-2022 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 * Newmarket, NH 03857 USA
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 static void add_to_tail(struct client_lease
** lease_list
, struct client_lease
* lease
);
56 /* False (default) => we write and use a pid file */
57 isc_boolean_t no_pid_file
= ISC_FALSE
;
59 int dhcp_max_agent_option_packet_length
= 0;
61 int interfaces_requested
= 0;
63 struct iaddr iaddr_broadcast
= { 4, { 255, 255, 255, 255 } };
64 struct iaddr iaddr_any
= { 4, { 0, 0, 0, 0 } };
65 struct in_addr inaddr_any
;
66 struct sockaddr_in sockaddr_broadcast
;
67 struct in_addr giaddr
;
68 struct data_string default_duid
;
73 int decline_wait_time
= 10; /* Default to 10 secs per, RFC 2131, 3.1.5 */
75 /* ASSERT_STATE() does nothing now; it used to be
76 assert (state_is == state_shouldbe). */
77 #define ASSERT_STATE(state_is, state_shouldbe) {}
80 static const char copyright
[] = "Copyright 2004-2022 Internet Systems Consortium.";
81 static const char arr
[] = "All rights reserved.";
82 static const char message
[] = "Internet Systems Consortium DHCP Client";
83 static const char url
[] = "For info, please visit https://www.isc.org/software/dhcp/";
84 #endif /* UNIT_TEST */
86 extern u_int16_t local_port
;
87 extern u_int16_t remote_port
;
89 #if defined(DHCPv6) && defined(DHCP4o6)
90 int dhcp4o6_state
= -1; /* -1 = stopped, 0 = polling, 1 = started */
93 int dfd
[2] = { -1, -1 };
94 struct string_list
*client_env
= NULL
;
95 int client_env_count
= 0;
100 int wanted_ia_na
= -1; /* the absolute value is the real one. */
101 int wanted_ia_ta
= 0;
102 int wanted_ia_pd
= 0;
103 int require_all_ias
= 0; /* If the user requires all of the IAs to
104 be available before accepting a lease
105 0 = no, 1 = requries */
107 int dad_wait_time
= 0;
108 int prefix_len_hint
= 0;
111 int address_prefix_len
= DHCLIENT_DEFAULT_PREFIX_LEN
;
112 char *mockup_relay
= NULL
;
114 char *progname
= NULL
;
116 void run_stateless(int exit_mode
, u_int16_t port
);
118 static isc_result_t
write_duid(struct data_string
*duid
);
119 static void add_reject(struct packet
*packet
);
121 static int check_domain_name(const char *ptr
, size_t len
, int dots
);
122 static int check_domain_name_list(const char *ptr
, size_t len
, int dots
);
123 static int check_option_values(struct universe
*universe
, unsigned int opt
,
124 const char *ptr
, size_t len
);
126 #if defined(NSUPDATE)
127 static void dhclient_ddns_cb_free(dhcp_ddns_cb_t
*ddns_cb
,
128 char* file
, int line
);
129 #endif /* defined NSUPDATE */
134 * \brief Print the generic usage message
136 * If the user has provided an incorrect command line print out
137 * the description of the command line. The arguments provide
138 * a way for the caller to request more specific information about
139 * the error be printed as well. Mostly this will be that some
140 * command doesn't include its argument.
142 * \param sfmt - The basic string and format for the specific error
143 * \param sarg - Generally the offending argument from the command line.
148 #if defined(DHCPv6) && defined(DHCP4o6)
149 static void dhcp4o6_poll(void *dummy
);
150 static void dhcp4o6_resume(void);
151 static void recv_dhcpv4_response(struct data_string
*raw
);
152 static int send_dhcpv4_query(struct client_state
*client
, int broadcast
);
154 static void dhcp4o6_stop(void);
155 static void forw_dhcpv4_response(struct packet
*packet
);
156 static void forw_dhcpv4_query(struct data_string
*raw
);
160 /* These are only used when we call usage() from the main routine
161 * which isn't compiled when building for unit tests
163 static const char use_noarg
[] = "No argument for command: %s";
165 static const char use_v6command
[] = "Command not used for DHCPv4: %s";
170 #define DHCLIENT_USAGE0 \
171 "[-4|-6] [-SNTPRI1dvrxi] [-nw] -4o6 <port>] [-p <port>] [-D LL|LLT]\n" \
172 " [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
173 " [--decline-wait-time <seconds>]\n" \
174 " [--address-prefix-len <length>]\n"
176 #define DHCLIENT_USAGE0 \
177 "[-4|-6] [-SNTPRI1dvrxi] [-nw] [-p <port>] [-D LL|LLT]\n" \
178 " [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
179 " [--decline-wait-time <seconds>]\n" \
180 " [--address-prefix-len <length>]\n"
183 #define DHCLIENT_USAGE0 \
184 "[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n" \
185 " [--decline-wait-time <seconds>]\n"
188 #define DHCLIENT_USAGEC \
189 " [-s server-addr] [-cf config-file]\n" \
190 " [-df duid-file] [-lf lease-file]\n" \
191 " [-pf pid-file] [--no-pid] [-e VAR=val]\n" \
192 " [-sf script-file] [interface]*"
194 #define DHCLIENT_USAGEH "{--version|--help|-h}"
197 usage(const char *sfmt
, const char *sarg
)
199 log_info("%s %s", message
, PACKAGE_VERSION
);
204 /* If desired print out the specific error message */
205 #ifdef PRINT_SPECIFIC_CL_ERRORS
207 log_error(sfmt
, sarg
);
210 log_fatal("Usage: %s %s%s\n %s %s",
211 isc_file_basename(progname
),
214 isc_file_basename(progname
),
218 extern void initialize_client_option_spaces();
221 main(int argc
, char **argv
) {
224 struct interface_info
*ip
;
225 struct client_state
*client
;
230 int release_mode
= 0;
232 omapi_object_t
*listener
;
235 int no_dhclient_conf
= 0;
236 int no_dhclient_db
= 0;
237 int no_dhclient_pid
= 0;
238 int no_dhclient_script
= 0;
240 int local_family_set
= 0;
242 u_int16_t dhcp4o6_port
= 0;
248 progname
= "dhclient";
252 /* Initialize client globals. */
253 memset(&default_duid
, 0, sizeof(default_duid
));
255 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
256 2 (stderr) are open. To do this, we assume that when we
257 open a file the lowest available file descriptor is used. */
258 fd
= open("/dev/null", O_RDWR
);
260 fd
= open("/dev/null", O_RDWR
);
262 fd
= open("/dev/null", O_RDWR
);
264 log_perror
= 0; /* No sense logging to /dev/null. */
268 openlog(isc_file_basename(progname
), DHCP_LOG_OPTIONS
, LOG_DAEMON
);
270 #if !(defined(DEBUG) || defined(__CYGWIN32__))
271 setlogmask(LOG_UPTO(LOG_INFO
));
274 /* Parse arguments changing no_daemon */
275 for (i
= 1; i
< argc
; i
++) {
276 if (!strcmp(argv
[i
], "-r")) {
278 } else if (!strcmp(argv
[i
], "-x")) {
280 } else if (!strcmp(argv
[i
], "-d")) {
282 } else if (!strcmp(argv
[i
], "--version")) {
283 const char vstring
[] = "isc-dhclient-";
284 IGNORE_RET(write(STDERR_FILENO
, vstring
,
286 IGNORE_RET(write(STDERR_FILENO
,
288 strlen(PACKAGE_VERSION
)));
289 IGNORE_RET(write(STDERR_FILENO
, "\n", 1));
291 } else if (!strcmp(argv
[i
], "--help") ||
292 !strcmp(argv
[i
], "-h")) {
293 const char *pname
= isc_file_basename(progname
);
294 IGNORE_RET(write(STDERR_FILENO
, "Usage: ", 7));
295 IGNORE_RET(write(STDERR_FILENO
, pname
, strlen(pname
)));
296 IGNORE_RET(write(STDERR_FILENO
, " ", 1));
297 IGNORE_RET(write(STDERR_FILENO
, DHCLIENT_USAGE0
,
298 strlen(DHCLIENT_USAGE0
)));
299 IGNORE_RET(write(STDERR_FILENO
, DHCLIENT_USAGEC
,
300 strlen(DHCLIENT_USAGEC
)));
301 IGNORE_RET(write(STDERR_FILENO
, "\n", 1));
302 IGNORE_RET(write(STDERR_FILENO
, " ", 7));
303 IGNORE_RET(write(STDERR_FILENO
, pname
, strlen(pname
)));
304 IGNORE_RET(write(STDERR_FILENO
, " ", 1));
305 IGNORE_RET(write(STDERR_FILENO
, DHCLIENT_USAGEH
,
306 strlen(DHCLIENT_USAGEH
)));
307 IGNORE_RET(write(STDERR_FILENO
, "\n", 1));
311 /* When not forbidden prepare to become a daemon */
316 log_fatal("Can't get pipe: %m");
317 if ((pid
= fork ()) < 0)
318 log_fatal("Can't fork daemon: %m");
320 /* Parent: wait for the child to start */
323 (void) close(dfd
[1]);
327 n
= read(dfd
[0], &buf
, 1);
330 } while (n
== -1 && errno
== EINTR
);
334 (void) close(dfd
[0]);
337 /* Set up the isc and dns library managers */
338 status
= dhcp_context_create(DHCP_CONTEXT_PRE_DB
| DHCP_CONTEXT_POST_DB
339 | DHCP_DNS_CLIENT_LAZY_INIT
, NULL
, NULL
);
340 if (status
!= ISC_R_SUCCESS
)
341 log_fatal("Can't initialize context: %s",
342 isc_result_totext(status
));
344 /* Set up the OMAPI. */
345 status
= omapi_init();
346 if (status
!= ISC_R_SUCCESS
)
347 log_fatal("Can't initialize OMAPI: %s",
348 isc_result_totext(status
));
350 /* Set up the OMAPI wrappers for various server database internal
352 dhcp_common_objects_setup();
354 dhcp_interface_discovery_hook
= dhclient_interface_discovery_hook
;
355 dhcp_interface_shutdown_hook
= dhclient_interface_shutdown_hook
;
356 dhcp_interface_startup_hook
= dhclient_interface_startup_hook
;
358 for (i
= 1; i
< argc
; i
++) {
359 if (!strcmp(argv
[i
], "-r")) {
363 } else if (!strcmp(argv
[i
], "-4")) {
364 if (local_family_set
&& local_family
!= AF_INET
)
365 log_fatal("Client can only do v4 or v6, not "
367 local_family_set
= 1;
368 local_family
= AF_INET
;
369 } else if (!strcmp(argv
[i
], "-6")) {
370 if (local_family_set
&& local_family
!= AF_INET6
)
371 log_fatal("Client can only do v4 or v6, not "
373 local_family_set
= 1;
374 local_family
= AF_INET6
;
376 } else if (!strcmp(argv
[i
], "-4o6")) {
378 usage(use_noarg
, argv
[i
-1]);
379 dhcp4o6_port
= validate_port_pair(argv
[i
]);
381 log_debug("DHCPv4 over DHCPv6 over ::1 port %d and %d",
383 ntohs(dhcp4o6_port
) + 1);
384 dhcpv4_over_dhcpv6
= 1;
387 } else if (!strcmp(argv
[i
], "-x")) { /* eXit, no release */
391 } else if (!strcmp(argv
[i
], "-p")) {
393 usage(use_noarg
, argv
[i
-1]);
394 local_port
= validate_port(argv
[i
]);
395 log_debug("binding to user-specified port %d",
397 } else if (!strcmp(argv
[i
], "-d")) {
400 } else if (!strcmp(argv
[i
], "-pf")) {
402 usage(use_noarg
, argv
[i
-1]);
403 path_dhclient_pid
= argv
[i
];
405 } else if (!strcmp(argv
[i
], "--no-pid")) {
406 no_pid_file
= ISC_TRUE
;
407 } else if (!strcmp(argv
[i
], "-cf")) {
409 usage(use_noarg
, argv
[i
-1]);
410 path_dhclient_conf
= argv
[i
];
411 no_dhclient_conf
= 1;
412 } else if (!strcmp(argv
[i
], "-df")) {
414 usage(use_noarg
, argv
[i
-1]);
415 path_dhclient_duid
= argv
[i
];
416 } else if (!strcmp(argv
[i
], "-lf")) {
418 usage(use_noarg
, argv
[i
-1]);
419 path_dhclient_db
= argv
[i
];
421 } else if (!strcmp(argv
[i
], "-sf")) {
423 usage(use_noarg
, argv
[i
-1]);
424 path_dhclient_script
= argv
[i
];
425 no_dhclient_script
= 1;
426 } else if (!strcmp(argv
[i
], "-1")) {
428 } else if (!strcmp(argv
[i
], "-q")) {
430 } else if (!strcmp(argv
[i
], "-s")) {
432 usage(use_noarg
, argv
[i
-1]);
434 } else if (!strcmp(argv
[i
], "-g")) {
436 usage(use_noarg
, argv
[i
-1]);
437 mockup_relay
= argv
[i
];
438 } else if (!strcmp(argv
[i
], "-nw")) {
440 } else if (!strcmp(argv
[i
], "-n")) {
441 /* do not start up any interfaces */
442 interfaces_requested
= -1;
443 } else if (!strcmp(argv
[i
], "-w")) {
444 /* do not exit if there are no broadcast interfaces. */
446 } else if (!strcmp(argv
[i
], "-e")) {
447 struct string_list
*tmp
;
449 usage(use_noarg
, argv
[i
-1]);
450 tmp
= dmalloc(strlen(argv
[i
]) + sizeof *tmp
, MDL
);
452 log_fatal("No memory for %s", argv
[i
]);
453 strcpy(tmp
->string
, argv
[i
]);
454 tmp
->next
= client_env
;
458 } else if (!strcmp(argv
[i
], "-S")) {
459 if (local_family_set
&& (local_family
== AF_INET
)) {
460 usage(use_v6command
, argv
[i
]);
462 local_family_set
= 1;
463 local_family
= AF_INET6
;
466 } else if (!strcmp(argv
[i
], "-N")) {
467 if (local_family_set
&& (local_family
== AF_INET
)) {
468 usage(use_v6command
, argv
[i
]);
470 local_family_set
= 1;
471 local_family
= AF_INET6
;
472 if (wanted_ia_na
< 0) {
476 } else if (!strcmp(argv
[i
], "-T")) {
477 if (local_family_set
&& (local_family
== AF_INET
)) {
478 usage(use_v6command
, argv
[i
]);
480 local_family_set
= 1;
481 local_family
= AF_INET6
;
482 if (wanted_ia_na
< 0) {
486 } else if (!strcmp(argv
[i
], "-P")) {
487 if (local_family_set
&& (local_family
== AF_INET
)) {
488 usage(use_v6command
, argv
[i
]);
490 local_family_set
= 1;
491 local_family
= AF_INET6
;
492 if (wanted_ia_na
< 0) {
496 } else if (!strcmp(argv
[i
], "-R")) {
497 if (local_family_set
&& (local_family
== AF_INET
)) {
498 usage(use_v6command
, argv
[i
]);
500 local_family_set
= 1;
501 local_family
= AF_INET6
;
503 } else if (!strcmp(argv
[i
], "--dad-wait-time")) {
505 usage(use_noarg
, argv
[i
-1]);
508 dad_wait_time
= (int)strtol(argv
[i
], &s
, 10);
509 if (errno
|| (*s
!= '\0') || (dad_wait_time
< 0)) {
510 usage("Invalid value for --dad-wait-time: %s",
513 } else if (!strcmp(argv
[i
], "--prefix-len-hint")) {
515 usage(use_noarg
, argv
[i
-1]);
519 prefix_len_hint
= (int)strtol(argv
[i
], &s
, 10);
520 if (errno
|| (*s
!= '\0') || (prefix_len_hint
< 0)) {
521 usage("Invalid value for --prefix-len-hint: %s",
524 } else if (!strcmp(argv
[i
], "--address-prefix-len")) {
526 usage(use_noarg
, argv
[i
-1]);
529 address_prefix_len
= (int)strtol(argv
[i
], &s
, 10);
530 if (errno
|| (*s
!= '\0') ||
531 (address_prefix_len
< 0)) {
532 usage("Invalid value for"
533 " --address-prefix-len: %s", argv
[i
]);
536 } else if (!strcmp(argv
[i
], "--decline-wait-time")) {
538 usage(use_noarg
, argv
[i
-1]);
542 decline_wait_time
= (int)strtol(argv
[i
], &s
, 10);
543 if (errno
|| (*s
!= '\0') ||
544 (decline_wait_time
< 0)) {
545 usage("Invalid value for "
546 "--decline-wait-time: %s", argv
[i
]);
548 } else if (!strcmp(argv
[i
], "-D")) {
551 usage(use_noarg
, argv
[i
-1]);
552 if (!strcasecmp(argv
[i
], "LL")) {
554 } else if (!strcasecmp(argv
[i
], "LLT")) {
555 duid_type
= DUID_LLT
;
557 usage("Unknown argument to -D: %s", argv
[i
]);
559 } else if (!strcmp(argv
[i
], "-i")) {
560 /* enable DUID support for DHCPv4 clients */
562 } else if (!strcmp(argv
[i
], "-I")) {
563 /* enable standard DHCID support for DDNS updates */
565 } else if (!strcmp(argv
[i
], "-v")) {
567 } else if (argv
[i
][0] == '-') {
568 usage("Unknown command: %s", argv
[i
]);
569 } else if (interfaces_requested
< 0) {
570 usage("No interfaces command -n and "
571 " requested interface %s", argv
[i
]);
573 struct interface_info
*tmp
= NULL
;
575 status
= interface_allocate(&tmp
, MDL
);
576 if (status
!= ISC_R_SUCCESS
)
577 log_fatal("Can't record interface %s:%s",
578 argv
[i
], isc_result_totext(status
));
579 if (strlen(argv
[i
]) >= sizeof(tmp
->name
))
580 log_fatal("%s: interface name too long (is %ld)",
581 argv
[i
], (long)strlen(argv
[i
]));
582 strcpy(tmp
->name
, argv
[i
]);
584 interface_reference(&tmp
->next
,
586 interface_dereference(&interfaces
, MDL
);
588 interface_reference(&interfaces
, tmp
, MDL
);
589 tmp
->flags
= INTERFACE_REQUESTED
;
590 interfaces_requested
++;
594 if (wanted_ia_na
< 0) {
598 /* Support only one (requested) interface for Prefix Delegation. */
599 if (wanted_ia_pd
&& (interfaces_requested
!= 1)) {
600 usage("PD %s only supports one requested interface", "-P");
603 #if defined(DHCPv6) && defined(DHCP4o6)
604 if ((local_family
== AF_INET6
) && dhcpv4_over_dhcpv6
&&
605 (exit_mode
|| release_mode
))
606 log_error("Can't relay DHCPv4-over-DHCPv6 "
607 "without a persistent DHCPv6 client");
608 if ((local_family
== AF_INET
) && dhcpv4_over_dhcpv6
&&
609 (interfaces_requested
!= 1))
610 log_fatal("DHCPv4-over-DHCPv6 requires an explicit "
611 "interface on which to be applied");
614 if (!no_dhclient_conf
&& (s
= getenv("PATH_DHCLIENT_CONF"))) {
615 path_dhclient_conf
= s
;
617 if (!no_dhclient_db
&& (s
= getenv("PATH_DHCLIENT_DB"))) {
618 path_dhclient_db
= s
;
620 if (!no_dhclient_pid
&& (s
= getenv("PATH_DHCLIENT_PID"))) {
621 path_dhclient_pid
= s
;
623 if (!no_dhclient_script
&& (s
= getenv("PATH_DHCLIENT_SCRIPT"))) {
624 path_dhclient_script
= s
;
627 /* Set up the initial dhcp option universe. */
628 initialize_common_option_spaces();
630 /* Set up the initial client option universe. */
631 initialize_client_option_spaces();
633 /* Assign v4 or v6 specific running parameters. */
634 if (local_family
== AF_INET
)
635 dhcpv4_client_assignments();
637 else if (local_family
== AF_INET6
)
638 dhcpv6_client_assignments();
641 log_fatal("Impossible condition at %s:%d.", MDL
);
644 * convert relative path names to absolute, for files that need
645 * to be reopened after chdir() has been called
647 if (path_dhclient_db
[0] != '/') {
648 path_dhclient_db
= absolute_path(path_dhclient_db
);
651 if (path_dhclient_script
[0] != '/') {
652 path_dhclient_script
= absolute_path(path_dhclient_script
);
656 * See if we should kill off any currently running client
657 * we don't try to kill it off if the user told us not
658 * to write a pid file - we assume they are controlling
659 * the process in some other fashion.
661 if ((release_mode
|| exit_mode
) && (no_pid_file
== ISC_FALSE
)) {
667 if ((pidfd
= fopen(path_dhclient_pid
, "r")) != NULL
) {
668 e
= fscanf(pidfd
, "%ld\n", &temp
);
669 oldpid
= (pid_t
)temp
;
671 if (e
!= 0 && e
!= EOF
&& oldpid
) {
672 if (kill(oldpid
, SIGTERM
) == 0) {
673 log_info("Killed old client process");
674 (void) unlink(path_dhclient_pid
);
676 * wait for the old process to
678 * Note kill() with sig=0 could
679 * detect termination but only
680 * the parent can be signaled...
683 } else if (errno
== ESRCH
) {
684 log_info("Removed stale PID file");
685 (void) unlink(path_dhclient_pid
);
693 log_info("%s %s", message
, PACKAGE_VERSION
);
700 quiet_interface_discovery
= 1;
703 /* If we're given a relay agent address to insert, for testing
704 purposes, figure out what it is. */
706 if (!inet_aton(mockup_relay
, &giaddr
)) {
708 he
= gethostbyname(mockup_relay
);
710 memcpy(&giaddr
, he
->h_addr_list
[0],
713 log_fatal("%s: no such host", mockup_relay
);
718 /* Get the current time... */
719 gettimeofday(&cur_tv
, NULL
);
721 sockaddr_broadcast
.sin_family
= AF_INET
;
722 sockaddr_broadcast
.sin_port
= remote_port
;
724 if (!inet_aton(server
, &sockaddr_broadcast
.sin_addr
)) {
726 he
= gethostbyname(server
);
728 memcpy(&sockaddr_broadcast
.sin_addr
,
730 sizeof sockaddr_broadcast
.sin_addr
);
732 sockaddr_broadcast
.sin_addr
.s_addr
=
736 sockaddr_broadcast
.sin_addr
.s_addr
= INADDR_BROADCAST
;
739 inaddr_any
.s_addr
= INADDR_ANY
;
741 /* Stateless special case. */
743 if (release_mode
|| (wanted_ia_na
> 0) ||
744 wanted_ia_ta
|| wanted_ia_pd
||
745 (interfaces_requested
!= 1)) {
746 usage("Stateless command: %s incompatibile with "
747 "other commands", "-S");
749 #if defined(DHCPv6) && defined(DHCP4o6)
750 run_stateless(exit_mode
, dhcp4o6_port
);
752 run_stateless(exit_mode
, 0);
757 /* Discover all the network interfaces. */
758 discover_interfaces(DISCOVER_UNCONFIGURED
);
760 /* Parse the dhclient.conf file. */
763 /* Parse the lease database. */
764 read_client_leases();
766 /* If desired parse the secondary lease database for a DUID */
767 if ((default_duid
.len
== 0) && (path_dhclient_duid
!= NULL
)) {
771 /* Rewrite the lease database... */
772 rewrite_client_leases();
775 /* config_counter(&snd_counter, &rcv_counter); */
778 * If no broadcast interfaces were discovered, call the script
783 * Call dhclient-script with the NBI flag,
784 * in case somebody cares.
786 script_init(NULL
, "NBI", NULL
);
790 * If we haven't been asked to persist, waiting for new
791 * interfaces, then just exit.
794 /* Nothing more to do. */
795 log_info("No broadcast interfaces found - exiting.");
798 } else if (!release_mode
&& !exit_mode
) {
799 /* Call the script with the list of interfaces. */
800 for (ip
= interfaces
; ip
; ip
= ip
->next
) {
802 * If interfaces were specified, don't configure
803 * interfaces that weren't specified!
805 if ((interfaces_requested
> 0) &&
806 ((ip
->flags
& (INTERFACE_REQUESTED
|
807 INTERFACE_AUTOMATIC
)) !=
808 INTERFACE_REQUESTED
))
811 if (local_family
== AF_INET6
) {
812 script_init(ip
->client
, "PREINIT6", NULL
);
814 script_init(ip
->client
, "PREINIT", NULL
);
815 if (ip
->client
->alias
!= NULL
)
816 script_write_params(ip
->client
,
820 script_go(ip
->client
);
824 /* At this point, all the interfaces that the script thinks
825 are relevant should be running, so now we once again call
826 discover_interfaces(), and this time ask it to actually set
827 up the interfaces. */
828 discover_interfaces(interfaces_requested
!= 0
832 /* PLEASE PREFER the random device: not all systems use random
833 * process identifiers so the alternative can be predictable. */
836 #ifdef ISC_PATH_RANDOMDEV
837 FILE *frnd
= fopen(ISC_PATH_RANDOMDEV
, "r");
839 nrnd
= fread(&seed
, sizeof(seed
), 1, frnd
);
843 /* Please leave the compiler to emit a warning about a constant
844 * condition in the if test. */
846 /* Make up a seed for the random number generator from current
847 time plus the sum of the last four bytes of each
848 interface's hardware address interpreted as an integer.
849 Not much entropy, but we're booting, so we're not likely to
850 find anything better. */
852 for (ip
= interfaces
; ip
; ip
= ip
->next
) {
855 &ip
->hw_address
.hbuf
[ip
->hw_address
.hlen
-
856 sizeof seed
], sizeof seed
);
859 seed
+= cur_time
+ (unsigned)getpid();
864 * Establish a default DUID. We always do so for v6 and
865 * do so if desired for v4 via the -D or -i options
867 if ((local_family
== AF_INET6
) ||
868 ((local_family
== AF_INET
) && (duid_v4
== 1))) {
869 if (default_duid
.len
== 0) {
870 if (default_duid
.buffer
!= NULL
)
871 data_string_forget(&default_duid
, MDL
);
873 form_duid(&default_duid
, MDL
);
874 write_duid(&default_duid
);
878 #if defined(DHCPv6) && defined(DHCP4o6)
879 if (dhcpv4_over_dhcpv6
&& !exit_mode
)
880 dhcp4o6_setup(dhcp4o6_port
);
883 /* Start a configuration state machine for each interface. */
885 if (local_family
== AF_INET6
) {
886 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
887 for (client
= ip
->client
; client
!= NULL
;
888 client
= client
->next
) {
890 start_release6(client
);
892 } else if (exit_mode
) {
893 unconfigure6(client
, "STOP6");
897 /* If we have a previous binding, Confirm
898 * that we can (or can't) still use it.
900 if ((client
->active_lease
!= NULL
) &&
901 !client
->active_lease
->released
)
902 start_confirm6(client
);
910 for (ip
= interfaces
; ip
; ip
= ip
->next
) {
911 ip
->flags
|= INTERFACE_RUNNING
;
912 for (client
= ip
->client
; client
;
913 client
= client
->next
) {
919 client
->state
= S_INIT
;
921 if (top_level_config
.initial_delay
>0)
924 if (top_level_config
.
930 tv
.tv_usec
= random()
934 * distribution than just
937 add_timeout(&tv
, state_reboot
,
940 state_reboot(client
);
953 if ((local_family
== AF_INET6
) || dhcpv4_over_dhcpv6
) {
961 /* Start up a listener for the object management API protocol. */
962 if (top_level_config
.omapi_port
!= -1) {
964 result
= omapi_generic_new(&listener
, MDL
);
965 if (result
!= ISC_R_SUCCESS
)
966 log_fatal("Can't allocate new generic object: %s\n",
967 isc_result_totext(result
));
968 result
= omapi_protocol_listen(listener
,
970 top_level_config
.omapi_port
,
972 if (result
!= ISC_R_SUCCESS
)
973 log_fatal("Can't start OMAPI protocol: %s",
974 isc_result_totext (result
));
977 /* Set up the bootp packet handler... */
978 bootp_packet_handler
= do_packet
;
980 dhcpv6_packet_handler
= do_packet6
;
983 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
984 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
985 dmalloc_cutoff_generation
= dmalloc_generation
;
986 dmalloc_longterm
= dmalloc_outstanding
;
987 dmalloc_outstanding
= 0;
990 #if defined(ENABLE_GENTLE_SHUTDOWN)
991 /* no signal handlers until we deal with the side effects */
992 /* install signal handlers */
993 signal(SIGINT
, dhcp_signal_handler
); /* control-c */
994 signal(SIGTERM
, dhcp_signal_handler
); /* kill */
997 /* If we're not supposed to wait before getting the address,
1002 /* If we're not going to daemonize, write the pid file
1004 if (no_daemon
|| nowait
)
1005 write_client_pid_file();
1007 /* Start dispatching packets and timeouts... */
1010 /* In fact dispatch() never returns. */
1015 * \brief Run the DHCPv6 stateless client (dhclient -6 -S)
1017 * \param exist_mode set to 1 when dhclient was called with -x
1018 * \param port DHCPv4-over-DHCPv6 client inter-process communication
1019 * UDP port pair (port,port+1 with port in network byte order)
1022 void run_stateless(int exit_mode
, u_int16_t port
)
1025 struct client_state
*client
;
1026 omapi_object_t
*listener
;
1027 isc_result_t result
;
1030 IGNORE_UNUSED(port
);
1033 /* Discover the network interface. */
1034 discover_interfaces(DISCOVER_REQUESTED
);
1037 usage("No interfaces available for stateless command: %s", "-S");
1039 /* Parse the dhclient.conf file. */
1041 if (dhcpv4_over_dhcpv6
) {
1042 /* Mark we want to request IRT too! */
1043 dhcpv4_over_dhcpv6
++;
1048 /* Parse the lease database. */
1049 read_client_leases();
1051 /* If desired parse the secondary lease database for a DUID */
1052 if ((default_duid
.len
== 0) && (path_dhclient_duid
!= NULL
)) {
1056 /* Establish a default DUID. */
1057 if (default_duid
.len
== 0) {
1058 if (default_duid
.buffer
!= NULL
)
1059 data_string_forget(&default_duid
, MDL
);
1061 form_duid(&default_duid
, MDL
);
1065 if (dhcpv4_over_dhcpv6
&& !exit_mode
)
1066 dhcp4o6_setup(port
);
1069 /* Start a configuration state machine. */
1070 for (client
= interfaces
->client
;
1072 client
= client
->next
) {
1074 unconfigure6(client
, "STOP6");
1077 start_info_request6(client
);
1082 /* Start up a listener for the object management API protocol. */
1083 if (top_level_config
.omapi_port
!= -1) {
1085 result
= omapi_generic_new(&listener
, MDL
);
1086 if (result
!= ISC_R_SUCCESS
)
1087 log_fatal("Can't allocate new generic object: %s\n",
1088 isc_result_totext(result
));
1089 result
= omapi_protocol_listen(listener
,
1091 top_level_config
.omapi_port
,
1093 if (result
!= ISC_R_SUCCESS
)
1094 log_fatal("Can't start OMAPI protocol: %s",
1095 isc_result_totext(result
));
1098 /* Set up the packet handler... */
1099 dhcpv6_packet_handler
= do_packet6
;
1101 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
1102 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1103 dmalloc_cutoff_generation
= dmalloc_generation
;
1104 dmalloc_longterm
= dmalloc_outstanding
;
1105 dmalloc_outstanding
= 0;
1108 /* If we're not supposed to wait before getting the address,
1113 /* If we're not going to daemonize, write the pid file
1115 if (no_daemon
|| nowait
)
1116 write_client_pid_file();
1118 /* Start dispatching packets and timeouts... */
1124 #endif /* !UNIT_TEST */
1126 isc_result_t
find_class (struct class **c
,
1127 const char *s
, const char *file
, int line
)
1132 int check_collection (packet
, lease
, collection
)
1133 struct packet
*packet
;
1134 struct lease
*lease
;
1135 struct collection
*collection
;
1140 void classify (packet
, class)
1141 struct packet
*packet
;
1142 struct class *class;
1146 void unbill_class (lease
)
1147 struct lease
*lease
;
1151 int find_subnet (struct subnet
**sp
,
1152 struct iaddr addr
, const char *file
, int line
)
1157 /* Individual States:
1159 * Each routine is called from the dhclient_state_machine() in one of
1161 * -> entering INIT state
1162 * -> recvpacket_flag == 0: timeout in this state
1163 * -> otherwise: received a packet in this state
1165 * Return conditions as handled by dhclient_state_machine():
1166 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
1167 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
1168 * Returns 0: finish the nap which was interrupted for no good reason.
1170 * Several per-interface variables are used to keep track of the process:
1171 * active_lease: the lease that is being used on the interface
1172 * (null pointer if not configured yet).
1173 * offered_leases: leases corresponding to DHCPOFFER messages that have
1174 * been sent to us by DHCP servers.
1175 * acked_leases: leases corresponding to DHCPACK messages that have been
1176 * sent to us by DHCP servers.
1177 * sendpacket: DHCP packet we're trying to send.
1178 * destination: IP address to send sendpacket to
1179 * In addition, there are several relevant per-lease variables.
1180 * T1_expiry, T2_expiry, lease_expiry: lease milestones
1181 * In the active lease, these control the process of renewing the lease;
1182 * In leases on the acked_leases list, this simply determines when we
1183 * can no longer legitimately use the lease.
1186 void state_reboot (cpp
)
1189 struct client_state
*client
= cpp
;
1191 #if defined(DHCPv6) && defined(DHCP4o6)
1192 if (dhcpv4_over_dhcpv6
&& (dhcp4o6_state
<= 0)) {
1193 if (dhcp4o6_state
< 0)
1195 client
->pending
= P_REBOOT
;
1200 client
->pending
= P_NONE
;
1202 /* If we don't remember an active lease, go straight to INIT. */
1203 if (!client
-> active
||
1204 client
-> active
-> is_bootp
||
1205 client
-> active
-> expiry
<= cur_time
) {
1206 state_init (client
);
1210 /* We are in the rebooting state. */
1211 client
-> state
= S_REBOOTING
;
1214 * make_request doesn't initialize xid because it normally comes
1215 * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
1216 * so pick an xid now.
1218 client
-> xid
= random ();
1221 * Make a DHCPREQUEST packet, and set
1222 * appropriate per-interface flags.
1224 make_request (client
, client
-> active
);
1225 client
-> destination
= iaddr_broadcast
;
1226 client
-> first_sending
= cur_time
;
1227 client
-> interval
= client
-> config
-> initial_interval
;
1229 /* Zap the medium list... */
1230 client
-> medium
= NULL
;
1232 /* Send out the first DHCPREQUEST packet. */
1233 send_request (client
);
1236 /* Called when a lease has completely expired and we've been unable to
1239 void state_init (cpp
)
1242 struct client_state
*client
= cpp
;
1244 ASSERT_STATE(state
, S_INIT
);
1246 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
1248 make_discover (client
, client
-> active
);
1249 client
-> xid
= client
-> packet
.xid
;
1250 client
-> destination
= iaddr_broadcast
;
1251 client
-> state
= S_SELECTING
;
1252 client
-> first_sending
= cur_time
;
1253 client
-> interval
= client
-> config
-> initial_interval
;
1255 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
1257 send_discover (client
);
1260 /* check_v6only is called by dhcpoffer and dhcpack. It checks if a
1261 * requested v6-only-preferred option is present and returned the
1262 * V6ONLY_WAIT delay to suspend DHCPv4. */
1264 uint32_t check_v6only(packet
, client
)
1265 struct packet
*packet
;
1266 struct client_state
*client
;
1269 struct option
**req
;
1270 isc_boolean_t found
= ISC_FALSE
;
1271 struct option_cache
*oc
;
1272 struct data_string data
;
1273 uint32_t v6only_wait
= 0;
1275 /* Check if the v6-only-preferred was requested. */
1276 req
= client
->config
->requested_options
;
1281 for (i
= 0 ; req
[i
] != NULL
; i
++) {
1282 if ((req
[i
]->universe
== &dhcp_universe
) &&
1283 (req
[i
]->code
== DHO_V6_ONLY_PREFERRED
)) {
1289 if (found
== ISC_FALSE
)
1292 /* Get the V6ONLY_WAIT timer. */
1293 oc
= lookup_option(&dhcp_universe
, packet
->options
,
1294 DHO_V6_ONLY_PREFERRED
);
1298 memset(&data
, 0, sizeof(data
));
1300 if (evaluate_option_cache(&data
, packet
, (struct lease
*)0, client
,
1301 packet
->options
, (struct option_state
*)0,
1302 &global_scope
, oc
, MDL
)) {
1303 if (data
.len
== 4) {
1304 v6only_wait
= getULong(data
.data
);
1305 if (v6only_wait
< MIN_V6ONLY_WAIT
)
1306 v6only_wait
= MIN_V6ONLY_WAIT
;
1308 data_string_forget(&data
, MDL
);
1311 return (v6only_wait
);
1314 /* finish_v6only is called when the V6ONLY_WAIT timer expired. */
1316 void finish_v6only(cpp
)
1319 struct client_state
*client
= cpp
;
1321 cancel_timeout(finish_v6only
, client
);
1322 client
->state
= S_INIT
;
1327 * start_v6only is called when a requested v6-only-preferred option was
1328 * returned by the server. */
1330 void start_v6only(client
, v6only_wait
)
1331 struct client_state
*client
;
1332 uint32_t v6only_wait
;
1336 /* Enter V6ONLY state. */
1338 client
->state
= S_V6ONLY
;
1340 /* Run the client script. */
1341 script_init(client
, "V6ONLY", NULL
);
1342 if (client
->active
) {
1343 script_write_params(client
, "old_", client
->active
);
1344 destroy_client_lease(client
->active
);
1345 client
->active
= NULL
;
1347 script_write_requested(client
);
1348 client_envadd(client
, "", "v6-only-preferred", "%lu",
1349 (long unsigned)v6only_wait
);
1352 /* Trigger finish_v6only after V6ONLY_WAIT seconds. */
1353 tv
.tv_sec
= cur_tv
.tv_sec
+ v6only_wait
;
1354 tv
.tv_usec
= cur_tv
.tv_usec
;
1356 add_timeout(&tv
, finish_v6only
, client
, 0, 0);
1360 * state_selecting is called when one or more DHCPOFFER packets have been
1361 * received and a configurable period of time has passed.
1364 void state_selecting (cpp
)
1367 struct client_state
*client
= cpp
;
1368 struct client_lease
*lp
, *next
, *picked
;
1371 ASSERT_STATE(state
, S_SELECTING
);
1374 * Cancel state_selecting and send_discover timeouts, since either
1375 * one could have got us here.
1377 cancel_timeout (state_selecting
, client
);
1378 cancel_timeout (send_discover
, client
);
1381 * We have received one or more DHCPOFFER packets. Currently,
1382 * the only criterion by which we judge leases is whether or
1383 * not we get a response when we arp for them.
1386 for (lp
= client
-> offered_leases
; lp
; lp
= next
) {
1390 * Check to see if we got an ARPREPLY for the address
1391 * in this particular lease.
1395 picked
-> next
= NULL
;
1397 destroy_client_lease (lp
);
1400 client
-> offered_leases
= NULL
;
1403 * If we just tossed all the leases we were offered, go back
1407 client
-> state
= S_INIT
;
1408 state_init (client
);
1412 /* If it was a BOOTREPLY, we can just take the address right now. */
1413 if (picked
-> is_bootp
) {
1414 client
-> new = picked
;
1416 /* Make up some lease expiry times
1417 XXX these should be configurable. */
1418 client
-> new -> expiry
= cur_time
+ 12000;
1419 client
-> new -> renewal
+= cur_time
+ 8000;
1420 client
-> new -> rebind
+= cur_time
+ 10000;
1422 client
-> state
= S_REQUESTING
;
1424 /* Bind to the address we received. */
1425 bind_lease (client
);
1429 /* Go to the REQUESTING state. */
1430 client
-> destination
= iaddr_broadcast
;
1431 client
-> state
= S_REQUESTING
;
1432 client
-> first_sending
= cur_time
;
1433 client
-> interval
= client
-> config
-> initial_interval
;
1435 /* Make a DHCPREQUEST packet from the lease we picked. */
1436 make_request (client
, picked
);
1437 client
-> xid
= client
-> packet
.xid
;
1439 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
1440 destroy_client_lease (picked
);
1442 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
1443 send_request (client
);
1446 /* state_requesting is called when we receive a DHCPACK message after
1447 having sent out one or more DHCPREQUEST packets. */
1449 void dhcpack (packet
)
1450 struct packet
*packet
;
1452 struct interface_info
*ip
= packet
-> interface
;
1453 struct client_state
*client
;
1454 uint32_t v6only_wait
;
1455 struct client_lease
*lease
;
1456 struct option_cache
*oc
;
1457 struct data_string ds
;
1459 /* If we're not receptive to an offer right now, or if the offer
1460 has an unrecognizable transaction id, then just drop it. */
1461 for (client
= ip
-> client
; client
; client
= client
-> next
) {
1462 if (client
-> xid
== packet
-> raw
-> xid
)
1466 (packet
-> interface
-> hw_address
.hlen
- 1 !=
1467 packet
-> raw
-> hlen
) ||
1468 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
1469 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
1471 log_debug ("DHCPACK in wrong transaction.");
1476 if (client
-> state
!= S_REBOOTING
&&
1477 client
-> state
!= S_REQUESTING
&&
1478 client
-> state
!= S_RENEWING
&&
1479 client
-> state
!= S_REBINDING
) {
1481 log_debug ("DHCPACK in wrong state.");
1486 log_info ("DHCPACK of %s from %s",
1487 inet_ntoa(packet
->raw
->yiaddr
),
1488 piaddr (packet
->client_addr
));
1490 /* Check v6only first. */
1491 v6only_wait
= check_v6only(packet
, client
);
1492 if (v6only_wait
> 0) {
1493 log_info("v6 only preferred for %lu seconds.",
1494 (long unsigned)v6only_wait
);
1495 cancel_timeout(send_request
, client
);
1496 start_v6only(client
, v6only_wait
);
1500 lease
= packet_to_lease (packet
, client
);
1502 log_info ("packet_to_lease failed.");
1506 client
-> new = lease
;
1508 /* Stop resending DHCPREQUEST. */
1509 cancel_timeout (send_request
, client
);
1511 /* Figure out the lease time. */
1512 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1513 DHO_DHCP_LEASE_TIME
);
1514 memset (&ds
, 0, sizeof ds
);
1516 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1517 packet
-> options
, client
-> new -> options
,
1518 &global_scope
, oc
, MDL
)) {
1520 client
-> new -> expiry
= getULong (ds
.data
);
1522 client
-> new -> expiry
= 0;
1523 data_string_forget (&ds
, MDL
);
1525 client
-> new -> expiry
= 0;
1527 if (client
->new->expiry
== 0) {
1530 log_error ("no expiry time on offered lease.");
1532 /* Quench this (broken) server. Return to INIT to reselect. */
1535 /* 1/2 second delay to restart at INIT. */
1536 tv
.tv_sec
= cur_tv
.tv_sec
;
1537 tv
.tv_usec
= cur_tv
.tv_usec
+ 500000;
1539 if (tv
.tv_usec
>= 1000000) {
1541 tv
.tv_usec
-= 1000000;
1544 add_timeout(&tv
, state_init
, client
, 0, 0);
1549 * A number that looks negative here is really just very large,
1550 * because the lease expiry offset is unsigned.
1552 if (client
->new->expiry
< 0)
1553 client
->new->expiry
= TIME_MAX
;
1555 /* Take the server-provided renewal time if there is one. */
1556 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1557 DHO_DHCP_RENEWAL_TIME
);
1559 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1560 packet
-> options
, client
-> new -> options
,
1561 &global_scope
, oc
, MDL
)) {
1563 client
-> new -> renewal
= getULong (ds
.data
);
1565 client
-> new -> renewal
= 0;
1566 data_string_forget (&ds
, MDL
);
1568 client
-> new -> renewal
= 0;
1570 /* If it wasn't specified by the server, calculate it. */
1571 if (!client
-> new -> renewal
)
1572 client
-> new -> renewal
= client
-> new -> expiry
/ 2 + 1;
1574 if (client
-> new -> renewal
<= 0)
1575 client
-> new -> renewal
= TIME_MAX
;
1577 /* Now introduce some randomness to the renewal time: */
1578 if (client
->new->renewal
<= ((TIME_MAX
/ 3) - 3))
1579 client
->new->renewal
= (((client
->new->renewal
* 3) + 3) / 4) +
1580 (((random() % client
->new->renewal
) + 3) / 4);
1582 /* Same deal with the rebind time. */
1583 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1584 DHO_DHCP_REBINDING_TIME
);
1586 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1587 packet
-> options
, client
-> new -> options
,
1588 &global_scope
, oc
, MDL
)) {
1590 client
-> new -> rebind
= getULong (ds
.data
);
1592 client
-> new -> rebind
= 0;
1593 data_string_forget (&ds
, MDL
);
1595 client
-> new -> rebind
= 0;
1597 if (client
-> new -> rebind
<= 0) {
1598 if (client
-> new -> expiry
<= TIME_MAX
/ 7)
1599 client
-> new -> rebind
=
1600 client
-> new -> expiry
* 7 / 8;
1602 client
-> new -> rebind
=
1603 client
-> new -> expiry
/ 8 * 7;
1606 /* Make sure our randomness didn't run the renewal time past the
1608 if (client
-> new -> renewal
> client
-> new -> rebind
) {
1609 if (client
-> new -> rebind
<= TIME_MAX
/ 3)
1610 client
-> new -> renewal
=
1611 client
-> new -> rebind
* 3 / 4;
1613 client
-> new -> renewal
=
1614 client
-> new -> rebind
/ 4 * 3;
1617 client
-> new -> expiry
+= cur_time
;
1618 /* Lease lengths can never be negative. */
1619 if (client
-> new -> expiry
< cur_time
)
1620 client
-> new -> expiry
= TIME_MAX
;
1621 client
-> new -> renewal
+= cur_time
;
1622 if (client
-> new -> renewal
< cur_time
)
1623 client
-> new -> renewal
= TIME_MAX
;
1624 client
-> new -> rebind
+= cur_time
;
1625 if (client
-> new -> rebind
< cur_time
)
1626 client
-> new -> rebind
= TIME_MAX
;
1628 bind_lease (client
);
1631 void bind_lease (client
)
1632 struct client_state
*client
;
1636 /* Remember the medium. */
1637 client
->new->medium
= client
->medium
;
1639 /* Run the client script with the new parameters. */
1640 script_init(client
, (client
->state
== S_REQUESTING
? "BOUND" :
1641 (client
->state
== S_RENEWING
? "RENEW" :
1642 (client
->state
== S_REBOOTING
? "REBOOT" :
1644 client
->new->medium
);
1645 if (client
->active
&& client
->state
!= S_REBOOTING
)
1646 script_write_params(client
, "old_", client
->active
);
1647 script_write_params(client
, "new_", client
->new);
1648 script_write_requested(client
);
1650 script_write_params(client
, "alias_", client
->alias
);
1652 /* If the BOUND/RENEW code detects another machine using the
1653 offered address, then per our man page it should exit with
1654 a non-zero status, to which we send a DHCPDECLINE and toss
1655 the lease. A return value of less than zero indicates
1656 the script crashed (e.g. segfault) which script_go will log
1657 but we will ignore here. */
1658 if (script_go(client
) > 0) {
1659 make_decline(client
, client
->new);
1660 send_decline(client
);
1661 destroy_client_lease(client
->new);
1665 log_info("Unable to obtain a lease on first "
1666 "try (declined). Exiting.");
1669 #if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
1670 /* Let's call a script and we're done */
1671 script_init(client
, "FAIL", (struct string_list
*)0);
1677 tv
.tv_sec
= cur_tv
.tv_sec
+ decline_wait_time
;
1678 tv
.tv_usec
= cur_tv
.tv_usec
;
1679 add_timeout(&tv
, state_init
, client
, 0, 0);
1684 /* Write out the new lease if it has been long enough. */
1685 if (!client
->last_write
||
1686 (cur_time
- client
->last_write
) >= MIN_LEASE_WRITE
)
1687 write_client_lease(client
, client
->new, 0, 1);
1689 /* Replace the old active lease with the new one. */
1690 if (client
->active
) {
1691 if (client
->active
->is_static
) {
1692 // We need to preserve the fallback lease in case
1693 // we lose DHCP service again.
1694 add_to_tail(&client
->leases
, client
->active
);
1696 destroy_client_lease(client
->active
);
1700 client
->active
= client
->new;
1703 /* Set up a timeout to start the renewal process. */
1704 tv
.tv_sec
= client
->active
->renewal
;
1705 tv
.tv_usec
= ((client
->active
->renewal
- cur_tv
.tv_sec
) > 1) ?
1706 random() % 1000000 : cur_tv
.tv_usec
;
1707 add_timeout(&tv
, state_bound
, client
, 0, 0);
1709 log_info("bound to %s -- renewal in %ld seconds.",
1710 piaddr(client
->active
->address
),
1711 (long)(client
->active
->renewal
- cur_time
));
1712 client
->state
= S_BOUND
;
1713 reinitialize_interfaces();
1715 #if defined (NSUPDATE)
1716 if (client
->config
->do_forward_update
)
1717 dhclient_schedule_updates(client
, &client
->active
->address
, 1);
1718 #endif /* defined NSUPDATE */
1722 /* state_bound is called when we've successfully bound to a particular
1723 lease, but the renewal time on that lease has expired. We are
1724 expected to unicast a DHCPREQUEST to the server that gave us our
1727 void state_bound (cpp
)
1730 struct client_state
*client
= cpp
;
1731 struct option_cache
*oc
;
1732 struct data_string ds
;
1734 ASSERT_STATE(state
, S_BOUND
);
1736 /* T1 has expired. */
1737 make_request (client
, client
-> active
);
1738 client
-> xid
= client
-> packet
.xid
;
1740 memset (&ds
, 0, sizeof ds
);
1741 oc
= lookup_option (&dhcp_universe
, client
-> active
-> options
,
1742 DHO_DHCP_SERVER_IDENTIFIER
);
1744 evaluate_option_cache (&ds
, (struct packet
*)0, (struct lease
*)0,
1745 client
, (struct option_state
*)0,
1746 client
-> active
-> options
,
1747 &global_scope
, oc
, MDL
)) {
1749 memcpy (client
-> destination
.iabuf
, ds
.data
, 4);
1750 client
-> destination
.len
= 4;
1752 client
-> destination
= iaddr_broadcast
;
1754 data_string_forget (&ds
, MDL
);
1756 client
-> destination
= iaddr_broadcast
;
1758 client
-> first_sending
= cur_time
;
1759 client
-> interval
= client
-> config
-> initial_interval
;
1760 client
-> state
= S_RENEWING
;
1762 /* Send the first packet immediately. */
1763 send_request (client
);
1766 /* state_stop is called when we've been told to shut down. We unconfigure
1767 the interfaces, and then stop operating until told otherwise. */
1769 void state_stop (cpp
)
1772 struct client_state
*client
= cpp
;
1774 client
->pending
= P_NONE
;
1776 /* Cancel all timeouts. */
1777 cancel_timeout(state_selecting
, client
);
1778 cancel_timeout(send_discover
, client
);
1779 cancel_timeout(send_request
, client
);
1780 cancel_timeout(state_bound
, client
);
1781 cancel_timeout(finish_v6only
, client
);
1783 /* If we have an address, unconfigure it. */
1784 if (client
->active
) {
1785 script_init(client
, "STOP", client
->active
->medium
);
1786 script_write_params(client
, "old_", client
->active
);
1787 script_write_requested(client
);
1789 script_write_params(client
, "alias_", client
->alias
);
1794 int commit_leases ()
1799 int write_lease (lease
)
1800 struct lease
*lease
;
1805 int write_host (host
)
1806 struct host_decl
*host
;
1811 void db_startup (testp
)
1817 struct packet
*packet
;
1819 struct iaddrmatchlist
*ap
;
1823 if (packet
-> raw
-> op
!= BOOTREPLY
)
1826 /* If there's a reject list, make sure this packet's sender isn't
1828 for (ap
= packet
-> interface
-> client
-> config
-> reject_list
;
1829 ap
; ap
= ap
-> next
) {
1830 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1832 /* piaddr() returns its result in a static
1833 buffer sized 4*16 (see common/inet.c). */
1835 strcpy(addrbuf
, piaddr(ap
->match
.addr
));
1836 strcpy(maskbuf
, piaddr(ap
->match
.mask
));
1838 log_info("BOOTREPLY from %s rejected by rule %s "
1839 "mask %s.", piaddr(packet
->client_addr
),
1850 struct packet
*packet
;
1852 struct iaddrmatchlist
*ap
;
1853 void (*handler
) (struct packet
*);
1858 switch (packet
-> packet_type
) {
1860 handler
= dhcpoffer
;
1878 /* If there's a reject list, make sure this packet's sender isn't
1880 for (ap
= packet
-> interface
-> client
-> config
-> reject_list
;
1881 ap
; ap
= ap
-> next
) {
1882 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1884 /* piaddr() returns its result in a static
1885 buffer sized 4*16 (see common/inet.c). */
1887 strcpy(addrbuf
, piaddr(ap
->match
.addr
));
1888 strcpy(maskbuf
, piaddr(ap
->match
.mask
));
1890 log_info("%s from %s rejected by rule %s mask %s.",
1891 type
, piaddr(packet
->client_addr
),
1896 (*handler
) (packet
);
1901 dhcpv6(struct packet
*packet
) {
1902 struct iaddrmatchlist
*ap
;
1903 struct client_state
*client
;
1904 char addrbuf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
1906 /* Silently drop bogus messages. */
1907 if (packet
->dhcpv6_msg_type
>= dhcpv6_type_name_max
)
1910 /* Discard, with log, packets from quenched sources. */
1911 for (ap
= packet
->interface
->client
->config
->reject_list
;
1912 ap
; ap
= ap
->next
) {
1913 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1914 strcpy(addrbuf
, piaddr(packet
->client_addr
));
1915 log_info("%s from %s rejected by rule %s",
1916 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1918 piaddrmask(&ap
->match
.addr
, &ap
->match
.mask
));
1923 /* Screen out nonsensical messages. */
1924 switch(packet
->dhcpv6_msg_type
) {
1926 case DHCPV6_DHCPV4_RESPONSE
:
1927 if (dhcpv4_over_dhcpv6
) {
1928 log_info("RCV: %s message on %s from %s.",
1929 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1930 packet
->interface
->name
,
1931 piaddr(packet
->client_addr
));
1932 forw_dhcpv4_response(packet
);
1936 case DHCPV6_ADVERTISE
:
1937 case DHCPV6_RECONFIGURE
:
1942 log_info("RCV: %s message on %s from %s.",
1943 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1944 packet
->interface
->name
, piaddr(packet
->client_addr
));
1951 /* Find a client state that matches the incoming XID. */
1952 for (client
= packet
->interface
->client
; client
;
1953 client
= client
->next
) {
1954 if (memcmp(&client
->dhcpv6_transaction_id
,
1955 packet
->dhcpv6_transaction_id
, 3) == 0) {
1956 client
->v6_handler(packet
, client
);
1961 /* XXX: temporary log for debugging */
1962 log_info("Packet received, but nothing done with it.");
1967 * \brief Forward a DHCPv4-response to the DHCPv4 client.
1968 * (DHCPv6 client function)
1970 * The DHCPv6 client receives a DHCPv4-response which is forwarded
1971 * to the DHCPv4 client.
1972 * Format: address:16 + DHCPv4 message content
1973 * (we have no state to keep the address so it is transported in
1974 * DHCPv6 <-> DHCPv6 inter-process messages)
1976 * \param packet the DHCPv4-response packet
1978 static void forw_dhcpv4_response(struct packet
*packet
)
1980 struct option_cache
*oc
;
1981 struct data_string enc_opt_data
;
1982 struct data_string ds
;
1986 * Discard if relay is not ready.
1988 if (dhcp4o6_state
== -1) {
1989 log_info("forw_dhcpv4_response: not ready.");
1993 if (packet
->client_addr
.len
!= 16) {
1994 log_error("forw_dhcpv4_response: bad address");
1999 * Get our encapsulated DHCPv4 message.
2001 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_DHCPV4_MSG
);
2003 log_info("DHCPv4-response from %s missing "
2004 "DHCPv4 Message option.",
2005 piaddr(packet
->client_addr
));
2009 memset(&enc_opt_data
, 0, sizeof(enc_opt_data
));
2010 if (!evaluate_option_cache(&enc_opt_data
, NULL
, NULL
, NULL
,
2011 NULL
, NULL
, &global_scope
, oc
, MDL
)) {
2012 log_error("forw_dhcpv4_response: error evaluating "
2014 data_string_forget(&enc_opt_data
, MDL
);
2018 if (enc_opt_data
.len
< DHCP_FIXED_NON_UDP
) {
2019 log_error("forw_dhcpv4_response: "
2020 "no memory for encapsulated packet.");
2021 data_string_forget(&enc_opt_data
, MDL
);
2028 memset(&ds
, 0, sizeof(ds
));
2029 if (!buffer_allocate(&ds
.buffer
, enc_opt_data
.len
+ 16, MDL
)) {
2030 log_error("forw_dhcpv4_response: no memory buffer.");
2031 data_string_forget(&enc_opt_data
, MDL
);
2034 ds
.data
= ds
.buffer
->data
;
2035 ds
.len
= enc_opt_data
.len
+ 16;
2036 memcpy(ds
.buffer
->data
, enc_opt_data
.data
, enc_opt_data
.len
);
2037 memcpy(ds
.buffer
->data
+ enc_opt_data
.len
,
2038 packet
->client_addr
.iabuf
, 16);
2039 data_string_forget(&enc_opt_data
, MDL
);
2044 cc
= send(dhcp4o6_fd
, ds
.data
, ds
.len
, 0);
2046 log_error("forw_dhcpv4_response: send(): %m");
2048 data_string_forget(&ds
, MDL
);
2052 * \brief Receive a DHCPv4-response from the DHCPv6 client.
2053 * (DHCPv4 client function)
2055 * The DHCPv4 client receives a DHCPv4-response forwarded
2056 * by the DHCPv6 client (using \ref forw_dhcpv4_response())
2058 * \param raw the DHCPv4-response raw packet
2060 static void recv_dhcpv4_response(struct data_string
*raw
)
2062 struct packet
*packet
;
2065 if (interfaces
== NULL
) {
2066 log_error("recv_dhcpv4_response: no interfaces.");
2071 memcpy(from
.iabuf
, raw
->data
+ (raw
->len
- 16), 16);
2074 * Build a packet structure.
2077 if (!packet_allocate(&packet
, MDL
)) {
2078 log_error("recv_dhcpv4_response: no memory for packet.");
2082 packet
->raw
= (struct dhcp_packet
*) raw
->data
;
2083 packet
->packet_length
= raw
->len
- 16;
2084 packet
->client_port
= remote_port
;
2085 packet
->client_addr
= from
;
2086 interface_reference(&packet
->interface
, interfaces
, MDL
);
2088 /* Allocate packet->options now so it is non-null for all packets */
2089 if (!option_state_allocate (&packet
->options
, MDL
)) {
2090 log_error("recv_dhcpv4_response: no memory for options.");
2091 packet_dereference (&packet
, MDL
);
2095 /* If there's an option buffer, try to parse it. */
2096 if (packet
->packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
2097 struct option_cache
*op
;
2098 if (!parse_options(packet
)) {
2099 if (packet
->options
)
2100 option_state_dereference
2101 (&packet
->options
, MDL
);
2102 packet_dereference (&packet
, MDL
);
2106 if (packet
->options_valid
&&
2107 (op
= lookup_option(&dhcp_universe
,
2109 DHO_DHCP_MESSAGE_TYPE
))) {
2110 struct data_string dp
;
2111 memset(&dp
, 0, sizeof dp
);
2112 evaluate_option_cache(&dp
, packet
, NULL
, NULL
,
2113 packet
->options
, NULL
,
2116 packet
->packet_type
= dp
.data
[0];
2118 packet
->packet_type
= 0;
2119 data_string_forget(&dp
, MDL
);
2123 if (validate_packet(packet
) != 0) {
2124 if (packet
->packet_type
)
2130 /* If the caller kept the packet, they'll have upped the refcnt. */
2131 packet_dereference(&packet
, MDL
);
2133 #endif /* DHCP4o6 */
2136 void dhcpoffer (packet
)
2137 struct packet
*packet
;
2139 struct interface_info
*ip
= packet
-> interface
;
2140 struct client_state
*client
;
2141 uint32_t v6only_wait
;
2142 struct client_lease
*lease
, *lp
;
2143 struct option
**req
;
2146 const char *name
= packet
-> packet_type
? "DHCPOFFER" : "BOOTREPLY";
2151 dump_packet (packet
);
2154 /* Find a client state that matches the xid... */
2155 for (client
= ip
-> client
; client
; client
= client
-> next
)
2156 if (client
-> xid
== packet
-> raw
-> xid
)
2159 /* If we're not receptive to an offer right now, or if the offer
2160 has an unrecognizable transaction id, then just drop it. */
2162 client
-> state
!= S_SELECTING
||
2163 (packet
-> interface
-> hw_address
.hlen
- 1 !=
2164 packet
-> raw
-> hlen
) ||
2165 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
2166 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
2168 log_debug ("%s in wrong transaction.", name
);
2173 sprintf (obuf
, "%s of %s from %s", name
,
2174 inet_ntoa(packet
->raw
->yiaddr
),
2175 piaddr(packet
->client_addr
));
2177 /* Check v6only first. */
2178 v6only_wait
= check_v6only(packet
, client
);
2179 if (v6only_wait
> 0) {
2180 log_info("%s: v6 only preferred for %lu.", obuf
,
2181 (long unsigned)v6only_wait
);
2182 cancel_timeout(send_discover
, client
);
2183 start_v6only(client
, v6only_wait
);
2187 /* If this lease doesn't supply the minimum required DHCPv4 parameters,
2190 req
= client
->config
->required_options
;
2192 for (i
= 0 ; req
[i
] != NULL
; i
++) {
2193 if ((req
[i
]->universe
== &dhcp_universe
) &&
2194 !lookup_option(&dhcp_universe
, packet
->options
,
2196 struct option
*option
= NULL
;
2197 unsigned code
= req
[i
]->code
;
2199 option_code_hash_lookup(&option
,
2200 dhcp_universe
.code_hash
,
2204 log_info("%s: no %s option.", obuf
,
2207 log_info("%s: no unknown-%u option.",
2210 option_dereference(&option
, MDL
);
2217 /* If we've already seen this lease, don't record it again. */
2218 for (lease
= client
-> offered_leases
; lease
; lease
= lease
-> next
) {
2219 if (lease
-> address
.len
== sizeof packet
-> raw
-> yiaddr
&&
2220 !memcmp (lease
-> address
.iabuf
,
2221 &packet
-> raw
-> yiaddr
, lease
-> address
.len
)) {
2222 log_debug ("%s: already seen.", obuf
);
2227 lease
= packet_to_lease (packet
, client
);
2229 log_info ("%s: packet_to_lease failed.", obuf
);
2233 /* log it now, so it emits before the request goes out */
2234 log_info("%s", obuf
);
2236 /* If this lease was acquired through a BOOTREPLY, record that
2238 if (!packet
-> options_valid
|| !packet
-> packet_type
)
2239 lease
-> is_bootp
= 1;
2241 /* Record the medium under which this lease was offered. */
2242 lease
-> medium
= client
-> medium
;
2244 /* Figure out when we're supposed to stop selecting. */
2245 stop_selecting
= (client
-> first_sending
+
2246 client
-> config
-> select_interval
);
2248 /* If this is the lease we asked for, put it at the head of the
2249 list, and don't mess with the arp request timeout. */
2250 if (lease
-> address
.len
== client
-> requested_address
.len
&&
2251 !memcmp (lease
-> address
.iabuf
,
2252 client
-> requested_address
.iabuf
,
2253 client
-> requested_address
.len
)) {
2254 lease
-> next
= client
-> offered_leases
;
2255 client
-> offered_leases
= lease
;
2257 /* Put the lease at the end of the list. */
2258 lease
-> next
= (struct client_lease
*)0;
2259 if (!client
-> offered_leases
)
2260 client
-> offered_leases
= lease
;
2262 for (lp
= client
-> offered_leases
; lp
-> next
;
2269 /* If the selecting interval has expired, go immediately to
2270 state_selecting(). Otherwise, time out into
2271 state_selecting at the select interval. */
2272 if (stop_selecting
<= cur_tv
.tv_sec
)
2273 state_selecting (client
);
2275 tv
.tv_sec
= stop_selecting
;
2276 tv
.tv_usec
= cur_tv
.tv_usec
;
2277 add_timeout(&tv
, state_selecting
, client
, 0, 0);
2278 cancel_timeout(send_discover
, client
);
2282 /* Allocate a client_lease structure and initialize it from the parameters
2283 in the specified packet. */
2285 struct client_lease
*packet_to_lease (packet
, client
)
2286 struct packet
*packet
;
2287 struct client_state
*client
;
2289 struct client_lease
*lease
;
2291 struct option_cache
*oc
;
2292 struct option
*option
= NULL
;
2293 struct data_string data
;
2295 lease
= (struct client_lease
*)new_client_lease (MDL
);
2298 log_error("packet_to_lease: no memory to record lease.\n");
2302 memset(lease
, 0, sizeof(*lease
));
2304 /* Copy the lease options. */
2305 option_state_reference(&lease
->options
, packet
->options
, MDL
);
2307 lease
->address
.len
= sizeof(packet
->raw
->yiaddr
);
2308 memcpy(lease
->address
.iabuf
, &packet
->raw
->yiaddr
,
2309 lease
->address
.len
);
2311 lease
->next_srv_addr
.len
= sizeof(packet
->raw
->siaddr
);
2312 memcpy(lease
->next_srv_addr
.iabuf
, &packet
->raw
->siaddr
,
2313 lease
->next_srv_addr
.len
);
2315 memset(&data
, 0, sizeof(data
));
2317 if (client
-> config
-> vendor_space_name
) {
2318 i
= DHO_VENDOR_ENCAPSULATED_OPTIONS
;
2320 /* See if there was a vendor encapsulation option. */
2321 oc
= lookup_option (&dhcp_universe
, lease
-> options
, i
);
2323 client
-> config
-> vendor_space_name
&&
2324 evaluate_option_cache (&data
, packet
,
2325 (struct lease
*)0, client
,
2326 packet
-> options
, lease
-> options
,
2327 &global_scope
, oc
, MDL
)) {
2329 if (!option_code_hash_lookup(&option
,
2330 dhcp_universe
.code_hash
,
2332 log_fatal("Unable to find VENDOR "
2333 "option (%s:%d).", MDL
);
2334 parse_encapsulated_suboptions
2335 (packet
-> options
, option
,
2336 data
.data
, data
.len
, &dhcp_universe
,
2337 client
-> config
-> vendor_space_name
2340 option_dereference(&option
, MDL
);
2342 data_string_forget (&data
, MDL
);
2347 /* Figure out the overload flag. */
2348 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
2349 DHO_DHCP_OPTION_OVERLOAD
);
2351 evaluate_option_cache (&data
, packet
, (struct lease
*)0, client
,
2352 packet
-> options
, lease
-> options
,
2353 &global_scope
, oc
, MDL
)) {
2358 data_string_forget (&data
, MDL
);
2362 /* If the server name was filled out, copy it. */
2363 if (!(i
& 2) && packet
-> raw
-> sname
[0]) {
2365 /* Don't count on the NUL terminator. */
2366 for (len
= 0; len
< DHCP_SNAME_LEN
; len
++)
2367 if (!packet
-> raw
-> sname
[len
])
2369 lease
-> server_name
= dmalloc (len
+ 1, MDL
);
2370 if (!lease
-> server_name
) {
2371 log_error ("dhcpoffer: no memory for server name.\n");
2372 destroy_client_lease (lease
);
2373 return (struct client_lease
*)0;
2375 memcpy (lease
-> server_name
,
2376 packet
-> raw
-> sname
, len
);
2377 lease
-> server_name
[len
] = 0;
2381 /* Ditto for the filename. */
2382 if (!(i
& 1) && packet
-> raw
-> file
[0]) {
2384 /* Don't count on the NUL terminator. */
2385 for (len
= 0; len
< DHCP_FILE_LEN
; len
++)
2386 if (!packet
-> raw
-> file
[len
])
2388 lease
-> filename
= dmalloc (len
+ 1, MDL
);
2389 if (!lease
-> filename
) {
2390 log_error ("dhcpoffer: no memory for filename.\n");
2391 destroy_client_lease (lease
);
2392 return (struct client_lease
*)0;
2394 memcpy (lease
-> filename
,
2395 packet
-> raw
-> file
, len
);
2396 lease
-> filename
[len
] = 0;
2400 execute_statements_in_scope(NULL
, (struct packet
*)packet
, NULL
,
2401 client
, lease
->options
, lease
->options
,
2402 &global_scope
, client
->config
->on_receipt
,
2408 void dhcpnak (packet
)
2409 struct packet
*packet
;
2411 struct interface_info
*ip
= packet
-> interface
;
2412 struct client_state
*client
;
2414 /* Find a client state that matches the xid... */
2415 for (client
= ip
-> client
; client
; client
= client
-> next
)
2416 if (client
-> xid
== packet
-> raw
-> xid
)
2419 /* If we're not receptive to an offer right now, or if the offer
2420 has an unrecognizable transaction id, then just drop it. */
2422 (packet
-> interface
-> hw_address
.hlen
- 1 !=
2423 packet
-> raw
-> hlen
) ||
2424 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
2425 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
2427 log_debug ("DHCPNAK in wrong transaction.");
2432 if (client
-> state
!= S_REBOOTING
&&
2433 client
-> state
!= S_REQUESTING
&&
2434 client
-> state
!= S_RENEWING
&&
2435 client
-> state
!= S_REBINDING
) {
2437 log_debug ("DHCPNAK in wrong state.");
2442 log_info ("DHCPNAK from %s", piaddr (packet
-> client_addr
));
2444 if (!client
-> active
) {
2446 log_info ("DHCPNAK with no active lease.\n");
2451 /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
2452 * to indicate that we want all old bindings to be removed. (It
2453 * is possible that we may get a NAK while in the RENEW state,
2454 * so we might have bindings active at that time)
2456 script_init(client
, "EXPIRE", NULL
);
2457 script_write_params(client
, "old_", client
->active
);
2458 script_write_requested(client
);
2460 script_write_params(client
, "alias_", client
->alias
);
2463 destroy_client_lease (client
-> active
);
2464 client
-> active
= (struct client_lease
*)0;
2466 /* Stop sending DHCPREQUEST packets... */
2467 cancel_timeout (send_request
, client
);
2469 /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
2470 * down (this expunges any routes and arp cache). This makes the
2471 * interface unusable by state_init(), which we call next. So, we
2472 * need to 'PREINIT' the interface to bring it back up.
2474 script_init(client
, "PREINIT", NULL
);
2476 script_write_params(client
, "alias_", client
->alias
);
2479 client
-> state
= S_INIT
;
2480 state_init (client
);
2483 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
2484 one after the right interval has expired. If we don't get an offer by
2485 the time we reach the panic interval, call the panic function. */
2487 void send_discover (cpp
)
2490 struct client_state
*client
= cpp
;
2497 /* Figure out how long it's been since we started transmitting. */
2498 interval
= cur_time
- client
-> first_sending
;
2500 /* If we're past the panic timeout, call the script and tell it
2501 we haven't found anything for this interface yet. */
2502 if (interval
> client
-> config
-> timeout
) {
2503 state_panic (client
);
2507 /* If we're selecting media, try the whole list before doing
2508 the exponential backoff, but if we've already received an
2509 offer, stop looping, because we obviously have it right. */
2510 if (!client
-> offered_leases
&&
2511 client
-> config
-> media
) {
2514 if (client
-> medium
) {
2515 client
-> medium
= client
-> medium
-> next
;
2518 if (!client
-> medium
) {
2520 log_fatal ("No valid media types for %s!",
2521 client
-> interface
-> name
);
2523 client
-> config
-> media
;
2527 log_info ("Trying medium \"%s\" %d",
2528 client
-> medium
-> string
, increase
);
2529 script_init(client
, "MEDIUM", client
-> medium
);
2530 if (script_go(client
)) {
2536 /* If we're supposed to increase the interval, do so. If it's
2537 currently zero (i.e., we haven't sent any packets yet), set
2538 it to initial_interval; otherwise, add to it a random number
2539 between zero and two times itself. On average, this means
2540 that it will double with every transmission. */
2542 if (!client
->interval
)
2543 client
->interval
= client
->config
->initial_interval
;
2545 client
->interval
+= random() % (2 * client
->interval
);
2547 /* Don't backoff past cutoff. */
2548 if (client
->interval
> client
->config
->backoff_cutoff
)
2549 client
->interval
= (client
->config
->backoff_cutoff
/ 2)
2550 + (random() % client
->config
->backoff_cutoff
);
2551 } else if (!client
->interval
)
2552 client
->interval
= client
->config
->initial_interval
;
2554 /* If the backoff would take us to the panic timeout, just use that
2556 if (cur_time
+ client
-> interval
>
2557 client
-> first_sending
+ client
-> config
-> timeout
)
2558 client
-> interval
=
2559 (client
-> first_sending
+
2560 client
-> config
-> timeout
) - cur_time
+ 1;
2562 /* Record the number of seconds since we started sending. */
2563 if (interval
< 65536)
2564 client
-> packet
.secs
= htons (interval
);
2566 client
-> packet
.secs
= htons (65535);
2567 client
-> secs
= client
-> packet
.secs
;
2569 #if defined(DHCPv6) && defined(DHCP4o6)
2570 if (dhcpv4_over_dhcpv6
) {
2571 log_info ("DHCPDISCOVER interval %ld",
2572 (long)(client
-> interval
));
2575 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
2576 client
-> name
? client
-> name
: client
-> interface
-> name
,
2577 inet_ntoa (sockaddr_broadcast
.sin_addr
),
2578 ntohs (sockaddr_broadcast
.sin_port
), (long)(client
-> interval
));
2580 /* Send out a packet. */
2581 #if defined(DHCPv6) && defined(DHCP4o6)
2582 if (dhcpv4_over_dhcpv6
) {
2583 result
= send_dhcpv4_query(client
, 1);
2586 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
2587 client
->packet_length
, inaddr_any
,
2588 &sockaddr_broadcast
, NULL
);
2590 #if defined(DHCPv6) && defined(DHCP4o6)
2591 if (dhcpv4_over_dhcpv6
) {
2592 log_error("%s:%d: Failed to send %d byte long packet.",
2593 MDL
, client
->packet_length
);
2596 log_error("%s:%d: Failed to send %d byte long packet over %s "
2597 "interface.", MDL
, client
->packet_length
,
2598 client
->interface
->name
);
2602 * If we used 0 microseconds here, and there were other clients on the
2603 * same network with a synchronized local clock (ntp), and a similar
2604 * zero-microsecond-scheduler behavior, then we could be participating
2605 * in a sub-second DOS ttck.
2607 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->interval
;
2608 tv
.tv_usec
= client
->interval
> 1 ? random() % 1000000 : cur_tv
.tv_usec
;
2609 add_timeout(&tv
, send_discover
, client
, 0, 0);
2614 * \brief Remove leases from a list of leases which duplicate a given lease
2616 * Searches through a linked-list of leases, remove the first one matches the
2617 * given lease's address and value of is_static. The latter test is done
2618 * so we only remove leases that are from the same source (i.e server/lease file
2619 * vs config file). This ensures we do not discard "fallback" config file leases
2620 * that happen to match non-config file leases.
2622 * \param lease_list list of leases to clean
2623 * \param lease lease for which duplicates should be removed
2625 void discard_duplicate (struct client_lease
** lease_list
, struct client_lease
* lease
) {
2626 struct client_lease
*cur
, *prev
, *next
;
2628 if (!lease_list
|| !lease
) {
2632 prev
= (struct client_lease
*)0;
2633 for (cur
= *lease_list
; cur
; cur
= next
) {
2635 if ((cur
->is_static
== lease
->is_static
) &&
2636 (cur
->address
.len
== lease
->address
.len
&&
2637 !memcmp (cur
->address
.iabuf
, lease
->address
.iabuf
,
2638 lease
->address
.len
))) {
2644 destroy_client_lease (cur
);
2653 * \brief Add a given lease to the end of list of leases
2655 * Searches through a linked-list of leases, removing any that match the
2656 * given lease's address and value of is_static. The latter test is done
2657 * so we only remove leases that are from the same source (i.e server/lease file
2658 * vs config file). This ensures we do not discard "fallback" config file leases
2659 * that happen to match non-config file leases.
2661 * \param lease_list list of leases to clean
2662 * \param lease lease for which duplicates should be removed
2664 void add_to_tail(struct client_lease
** lease_list
,
2665 struct client_lease
* lease
)
2667 if (!lease_list
|| !lease
) {
2671 /* If there is already a lease for this address and
2672 * is_static value, toss discard it. This ensures
2673 * we only keep one dynamic and/or one static lease
2674 * for a given address. */
2675 discard_duplicate(lease_list
, lease
);
2678 struct client_lease
* tail
;
2679 for (tail
= *lease_list
; tail
&& tail
->next
; tail
= tail
->next
){};
2681 /* Ensure the tail points nowhere. */
2684 /* Add to the tail. */
2686 *lease_list
= lease
;
2693 void dbg_print_lease(char *text
, struct client_lease
* lease
) {
2695 log_debug("%s, lease is null", text
);
2697 log_debug ("%s: %p addr:%s expires:%ld :is_static? %d",
2698 text
, lease
, piaddr (lease
->address
),
2699 (lease
->expiry
- cur_time
),
2705 /* state_panic gets called if we haven't received any offers in a preset
2706 amount of time. When this happens, we try to use existing leases that
2707 haven't yet expired, and failing that, we call the client script and
2708 hope it can do something. */
2710 void state_panic (cpp
)
2713 struct client_state
*client
= cpp
;
2714 struct client_lease
*loop
;
2715 struct client_lease
*lp
;
2718 loop
= lp
= client
-> active
;
2720 log_info ("No DHCPOFFERS received.");
2722 /* We may not have an active lease, but we may have some
2723 predefined leases that we can try. */
2724 if (!client
-> active
&& client
-> leases
)
2727 /* Run through the list of leases and see if one can be used. */
2728 while (client
-> active
) {
2729 if (client
-> active
-> expiry
> cur_time
) {
2730 log_info ("Trying %s lease %s",
2731 (client
-> active
-> is_static
2732 ? "fallback" : "recorded"),
2733 piaddr (client
-> active
-> address
));
2734 /* Run the client script with the existing
2736 script_init(client
, "TIMEOUT",
2737 client
-> active
-> medium
);
2738 script_write_params(client
, "new_", client
-> active
);
2739 script_write_requested(client
);
2740 if (client
-> alias
)
2741 script_write_params(client
, "alias_",
2744 /* If the old lease is still good and doesn't
2745 yet need renewal, go into BOUND state and
2746 timeout at the renewal time. */
2747 if (!script_go(client
)) {
2748 if (cur_time
< client
-> active
-> renewal
) {
2749 client
-> state
= S_BOUND
;
2750 log_info ("bound: renewal in %ld %s.",
2751 (long)(client
-> active
-> renewal
-
2752 cur_time
), "seconds");
2753 tv
.tv_sec
= client
->active
->renewal
;
2754 tv
.tv_usec
= ((client
->active
->renewal
-
2756 random() % 1000000 :
2758 add_timeout(&tv
, state_bound
, client
, 0, 0);
2760 client
-> state
= S_BOUND
;
2761 log_info ("bound: immediate renewal.");
2762 state_bound (client
);
2764 reinitialize_interfaces ();
2770 /* If there are no other leases, give up. */
2771 if (!client
-> leases
) {
2772 client
-> leases
= client
-> active
;
2773 client
-> active
= (struct client_lease
*)0;
2778 /* Otherwise, put the active lease at the end of the
2779 lease list, and try another lease.. */
2780 add_to_tail(&client
->leases
, client
->active
);
2782 client
-> active
= client
-> leases
;
2783 client
-> leases
= client
-> leases
-> next
;
2785 /* If we already tried this lease, we've exhausted the
2786 set of leases, so we might as well give up for
2788 if (client
-> active
== loop
)
2791 loop
= client
-> active
;
2794 /* No leases were available, or what was available didn't work, so
2795 tell the shell script that we failed to allocate an address,
2796 and try again later. */
2799 log_info ("Unable to obtain a lease on first try.%s",
2803 #if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
2804 /* Let's call a script and we're done */
2805 script_init(client
, "FAIL", (struct string_list
*)0);
2811 log_info ("No working leases in persistent database - sleeping.");
2812 script_init(client
, "FAIL", (struct string_list
*)0);
2813 if (client
-> alias
)
2814 script_write_params(client
, "alias_", client
-> alias
);
2816 client
-> state
= S_INIT
;
2817 tv
.tv_sec
= cur_tv
.tv_sec
+ ((client
->config
->retry_interval
+ 1) / 2 +
2818 (random() % client
->config
->retry_interval
));
2819 tv
.tv_usec
= ((tv
.tv_sec
- cur_tv
.tv_sec
) > 1) ?
2820 random() % 1000000 : cur_tv
.tv_usec
;
2821 add_timeout(&tv
, state_init
, client
, 0, 0);
2825 void send_request (cpp
)
2828 struct client_state
*client
= cpp
;
2832 struct sockaddr_in destination
;
2833 struct in_addr from
;
2836 const char* rip_str
= "";
2838 /* Figure out how long it's been since we started transmitting. */
2839 interval
= cur_time
- client
-> first_sending
;
2841 /* If we're in the INIT-REBOOT or REQUESTING state and we're
2842 past the reboot timeout, go to INIT and see if we can
2843 DISCOVER an address... */
2844 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
2845 means either that we're on a network with no DHCP server,
2846 or that our server is down. In the latter case, assuming
2847 that there is a backup DHCP server, DHCPDISCOVER will get
2848 us a new address, but we could also have successfully
2849 reused our old address. In the former case, we're hosed
2850 anyway. This is not a win-prone situation. */
2851 if ((client
-> state
== S_REBOOTING
||
2852 client
-> state
== S_REQUESTING
) &&
2853 interval
> client
-> config
-> reboot_timeout
) {
2855 client
-> state
= S_INIT
;
2856 cancel_timeout (send_request
, client
);
2857 state_init (client
);
2861 /* If we're in the reboot state, make sure the media is set up
2863 if (client
-> state
== S_REBOOTING
&&
2864 !client
-> medium
&&
2865 client
-> active
-> medium
) {
2866 script_init(client
, "MEDIUM", client
-> active
-> medium
);
2868 /* If the medium we chose won't fly, go to INIT state. */
2869 if (script_go(client
))
2872 /* Record the medium. */
2873 client
-> medium
= client
-> active
-> medium
;
2876 /* If the lease has expired, relinquish the address and go back
2877 to the INIT state. */
2878 if (client
-> state
!= S_REQUESTING
&&
2879 cur_time
> client
-> active
-> expiry
) {
2880 /* Run the client script with the new parameters. */
2881 script_init(client
, "EXPIRE", (struct string_list
*)0);
2882 script_write_params(client
, "old_", client
-> active
);
2883 script_write_requested(client
);
2884 if (client
-> alias
)
2885 script_write_params(client
, "alias_",
2889 /* Now do a preinit on the interface so that we can
2890 discover a new address. */
2891 script_init(client
, "PREINIT", (struct string_list
*)0);
2892 if (client
-> alias
)
2893 script_write_params(client
, "alias_",
2897 client
-> state
= S_INIT
;
2898 state_init (client
);
2902 /* Do the exponential backoff... */
2903 if (!client
-> interval
)
2904 client
-> interval
= client
-> config
-> initial_interval
;
2906 client
-> interval
+= ((random () >> 2) %
2907 (2 * client
-> interval
));
2910 /* Don't backoff past cutoff. */
2911 if (client
-> interval
>
2912 client
-> config
-> backoff_cutoff
)
2913 client
-> interval
=
2914 ((client
-> config
-> backoff_cutoff
/ 2)
2915 + ((random () >> 2) %
2916 client
-> config
-> backoff_cutoff
));
2918 /* If the backoff would take us to the expiry time, just set the
2919 timeout to the expiry time. */
2920 if (client
-> state
!= S_REQUESTING
&&
2921 cur_time
+ client
-> interval
> client
-> active
-> expiry
)
2922 client
-> interval
=
2923 client
-> active
-> expiry
- cur_time
+ 1;
2925 /* If the lease T2 time has elapsed, or if we're not yet bound,
2926 broadcast the DHCPREQUEST rather than unicasting. */
2927 if (client
-> state
== S_REQUESTING
||
2928 client
-> state
== S_REBOOTING
||
2929 cur_time
> client
-> active
-> rebind
)
2930 destination
.sin_addr
= sockaddr_broadcast
.sin_addr
;
2932 memcpy (&destination
.sin_addr
.s_addr
,
2933 client
-> destination
.iabuf
,
2934 sizeof destination
.sin_addr
.s_addr
);
2935 destination
.sin_port
= remote_port
;
2936 destination
.sin_family
= AF_INET
;
2938 destination
.sin_len
= sizeof destination
;
2941 if (client
-> state
== S_RENEWING
||
2942 client
-> state
== S_REBINDING
)
2943 memcpy (&from
, client
-> active
-> address
.iabuf
,
2946 from
.s_addr
= INADDR_ANY
;
2948 /* Record the number of seconds since we started sending. */
2949 if (client
-> state
== S_REQUESTING
)
2950 client
-> packet
.secs
= client
-> secs
;
2952 if (interval
< 65536)
2953 client
-> packet
.secs
= htons (interval
);
2955 client
-> packet
.secs
= htons (65535);
2958 #if defined(DHCPv6) && defined(DHCP4o6)
2959 if (dhcpv4_over_dhcpv6
) {
2960 log_info ("DHCPREQUEST");
2963 memset(rip_buf
, 0x0, sizeof(rip_buf
));
2964 if (client
->state
== S_BOUND
|| client
->state
== S_RENEWING
||
2965 client
->state
== S_REBINDING
) {
2966 rip_str
= inet_ntoa(client
->packet
.ciaddr
);
2968 rip_str
= piaddr(client
->requested_address
);
2971 strncpy(rip_buf
, rip_str
, sizeof(rip_buf
)-1);
2972 log_info ("DHCPREQUEST for %s on %s to %s port %d", rip_buf
,
2973 client
->name
? client
->name
: client
->interface
->name
,
2974 inet_ntoa(destination
.sin_addr
),
2975 ntohs (destination
.sin_port
));
2977 #if defined(DHCPv6) && defined(DHCP4o6)
2978 if (dhcpv4_over_dhcpv6
) {
2980 if (destination
.sin_addr
.s_addr
== INADDR_BROADCAST
)
2982 result
= send_dhcpv4_query(client
, broadcast
);
2984 log_error("%s:%d: Failed to send %d byte long packet.",
2985 MDL
, client
->packet_length
);
2989 if (destination
.sin_addr
.s_addr
!= INADDR_BROADCAST
&&
2990 fallback_interface
) {
2991 result
= send_packet(fallback_interface
, NULL
, &client
->packet
,
2992 client
->packet_length
, from
, &destination
,
2995 log_error("%s:%d: Failed to send %d byte long packet "
2996 "over %s interface.", MDL
,
2997 client
->packet_length
,
2998 fallback_interface
->name
);
3002 /* Send out a packet. */
3003 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
3004 client
->packet_length
, from
, &destination
,
3007 log_error("%s:%d: Failed to send %d byte long packet"
3008 " over %s interface.", MDL
,
3009 client
->packet_length
,
3010 client
->interface
->name
);
3014 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->interval
;
3015 tv
.tv_usec
= ((tv
.tv_sec
- cur_tv
.tv_sec
) > 1) ?
3016 random() % 1000000 : cur_tv
.tv_usec
;
3017 add_timeout(&tv
, send_request
, client
, 0, 0);
3020 void send_decline (cpp
)
3023 struct client_state
*client
= cpp
;
3027 #if defined(DHCPv6) && defined(DHCP4o6)
3028 if (dhcpv4_over_dhcpv6
) {
3029 log_info ("DHCPDECLINE");
3032 log_info ("DHCPDECLINE of %s on %s to %s port %d",
3033 piaddr(client
->requested_address
),
3034 (client
->name
? client
->name
: client
->interface
->name
),
3035 inet_ntoa(sockaddr_broadcast
.sin_addr
),
3036 ntohs(sockaddr_broadcast
.sin_port
));
3038 /* Send out a packet. */
3039 #if defined(DHCPv6) && defined(DHCP4o6)
3040 if (dhcpv4_over_dhcpv6
) {
3041 result
= send_dhcpv4_query(client
, 1);
3044 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
3045 client
->packet_length
, inaddr_any
,
3046 &sockaddr_broadcast
, NULL
);
3048 #if defined(DHCPv6) && defined(DHCP4o6)
3049 if (dhcpv4_over_dhcpv6
) {
3050 log_error("%s:%d: Failed to send %d byte long packet.",
3051 MDL
, client
->packet_length
);
3054 log_error("%s:%d: Failed to send %d byte long packet over %s"
3055 " interface.", MDL
, client
->packet_length
,
3056 client
->interface
->name
);
3060 void send_release (cpp
)
3063 struct client_state
*client
= cpp
;
3066 struct sockaddr_in destination
;
3067 struct in_addr from
;
3069 memcpy (&from
, client
-> active
-> address
.iabuf
,
3071 memcpy (&destination
.sin_addr
.s_addr
,
3072 client
-> destination
.iabuf
,
3073 sizeof destination
.sin_addr
.s_addr
);
3074 destination
.sin_port
= remote_port
;
3075 destination
.sin_family
= AF_INET
;
3077 destination
.sin_len
= sizeof destination
;
3080 /* Set the lease to end now, so that we don't accidentally
3081 reuse it if we restart before the old expiry time. */
3082 client
-> active
-> expiry
=
3083 client
-> active
-> renewal
=
3084 client
-> active
-> rebind
= cur_time
;
3085 if (!write_client_lease (client
, client
-> active
, 1, 1)) {
3086 log_error ("Can't release lease: lease write failed.");
3090 #if defined(DHCPv6) && defined(DHCP4o6)
3091 if (dhcpv4_over_dhcpv6
) {
3092 log_info ("DHCPRELEASE");
3095 log_info ("DHCPRELEASE of %s on %s to %s port %d",
3096 piaddr(client
->active
->address
),
3097 client
->name
? client
->name
: client
->interface
->name
,
3098 inet_ntoa (destination
.sin_addr
),
3099 ntohs (destination
.sin_port
));
3101 #if defined(DHCPv6) && defined(DHCP4o6)
3102 if (dhcpv4_over_dhcpv6
) {
3104 if (destination
.sin_addr
.s_addr
== INADDR_BROADCAST
)
3106 result
= send_dhcpv4_query(client
, broadcast
);
3108 log_error("%s:%d: Failed to send %d byte long packet.",
3109 MDL
, client
->packet_length
);
3113 if (fallback_interface
) {
3114 result
= send_packet(fallback_interface
, NULL
, &client
->packet
,
3115 client
->packet_length
, from
, &destination
,
3118 log_error("%s:%d: Failed to send %d byte long packet"
3119 " over %s interface.", MDL
,
3120 client
->packet_length
,
3121 fallback_interface
->name
);
3124 /* Send out a packet. */
3125 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
3126 client
->packet_length
, from
, &destination
,
3129 log_error ("%s:%d: Failed to send %d byte long packet"
3130 " over %s interface.", MDL
,
3131 client
->packet_length
,
3132 client
->interface
->name
);
3138 #if defined(DHCPv6) && defined(DHCP4o6)
3140 * \brief Send a DHCPv4-query to the DHCPv6 client
3141 * (DHCPv4 client function)
3143 * The DHCPv4 client sends a DHCPv4-query to the DHCPv6 client over
3144 * the inter-process communication socket.
3146 * \param client the DHCPv4 client state
3147 * \param broadcast the broadcast flag
3148 * \return the sent byte count (-1 on error)
3150 static int send_dhcpv4_query(struct client_state
*client
, int broadcast
) {
3151 struct data_string ds
;
3152 struct dhcpv4_over_dhcpv6_packet
*query
;
3155 if (dhcp4o6_state
<= 0) {
3156 log_info("send_dhcpv4_query: not ready.");
3161 * Compute buffer length and allocate it.
3163 len
= ofs
= (int)(offsetof(struct dhcpv4_over_dhcpv6_packet
, options
));
3164 len
+= dhcpv6_universe
.tag_size
+ dhcpv6_universe
.length_size
;
3165 len
+= client
->packet_length
;
3166 memset(&ds
, 0, sizeof(ds
));
3167 if (!buffer_allocate(&ds
.buffer
, len
, MDL
)) {
3168 log_error("Unable to allocate memory for DHCPv4-query.");
3171 ds
.data
= ds
.buffer
->data
;
3177 query
= (struct dhcpv4_over_dhcpv6_packet
*)ds
.data
;
3178 query
->msg_type
= DHCPV6_DHCPV4_QUERY
;
3179 query
->flags
[0] = query
->flags
[1] = query
->flags
[2] = 0;
3181 query
->flags
[0] |= DHCP4O6_QUERY_UNICAST
;
3184 * Append DHCPv4 message.
3186 dhcpv6_universe
.store_tag(ds
.buffer
->data
+ ofs
, D6O_DHCPV4_MSG
);
3187 ofs
+= dhcpv6_universe
.tag_size
;
3188 dhcpv6_universe
.store_length(ds
.buffer
->data
+ ofs
,
3189 client
->packet_length
);
3190 ofs
+= dhcpv6_universe
.length_size
;
3191 memcpy(ds
.buffer
->data
+ ofs
, &client
->packet
, client
->packet_length
);
3194 * Send DHCPv6 message.
3196 cc
= send(dhcp4o6_fd
, ds
.data
, ds
.len
, 0);
3198 log_error("send_dhcpv4_query: send(): %m");
3200 data_string_forget(&ds
, MDL
);
3206 * \brief Forward a DHCPv4-query to all DHCPv4 over DHCPv6 server addresses.
3207 * (DHCPv6 client function)
3209 * \param raw the DHCPv6 DHCPv4-query message raw content
3211 static void forw_dhcpv4_query(struct data_string
*raw
) {
3212 struct interface_info
*ip
;
3213 struct client_state
*client
;
3214 struct dhc6_lease
*lease
;
3215 struct option_cache
*oc
;
3216 struct data_string addrs
;
3217 struct sockaddr_in6 sin6
;
3218 int i
, send_ret
, attempt
, success
;
3220 attempt
= success
= 0;
3221 memset(&sin6
, 0, sizeof(sin6
));
3222 sin6
.sin6_family
= AF_INET6
;
3223 sin6
.sin6_port
= remote_port
;
3225 sin6
.sin6_len
= sizeof(sin6
);
3227 memset(&addrs
, 0, sizeof(addrs
));
3228 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
3229 for (client
= ip
->client
; client
!= NULL
;
3230 client
= client
->next
) {
3231 if ((client
->state
!= S_BOUND
) &&
3232 (client
->state
!= S_RENEWING
) &&
3233 (client
->state
!= S_REBINDING
))
3235 lease
= client
->active_lease
;
3236 if ((lease
== NULL
) || lease
->released
)
3238 oc
= lookup_option(&dhcpv6_universe
,
3240 D6O_DHCP4_O_DHCP6_SERVER
);
3242 !evaluate_option_cache(&addrs
, NULL
, NULL
, NULL
,
3243 lease
->options
, NULL
,
3244 &global_scope
, oc
, MDL
) ||
3245 ((addrs
.len
% sizeof(sin6
.sin6_addr
)) != 0)) {
3246 data_string_forget(&addrs
, MDL
);
3249 if (addrs
.len
== 0) {
3250 /* note there is nothing to forget */
3252 All_DHCP_Relay_Agents_and_Servers
,
3255 send_ret
= send_packet6(ip
, raw
->data
,
3257 if (send_ret
== raw
->len
)
3261 for (i
= 0; i
< addrs
.len
;
3262 i
+= sizeof(sin6
.sin6_addr
)) {
3263 memcpy(&sin6
.sin6_addr
, addrs
.data
+ i
,
3264 sizeof(sin6
.sin6_addr
));
3266 send_ret
= send_packet6(ip
, raw
->data
,
3268 if (send_ret
== raw
->len
)
3271 data_string_forget(&addrs
, MDL
);
3275 log_info("forw_dhcpv4_query: sent(%d): %d/%d",
3276 raw
->len
, success
, attempt
);
3284 make_client_options(struct client_state
*client
, struct client_lease
*lease
,
3285 u_int8_t
*type
, struct option_cache
*sid
,
3286 struct iaddr
*rip
, struct option
**prl
,
3287 struct option_state
**op
)
3290 struct option_cache
*oc
;
3291 struct option
*option
= NULL
;
3292 struct buffer
*bp
= NULL
;
3294 /* If there are any leftover options, get rid of them. */
3296 option_state_dereference(op
, MDL
);
3298 /* Allocate space for options. */
3299 option_state_allocate(op
, MDL
);
3301 /* Send the server identifier if provided. */
3303 save_option(&dhcp_universe
, *op
, sid
);
3307 /* Send the requested address if provided. */
3309 client
->requested_address
= *rip
;
3310 i
= DHO_DHCP_REQUESTED_ADDRESS
;
3311 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
3313 make_const_option_cache(&oc
, NULL
, rip
->iabuf
, rip
->len
,
3315 log_error ("can't make requested address cache.");
3317 save_option(&dhcp_universe
, *op
, oc
);
3318 option_cache_dereference(&oc
, MDL
);
3320 option_dereference(&option
, MDL
);
3322 client
->requested_address
.len
= 0;
3325 i
= DHO_DHCP_MESSAGE_TYPE
;
3326 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
, &i
, 0,
3328 make_const_option_cache(&oc
, NULL
, type
, 1, option
, MDL
)))
3329 log_error("can't make message type.");
3331 save_option(&dhcp_universe
, *op
, oc
);
3332 option_cache_dereference(&oc
, MDL
);
3334 option_dereference(&option
, MDL
);
3339 /* Probe the length of the list. */
3341 for (i
= 0 ; prl
[i
] != NULL
; i
++)
3342 if (prl
[i
]->universe
== &dhcp_universe
)
3345 if (!buffer_allocate(&bp
, len
, MDL
))
3346 log_error("can't make parameter list buffer.");
3348 unsigned code
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
3351 for (i
= 0 ; prl
[i
] != NULL
; i
++)
3352 if (prl
[i
]->universe
== &dhcp_universe
)
3353 bp
->data
[len
++] = prl
[i
]->code
;
3355 if (!(option_code_hash_lookup(&option
,
3356 dhcp_universe
.code_hash
,
3358 make_const_option_cache(&oc
, &bp
, NULL
, len
,
3361 buffer_dereference(&bp
, MDL
);
3362 log_error ("can't make option cache");
3364 save_option(&dhcp_universe
, *op
, oc
);
3365 option_cache_dereference(&oc
, MDL
);
3367 option_dereference(&option
, MDL
);
3372 * If requested (duid_v4 == 1) add an RFC4361 compliant client-identifier
3373 * This can be overridden by including a client id in the configuration
3377 struct data_string client_identifier
;
3380 memset(&client_identifier
, 0, sizeof(client_identifier
));
3381 client_identifier
.len
= 1 + 4 + default_duid
.len
;
3382 if (!buffer_allocate(&client_identifier
.buffer
,
3383 client_identifier
.len
, MDL
))
3384 log_fatal("no memory for default DUID!");
3385 client_identifier
.data
= client_identifier
.buffer
->data
;
3387 i
= DHO_DHCP_CLIENT_IDENTIFIER
;
3389 /* Client-identifier type : 1 byte */
3390 *client_identifier
.buffer
->data
= 255;
3393 * we use the low 4 bytes from the interface address
3395 if (client
->interface
->hw_address
.hlen
> 4) {
3396 hw_idx
= client
->interface
->hw_address
.hlen
- 4;
3400 hw_len
= client
->interface
->hw_address
.hlen
;
3402 memcpy(client_identifier
.buffer
->data
+ 5 - hw_len
,
3403 client
->interface
->hw_address
.hbuf
+ hw_idx
,
3406 /* Add the default duid */
3407 memcpy(client_identifier
.buffer
->data
+ (1 + 4),
3408 default_duid
.data
, default_duid
.len
);
3410 /* And save the option */
3411 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
3413 make_const_option_cache(&oc
, NULL
,
3414 (u_int8_t
*)client_identifier
.data
,
3415 client_identifier
.len
,
3417 log_error ("can't make requested client id cache..");
3419 save_option (&dhcp_universe
, *op
, oc
);
3420 option_cache_dereference (&oc
, MDL
);
3422 option_dereference(&option
, MDL
);
3425 /* Run statements that need to be run on transmission. */
3426 if (client
->config
->on_transmission
)
3427 execute_statements_in_scope(NULL
, NULL
, NULL
, client
,
3428 (lease
? lease
->options
: NULL
),
3430 client
->config
->on_transmission
,
3434 void make_discover (client
, lease
)
3435 struct client_state
*client
;
3436 struct client_lease
*lease
;
3438 unsigned char discover
= DHCPDISCOVER
;
3439 struct option_state
*options
= (struct option_state
*)0;
3441 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3443 make_client_options (client
,
3444 lease
, &discover
, (struct option_cache
*)0,
3445 lease
? &lease
-> address
: (struct iaddr
*)0,
3446 client
-> config
-> requested_options
,
3449 /* Set up the option buffer... */
3450 client
-> packet_length
=
3451 cons_options ((struct packet
*)0, &client
-> packet
,
3452 (struct lease
*)0, client
,
3453 /* maximum packet size */1500,
3454 (struct option_state
*)0,
3456 /* scope */ &global_scope
,
3460 (struct data_string
*)0,
3461 client
-> config
-> vendor_space_name
);
3463 option_state_dereference (&options
, MDL
);
3464 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3465 client
-> packet_length
= BOOTP_MIN_LEN
;
3467 client
-> packet
.op
= BOOTREQUEST
;
3468 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3469 /* Assumes hw_address is known, otherwise a random value may result */
3470 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3471 client
-> packet
.hops
= 0;
3472 client
-> packet
.xid
= random ();
3473 client
-> packet
.secs
= 0; /* filled in by send_discover. */
3475 if (can_receive_unicast_unconfigured (client
-> interface
))
3476 client
-> packet
.flags
= 0;
3478 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3480 memset (&(client
-> packet
.ciaddr
),
3481 0, sizeof client
-> packet
.ciaddr
);
3482 memset (&(client
-> packet
.yiaddr
),
3483 0, sizeof client
-> packet
.yiaddr
);
3484 memset (&(client
-> packet
.siaddr
),
3485 0, sizeof client
-> packet
.siaddr
);
3486 client
-> packet
.giaddr
= giaddr
;
3487 if (client
-> interface
-> hw_address
.hlen
> 0)
3488 memcpy (client
-> packet
.chaddr
,
3489 &client
-> interface
-> hw_address
.hbuf
[1],
3490 (unsigned)(client
-> interface
-> hw_address
.hlen
- 1));
3493 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3498 void make_request (client
, lease
)
3499 struct client_state
*client
;
3500 struct client_lease
*lease
;
3502 unsigned char request
= DHCPREQUEST
;
3503 struct option_cache
*oc
;
3505 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3507 if (client
-> state
== S_REQUESTING
)
3508 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3509 DHO_DHCP_SERVER_IDENTIFIER
);
3511 oc
= (struct option_cache
*)0;
3513 if (client
-> sent_options
)
3514 option_state_dereference (&client
-> sent_options
, MDL
);
3516 make_client_options (client
, lease
, &request
, oc
,
3517 ((client
-> state
== S_REQUESTING
||
3518 client
-> state
== S_REBOOTING
)
3520 : (struct iaddr
*)0),
3521 client
-> config
-> requested_options
,
3522 &client
-> sent_options
);
3524 /* Set up the option buffer... */
3525 client
-> packet_length
=
3526 cons_options ((struct packet
*)0, &client
-> packet
,
3527 (struct lease
*)0, client
,
3528 /* maximum packet size */1500,
3529 (struct option_state
*)0,
3530 client
-> sent_options
,
3531 /* scope */ &global_scope
,
3535 (struct data_string
*)0,
3536 client
-> config
-> vendor_space_name
);
3538 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3539 client
-> packet_length
= BOOTP_MIN_LEN
;
3541 client
-> packet
.op
= BOOTREQUEST
;
3542 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3543 /* Assumes hw_address is known, otherwise a random value may result */
3544 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3545 client
-> packet
.hops
= 0;
3546 client
-> packet
.xid
= client
-> xid
;
3547 client
-> packet
.secs
= 0; /* Filled in by send_request. */
3549 /* If we own the address we're requesting, put it in ciaddr;
3550 otherwise set ciaddr to zero. */
3551 if (client
-> state
== S_BOUND
||
3552 client
-> state
== S_RENEWING
||
3553 client
-> state
== S_REBINDING
) {
3554 memcpy (&client
-> packet
.ciaddr
,
3555 lease
-> address
.iabuf
, lease
-> address
.len
);
3556 client
-> packet
.flags
= 0;
3558 memset (&client
-> packet
.ciaddr
, 0,
3559 sizeof client
-> packet
.ciaddr
);
3560 if (can_receive_unicast_unconfigured (client
-> interface
))
3561 client
-> packet
.flags
= 0;
3563 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3566 memset (&client
-> packet
.yiaddr
, 0,
3567 sizeof client
-> packet
.yiaddr
);
3568 memset (&client
-> packet
.siaddr
, 0,
3569 sizeof client
-> packet
.siaddr
);
3570 if (client
-> state
!= S_BOUND
&&
3571 client
-> state
!= S_RENEWING
)
3572 client
-> packet
.giaddr
= giaddr
;
3574 memset (&client
-> packet
.giaddr
, 0,
3575 sizeof client
-> packet
.giaddr
);
3576 if (client
-> interface
-> hw_address
.hlen
> 0)
3577 memcpy (client
-> packet
.chaddr
,
3578 &client
-> interface
-> hw_address
.hbuf
[1],
3579 (unsigned)(client
-> interface
-> hw_address
.hlen
- 1));
3582 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3586 void make_decline (client
, lease
)
3587 struct client_state
*client
;
3588 struct client_lease
*lease
;
3590 unsigned char decline
= DHCPDECLINE
;
3591 struct option_cache
*oc
;
3593 struct option_state
*options
= (struct option_state
*)0;
3595 /* Create the options cache. */
3596 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3597 DHO_DHCP_SERVER_IDENTIFIER
);
3598 make_client_options(client
, lease
, &decline
, oc
, &lease
->address
,
3601 /* Consume the options cache into the option buffer. */
3602 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3603 client
-> packet_length
=
3604 cons_options ((struct packet
*)0, &client
-> packet
,
3605 (struct lease
*)0, client
, 0,
3606 (struct option_state
*)0, options
,
3607 &global_scope
, 0, 0, 0, (struct data_string
*)0,
3608 client
-> config
-> vendor_space_name
);
3610 /* Destroy the options cache. */
3611 option_state_dereference (&options
, MDL
);
3613 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3614 client
-> packet_length
= BOOTP_MIN_LEN
;
3616 client
-> packet
.op
= BOOTREQUEST
;
3617 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3618 /* Assumes hw_address is known, otherwise a random value may result */
3619 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3620 client
-> packet
.hops
= 0;
3621 client
-> packet
.xid
= client
-> xid
;
3622 client
-> packet
.secs
= 0; /* Filled in by send_request. */
3623 if (can_receive_unicast_unconfigured (client
-> interface
))
3624 client
-> packet
.flags
= 0;
3626 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3628 /* ciaddr must always be zero. */
3629 memset (&client
-> packet
.ciaddr
, 0,
3630 sizeof client
-> packet
.ciaddr
);
3631 memset (&client
-> packet
.yiaddr
, 0,
3632 sizeof client
-> packet
.yiaddr
);
3633 memset (&client
-> packet
.siaddr
, 0,
3634 sizeof client
-> packet
.siaddr
);
3635 client
-> packet
.giaddr
= giaddr
;
3636 memcpy (client
-> packet
.chaddr
,
3637 &client
-> interface
-> hw_address
.hbuf
[1],
3638 client
-> interface
-> hw_address
.hlen
);
3641 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3645 void make_release (client
, lease
)
3646 struct client_state
*client
;
3647 struct client_lease
*lease
;
3649 unsigned char request
= DHCPRELEASE
;
3650 struct option_cache
*oc
;
3652 struct option_state
*options
= (struct option_state
*)0;
3654 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3656 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3657 DHO_DHCP_SERVER_IDENTIFIER
);
3658 make_client_options(client
, lease
, &request
, oc
, NULL
, NULL
, &options
);
3660 /* Set up the option buffer... */
3661 client
-> packet_length
=
3662 cons_options ((struct packet
*)0, &client
-> packet
,
3663 (struct lease
*)0, client
,
3664 /* maximum packet size */1500,
3665 (struct option_state
*)0,
3667 /* scope */ &global_scope
,
3671 (struct data_string
*)0,
3672 client
-> config
-> vendor_space_name
);
3674 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3675 client
-> packet_length
= BOOTP_MIN_LEN
;
3676 option_state_dereference (&options
, MDL
);
3678 client
-> packet
.op
= BOOTREQUEST
;
3679 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3680 /* Assumes hw_address is known, otherwise a random value may result */
3681 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3682 client
-> packet
.hops
= 0;
3683 client
-> packet
.xid
= random ();
3684 client
-> packet
.secs
= 0;
3685 client
-> packet
.flags
= 0;
3686 memcpy (&client
-> packet
.ciaddr
,
3687 lease
-> address
.iabuf
, lease
-> address
.len
);
3688 memset (&client
-> packet
.yiaddr
, 0,
3689 sizeof client
-> packet
.yiaddr
);
3690 memset (&client
-> packet
.siaddr
, 0,
3691 sizeof client
-> packet
.siaddr
);
3692 client
-> packet
.giaddr
= giaddr
;
3693 memcpy (client
-> packet
.chaddr
,
3694 &client
-> interface
-> hw_address
.hbuf
[1],
3695 client
-> interface
-> hw_address
.hlen
);
3698 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3702 void destroy_client_lease (lease
)
3703 struct client_lease
*lease
;
3705 if (lease
-> server_name
)
3706 dfree (lease
-> server_name
, MDL
);
3707 if (lease
-> filename
)
3708 dfree (lease
-> filename
, MDL
);
3709 option_state_dereference (&lease
-> options
, MDL
);
3710 free_client_lease (lease
, MDL
);
3713 FILE *leaseFile
= NULL
;
3714 int leases_written
= 0;
3716 void rewrite_client_leases ()
3718 struct interface_info
*ip
;
3719 struct client_state
*client
;
3720 struct client_lease
*lp
;
3722 if (leaseFile
!= NULL
)
3724 leaseFile
= fopen (path_dhclient_db
, "w");
3725 if (leaseFile
== NULL
) {
3726 log_error ("can't create %s: %m", path_dhclient_db
);
3730 /* If there is a default duid, write it out. */
3731 if (default_duid
.len
!= 0)
3732 write_duid(&default_duid
);
3734 /* Write out all the leases attached to configured interfaces that
3736 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
3737 for (client
= ip
-> client
; client
; client
= client
-> next
) {
3738 for (lp
= client
-> leases
; lp
; lp
= lp
-> next
) {
3739 write_client_lease (client
, lp
, 1, 0);
3741 if (client
-> active
)
3742 write_client_lease (client
,
3743 client
-> active
, 1, 0);
3745 if (client
->active_lease
!= NULL
)
3746 write_client6_lease(client
,
3747 client
->active_lease
,
3750 /* Reset last_write after rewrites. */
3751 client
->last_write
= 0;
3755 /* Write out any leases that are attached to interfaces that aren't
3756 currently configured. */
3757 for (ip
= dummy_interfaces
; ip
; ip
= ip
-> next
) {
3758 for (client
= ip
-> client
; client
; client
= client
-> next
) {
3759 for (lp
= client
-> leases
; lp
; lp
= lp
-> next
) {
3760 write_client_lease (client
, lp
, 1, 0);
3762 if (client
-> active
)
3763 write_client_lease (client
,
3764 client
-> active
, 1, 0);
3766 if (client
->active_lease
!= NULL
)
3767 write_client6_lease(client
,
3768 client
->active_lease
,
3771 /* Reset last_write after rewrites. */
3772 client
->last_write
= 0;
3778 void write_lease_option (struct option_cache
*oc
,
3779 struct packet
*packet
, struct lease
*lease
,
3780 struct client_state
*client_state
,
3781 struct option_state
*in_options
,
3782 struct option_state
*cfg_options
,
3783 struct binding_scope
**scope
,
3784 struct universe
*u
, void *stuff
)
3786 const char *name
, *dot
;
3787 struct data_string ds
;
3788 char *preamble
= stuff
;
3790 memset (&ds
, 0, sizeof ds
);
3792 if (u
!= &dhcp_universe
) {
3799 if (evaluate_option_cache (&ds
, packet
, lease
, client_state
,
3800 in_options
, cfg_options
, scope
, oc
, MDL
)) {
3801 /* The option name */
3802 fprintf(leaseFile
, "%soption %s%s%s", preamble
,
3803 name
, dot
, oc
->option
->name
);
3805 /* The option value if there is one */
3806 if ((oc
->option
->format
== NULL
) ||
3807 (oc
->option
->format
[0] != 'Z')) {
3808 fprintf(leaseFile
, " %s",
3809 pretty_print_option(oc
->option
, ds
.data
,
3813 /* The closing semi-colon and newline */
3814 fprintf(leaseFile
, ";\n");
3816 data_string_forget (&ds
, MDL
);
3820 /* Write an option cache to the lease store. */
3822 write_options(struct client_state
*client
, struct option_state
*options
,
3823 const char *preamble
)
3827 for (i
= 0; i
< options
->universe_count
; i
++) {
3828 option_space_foreach(NULL
, NULL
, client
, NULL
, options
,
3829 &global_scope
, universes
[i
],
3830 (char *)preamble
, write_lease_option
);
3835 * The "best" default DUID, since we cannot predict any information
3836 * about the system (such as whether or not the hardware addresses are
3837 * integrated into the motherboard or similar), is the "LLT", link local
3838 * plus time, DUID. For real stateless "LL" is better.
3840 * Once generated, this duid is stored into the state database, and
3841 * retained across restarts.
3843 * For the time being, there is probably a different state database for
3844 * every daemon, so this winds up being a per-interface identifier...which
3845 * is not how it is intended. Upcoming rearchitecting the client should
3846 * address this "one daemon model."
3849 form_duid(struct data_string
*duid
, const char *file
, int line
)
3851 struct interface_info
*ip
;
3855 /* For now, just use the first interface on the list. */
3859 log_fatal("Impossible condition at %s:%d.", MDL
);
3861 if ((ip
->hw_address
.hlen
== 0) ||
3862 (ip
->hw_address
.hlen
> sizeof(ip
->hw_address
.hbuf
)))
3863 log_fatal("Impossible hardware address length at %s:%d.", MDL
);
3866 duid_type
= stateless
? DUID_LL
: DUID_LLT
;
3869 * 2 bytes for the 'duid type' field.
3870 * 2 bytes for the 'htype' field.
3871 * (DUID_LLT) 4 bytes for the 'current time'.
3872 * enough bytes for the hardware address (note that hw_address has
3873 * the 'htype' on byte zero).
3875 len
= 4 + (ip
->hw_address
.hlen
- 1);
3876 if (duid_type
== DUID_LLT
)
3878 if (!buffer_allocate(&duid
->buffer
, len
, MDL
))
3879 log_fatal("no memory for default DUID!");
3880 duid
->data
= duid
->buffer
->data
;
3883 /* Basic Link Local Address type of DUID. */
3884 if (duid_type
== DUID_LLT
) {
3885 putUShort(duid
->buffer
->data
, DUID_LLT
);
3886 putUShort(duid
->buffer
->data
+ 2, ip
->hw_address
.hbuf
[0]);
3887 putULong(duid
->buffer
->data
+ 4, cur_time
- DUID_TIME_EPOCH
);
3888 memcpy(duid
->buffer
->data
+ 8, ip
->hw_address
.hbuf
+ 1,
3889 ip
->hw_address
.hlen
- 1);
3891 putUShort(duid
->buffer
->data
, DUID_LL
);
3892 putUShort(duid
->buffer
->data
+ 2, ip
->hw_address
.hbuf
[0]);
3893 memcpy(duid
->buffer
->data
+ 4, ip
->hw_address
.hbuf
+ 1,
3894 ip
->hw_address
.hlen
- 1);
3897 /* Now format the output based on lease-id-format */
3898 str
= format_lease_id(duid
->data
, duid
->len
,
3899 top_level_config
.lease_id_format
, MDL
);
3901 log_info("form_duid: Couldn't allocate memory to log duid!");
3903 log_info("Created duid %s.", str
);
3908 /* Write the default DUID to the lease store. */
3910 write_duid(struct data_string
*duid
)
3915 if ((duid
== NULL
) || (duid
->len
<= 2))
3916 return DHCP_R_INVALIDARG
;
3918 if (leaseFile
== NULL
) { /* XXX? */
3919 leaseFile
= fopen(path_dhclient_db
, "w");
3920 if (leaseFile
== NULL
) {
3921 log_error("can't create %s: %m", path_dhclient_db
);
3922 return ISC_R_IOERROR
;
3926 /* Generate a formatted duid string per lease-id-format */
3927 str
= format_lease_id(duid
->data
, duid
->len
,
3928 top_level_config
.lease_id_format
, MDL
);
3930 return ISC_R_NOMEMORY
;
3932 stat
= fprintf(leaseFile
, "default-duid %s;\n", str
);
3935 return ISC_R_IOERROR
;
3937 if (fflush(leaseFile
) != 0)
3938 return ISC_R_IOERROR
;
3940 return ISC_R_SUCCESS
;
3943 /* Write a DHCPv6 lease to the store. */
3945 write_client6_lease(struct client_state
*client
, struct dhc6_lease
*lease
,
3946 int rewrite
, int sync
)
3949 struct dhc6_addr
*addr
;
3953 /* This should include the current lease. */
3954 if (!rewrite
&& (leases_written
++ > 20)) {
3955 rewrite_client_leases();
3957 return ISC_R_SUCCESS
;
3960 if (client
== NULL
|| lease
== NULL
)
3961 return DHCP_R_INVALIDARG
;
3963 if (leaseFile
== NULL
) { /* XXX? */
3964 leaseFile
= fopen(path_dhclient_db
, "w");
3965 if (leaseFile
== NULL
) {
3966 log_error("can't create %s: %m", path_dhclient_db
);
3967 return ISC_R_IOERROR
;
3971 stat
= fprintf(leaseFile
, "lease6 {\n");
3973 return ISC_R_IOERROR
;
3975 stat
= fprintf(leaseFile
, " interface \"%s\";\n",
3976 client
->interface
->name
);
3978 return ISC_R_IOERROR
;
3980 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
3981 switch (ia
->ia_type
) {
3994 /* For some reason IAID was never octal or hex, but string or
3995 * hex. Go figure. So for compatibilty's sake we will either
3996 * do hex or "legacy" i.e string rather than octal. What a
3998 switch(top_level_config
.lease_id_format
) {
4000 char* iaid_str
= format_lease_id(
4001 (const unsigned char *) &ia
->iaid
, 4,
4002 top_level_config
.lease_id_format
, MDL
);
4005 log_error("Can't format iaid");
4006 return ISC_R_IOERROR
;
4009 stat
= fprintf(leaseFile
, " %s %s {\n",
4011 dfree(iaid_str
, MDL
);
4017 stat
= fprintf(leaseFile
, " %s %s {\n", ianame
,
4018 print_hex_1(4, ia
->iaid
, 12));
4023 return ISC_R_IOERROR
;
4025 if (ia
->ia_type
!= D6O_IA_TA
)
4026 stat
= fprintf(leaseFile
, " starts %d;\n"
4029 (int)ia
->starts
, ia
->renew
, ia
->rebind
);
4031 stat
= fprintf(leaseFile
, " starts %d;\n",
4034 return ISC_R_IOERROR
;
4036 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
4037 if (ia
->ia_type
!= D6O_IA_PD
)
4038 stat
= fprintf(leaseFile
,
4040 piaddr(addr
->address
));
4042 stat
= fprintf(leaseFile
,
4043 " iaprefix %s/%d {\n",
4044 piaddr(addr
->address
),
4047 return ISC_R_IOERROR
;
4049 stat
= fprintf(leaseFile
, " starts %d;\n"
4050 " preferred-life %u;\n"
4052 (int)addr
->starts
, addr
->preferred_life
,
4055 return ISC_R_IOERROR
;
4057 if (addr
->options
!= NULL
)
4058 write_options(client
, addr
->options
, " ");
4060 stat
= fprintf(leaseFile
, " }\n");
4062 return ISC_R_IOERROR
;
4065 if (ia
->options
!= NULL
)
4066 write_options(client
, ia
->options
, " ");
4068 stat
= fprintf(leaseFile
, " }\n");
4070 return ISC_R_IOERROR
;
4073 if (lease
->released
) {
4074 stat
= fprintf(leaseFile
, " released;\n");
4076 return ISC_R_IOERROR
;
4079 if (lease
->options
!= NULL
)
4080 write_options(client
, lease
->options
, " ");
4082 stat
= fprintf(leaseFile
, "}\n");
4084 return ISC_R_IOERROR
;
4086 if (fflush(leaseFile
) != 0)
4087 return ISC_R_IOERROR
;
4090 if (fsync(fileno(leaseFile
)) < 0) {
4091 log_error("write_client_lease: fsync(): %m");
4092 return ISC_R_IOERROR
;
4096 return ISC_R_SUCCESS
;
4099 int write_client_lease (client
, lease
, rewrite
, makesure
)
4100 struct client_state
*client
;
4101 struct client_lease
*lease
;
4105 struct data_string ds
;
4111 if (leases_written
++ > 20) {
4112 rewrite_client_leases ();
4117 /* If the lease came from the config file, we don't need to stash
4118 a copy in the lease database. */
4119 if (lease
-> is_static
)
4122 if (leaseFile
== NULL
) { /* XXX */
4123 leaseFile
= fopen (path_dhclient_db
, "w");
4124 if (leaseFile
== NULL
) {
4125 log_error ("can't create %s: %m", path_dhclient_db
);
4131 fprintf (leaseFile
, "lease {\n");
4132 if (lease
-> is_bootp
) {
4133 fprintf (leaseFile
, " bootp;\n");
4139 fprintf (leaseFile
, " interface \"%s\";\n",
4140 client
-> interface
-> name
);
4145 if (client
-> name
) {
4146 fprintf (leaseFile
, " name \"%s\";\n", client
-> name
);
4152 fprintf (leaseFile
, " fixed-address %s;\n",
4153 piaddr (lease
-> address
));
4158 if (lease
-> filename
) {
4159 s
= quotify_string (lease
-> filename
, MDL
);
4161 fprintf (leaseFile
, " filename \"%s\";\n", s
);
4171 if (lease
->server_name
!= NULL
) {
4172 s
= quotify_string(lease
->server_name
, MDL
);
4174 fprintf(leaseFile
, " server-name \"%s\";\n", s
);
4183 if (lease
-> medium
) {
4184 s
= quotify_string (lease
-> medium
-> string
, MDL
);
4186 fprintf (leaseFile
, " medium \"%s\";\n", s
);
4200 memset (&ds
, 0, sizeof ds
);
4202 write_options(client
, lease
->options
, " ");
4204 tval
= print_time(lease
->renewal
);
4206 fprintf(leaseFile
, " renew %s\n", tval
) < 0)
4209 tval
= print_time(lease
->rebind
);
4211 fprintf(leaseFile
, " rebind %s\n", tval
) < 0)
4214 tval
= print_time(lease
->expiry
);
4216 fprintf(leaseFile
, " expire %s\n", tval
) < 0)
4219 if (fprintf(leaseFile
, "}\n") < 0)
4222 if (fflush(leaseFile
) != 0)
4225 client
->last_write
= cur_time
;
4227 if (!errors
&& makesure
) {
4228 if (fsync (fileno (leaseFile
)) < 0) {
4229 log_info ("write_client_lease: %m");
4234 return errors
? 0 : 1;
4237 /* Variables holding name of script and file pointer for writing to
4238 script. Needless to say, this is not reentrant - only one script
4239 can be invoked at a time. */
4240 char scriptName
[256];
4244 * @brief Initializes basic variables for a script
4246 * This function is called as an initial preparation for calling a script.
4247 * It sets up a number of common env. variables that will be passed to
4248 * the script. For actual script calling, see @ref script_go .
4250 * @param client variables will be stored here (if null, the whole function
4252 * @param reason specified the reason for calling a script (must be non-null)
4253 * @param medium if specified, defines medium type (may be null)
4255 void script_init(struct client_state
*client
, const char *reason
,
4256 struct string_list
*medium
)
4258 struct string_list
*sl
, *next
;
4261 for (sl
= client
-> env
; sl
; sl
= next
) {
4265 client
-> env
= (struct string_list
*)0;
4268 if (client
-> interface
) {
4269 client_envadd (client
, "", "interface", "%s",
4270 client
-> interface
-> name
);
4273 client_envadd (client
,
4274 "", "client", "%s", client
-> name
);
4276 client_envadd (client
,
4277 "", "medium", "%s", medium
-> string
);
4279 client_envadd (client
, "", "reason", "%s", reason
);
4280 client_envadd (client
, "", "pid", "%ld", (long int)getpid ());
4282 client_envadd (client
, "", "dad_wait_time", "%ld",
4283 (long int)dad_wait_time
);
4288 void client_option_envadd (struct option_cache
*oc
,
4289 struct packet
*packet
, struct lease
*lease
,
4290 struct client_state
*client_state
,
4291 struct option_state
*in_options
,
4292 struct option_state
*cfg_options
,
4293 struct binding_scope
**scope
,
4294 struct universe
*u
, void *stuff
)
4296 struct envadd_state
*es
= stuff
;
4297 struct data_string data
;
4298 memset (&data
, 0, sizeof data
);
4300 if (evaluate_option_cache (&data
, packet
, lease
, client_state
,
4301 in_options
, cfg_options
, scope
, oc
, MDL
)) {
4304 if (dhcp_option_ev_name (name
, sizeof name
,
4308 value
= pretty_print_option(oc
->option
,
4311 length
= strlen(value
);
4313 if (check_option_values(oc
->option
->universe
,
4315 value
, length
) == 0) {
4316 client_envadd(es
->client
, es
->prefix
,
4319 log_error("suspect value in %s "
4320 "option - discarded",
4326 data_string_forget (&data
, MDL
);
4331 * @brief Adds parameters to environment variables for a script
4333 * This function add details of specified lease to a list of env. variables
4334 * to be passed to a script. The lease details will be prepended with
4335 * specified prefix (e.g. "old_") and added to the list stored in client.
4336 * Following variables may be set:
4340 * - broadcast_address
4345 * @param client env. variables will be stored here
4346 * @param prefix textual prefix to be added to each variable (e.g. "old_")
4347 * @param lease lease details will be extracted from here
4349 void script_write_params(struct client_state
*client
, const char *prefix
,
4350 struct client_lease
*lease
)
4353 struct data_string data
;
4354 struct option_cache
*oc
;
4355 struct envadd_state es
;
4360 client_envadd (client
,
4361 prefix
, "ip_address", "%s", piaddr (lease
-> address
));
4363 /* If we've set the next server address in the lease structure
4364 put it into an environment variable for the script */
4365 if (lease
->next_srv_addr
.len
!= 0) {
4366 client_envadd(client
, prefix
, "next_server", "%s",
4367 piaddr(lease
->next_srv_addr
));
4370 /* For the benefit of Linux (and operating systems which may
4371 have similar needs), compute the network address based on
4372 the supplied ip address and netmask, if provided. Also
4373 compute the broadcast address (the host address all ones
4374 broadcast address, not the host address all zeroes
4375 broadcast address). */
4377 memset (&data
, 0, sizeof data
);
4378 oc
= lookup_option (&dhcp_universe
, lease
-> options
, DHO_SUBNET_MASK
);
4379 if (oc
&& evaluate_option_cache (&data
, (struct packet
*)0,
4380 (struct lease
*)0, client
,
4381 (struct option_state
*)0,
4383 &global_scope
, oc
, MDL
)) {
4385 struct iaddr netmask
, subnet
, broadcast
;
4388 * No matter the length of the subnet-mask option,
4389 * use only the first four octets. Note that
4390 * subnet-mask options longer than 4 octets are not
4391 * in conformance with RFC 2132, but servers with this
4394 memcpy(netmask
.iabuf
, data
.data
, 4);
4396 data_string_forget (&data
, MDL
);
4398 subnet
= subnet_number (lease
-> address
, netmask
);
4400 client_envadd (client
, prefix
, "network_number",
4401 "%s", piaddr (subnet
));
4403 oc
= lookup_option (&dhcp_universe
,
4405 DHO_BROADCAST_ADDRESS
);
4407 !(evaluate_option_cache
4408 (&data
, (struct packet
*)0,
4409 (struct lease
*)0, client
,
4410 (struct option_state
*)0,
4412 &global_scope
, oc
, MDL
))) {
4413 broadcast
= broadcast_addr (subnet
, netmask
);
4414 if (broadcast
.len
) {
4415 client_envadd (client
,
4416 prefix
, "broadcast_address",
4417 "%s", piaddr (broadcast
));
4422 data_string_forget (&data
, MDL
);
4425 if (lease
->filename
) {
4426 if (check_option_values(NULL
, DHO_ROOT_PATH
,
4428 strlen(lease
->filename
)) == 0) {
4429 client_envadd(client
, prefix
, "filename",
4430 "%s", lease
->filename
);
4432 log_error("suspect value in %s "
4433 "option - discarded",
4438 if (lease
->server_name
) {
4439 if (check_option_values(NULL
, DHO_HOST_NAME
,
4441 strlen(lease
->server_name
)) == 0 ) {
4442 client_envadd (client
, prefix
, "server_name",
4443 "%s", lease
->server_name
);
4445 log_error("suspect value in %s "
4446 "option - discarded",
4447 lease
->server_name
);
4451 for (i
= 0; i
< lease
-> options
-> universe_count
; i
++) {
4452 option_space_foreach ((struct packet
*)0, (struct lease
*)0,
4453 client
, (struct option_state
*)0,
4454 lease
-> options
, &global_scope
,
4456 &es
, client_option_envadd
);
4459 client_envadd (client
, prefix
, "expiry", "%lu",
4460 (unsigned long)(lease
-> expiry
));
4464 * @brief Write out the environent variable the client requested.
4465 * Write out the environment variables for the objects that the
4466 * client requested. If the object was requested the variable will be:
4467 * requested_<option_name>=1
4468 * If it wasn't requested there won't be a variable.
4470 * @param client client structure
4472 void script_write_requested(struct client_state
*client
)
4475 struct option
**req
;
4477 req
= client
->config
->requested_options
;
4482 for (i
= 0 ; req
[i
] != NULL
; i
++) {
4483 if ((req
[i
]->universe
== &dhcp_universe
) &&
4484 dhcp_option_ev_name(name
, sizeof(name
), req
[i
])) {
4485 client_envadd(client
, "requested_", name
, "%d", 1);
4491 * @brief Calls external script.
4493 * External script is specified either using -sf command line or
4494 * script parameter in the configuration file.
4496 * @param client specifies client information (environment variables,
4497 * and other parameters will be extracted and passed to the script.
4498 * @return If positive, it contains exit code of the process running script.
4499 * If negative, returns the signal number that cause the script process
4502 int script_go(struct client_state
*client
)
4507 char reason
[] = "REASON=NBI";
4508 static char client_path
[] = CLIENT_PATH
;
4510 struct string_list
*sp
, *next
;
4511 int pid
, wpid
, wstatus
;
4514 scriptName
= client
-> config
-> script_name
;
4516 scriptName
= top_level_config
.script_name
;
4518 envp
= dmalloc (((client
? client
-> envc
: 2) +
4519 client_env_count
+ 2) * sizeof (char *), MDL
);
4521 log_error ("No memory for client script environment.");
4525 /* Copy out the environment specified on the command line,
4527 for (sp
= client_env
; sp
; sp
= sp
-> next
) {
4528 envp
[i
++] = sp
-> string
;
4530 /* Copy out the environment specified by dhclient. */
4532 for (sp
= client
-> env
; sp
; sp
= sp
-> next
) {
4533 envp
[i
++] = sp
-> string
;
4536 envp
[i
++] = reason
;
4539 envp
[i
++] = client_path
;
4540 envp
[i
] = (char *)0;
4542 argv
[0] = scriptName
;
4543 argv
[1] = (char *)0;
4547 log_error ("fork: %m");
4551 wpid
= wait (&wstatus
);
4552 } while (wpid
!= pid
&& wpid
> 0);
4554 log_error ("wait: %m");
4558 /* We don't want to pass an open file descriptor for
4559 * dhclient.leases when executing dhclient-script.
4561 if (leaseFile
!= NULL
)
4563 execve (scriptName
, argv
, envp
);
4564 log_error ("execve (%s, ...): %m", scriptName
);
4569 for (sp
= client
-> env
; sp
; sp
= next
) {
4573 client
-> env
= (struct string_list
*)0;
4577 gettimeofday(&cur_tv
, NULL
);
4579 if (!WIFEXITED(wstatus
)) {
4580 int sigval
= WTERMSIG(wstatus
);
4581 log_error ("script_go script: %s was terminated by signal %d", scriptName
, sigval
);
4585 return (WEXITSTATUS(wstatus
));
4588 void client_envadd (struct client_state
*client
,
4589 const char *prefix
, const char *name
, const char *fmt
, ...)
4594 struct string_list
*val
;
4597 va_start (list
, fmt
);
4598 len
= vsnprintf (spbuf
, sizeof spbuf
, fmt
, list
);
4601 val
= dmalloc (strlen (prefix
) + strlen (name
) + 1 /* = */ +
4602 len
+ sizeof *val
, MDL
);
4604 log_error ("client_envadd: cannot allocate space for variable");
4613 if (len
>= sizeof spbuf
) {
4614 va_start (list
, fmt
);
4615 vsnprintf (s
, len
+ 1, fmt
, list
);
4621 val
-> next
= client
-> env
;
4622 client
-> env
= val
;
4626 int dhcp_option_ev_name (buf
, buflen
, option
)
4629 struct option
*option
;
4635 if (option
-> universe
!= &dhcp_universe
) {
4636 s
= option
-> universe
-> name
;
4645 if (j
+ 1 == buflen
)
4655 if (j
+ 1 == buflen
)
4666 void finish (char ret
)
4668 if (no_daemon
|| dfd
[0] == -1 || dfd
[1] == -1)
4670 if (write(dfd
[1], &ret
, 1) != 1)
4671 log_fatal("write to parent: %m");
4672 (void) close(dfd
[1]);
4673 dfd
[0] = dfd
[1] = -1;
4681 /* Don't become a daemon if the user requested otherwise. */
4683 write_client_pid_file ();
4687 /* Only do it once. */
4688 if (dfd
[0] == -1 || dfd
[1] == -1)
4691 /* Signal parent we started successfully. */
4692 if (write(dfd
[1], &buf
, 1) != 1)
4693 log_fatal("write to parent: %m");
4694 (void) close(dfd
[1]);
4695 dfd
[0] = dfd
[1] = -1;
4697 /* Stop logging to stderr... */
4700 /* Become session leader and get pid... */
4703 /* Close standard I/O descriptors. */
4708 /* Reopen them on /dev/null. */
4709 (void) open("/dev/null", O_RDWR
);
4710 (void) open("/dev/null", O_RDWR
);
4711 (void) open("/dev/null", O_RDWR
);
4713 write_client_pid_file ();
4715 IGNORE_RET (chdir("/"));
4719 void write_client_pid_file ()
4724 /* nothing to do if the user doesn't want a pid file */
4725 if (no_pid_file
== ISC_TRUE
) {
4729 pfdesc
= open (path_dhclient_pid
, O_CREAT
| O_TRUNC
| O_WRONLY
, 0644);
4732 log_error ("Can't create %s: %m", path_dhclient_pid
);
4736 pf
= fdopen (pfdesc
, "w");
4739 log_error ("Can't fdopen %s: %m", path_dhclient_pid
);
4741 fprintf (pf
, "%ld\n", (long)getpid ());
4746 void client_location_changed ()
4748 struct interface_info
*ip
;
4749 struct client_state
*client
;
4751 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4752 for (client
= ip
-> client
; client
; client
= client
-> next
) {
4753 switch (client
-> state
) {
4755 cancel_timeout (send_discover
, client
);
4759 cancel_timeout (state_bound
, client
);
4765 cancel_timeout (send_request
, client
);
4775 client
-> state
= S_INIT
;
4776 state_reboot (client
);
4781 void do_release(client
)
4782 struct client_state
*client
;
4784 struct data_string ds
;
4785 struct option_cache
*oc
;
4787 #if defined(DHCPv6) && defined(DHCP4o6)
4788 if (dhcpv4_over_dhcpv6
&& (dhcp4o6_state
<= 0)) {
4789 if (dhcp4o6_state
< 0)
4791 client
->pending
= P_RELEASE
;
4796 /* Pick a random xid. */
4797 client
-> xid
= random ();
4799 /* is there even a lease to release? */
4800 if (client
-> active
) {
4801 /* Make a DHCPRELEASE packet, and set appropriate per-interface
4803 make_release (client
, client
-> active
);
4805 memset (&ds
, 0, sizeof ds
);
4806 oc
= lookup_option (&dhcp_universe
,
4807 client
-> active
-> options
,
4808 DHO_DHCP_SERVER_IDENTIFIER
);
4810 evaluate_option_cache (&ds
, (struct packet
*)0,
4811 (struct lease
*)0, client
,
4812 (struct option_state
*)0,
4813 client
-> active
-> options
,
4814 &global_scope
, oc
, MDL
)) {
4816 memcpy (client
-> destination
.iabuf
,
4818 client
-> destination
.len
= 4;
4820 client
-> destination
= iaddr_broadcast
;
4822 data_string_forget (&ds
, MDL
);
4824 client
-> destination
= iaddr_broadcast
;
4825 client
-> first_sending
= cur_time
;
4826 client
-> interval
= client
-> config
-> initial_interval
;
4828 /* Zap the medium list... */
4829 client
-> medium
= (struct string_list
*)0;
4831 /* Send out the first and only DHCPRELEASE packet. */
4832 send_release (client
);
4834 /* Do the client script RELEASE operation. */
4835 script_init (client
,
4836 "RELEASE", (struct string_list
*)0);
4837 if (client
-> alias
)
4838 script_write_params(client
, "alias_",
4840 script_write_params(client
, "old_", client
-> active
);
4841 script_write_requested(client
);
4845 /* Cancel any timeouts. */
4846 cancel_timeout (state_bound
, client
);
4847 cancel_timeout (send_discover
, client
);
4848 cancel_timeout (state_init
, client
);
4849 cancel_timeout (send_request
, client
);
4850 cancel_timeout (state_reboot
, client
);
4851 cancel_timeout (finish_v6only
, client
);
4852 client
-> state
= S_STOPPED
;
4854 #if defined(DHCPv6) && defined(DHCP4o6)
4855 if (dhcpv4_over_dhcpv6
)
4860 int dhclient_interface_shutdown_hook (struct interface_info
*interface
)
4862 do_release (interface
-> client
);
4867 int dhclient_interface_discovery_hook (struct interface_info
*tmp
)
4869 struct interface_info
*last
, *ip
;
4870 /* See if we can find the client from dummy_interfaces */
4872 for (ip
= dummy_interfaces
; ip
; ip
= ip
-> next
) {
4873 if (!strcmp (ip
-> name
, tmp
-> name
)) {
4874 /* Remove from dummy_interfaces */
4876 ip
= (struct interface_info
*)0;
4877 interface_reference (&ip
, last
-> next
, MDL
);
4878 interface_dereference (&last
-> next
, MDL
);
4880 interface_reference (&last
-> next
,
4882 interface_dereference (&ip
-> next
,
4886 ip
= (struct interface_info
*)0;
4887 interface_reference (&ip
,
4888 dummy_interfaces
, MDL
);
4889 interface_dereference (&dummy_interfaces
, MDL
);
4891 interface_reference (&dummy_interfaces
,
4893 interface_dereference (&ip
-> next
,
4897 /* Copy "client" to tmp */
4899 tmp
-> client
= ip
-> client
;
4900 tmp
-> client
-> interface
= tmp
;
4902 interface_dereference (&ip
, MDL
);
4910 isc_result_t
dhclient_interface_startup_hook (struct interface_info
*interface
)
4912 struct interface_info
*ip
;
4913 struct client_state
*client
;
4915 /* This code needs some rethinking. It doesn't test against
4916 a signal name, and it just kind of bulls into doing something
4917 that may or may not be appropriate. */
4920 interface_reference (&interface
-> next
, interfaces
, MDL
);
4921 interface_dereference (&interfaces
, MDL
);
4923 interface_reference (&interfaces
, interface
, MDL
);
4925 discover_interfaces (DISCOVER_UNCONFIGURED
);
4927 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4928 /* If interfaces were specified, don't configure
4929 interfaces that weren't specified! */
4930 if (ip
-> flags
& INTERFACE_RUNNING
||
4931 (ip
-> flags
& (INTERFACE_REQUESTED
|
4932 INTERFACE_AUTOMATIC
)) !=
4933 INTERFACE_REQUESTED
)
4935 script_init (ip
-> client
,
4936 "PREINIT", (struct string_list
*)0);
4937 if (ip
-> client
-> alias
)
4938 script_write_params(ip
-> client
, "alias_",
4939 ip
-> client
-> alias
);
4940 script_go(ip
-> client
);
4943 discover_interfaces (interfaces_requested
!= 0
4944 ? DISCOVER_REQUESTED
4945 : DISCOVER_RUNNING
);
4947 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4948 if (ip
-> flags
& INTERFACE_RUNNING
)
4950 ip
-> flags
|= INTERFACE_RUNNING
;
4951 for (client
= ip
->client
; client
; client
= client
->next
) {
4952 client
->state
= S_INIT
;
4953 state_reboot(client
);
4956 return ISC_R_SUCCESS
;
4959 /* The client should never receive a relay agent information option,
4960 so if it does, log it and discard it. */
4962 int parse_agent_information_option (packet
, len
, data
)
4963 struct packet
*packet
;
4970 /* The client never sends relay agent information options. */
4972 unsigned cons_agent_information_options (cfg_options
, outpacket
,
4974 struct option_state
*cfg_options
;
4975 struct dhcp_packet
*outpacket
;
4982 static void shutdown_exit (void *foo
)
4984 /* get rid of the pid if we can */
4985 if (no_pid_file
== ISC_FALSE
)
4986 (void) unlink(path_dhclient_pid
);
4990 #if defined (NSUPDATE)
4992 * If the first query fails, the updater MUST NOT delete the DNS name. It
4993 * may be that the host whose lease on the server has expired has moved
4994 * to another network and obtained a lease from a different server,
4995 * which has caused the client's A RR to be replaced. It may also be
4996 * that some other client has been configured with a name that matches
4997 * the name of the DHCP client, and the policy was that the last client
4998 * to specify the name would get the name. In this case, the DHCID RR
4999 * will no longer match the updater's notion of the client-identity of
5000 * the host pointed to by the DNS name.
5001 * -- "Interaction between DHCP and DNS"
5004 /* The first and second stages are pretty similar so we combine them */
5006 client_dns_remove_action(dhcp_ddns_cb_t
*ddns_cb
,
5007 isc_result_t eresult
)
5010 isc_result_t result
;
5012 if ((eresult
== ISC_R_SUCCESS
) &&
5013 (ddns_cb
->state
== DDNS_STATE_REM_FW_YXDHCID
)) {
5014 /* Do the second stage of the FWD removal */
5015 ddns_cb
->state
= DDNS_STATE_REM_FW_NXRR
;
5017 result
= ddns_modify_fwd(ddns_cb
, MDL
);
5018 if (result
== ISC_R_SUCCESS
) {
5023 /* If we are done or have an error clean up */
5024 dhclient_ddns_cb_free(ddns_cb
, MDL
);
5029 client_dns_remove(struct client_state
*client
,
5032 dhcp_ddns_cb_t
*ddns_cb
;
5033 isc_result_t result
;
5035 /* if we have an old ddns request for this client, cancel it */
5036 if (client
->ddns_cb
!= NULL
) {
5037 ddns_cancel(client
->ddns_cb
, MDL
);
5038 client
->ddns_cb
= NULL
;
5041 ddns_cb
= ddns_cb_alloc(MDL
);
5042 if (ddns_cb
!= NULL
) {
5043 ddns_cb
->address
= *addr
;
5044 ddns_cb
->timeout
= 0;
5046 ddns_cb
->state
= DDNS_STATE_REM_FW_YXDHCID
;
5047 ddns_cb
->flags
= DDNS_UPDATE_ADDR
;
5048 ddns_cb
->cur_func
= client_dns_remove_action
;
5050 result
= client_dns_update(client
, ddns_cb
);
5052 if (result
!= ISC_R_TIMEDOUT
) {
5053 dhclient_ddns_cb_free(ddns_cb
, MDL
);
5057 #endif /* defined NSUPDATE */
5060 isc_result_t
dhcp_set_control_state (control_object_state_t oldstate
,
5061 control_object_state_t newstate
)
5063 struct interface_info
*ip
;
5064 struct client_state
*client
;
5067 if (newstate
== server_shutdown
) {
5069 if (shutdown_signal
== SIGUSR1
)
5070 return ISC_R_SUCCESS
;
5071 /* Log shutdown on signal. */
5072 if ((shutdown_signal
== SIGINT
) ||
5073 (shutdown_signal
== SIGTERM
)) {
5074 log_info("Received signal %d, initiating shutdown.",
5077 /* Mark it was called. */
5078 shutdown_signal
= SIGUSR1
;
5081 /* Do the right thing for each interface. */
5082 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
5083 for (client
= ip
-> client
; client
; client
= client
-> next
) {
5085 case server_startup
:
5086 return ISC_R_SUCCESS
;
5088 case server_running
:
5089 return ISC_R_SUCCESS
;
5091 case server_shutdown
:
5092 if (client
-> active
&&
5093 client
-> active
-> expiry
> cur_time
) {
5094 #if defined (NSUPDATE)
5095 if (client
->config
->do_forward_update
) {
5096 client_dns_remove(client
,
5097 &client
->active
->address
);
5099 #endif /* defined NSUPDATE */
5101 do_release (client
);
5105 case server_hibernate
:
5106 state_stop (client
);
5110 state_reboot (client
);
5116 if (newstate
== server_shutdown
) {
5117 tv
.tv_sec
= cur_tv
.tv_sec
;
5118 tv
.tv_usec
= cur_tv
.tv_usec
+ 1;
5119 add_timeout(&tv
, shutdown_exit
, 0, 0, 0);
5121 return ISC_R_SUCCESS
;
5124 #if defined (NSUPDATE)
5126 * Called after a timeout if the DNS update failed on the previous try.
5127 * Starts the retry process. If the retry times out it will schedule
5128 * this routine to run again after a 10x wait.
5131 client_dns_update_timeout (void *cp
)
5133 dhcp_ddns_cb_t
*ddns_cb
= (dhcp_ddns_cb_t
*)cp
;
5134 struct client_state
*client
= (struct client_state
*)ddns_cb
->lease
;
5135 isc_result_t status
= ISC_R_FAILURE
;
5137 if ((client
!= NULL
) &&
5138 ((client
->active
!= NULL
) ||
5139 (client
->active_lease
!= NULL
)))
5140 status
= client_dns_update(client
, ddns_cb
);
5143 * A status of timedout indicates that we started the update and
5144 * have released control of the control block. Any other status
5145 * indicates that we should clean up the control block. We either
5146 * got a success which indicates that we didn't really need to
5147 * send an update or some other error in which case we weren't able
5148 * to start the update process. In both cases we still own
5149 * the control block and should free it.
5151 if (status
!= ISC_R_TIMEDOUT
) {
5152 dhclient_ddns_cb_free(ddns_cb
, MDL
);
5157 * If the first query succeeds, the updater can conclude that it
5158 * has added a new name whose only RRs are the A and DHCID RR records.
5159 * The A RR update is now complete (and a client updater is finished,
5160 * while a server might proceed to perform a PTR RR update).
5161 * -- "Interaction between DHCP and DNS"
5163 * If the second query succeeds, the updater can conclude that the current
5164 * client was the last client associated with the domain name, and that
5165 * the name now contains the updated A RR. The A RR update is now
5166 * complete (and a client updater is finished, while a server would
5167 * then proceed to perform a PTR RR update).
5168 * -- "Interaction between DHCP and DNS"
5170 * If the second query fails with NXRRSET, the updater must conclude
5171 * that the client's desired name is in use by another host. At this
5172 * juncture, the updater can decide (based on some administrative
5173 * configuration outside of the scope of this document) whether to let
5174 * the existing owner of the name keep that name, and to (possibly)
5175 * perform some name disambiguation operation on behalf of the current
5176 * client, or to replace the RRs on the name with RRs that represent
5177 * the current client. If the configured policy allows replacement of
5178 * existing records, the updater submits a query that deletes the
5179 * existing A RR and the existing DHCID RR, adding A and DHCID RRs that
5180 * represent the IP address and client-identity of the new client.
5181 * -- "Interaction between DHCP and DNS"
5184 /* The first and second stages are pretty similar so we combine them */
5186 client_dns_update_action(dhcp_ddns_cb_t
*ddns_cb
,
5187 isc_result_t eresult
)
5189 isc_result_t result
;
5195 /* Either we succeeded or broke in a bad way, clean up */
5200 * This is the only difference between the two stages,
5201 * check to see if it is the first stage, in which case
5202 * start the second stage
5204 if (ddns_cb
->state
== DDNS_STATE_ADD_FW_NXDOMAIN
) {
5205 ddns_cb
->state
= DDNS_STATE_ADD_FW_YXDHCID
;
5206 ddns_cb
->cur_func
= client_dns_update_action
;
5208 result
= ddns_modify_fwd(ddns_cb
, MDL
);
5209 if (result
== ISC_R_SUCCESS
) {
5215 case ISC_R_TIMEDOUT
:
5217 * We got a timeout response from the DNS module. Schedule
5218 * another attempt for later. We forget the name, dhcid and
5219 * zone so if it gets changed we will get the new information.
5221 data_string_forget(&ddns_cb
->fwd_name
, MDL
);
5222 data_string_forget(&ddns_cb
->dhcid
, MDL
);
5223 if (ddns_cb
->zone
!= NULL
) {
5224 forget_zone((struct dns_zone
**)&ddns_cb
->zone
);
5227 /* Reset to doing the first stage */
5228 ddns_cb
->state
= DDNS_STATE_ADD_FW_NXDOMAIN
;
5229 ddns_cb
->cur_func
= client_dns_update_action
;
5231 /* and update our timer */
5232 if (ddns_cb
->timeout
< 3600)
5233 ddns_cb
->timeout
*= 10;
5234 tv
.tv_sec
= cur_tv
.tv_sec
+ ddns_cb
->timeout
;
5235 tv
.tv_usec
= cur_tv
.tv_usec
;
5236 add_timeout(&tv
, client_dns_update_timeout
,
5237 ddns_cb
, NULL
, NULL
);
5241 dhclient_ddns_cb_free(ddns_cb
, MDL
);
5245 /* See if we should do a DNS update, and if so, do it. */
5248 client_dns_update(struct client_state
*client
, dhcp_ddns_cb_t
*ddns_cb
)
5250 struct data_string client_identifier
;
5251 struct option_cache
*oc
;
5257 /* If we didn't send an FQDN option, we certainly aren't going to
5258 be doing an update. */
5259 if (!client
-> sent_options
)
5260 return ISC_R_SUCCESS
;
5262 /* If we don't have a lease, we can't do an update. */
5263 if ((client
->active
== NULL
) && (client
->active_lease
== NULL
))
5264 return ISC_R_SUCCESS
;
5266 /* If we set the no client update flag, don't do the update. */
5267 if ((oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5268 FQDN_NO_CLIENT_UPDATE
)) &&
5269 evaluate_boolean_option_cache (&ignorep
, (struct packet
*)0,
5270 (struct lease
*)0, client
,
5271 client
-> sent_options
,
5272 (struct option_state
*)0,
5273 &global_scope
, oc
, MDL
))
5274 return ISC_R_SUCCESS
;
5276 /* If we set the "server, please update" flag, or didn't set it
5277 to false, don't do the update. */
5278 if (!(oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5279 FQDN_SERVER_UPDATE
)) ||
5280 evaluate_boolean_option_cache (&ignorep
, (struct packet
*)0,
5281 (struct lease
*)0, client
,
5282 client
-> sent_options
,
5283 (struct option_state
*)0,
5284 &global_scope
, oc
, MDL
))
5285 return ISC_R_SUCCESS
;
5287 /* If no FQDN option was supplied, don't do the update. */
5288 if (!(oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5290 !evaluate_option_cache (&ddns_cb
->fwd_name
, (struct packet
*)0,
5291 (struct lease
*)0, client
,
5292 client
-> sent_options
,
5293 (struct option_state
*)0,
5294 &global_scope
, oc
, MDL
))
5295 return ISC_R_SUCCESS
;
5298 * Construct the DHCID value for use in the DDNS update process
5299 * We have the newer standard version and the older interim version
5300 * chosen by the '-I' option. The interim version is left as is
5301 * for backwards compatibility. The standard version is based on
5302 * RFC 4701 section 3.3
5307 memset(&client_identifier
, 0, sizeof(client_identifier
));
5309 if (std_dhcid
== 1) {
5310 /* standard style */
5311 ddns_cb
->dhcid_class
= dns_rdatatype_dhcid
;
5315 ddns_cb
->dhcid_class
= dns_rdatatype_txt
;
5316 /* for backwards compatibility */
5317 ddns_v4_type
= DHO_DHCP_CLIENT_IDENTIFIER
;
5319 if (client
->active_lease
!= NULL
) {
5320 /* V6 request, get the client identifier, then
5321 * construct the dhcid for either standard
5323 if (((oc
= lookup_option(&dhcpv6_universe
,
5324 client
->sent_options
,
5325 D6O_CLIENTID
)) != NULL
) &&
5326 evaluate_option_cache(&client_identifier
, NULL
,
5328 client
->sent_options
, NULL
,
5329 &global_scope
, oc
, MDL
)) {
5330 result
= get_dhcid(ddns_cb
, 2,
5331 client_identifier
.data
,
5332 client_identifier
.len
);
5333 data_string_forget(&client_identifier
, MDL
);
5335 log_fatal("Impossible condition at %s:%d.", MDL
);
5338 * V4 request, use the client id if there is one or the
5339 * mac address if there isn't. If we have a client id
5340 * we check to see if it is an embedded DUID.
5342 if (((oc
= lookup_option(&dhcp_universe
,
5343 client
->sent_options
,
5344 DHO_DHCP_CLIENT_IDENTIFIER
)) != NULL
) &&
5345 evaluate_option_cache(&client_identifier
, NULL
,
5347 client
->sent_options
, NULL
,
5348 &global_scope
, oc
, MDL
)) {
5349 if ((std_dhcid
== 1) && (duid_v4
== 1) &&
5350 (client_identifier
.data
[0] == 255)) {
5352 * This appears to be an embedded DUID,
5353 * extract it and treat it as such
5355 if (client_identifier
.len
<= 5)
5356 log_fatal("Impossible condition at %s:%d.",
5358 result
= get_dhcid(ddns_cb
, 2,
5359 client_identifier
.data
+ 5,
5360 client_identifier
.len
- 5);
5362 result
= get_dhcid(ddns_cb
, ddns_v4_type
,
5363 client_identifier
.data
,
5364 client_identifier
.len
);
5366 data_string_forget(&client_identifier
, MDL
);
5368 result
= get_dhcid(ddns_cb
, 0,
5369 client
->interface
->hw_address
.hbuf
,
5370 client
->interface
->hw_address
.hlen
);
5374 return ISC_R_SUCCESS
;
5380 if (ddns_cb
->fwd_name
.len
&& ddns_cb
->dhcid
.len
) {
5381 rcode
= ddns_modify_fwd(ddns_cb
, MDL
);
5383 rcode
= ISC_R_FAILURE
;
5386 * A success from the modify routine means we are performing
5387 * async processing, for which we use the timedout error message.
5389 if (rcode
== ISC_R_SUCCESS
) {
5390 rcode
= ISC_R_TIMEDOUT
;
5398 * Schedule the first update. They will continue to retry occasionally
5399 * until they no longer time out (or fail).
5402 dhclient_schedule_updates(struct client_state
*client
,
5406 dhcp_ddns_cb_t
*ddns_cb
;
5409 if (!client
->config
->do_forward_update
)
5412 /* cancel any outstanding ddns requests */
5413 if (client
->ddns_cb
!= NULL
) {
5414 ddns_cancel(client
->ddns_cb
, MDL
);
5415 client
->ddns_cb
= NULL
;
5418 ddns_cb
= ddns_cb_alloc(MDL
);
5420 if (ddns_cb
!= NULL
) {
5421 ddns_cb
->lease
= (void *)client
;
5422 ddns_cb
->address
= *addr
;
5423 ddns_cb
->timeout
= 1;
5426 * XXX: DNS TTL is a problem we need to solve properly.
5427 * Until that time, 300 is a placeholder default for
5428 * something that is less insane than a value scaled
5433 ddns_cb
->state
= DDNS_STATE_ADD_FW_NXDOMAIN
;
5434 ddns_cb
->cur_func
= client_dns_update_action
;
5435 ddns_cb
->flags
= DDNS_UPDATE_ADDR
| DDNS_INCLUDE_RRSET
;
5437 client
->ddns_cb
= ddns_cb
;
5438 tv
.tv_sec
= cur_tv
.tv_sec
+ offset
;
5439 tv
.tv_usec
= cur_tv
.tv_usec
;
5440 add_timeout(&tv
, client_dns_update_timeout
,
5441 ddns_cb
, NULL
, NULL
);
5443 log_error("Unable to allocate dns update state for %s",
5447 #endif /* defined NSUPDATE */
5450 dhcpv4_client_assignments(void)
5452 struct servent
*ent
;
5454 if (path_dhclient_pid
== NULL
)
5455 path_dhclient_pid
= _PATH_DHCLIENT_PID
;
5456 if (path_dhclient_db
== NULL
)
5457 path_dhclient_db
= _PATH_DHCLIENT_DB
;
5459 /* Default to the DHCP/BOOTP port. */
5461 /* If we're faking a relay agent, and we're not using loopback,
5462 use the server port, not the client port. */
5463 if (mockup_relay
&& giaddr
.s_addr
!= htonl(INADDR_LOOPBACK
)) {
5464 local_port
= htons(67);
5466 ent
= getservbyname("dhcpc", "udp");
5468 ent
= getservbyname("bootpc", "udp");
5470 local_port
= htons(68);
5472 local_port
= ent
->s_port
;
5473 #ifndef __CYGWIN32__
5479 /* If we're faking a relay agent, and we're not using loopback,
5480 we're using the server port, not the client port. */
5481 if (mockup_relay
&& giaddr
.s_addr
!= htonl(INADDR_LOOPBACK
)) {
5482 remote_port
= local_port
;
5484 remote_port
= htons(ntohs(local_port
) - 1); /* XXX */
5488 * The following routines are used to check that certain
5489 * strings are reasonable before we pass them to the scripts.
5490 * This avoids some problems with scripts treating the strings
5491 * as commands - see ticket 23722
5492 * The domain checking code should be done as part of assembling
5493 * the string but we are doing it here for now due to time
5497 static int check_domain_name(const char *ptr
, size_t len
, int dots
)
5501 /* not empty or complete length not over 255 characters */
5502 if ((len
== 0) || (len
> 256))
5505 /* consists of [[:alnum:]-]+ labels separated by [.] */
5506 /* a [_] is against RFC but seems to be "widely used"... */
5507 for (p
=ptr
; (*p
!= 0) && (len
-- > 0); p
++) {
5508 if ((*p
== '-') || (*p
== '_')) {
5509 /* not allowed at begin or end of a label */
5510 if (((p
- ptr
) == 0) || (len
== 0) || (p
[1] == '.'))
5512 } else if (*p
== '.') {
5513 /* each label has to be 1-63 characters;
5514 we allow [.] at the end ('foo.bar.') */
5516 if ((d
<= 0) || (d
>= 64))
5518 ptr
= p
+ 1; /* jump to the next label */
5519 if ((dots
> 0) && (len
> 0))
5521 } else if (isalnum((unsigned char)*p
) == 0) {
5522 /* also numbers at the begin are fine */
5526 return(dots
? -1 : 0);
5529 static int check_domain_name_list(const char *ptr
, size_t len
, int dots
)
5532 int ret
= -1; /* at least one needed */
5534 if ((ptr
== NULL
) || (len
== 0))
5537 for (p
=ptr
; (*p
!= 0) && (len
> 0); p
++, len
--) {
5541 if (check_domain_name(ptr
, p
- ptr
, dots
) != 0)
5548 return(check_domain_name(ptr
, p
- ptr
, dots
));
5553 static int check_option_values(struct universe
*universe
,
5561 /* just reject options we want to protect, will be escaped anyway */
5562 if ((universe
== NULL
) || (universe
== &dhcp_universe
)) {
5564 case DHO_DOMAIN_NAME
:
5565 #ifdef ACCEPT_LIST_IN_DOMAIN_NAME
5566 return check_domain_name_list(ptr
, len
, 0);
5568 return check_domain_name(ptr
, len
, 0);
5571 case DHO_NIS_DOMAIN
:
5572 case DHO_NETBIOS_SCOPE
:
5573 return check_domain_name(ptr
, len
, 0);
5575 case DHO_DOMAIN_SEARCH
:
5576 return check_domain_name_list(ptr
, len
, 0);
5581 for (; (*ptr
!= 0) && (len
-- > 0); ptr
++) {
5582 if(!(isalnum((unsigned char)*ptr
) ||
5583 *ptr
== '#' || *ptr
== '%' ||
5584 *ptr
== '+' || *ptr
== '-' ||
5585 *ptr
== '_' || *ptr
== ':' ||
5586 *ptr
== '.' || *ptr
== ',' ||
5587 *ptr
== '@' || *ptr
== '~' ||
5588 *ptr
== '\\' || *ptr
== '/' ||
5589 *ptr
== '[' || *ptr
== ']' ||
5590 *ptr
== '=' || *ptr
== ' '))
5599 if (universe
== &dhcpv6_universe
) {
5601 case D6O_SIP_SERVERS_DNS
:
5602 case D6O_DOMAIN_SEARCH
:
5603 case D6O_NIS_DOMAIN_NAME
:
5604 case D6O_NISP_DOMAIN_NAME
:
5605 return check_domain_name_list(ptr
, len
, 0);
5615 add_reject(struct packet
*packet
) {
5616 struct iaddrmatchlist
*list
;
5618 list
= dmalloc(sizeof(struct iaddrmatchlist
), MDL
);
5620 log_fatal ("no memory for reject list!");
5623 * client_addr is misleading - it is set to source address in common
5626 list
->match
.addr
= packet
->client_addr
;
5627 /* Set mask to indicate host address. */
5628 list
->match
.mask
.len
= list
->match
.addr
.len
;
5629 memset(list
->match
.mask
.iabuf
, 0xff, sizeof(list
->match
.mask
.iabuf
));
5631 /* Append to reject list for the source interface. */
5632 list
->next
= packet
->interface
->client
->config
->reject_list
;
5633 packet
->interface
->client
->config
->reject_list
= list
;
5636 * We should inform user that we won't be accepting this server
5639 log_info("Server added to list of rejected servers.");
5642 #if defined(NSUPDATE)
5643 /* Wrapper function around common ddns_cb_free function that ensures
5644 * we set the client_state pointer to the control block to NULL. */
5646 dhclient_ddns_cb_free(dhcp_ddns_cb_t
*ddns_cb
, char* file
, int line
) {
5648 struct client_state
*client
= (struct client_state
*)ddns_cb
->lease
;
5649 if (client
!= NULL
) {
5650 client
->ddns_cb
= NULL
;
5653 ddns_cb_free(ddns_cb
, file
, line
);
5656 #endif /* defined NSUPDATE */
5658 #if defined(DHCPv6) && defined(DHCP4o6)
5660 * \brief Omapi I/O handler
5662 * The inter-process communication receive handler.
5664 * On the DHCPv6 side, the message is either a POLL (which is answered
5665 * by a START or a STOP) or a DHCPv4-QUERY (which is forwarded to
5666 * DHCPv4 over DHCPv6 servers by forw_dhcpv4_query()).
5668 * On the DHCPv4 side, the message is either a START, a STOP
5669 * (both for the DHCP4 over DHCPv6 state machine) or a DHCPv4-RESPONSE
5670 * (which is processed by recv_dhcpv4_response()).
5672 * \param h the OMAPI object
5673 * \return a result for I/O success or error (used by the I/O subsystem)
5675 isc_result_t
dhcpv4o6_handler(omapi_object_t
*h
) {
5677 char start_msg
[5] = { 'S', 'T', 'A', 'R', 'T' };
5678 char stop_msg
[4] = { 'S', 'T', 'O', 'P' };
5679 char poll_msg
[4] = { 'P', 'O', 'L', 'L' };
5680 struct data_string raw
;
5683 if (h
->type
!= dhcp4o6_type
)
5684 return DHCP_R_INVALIDARG
;
5686 cc
= recv(dhcp4o6_fd
, buf
, sizeof(buf
), 0);
5688 return ISC_R_UNEXPECTED
;
5690 if (local_family
== AF_INET6
) {
5692 (memcmp(buf
, poll_msg
, sizeof(poll_msg
)) == 0)) {
5693 log_info("RCV: POLL");
5694 if (dhcp4o6_state
< 0)
5695 cc
= send(dhcp4o6_fd
, stop_msg
,
5696 sizeof(stop_msg
), 0);
5698 cc
= send(dhcp4o6_fd
, start_msg
,
5699 sizeof(start_msg
), 0);
5701 log_error("dhcpv4o6_handler: send(): %m");
5702 return ISC_R_IOERROR
;
5705 if (cc
< DHCP_FIXED_NON_UDP
+ 8)
5706 return ISC_R_UNEXPECTED
;
5707 memset(&raw
, 0, sizeof(raw
));
5708 if (!buffer_allocate(&raw
.buffer
, cc
, MDL
)) {
5709 log_error("dhcpv4o6_handler: "
5710 "no memory buffer.");
5711 return ISC_R_NOMEMORY
;
5713 raw
.data
= raw
.buffer
->data
;
5715 memcpy(raw
.buffer
->data
, buf
, cc
);
5717 forw_dhcpv4_query(&raw
);
5719 data_string_forget(&raw
, MDL
);
5723 (memcmp(buf
, stop_msg
, sizeof(stop_msg
)) == 0)) {
5724 log_info("RCV: STOP");
5725 if (dhcp4o6_state
> 0) {
5729 } else if ((cc
== 5) &&
5730 (memcmp(buf
, start_msg
, sizeof(start_msg
)) == 0)) {
5731 log_info("RCV: START");
5732 if (dhcp4o6_state
== 0)
5733 cancel_timeout(dhcp4o6_poll
, NULL
);
5737 if (cc
< DHCP_FIXED_NON_UDP
+ 16)
5738 return ISC_R_UNEXPECTED
;
5739 memset(&raw
, 0, sizeof(raw
));
5740 if (!buffer_allocate(&raw
.buffer
, cc
, MDL
)) {
5741 log_error("dhcpv4o6_handler: "
5742 "no memory buffer.");
5743 return ISC_R_NOMEMORY
;
5745 raw
.data
= raw
.buffer
->data
;
5747 memcpy(raw
.buffer
->data
, buf
, cc
);
5749 recv_dhcpv4_response(&raw
);
5751 data_string_forget(&raw
, MDL
);
5755 return ISC_R_SUCCESS
;
5759 * \brief Poll the DHCPv6 client
5760 * (DHCPv4 client function)
5762 * A POLL message is sent to the DHCPv6 client periodically to check
5763 * if the DHCPv6 is ready (i.e., has a valid DHCPv4-over-DHCPv6 server
5766 static void dhcp4o6_poll(void *dummy
) {
5767 char msg
[4] = { 'P', 'O', 'L', 'L' };
5771 IGNORE_UNUSED(dummy
);
5773 if (dhcp4o6_state
< 0)
5778 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5780 log_error("dhcp4o6_poll: send(): %m");
5782 tv
.tv_sec
= cur_time
+ 60;
5783 tv
.tv_usec
= random() % 1000000;
5785 add_timeout(&tv
, dhcp4o6_poll
, NULL
, 0, 0);
5789 * \brief Resume pending operations
5790 * (DHCPv4 client function)
5792 * A START message was received from the DHCPv6 client so pending
5793 * operations (RELEASE or REBOOT) must be resumed.
5795 static void dhcp4o6_resume() {
5796 struct interface_info
*ip
;
5797 struct client_state
*client
;
5799 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
5800 for (client
= ip
->client
; client
!= NULL
;
5801 client
= client
->next
) {
5802 if (client
->pending
== P_RELEASE
)
5804 else if (client
->pending
== P_REBOOT
)
5805 state_reboot(client
);
5811 * \brief Send a START to the DHCPv4 client
5812 * (DHCPv6 client function)
5814 * First check if there is a valid DHCPv4-over-DHCPv6 server address option,
5815 * and when found go UP and on a transition from another state send
5816 * a START message to the DHCPv4 client.
5818 void dhcp4o6_start() {
5819 struct interface_info
*ip
;
5820 struct client_state
*client
;
5821 struct dhc6_lease
*lease
;
5822 struct option_cache
*oc
;
5823 struct data_string addrs
;
5824 char msg
[5] = { 'S', 'T', 'A', 'R', 'T' };
5827 memset(&addrs
, 0, sizeof(addrs
));
5828 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
5829 for (client
= ip
->client
; client
!= NULL
;
5830 client
= client
->next
) {
5831 if ((client
->state
!= S_BOUND
) &&
5832 (client
->state
!= S_RENEWING
) &&
5833 (client
->state
!= S_REBINDING
))
5835 lease
= client
->active_lease
;
5836 if ((lease
== NULL
) || lease
->released
)
5838 oc
= lookup_option(&dhcpv6_universe
,
5840 D6O_DHCP4_O_DHCP6_SERVER
);
5842 !evaluate_option_cache(&addrs
, NULL
, NULL
, NULL
,
5843 lease
->options
, NULL
,
5844 &global_scope
, oc
, MDL
))
5846 if ((addrs
.len
% 16) != 0) {
5847 data_string_forget(&addrs
, MDL
);
5850 data_string_forget(&addrs
, MDL
);
5854 log_info("dhcp4o6_start: failed");
5859 if (dhcp4o6_state
== 1)
5861 log_info("dhcp4o6_start: go to UP");
5864 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5866 log_info("dhcp4o6_start: send(): %m");
5870 * Send a STOP to the DHCPv4 client
5871 * (DHCPv6 client function)
5873 * Go DOWN and on a transition from another state send a STOP message
5874 * to the DHCPv4 client.
5876 static void dhcp4o6_stop() {
5877 char msg
[4] = { 'S', 'T', 'O', 'P' };
5880 if (dhcp4o6_state
== -1)
5883 log_info("dhcp4o6_stop: go to DOWN");
5886 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5888 log_error("dhcp4o6_stop: send(): %m");
5890 #endif /* DHCPv6 && DHCP4o6 */