6 * Copyright (c) 2004-2020 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
25 * https://www.isc.org/
27 * This code is based on the original client state machine that was
28 * written by Elliot Poger. The code has been extensively hacked on
29 * by Ted Lemon since then, so any mistakes you find are probably his
30 * fault and not Elliot's.
36 #include <dns/result.h>
44 TIME default_lease_time
= 43200; /* 12 hours... */
45 TIME max_lease_time
= 86400; /* 24 hours... */
47 const char *path_dhclient_conf
= _PATH_DHCLIENT_CONF
;
48 const char *path_dhclient_db
= NULL
;
49 const char *path_dhclient_pid
= NULL
;
50 static char path_dhclient_script_array
[] = _PATH_DHCLIENT_SCRIPT
;
51 char *path_dhclient_script
= path_dhclient_script_array
;
52 const char *path_dhclient_duid
= NULL
;
54 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-2020 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 * comamnd 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 comamnd 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 comamnd -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 /* Make up a seed for the random number generator from current
833 time plus the sum of the last four bytes of each
834 interface's hardware address interpreted as an integer.
835 Not much entropy, but we're booting, so we're not likely to
836 find anything better. */
838 for (ip
= interfaces
; ip
; ip
= ip
->next
) {
841 &ip
->hw_address
.hbuf
[ip
->hw_address
.hlen
-
842 sizeof seed
], sizeof seed
);
845 srandom(seed
+ cur_time
+ (unsigned)getpid());
849 * Establish a default DUID. We always do so for v6 and
850 * do so if desired for v4 via the -D or -i options
852 if ((local_family
== AF_INET6
) ||
853 ((local_family
== AF_INET
) && (duid_v4
== 1))) {
854 if (default_duid
.len
== 0) {
855 if (default_duid
.buffer
!= NULL
)
856 data_string_forget(&default_duid
, MDL
);
858 form_duid(&default_duid
, MDL
);
859 write_duid(&default_duid
);
863 #if defined(DHCPv6) && defined(DHCP4o6)
864 if (dhcpv4_over_dhcpv6
&& !exit_mode
)
865 dhcp4o6_setup(dhcp4o6_port
);
868 /* Start a configuration state machine for each interface. */
870 if (local_family
== AF_INET6
) {
871 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
872 for (client
= ip
->client
; client
!= NULL
;
873 client
= client
->next
) {
875 start_release6(client
);
877 } else if (exit_mode
) {
878 unconfigure6(client
, "STOP6");
882 /* If we have a previous binding, Confirm
883 * that we can (or can't) still use it.
885 if ((client
->active_lease
!= NULL
) &&
886 !client
->active_lease
->released
)
887 start_confirm6(client
);
895 for (ip
= interfaces
; ip
; ip
= ip
->next
) {
896 ip
->flags
|= INTERFACE_RUNNING
;
897 for (client
= ip
->client
; client
;
898 client
= client
->next
) {
904 client
->state
= S_INIT
;
906 if (top_level_config
.initial_delay
>0)
909 if (top_level_config
.
915 tv
.tv_usec
= random()
919 * distribution than just
922 add_timeout(&tv
, state_reboot
,
925 state_reboot(client
);
938 if ((local_family
== AF_INET6
) || dhcpv4_over_dhcpv6
) {
946 /* Start up a listener for the object management API protocol. */
947 if (top_level_config
.omapi_port
!= -1) {
949 result
= omapi_generic_new(&listener
, MDL
);
950 if (result
!= ISC_R_SUCCESS
)
951 log_fatal("Can't allocate new generic object: %s\n",
952 isc_result_totext(result
));
953 result
= omapi_protocol_listen(listener
,
955 top_level_config
.omapi_port
,
957 if (result
!= ISC_R_SUCCESS
)
958 log_fatal("Can't start OMAPI protocol: %s",
959 isc_result_totext (result
));
962 /* Set up the bootp packet handler... */
963 bootp_packet_handler
= do_packet
;
965 dhcpv6_packet_handler
= do_packet6
;
968 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
969 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
970 dmalloc_cutoff_generation
= dmalloc_generation
;
971 dmalloc_longterm
= dmalloc_outstanding
;
972 dmalloc_outstanding
= 0;
975 #if defined(ENABLE_GENTLE_SHUTDOWN)
976 /* no signal handlers until we deal with the side effects */
977 /* install signal handlers */
978 signal(SIGINT
, dhcp_signal_handler
); /* control-c */
979 signal(SIGTERM
, dhcp_signal_handler
); /* kill */
982 /* If we're not supposed to wait before getting the address,
987 /* If we're not going to daemonize, write the pid file
989 if (no_daemon
|| nowait
)
990 write_client_pid_file();
992 /* Start dispatching packets and timeouts... */
995 /* In fact dispatch() never returns. */
1000 * \brief Run the DHCPv6 stateless client (dhclient -6 -S)
1002 * \param exist_mode set to 1 when dhclient was called with -x
1003 * \param port DHCPv4-over-DHCPv6 client inter-process communication
1004 * UDP port pair (port,port+1 with port in network byte order)
1007 void run_stateless(int exit_mode
, u_int16_t port
)
1010 struct client_state
*client
;
1011 omapi_object_t
*listener
;
1012 isc_result_t result
;
1015 IGNORE_UNUSED(port
);
1018 /* Discover the network interface. */
1019 discover_interfaces(DISCOVER_REQUESTED
);
1022 usage("No interfaces available for stateless command: %s", "-S");
1024 /* Parse the dhclient.conf file. */
1026 if (dhcpv4_over_dhcpv6
) {
1027 /* Mark we want to request IRT too! */
1028 dhcpv4_over_dhcpv6
++;
1033 /* Parse the lease database. */
1034 read_client_leases();
1036 /* If desired parse the secondary lease database for a DUID */
1037 if ((default_duid
.len
== 0) && (path_dhclient_duid
!= NULL
)) {
1041 /* Establish a default DUID. */
1042 if (default_duid
.len
== 0) {
1043 if (default_duid
.buffer
!= NULL
)
1044 data_string_forget(&default_duid
, MDL
);
1046 form_duid(&default_duid
, MDL
);
1050 if (dhcpv4_over_dhcpv6
&& !exit_mode
)
1051 dhcp4o6_setup(port
);
1054 /* Start a configuration state machine. */
1055 for (client
= interfaces
->client
;
1057 client
= client
->next
) {
1059 unconfigure6(client
, "STOP6");
1062 start_info_request6(client
);
1067 /* Start up a listener for the object management API protocol. */
1068 if (top_level_config
.omapi_port
!= -1) {
1070 result
= omapi_generic_new(&listener
, MDL
);
1071 if (result
!= ISC_R_SUCCESS
)
1072 log_fatal("Can't allocate new generic object: %s\n",
1073 isc_result_totext(result
));
1074 result
= omapi_protocol_listen(listener
,
1076 top_level_config
.omapi_port
,
1078 if (result
!= ISC_R_SUCCESS
)
1079 log_fatal("Can't start OMAPI protocol: %s",
1080 isc_result_totext(result
));
1083 /* Set up the packet handler... */
1084 dhcpv6_packet_handler
= do_packet6
;
1086 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
1087 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1088 dmalloc_cutoff_generation
= dmalloc_generation
;
1089 dmalloc_longterm
= dmalloc_outstanding
;
1090 dmalloc_outstanding
= 0;
1093 /* If we're not supposed to wait before getting the address,
1098 /* If we're not going to daemonize, write the pid file
1100 if (no_daemon
|| nowait
)
1101 write_client_pid_file();
1103 /* Start dispatching packets and timeouts... */
1109 #endif /* !UNIT_TEST */
1111 isc_result_t
find_class (struct class **c
,
1112 const char *s
, const char *file
, int line
)
1117 int check_collection (packet
, lease
, collection
)
1118 struct packet
*packet
;
1119 struct lease
*lease
;
1120 struct collection
*collection
;
1125 void classify (packet
, class)
1126 struct packet
*packet
;
1127 struct class *class;
1131 void unbill_class (lease
)
1132 struct lease
*lease
;
1136 int find_subnet (struct subnet
**sp
,
1137 struct iaddr addr
, const char *file
, int line
)
1142 /* Individual States:
1144 * Each routine is called from the dhclient_state_machine() in one of
1146 * -> entering INIT state
1147 * -> recvpacket_flag == 0: timeout in this state
1148 * -> otherwise: received a packet in this state
1150 * Return conditions as handled by dhclient_state_machine():
1151 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
1152 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
1153 * Returns 0: finish the nap which was interrupted for no good reason.
1155 * Several per-interface variables are used to keep track of the process:
1156 * active_lease: the lease that is being used on the interface
1157 * (null pointer if not configured yet).
1158 * offered_leases: leases corresponding to DHCPOFFER messages that have
1159 * been sent to us by DHCP servers.
1160 * acked_leases: leases corresponding to DHCPACK messages that have been
1161 * sent to us by DHCP servers.
1162 * sendpacket: DHCP packet we're trying to send.
1163 * destination: IP address to send sendpacket to
1164 * In addition, there are several relevant per-lease variables.
1165 * T1_expiry, T2_expiry, lease_expiry: lease milestones
1166 * In the active lease, these control the process of renewing the lease;
1167 * In leases on the acked_leases list, this simply determines when we
1168 * can no longer legitimately use the lease.
1171 void state_reboot (cpp
)
1174 struct client_state
*client
= cpp
;
1176 #if defined(DHCPv6) && defined(DHCP4o6)
1177 if (dhcpv4_over_dhcpv6
&& (dhcp4o6_state
<= 0)) {
1178 if (dhcp4o6_state
< 0)
1180 client
->pending
= P_REBOOT
;
1185 client
->pending
= P_NONE
;
1187 /* If we don't remember an active lease, go straight to INIT. */
1188 if (!client
-> active
||
1189 client
-> active
-> is_bootp
||
1190 client
-> active
-> expiry
<= cur_time
) {
1191 state_init (client
);
1195 /* We are in the rebooting state. */
1196 client
-> state
= S_REBOOTING
;
1199 * make_request doesn't initialize xid because it normally comes
1200 * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
1201 * so pick an xid now.
1203 client
-> xid
= random ();
1206 * Make a DHCPREQUEST packet, and set
1207 * appropriate per-interface flags.
1209 make_request (client
, client
-> active
);
1210 client
-> destination
= iaddr_broadcast
;
1211 client
-> first_sending
= cur_time
;
1212 client
-> interval
= client
-> config
-> initial_interval
;
1214 /* Zap the medium list... */
1215 client
-> medium
= NULL
;
1217 /* Send out the first DHCPREQUEST packet. */
1218 send_request (client
);
1221 /* Called when a lease has completely expired and we've been unable to
1224 void state_init (cpp
)
1227 struct client_state
*client
= cpp
;
1229 ASSERT_STATE(state
, S_INIT
);
1231 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
1233 make_discover (client
, client
-> active
);
1234 client
-> xid
= client
-> packet
.xid
;
1235 client
-> destination
= iaddr_broadcast
;
1236 client
-> state
= S_SELECTING
;
1237 client
-> first_sending
= cur_time
;
1238 client
-> interval
= client
-> config
-> initial_interval
;
1240 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
1242 send_discover (client
);
1245 /* v6only_timeout is called when the V6ONLY_WAIT timer expired. */
1247 void finish_v6only(cpp
)
1250 struct client_state
*client
= cpp
;
1251 client
->state
= S_INIT
;
1256 * state_v6only is called when a requested v6-only-preferred option was
1257 * returned by the server. */
1259 void start_v6only(packet
, client
)
1260 struct packet
*packet
;
1261 struct client_state
*client
;
1263 struct option_cache
*oc
;
1264 struct data_string data
;
1265 uint32_t v6only_wait
= 0;
1268 /* Get the V6ONLY_WAIT timer. */
1269 oc
= lookup_option(&dhcp_universe
, packet
->options
,
1270 DHO_V6_ONLY_PREFERRED
);
1272 /* Should not happen... */
1276 memset(&data
, 0, sizeof(data
));
1278 if (evaluate_option_cache(&data
, packet
, (struct lease
*)0, client
,
1279 packet
->options
, (struct option_state
*)0,
1280 &global_scope
, oc
, MDL
)) {
1282 v6only_wait
= getULong(data
.data
);
1283 data_string_forget(&data
, MDL
);
1286 if (v6only_wait
< MIN_V6ONLY_WAIT
)
1287 v6only_wait
= MIN_V6ONLY_WAIT
;
1289 /* Enter V6ONLY state. */
1291 client
->state
= S_V6ONLY
;
1293 /* Run the client script. */
1294 script_init(client
, "V6ONLY", NULL
);
1295 if (client
->active
) {
1296 script_write_params(client
, "old_", client
->active
);
1297 destroy_client_lease(client
->active
);
1298 client
->active
= NULL
;
1300 script_write_requested(client
);
1301 client_envadd(client
, "", "v6-only-preferred", "%lu",
1302 (long unsigned)v6only_wait
);
1305 /* Trigger finish_v6only after V6ONLY_WAIT seconds. */
1306 tv
.tv_sec
= cur_tv
.tv_sec
+ v6only_wait
;
1307 tv
.tv_usec
= cur_tv
.tv_usec
;
1309 add_timeout(&tv
, finish_v6only
, client
, 0, 0);
1313 * state_selecting is called when one or more DHCPOFFER packets have been
1314 * received and a configurable period of time has passed.
1317 void state_selecting (cpp
)
1320 struct client_state
*client
= cpp
;
1321 struct client_lease
*lp
, *next
, *picked
;
1324 ASSERT_STATE(state
, S_SELECTING
);
1327 * Cancel state_selecting and send_discover timeouts, since either
1328 * one could have got us here.
1330 cancel_timeout (state_selecting
, client
);
1331 cancel_timeout (send_discover
, client
);
1334 * We have received one or more DHCPOFFER packets. Currently,
1335 * the only criterion by which we judge leases is whether or
1336 * not we get a response when we arp for them.
1339 for (lp
= client
-> offered_leases
; lp
; lp
= next
) {
1343 * Check to see if we got an ARPREPLY for the address
1344 * in this particular lease.
1348 picked
-> next
= NULL
;
1350 destroy_client_lease (lp
);
1353 client
-> offered_leases
= NULL
;
1356 * If we just tossed all the leases we were offered, go back
1360 client
-> state
= S_INIT
;
1361 state_init (client
);
1365 /* If it was a BOOTREPLY, we can just take the address right now. */
1366 if (picked
-> is_bootp
) {
1367 client
-> new = picked
;
1369 /* Make up some lease expiry times
1370 XXX these should be configurable. */
1371 client
-> new -> expiry
= cur_time
+ 12000;
1372 client
-> new -> renewal
+= cur_time
+ 8000;
1373 client
-> new -> rebind
+= cur_time
+ 10000;
1375 client
-> state
= S_REQUESTING
;
1377 /* Bind to the address we received. */
1378 bind_lease (client
);
1382 /* Go to the REQUESTING state. */
1383 client
-> destination
= iaddr_broadcast
;
1384 client
-> state
= S_REQUESTING
;
1385 client
-> first_sending
= cur_time
;
1386 client
-> interval
= client
-> config
-> initial_interval
;
1388 /* Make a DHCPREQUEST packet from the lease we picked. */
1389 make_request (client
, picked
);
1390 client
-> xid
= client
-> packet
.xid
;
1392 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
1393 destroy_client_lease (picked
);
1395 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
1396 send_request (client
);
1399 /* state_requesting is called when we receive a DHCPACK message after
1400 having sent out one or more DHCPREQUEST packets. */
1402 void dhcpack (packet
)
1403 struct packet
*packet
;
1405 struct interface_info
*ip
= packet
-> interface
;
1406 struct client_state
*client
;
1407 struct client_lease
*lease
;
1408 struct option_cache
*oc
;
1409 struct data_string ds
;
1411 /* If we're not receptive to an offer right now, or if the offer
1412 has an unrecognizable transaction id, then just drop it. */
1413 for (client
= ip
-> client
; client
; client
= client
-> next
) {
1414 if (client
-> xid
== packet
-> raw
-> xid
)
1418 (packet
-> interface
-> hw_address
.hlen
- 1 !=
1419 packet
-> raw
-> hlen
) ||
1420 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
1421 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
1423 log_debug ("DHCPACK in wrong transaction.");
1428 if (client
-> state
!= S_REBOOTING
&&
1429 client
-> state
!= S_REQUESTING
&&
1430 client
-> state
!= S_RENEWING
&&
1431 client
-> state
!= S_REBINDING
) {
1433 log_debug ("DHCPACK in wrong state.");
1438 log_info ("DHCPACK of %s from %s",
1439 inet_ntoa(packet
->raw
->yiaddr
),
1440 piaddr (packet
->client_addr
));
1442 lease
= packet_to_lease (packet
, client
);
1444 log_info ("packet_to_lease failed.");
1448 client
-> new = lease
;
1450 /* Stop resending DHCPREQUEST. */
1451 cancel_timeout (send_request
, client
);
1453 /* Figure out the lease time. */
1454 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1455 DHO_DHCP_LEASE_TIME
);
1456 memset (&ds
, 0, sizeof ds
);
1458 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1459 packet
-> options
, client
-> new -> options
,
1460 &global_scope
, oc
, MDL
)) {
1462 client
-> new -> expiry
= getULong (ds
.data
);
1464 client
-> new -> expiry
= 0;
1465 data_string_forget (&ds
, MDL
);
1467 client
-> new -> expiry
= 0;
1469 if (client
->new->expiry
== 0) {
1472 log_error ("no expiry time on offered lease.");
1474 /* Quench this (broken) server. Return to INIT to reselect. */
1477 /* 1/2 second delay to restart at INIT. */
1478 tv
.tv_sec
= cur_tv
.tv_sec
;
1479 tv
.tv_usec
= cur_tv
.tv_usec
+ 500000;
1481 if (tv
.tv_usec
>= 1000000) {
1483 tv
.tv_usec
-= 1000000;
1486 add_timeout(&tv
, state_init
, client
, 0, 0);
1491 * A number that looks negative here is really just very large,
1492 * because the lease expiry offset is unsigned.
1494 if (client
->new->expiry
< 0)
1495 client
->new->expiry
= TIME_MAX
;
1497 /* Take the server-provided renewal time if there is one. */
1498 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1499 DHO_DHCP_RENEWAL_TIME
);
1501 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1502 packet
-> options
, client
-> new -> options
,
1503 &global_scope
, oc
, MDL
)) {
1505 client
-> new -> renewal
= getULong (ds
.data
);
1507 client
-> new -> renewal
= 0;
1508 data_string_forget (&ds
, MDL
);
1510 client
-> new -> renewal
= 0;
1512 /* If it wasn't specified by the server, calculate it. */
1513 if (!client
-> new -> renewal
)
1514 client
-> new -> renewal
= client
-> new -> expiry
/ 2 + 1;
1516 if (client
-> new -> renewal
<= 0)
1517 client
-> new -> renewal
= TIME_MAX
;
1519 /* Now introduce some randomness to the renewal time: */
1520 if (client
->new->renewal
<= ((TIME_MAX
/ 3) - 3))
1521 client
->new->renewal
= (((client
->new->renewal
* 3) + 3) / 4) +
1522 (((random() % client
->new->renewal
) + 3) / 4);
1524 /* Same deal with the rebind time. */
1525 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1526 DHO_DHCP_REBINDING_TIME
);
1528 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1529 packet
-> options
, client
-> new -> options
,
1530 &global_scope
, oc
, MDL
)) {
1532 client
-> new -> rebind
= getULong (ds
.data
);
1534 client
-> new -> rebind
= 0;
1535 data_string_forget (&ds
, MDL
);
1537 client
-> new -> rebind
= 0;
1539 if (client
-> new -> rebind
<= 0) {
1540 if (client
-> new -> expiry
<= TIME_MAX
/ 7)
1541 client
-> new -> rebind
=
1542 client
-> new -> expiry
* 7 / 8;
1544 client
-> new -> rebind
=
1545 client
-> new -> expiry
/ 8 * 7;
1548 /* Make sure our randomness didn't run the renewal time past the
1550 if (client
-> new -> renewal
> client
-> new -> rebind
) {
1551 if (client
-> new -> rebind
<= TIME_MAX
/ 3)
1552 client
-> new -> renewal
=
1553 client
-> new -> rebind
* 3 / 4;
1555 client
-> new -> renewal
=
1556 client
-> new -> rebind
/ 4 * 3;
1559 client
-> new -> expiry
+= cur_time
;
1560 /* Lease lengths can never be negative. */
1561 if (client
-> new -> expiry
< cur_time
)
1562 client
-> new -> expiry
= TIME_MAX
;
1563 client
-> new -> renewal
+= cur_time
;
1564 if (client
-> new -> renewal
< cur_time
)
1565 client
-> new -> renewal
= TIME_MAX
;
1566 client
-> new -> rebind
+= cur_time
;
1567 if (client
-> new -> rebind
< cur_time
)
1568 client
-> new -> rebind
= TIME_MAX
;
1570 bind_lease (client
);
1573 void bind_lease (client
)
1574 struct client_state
*client
;
1578 /* Remember the medium. */
1579 client
->new->medium
= client
->medium
;
1581 /* Run the client script with the new parameters. */
1582 script_init(client
, (client
->state
== S_REQUESTING
? "BOUND" :
1583 (client
->state
== S_RENEWING
? "RENEW" :
1584 (client
->state
== S_REBOOTING
? "REBOOT" :
1586 client
->new->medium
);
1587 if (client
->active
&& client
->state
!= S_REBOOTING
)
1588 script_write_params(client
, "old_", client
->active
);
1589 script_write_params(client
, "new_", client
->new);
1590 script_write_requested(client
);
1592 script_write_params(client
, "alias_", client
->alias
);
1594 /* If the BOUND/RENEW code detects another machine using the
1595 offered address, it exits nonzero. We need to send a
1596 DHCPDECLINE and toss the lease. */
1597 if (script_go(client
)) {
1598 make_decline(client
, client
->new);
1599 send_decline(client
);
1600 destroy_client_lease(client
->new);
1604 log_info("Unable to obtain a lease on first "
1605 "try (declined). Exiting.");
1608 #if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
1609 /* Let's call a script and we're done */
1610 script_init(client
, "FAIL", (struct string_list
*)0);
1616 tv
.tv_sec
= cur_tv
.tv_sec
+ decline_wait_time
;
1617 tv
.tv_usec
= cur_tv
.tv_usec
;
1618 add_timeout(&tv
, state_init
, client
, 0, 0);
1623 /* Write out the new lease if it has been long enough. */
1624 if (!client
->last_write
||
1625 (cur_time
- client
->last_write
) >= MIN_LEASE_WRITE
)
1626 write_client_lease(client
, client
->new, 0, 1);
1628 /* Replace the old active lease with the new one. */
1629 if (client
->active
) {
1630 if (client
->active
->is_static
) {
1631 // We need to preserve the fallback lease in case
1632 // we lose DHCP service again.
1633 add_to_tail(&client
->leases
, client
->active
);
1635 destroy_client_lease(client
->active
);
1639 client
->active
= client
->new;
1642 /* Set up a timeout to start the renewal process. */
1643 tv
.tv_sec
= client
->active
->renewal
;
1644 tv
.tv_usec
= ((client
->active
->renewal
- cur_tv
.tv_sec
) > 1) ?
1645 random() % 1000000 : cur_tv
.tv_usec
;
1646 add_timeout(&tv
, state_bound
, client
, 0, 0);
1648 log_info("bound to %s -- renewal in %ld seconds.",
1649 piaddr(client
->active
->address
),
1650 (long)(client
->active
->renewal
- cur_time
));
1651 client
->state
= S_BOUND
;
1652 reinitialize_interfaces();
1654 #if defined (NSUPDATE)
1655 if (client
->config
->do_forward_update
)
1656 dhclient_schedule_updates(client
, &client
->active
->address
, 1);
1657 #endif /* defined NSUPDATE */
1661 /* state_bound is called when we've successfully bound to a particular
1662 lease, but the renewal time on that lease has expired. We are
1663 expected to unicast a DHCPREQUEST to the server that gave us our
1666 void state_bound (cpp
)
1669 struct client_state
*client
= cpp
;
1670 struct option_cache
*oc
;
1671 struct data_string ds
;
1673 ASSERT_STATE(state
, S_BOUND
);
1675 /* T1 has expired. */
1676 make_request (client
, client
-> active
);
1677 client
-> xid
= client
-> packet
.xid
;
1679 memset (&ds
, 0, sizeof ds
);
1680 oc
= lookup_option (&dhcp_universe
, client
-> active
-> options
,
1681 DHO_DHCP_SERVER_IDENTIFIER
);
1683 evaluate_option_cache (&ds
, (struct packet
*)0, (struct lease
*)0,
1684 client
, (struct option_state
*)0,
1685 client
-> active
-> options
,
1686 &global_scope
, oc
, MDL
)) {
1688 memcpy (client
-> destination
.iabuf
, ds
.data
, 4);
1689 client
-> destination
.len
= 4;
1691 client
-> destination
= iaddr_broadcast
;
1693 data_string_forget (&ds
, MDL
);
1695 client
-> destination
= iaddr_broadcast
;
1697 client
-> first_sending
= cur_time
;
1698 client
-> interval
= client
-> config
-> initial_interval
;
1699 client
-> state
= S_RENEWING
;
1701 /* Send the first packet immediately. */
1702 send_request (client
);
1705 /* state_stop is called when we've been told to shut down. We unconfigure
1706 the interfaces, and then stop operating until told otherwise. */
1708 void state_stop (cpp
)
1711 struct client_state
*client
= cpp
;
1713 client
->pending
= P_NONE
;
1715 /* Cancel all timeouts. */
1716 cancel_timeout(state_selecting
, client
);
1717 cancel_timeout(send_discover
, client
);
1718 cancel_timeout(send_request
, client
);
1719 cancel_timeout(state_bound
, client
);
1720 cancel_timeout(finish_v6only
, client
);
1722 /* If we have an address, unconfigure it. */
1723 if (client
->active
) {
1724 script_init(client
, "STOP", client
->active
->medium
);
1725 script_write_params(client
, "old_", client
->active
);
1726 script_write_requested(client
);
1728 script_write_params(client
, "alias_", client
->alias
);
1733 int commit_leases ()
1738 int write_lease (lease
)
1739 struct lease
*lease
;
1744 int write_host (host
)
1745 struct host_decl
*host
;
1750 void db_startup (testp
)
1756 struct packet
*packet
;
1758 struct iaddrmatchlist
*ap
;
1762 if (packet
-> raw
-> op
!= BOOTREPLY
)
1765 /* If there's a reject list, make sure this packet's sender isn't
1767 for (ap
= packet
-> interface
-> client
-> config
-> reject_list
;
1768 ap
; ap
= ap
-> next
) {
1769 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1771 /* piaddr() returns its result in a static
1772 buffer sized 4*16 (see common/inet.c). */
1774 strcpy(addrbuf
, piaddr(ap
->match
.addr
));
1775 strcpy(maskbuf
, piaddr(ap
->match
.mask
));
1777 log_info("BOOTREPLY from %s rejected by rule %s "
1778 "mask %s.", piaddr(packet
->client_addr
),
1789 struct packet
*packet
;
1791 struct iaddrmatchlist
*ap
;
1792 void (*handler
) (struct packet
*);
1797 switch (packet
-> packet_type
) {
1799 handler
= dhcpoffer
;
1817 /* If there's a reject list, make sure this packet's sender isn't
1819 for (ap
= packet
-> interface
-> client
-> config
-> reject_list
;
1820 ap
; ap
= ap
-> next
) {
1821 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1823 /* piaddr() returns its result in a static
1824 buffer sized 4*16 (see common/inet.c). */
1826 strcpy(addrbuf
, piaddr(ap
->match
.addr
));
1827 strcpy(maskbuf
, piaddr(ap
->match
.mask
));
1829 log_info("%s from %s rejected by rule %s mask %s.",
1830 type
, piaddr(packet
->client_addr
),
1835 (*handler
) (packet
);
1840 dhcpv6(struct packet
*packet
) {
1841 struct iaddrmatchlist
*ap
;
1842 struct client_state
*client
;
1843 char addrbuf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
1845 /* Silently drop bogus messages. */
1846 if (packet
->dhcpv6_msg_type
>= dhcpv6_type_name_max
)
1849 /* Discard, with log, packets from quenched sources. */
1850 for (ap
= packet
->interface
->client
->config
->reject_list
;
1851 ap
; ap
= ap
->next
) {
1852 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1853 strcpy(addrbuf
, piaddr(packet
->client_addr
));
1854 log_info("%s from %s rejected by rule %s",
1855 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1857 piaddrmask(&ap
->match
.addr
, &ap
->match
.mask
));
1862 /* Screen out nonsensical messages. */
1863 switch(packet
->dhcpv6_msg_type
) {
1865 case DHCPV6_DHCPV4_RESPONSE
:
1866 if (dhcpv4_over_dhcpv6
) {
1867 log_info("RCV: %s message on %s from %s.",
1868 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1869 packet
->interface
->name
,
1870 piaddr(packet
->client_addr
));
1871 forw_dhcpv4_response(packet
);
1875 case DHCPV6_ADVERTISE
:
1876 case DHCPV6_RECONFIGURE
:
1881 log_info("RCV: %s message on %s from %s.",
1882 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1883 packet
->interface
->name
, piaddr(packet
->client_addr
));
1890 /* Find a client state that matches the incoming XID. */
1891 for (client
= packet
->interface
->client
; client
;
1892 client
= client
->next
) {
1893 if (memcmp(&client
->dhcpv6_transaction_id
,
1894 packet
->dhcpv6_transaction_id
, 3) == 0) {
1895 client
->v6_handler(packet
, client
);
1900 /* XXX: temporary log for debugging */
1901 log_info("Packet received, but nothing done with it.");
1906 * \brief Forward a DHCPv4-response to the DHCPv4 client.
1907 * (DHCPv6 client function)
1909 * The DHCPv6 client receives a DHCPv4-response which is forwarded
1910 * to the DHCPv4 client.
1911 * Format: address:16 + DHCPv4 message content
1912 * (we have no state to keep the address so it is transported in
1913 * DHCPv6 <-> DHCPv6 inter-process messages)
1915 * \param packet the DHCPv4-response packet
1917 static void forw_dhcpv4_response(struct packet
*packet
)
1919 struct option_cache
*oc
;
1920 struct data_string enc_opt_data
;
1921 struct data_string ds
;
1925 * Discard if relay is not ready.
1927 if (dhcp4o6_state
== -1) {
1928 log_info("forw_dhcpv4_response: not ready.");
1932 if (packet
->client_addr
.len
!= 16) {
1933 log_error("forw_dhcpv4_response: bad address");
1938 * Get our encapsulated DHCPv4 message.
1940 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_DHCPV4_MSG
);
1942 log_info("DHCPv4-response from %s missing "
1943 "DHCPv4 Message option.",
1944 piaddr(packet
->client_addr
));
1948 memset(&enc_opt_data
, 0, sizeof(enc_opt_data
));
1949 if (!evaluate_option_cache(&enc_opt_data
, NULL
, NULL
, NULL
,
1950 NULL
, NULL
, &global_scope
, oc
, MDL
)) {
1951 log_error("forw_dhcpv4_response: error evaluating "
1953 data_string_forget(&enc_opt_data
, MDL
);
1957 if (enc_opt_data
.len
< DHCP_FIXED_NON_UDP
) {
1958 log_error("forw_dhcpv4_response: "
1959 "no memory for encapsulated packet.");
1960 data_string_forget(&enc_opt_data
, MDL
);
1967 memset(&ds
, 0, sizeof(ds
));
1968 if (!buffer_allocate(&ds
.buffer
, enc_opt_data
.len
+ 16, MDL
)) {
1969 log_error("forw_dhcpv4_response: no memory buffer.");
1970 data_string_forget(&enc_opt_data
, MDL
);
1973 ds
.data
= ds
.buffer
->data
;
1974 ds
.len
= enc_opt_data
.len
+ 16;
1975 memcpy(ds
.buffer
->data
, enc_opt_data
.data
, enc_opt_data
.len
);
1976 memcpy(ds
.buffer
->data
+ enc_opt_data
.len
,
1977 packet
->client_addr
.iabuf
, 16);
1978 data_string_forget(&enc_opt_data
, MDL
);
1983 cc
= send(dhcp4o6_fd
, ds
.data
, ds
.len
, 0);
1985 log_error("forw_dhcpv4_response: send(): %m");
1987 data_string_forget(&ds
, MDL
);
1991 * \brief Receive a DHCPv4-response from the DHCPv6 client.
1992 * (DHCPv4 client function)
1994 * The DHCPv4 client receives a DHCPv4-response forwarded
1995 * by the DHCPv6 client (using \ref forw_dhcpv4_response())
1997 * \param raw the DHCPv4-response raw packet
1999 static void recv_dhcpv4_response(struct data_string
*raw
)
2001 struct packet
*packet
;
2004 if (interfaces
== NULL
) {
2005 log_error("recv_dhcpv4_response: no interfaces.");
2010 memcpy(from
.iabuf
, raw
->data
+ (raw
->len
- 16), 16);
2013 * Build a packet structure.
2016 if (!packet_allocate(&packet
, MDL
)) {
2017 log_error("recv_dhcpv4_response: no memory for packet.");
2021 packet
->raw
= (struct dhcp_packet
*) raw
->data
;
2022 packet
->packet_length
= raw
->len
- 16;
2023 packet
->client_port
= remote_port
;
2024 packet
->client_addr
= from
;
2025 interface_reference(&packet
->interface
, interfaces
, MDL
);
2027 /* Allocate packet->options now so it is non-null for all packets */
2028 if (!option_state_allocate (&packet
->options
, MDL
)) {
2029 log_error("recv_dhcpv4_response: no memory for options.");
2030 packet_dereference (&packet
, MDL
);
2034 /* If there's an option buffer, try to parse it. */
2035 if (packet
->packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
2036 struct option_cache
*op
;
2037 if (!parse_options(packet
)) {
2038 if (packet
->options
)
2039 option_state_dereference
2040 (&packet
->options
, MDL
);
2041 packet_dereference (&packet
, MDL
);
2045 if (packet
->options_valid
&&
2046 (op
= lookup_option(&dhcp_universe
,
2048 DHO_DHCP_MESSAGE_TYPE
))) {
2049 struct data_string dp
;
2050 memset(&dp
, 0, sizeof dp
);
2051 evaluate_option_cache(&dp
, packet
, NULL
, NULL
,
2052 packet
->options
, NULL
,
2055 packet
->packet_type
= dp
.data
[0];
2057 packet
->packet_type
= 0;
2058 data_string_forget(&dp
, MDL
);
2062 if (validate_packet(packet
) != 0) {
2063 if (packet
->packet_type
)
2069 /* If the caller kept the packet, they'll have upped the refcnt. */
2070 packet_dereference(&packet
, MDL
);
2072 #endif /* DHCP4o6 */
2075 void dhcpoffer (packet
)
2076 struct packet
*packet
;
2078 struct interface_info
*ip
= packet
-> interface
;
2079 struct client_state
*client
;
2080 struct client_lease
*lease
, *lp
;
2081 struct option
**req
;
2084 const char *name
= packet
-> packet_type
? "DHCPOFFER" : "BOOTREPLY";
2089 dump_packet (packet
);
2092 /* Find a client state that matches the xid... */
2093 for (client
= ip
-> client
; client
; client
= client
-> next
)
2094 if (client
-> xid
== packet
-> raw
-> xid
)
2097 /* If we're not receptive to an offer right now, or if the offer
2098 has an unrecognizable transaction id, then just drop it. */
2100 client
-> state
!= S_SELECTING
||
2101 (packet
-> interface
-> hw_address
.hlen
- 1 !=
2102 packet
-> raw
-> hlen
) ||
2103 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
2104 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
2106 log_debug ("%s in wrong transaction.", name
);
2111 sprintf (obuf
, "%s of %s from %s", name
,
2112 inet_ntoa(packet
->raw
->yiaddr
),
2113 piaddr(packet
->client_addr
));
2115 /* If this lease doesn't supply the minimum required DHCPv4 parameters,
2118 req
= client
->config
->required_options
;
2120 for (i
= 0 ; req
[i
] != NULL
; i
++) {
2121 if ((req
[i
]->universe
== &dhcp_universe
) &&
2122 !lookup_option(&dhcp_universe
, packet
->options
,
2124 struct option
*option
= NULL
;
2125 unsigned code
= req
[i
]->code
;
2127 option_code_hash_lookup(&option
,
2128 dhcp_universe
.code_hash
,
2132 log_info("%s: no %s option.", obuf
,
2135 log_info("%s: no unknown-%u option.",
2138 option_dereference(&option
, MDL
);
2145 /* If we've already seen this lease, don't record it again. */
2146 for (lease
= client
-> offered_leases
; lease
; lease
= lease
-> next
) {
2147 if (lease
-> address
.len
== sizeof packet
-> raw
-> yiaddr
&&
2148 !memcmp (lease
-> address
.iabuf
,
2149 &packet
-> raw
-> yiaddr
, lease
-> address
.len
)) {
2150 log_debug ("%s: already seen.", obuf
);
2155 lease
= packet_to_lease (packet
, client
);
2157 log_info ("%s: packet_to_lease failed.", obuf
);
2161 /* log it now, so it emits before the request goes out */
2162 log_info("%s", obuf
);
2164 /* If this lease was acquired through a BOOTREPLY, record that
2166 if (!packet
-> options_valid
|| !packet
-> packet_type
)
2167 lease
-> is_bootp
= 1;
2169 /* Record the medium under which this lease was offered. */
2170 lease
-> medium
= client
-> medium
;
2172 /* Figure out when we're supposed to stop selecting. */
2173 stop_selecting
= (client
-> first_sending
+
2174 client
-> config
-> select_interval
);
2176 /* If this is the lease we asked for, put it at the head of the
2177 list, and don't mess with the arp request timeout. */
2178 if (lease
-> address
.len
== client
-> requested_address
.len
&&
2179 !memcmp (lease
-> address
.iabuf
,
2180 client
-> requested_address
.iabuf
,
2181 client
-> requested_address
.len
)) {
2182 lease
-> next
= client
-> offered_leases
;
2183 client
-> offered_leases
= lease
;
2185 /* Put the lease at the end of the list. */
2186 lease
-> next
= (struct client_lease
*)0;
2187 if (!client
-> offered_leases
)
2188 client
-> offered_leases
= lease
;
2190 for (lp
= client
-> offered_leases
; lp
-> next
;
2197 /* If the selecting interval has expired, go immediately to
2198 state_selecting(). Otherwise, time out into
2199 state_selecting at the select interval. */
2200 if (stop_selecting
<= cur_tv
.tv_sec
)
2201 state_selecting (client
);
2203 tv
.tv_sec
= stop_selecting
;
2204 tv
.tv_usec
= cur_tv
.tv_usec
;
2205 add_timeout(&tv
, state_selecting
, client
, 0, 0);
2206 cancel_timeout(send_discover
, client
);
2210 /* Allocate a client_lease structure and initialize it from the parameters
2211 in the specified packet. */
2213 struct client_lease
*packet_to_lease (packet
, client
)
2214 struct packet
*packet
;
2215 struct client_state
*client
;
2217 struct client_lease
*lease
;
2219 struct option_cache
*oc
;
2220 struct option
*option
= NULL
;
2221 struct data_string data
;
2223 lease
= (struct client_lease
*)new_client_lease (MDL
);
2226 log_error("packet_to_lease: no memory to record lease.\n");
2230 memset(lease
, 0, sizeof(*lease
));
2232 /* Copy the lease options. */
2233 option_state_reference(&lease
->options
, packet
->options
, MDL
);
2235 lease
->address
.len
= sizeof(packet
->raw
->yiaddr
);
2236 memcpy(lease
->address
.iabuf
, &packet
->raw
->yiaddr
,
2237 lease
->address
.len
);
2239 lease
->next_srv_addr
.len
= sizeof(packet
->raw
->siaddr
);
2240 memcpy(lease
->next_srv_addr
.iabuf
, &packet
->raw
->siaddr
,
2241 lease
->next_srv_addr
.len
);
2243 memset(&data
, 0, sizeof(data
));
2245 if (client
-> config
-> vendor_space_name
) {
2246 i
= DHO_VENDOR_ENCAPSULATED_OPTIONS
;
2248 /* See if there was a vendor encapsulation option. */
2249 oc
= lookup_option (&dhcp_universe
, lease
-> options
, i
);
2251 client
-> config
-> vendor_space_name
&&
2252 evaluate_option_cache (&data
, packet
,
2253 (struct lease
*)0, client
,
2254 packet
-> options
, lease
-> options
,
2255 &global_scope
, oc
, MDL
)) {
2257 if (!option_code_hash_lookup(&option
,
2258 dhcp_universe
.code_hash
,
2260 log_fatal("Unable to find VENDOR "
2261 "option (%s:%d).", MDL
);
2262 parse_encapsulated_suboptions
2263 (packet
-> options
, option
,
2264 data
.data
, data
.len
, &dhcp_universe
,
2265 client
-> config
-> vendor_space_name
2268 option_dereference(&option
, MDL
);
2270 data_string_forget (&data
, MDL
);
2275 /* Figure out the overload flag. */
2276 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
2277 DHO_DHCP_OPTION_OVERLOAD
);
2279 evaluate_option_cache (&data
, packet
, (struct lease
*)0, client
,
2280 packet
-> options
, lease
-> options
,
2281 &global_scope
, oc
, MDL
)) {
2286 data_string_forget (&data
, MDL
);
2290 /* If the server name was filled out, copy it. */
2291 if (!(i
& 2) && packet
-> raw
-> sname
[0]) {
2293 /* Don't count on the NUL terminator. */
2294 for (len
= 0; len
< DHCP_SNAME_LEN
; len
++)
2295 if (!packet
-> raw
-> sname
[len
])
2297 lease
-> server_name
= dmalloc (len
+ 1, MDL
);
2298 if (!lease
-> server_name
) {
2299 log_error ("dhcpoffer: no memory for server name.\n");
2300 destroy_client_lease (lease
);
2301 return (struct client_lease
*)0;
2303 memcpy (lease
-> server_name
,
2304 packet
-> raw
-> sname
, len
);
2305 lease
-> server_name
[len
] = 0;
2309 /* Ditto for the filename. */
2310 if (!(i
& 1) && packet
-> raw
-> file
[0]) {
2312 /* Don't count on the NUL terminator. */
2313 for (len
= 0; len
< DHCP_FILE_LEN
; len
++)
2314 if (!packet
-> raw
-> file
[len
])
2316 lease
-> filename
= dmalloc (len
+ 1, MDL
);
2317 if (!lease
-> filename
) {
2318 log_error ("dhcpoffer: no memory for filename.\n");
2319 destroy_client_lease (lease
);
2320 return (struct client_lease
*)0;
2322 memcpy (lease
-> filename
,
2323 packet
-> raw
-> file
, len
);
2324 lease
-> filename
[len
] = 0;
2328 execute_statements_in_scope(NULL
, (struct packet
*)packet
, NULL
,
2329 client
, lease
->options
, lease
->options
,
2330 &global_scope
, client
->config
->on_receipt
,
2336 void dhcpnak (packet
)
2337 struct packet
*packet
;
2339 struct interface_info
*ip
= packet
-> interface
;
2340 struct client_state
*client
;
2342 /* Find a client state that matches the xid... */
2343 for (client
= ip
-> client
; client
; client
= client
-> next
)
2344 if (client
-> xid
== packet
-> raw
-> xid
)
2347 /* If we're not receptive to an offer right now, or if the offer
2348 has an unrecognizable transaction id, then just drop it. */
2350 (packet
-> interface
-> hw_address
.hlen
- 1 !=
2351 packet
-> raw
-> hlen
) ||
2352 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
2353 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
2355 log_debug ("DHCPNAK in wrong transaction.");
2360 if (client
-> state
!= S_REBOOTING
&&
2361 client
-> state
!= S_REQUESTING
&&
2362 client
-> state
!= S_RENEWING
&&
2363 client
-> state
!= S_REBINDING
) {
2365 log_debug ("DHCPNAK in wrong state.");
2370 log_info ("DHCPNAK from %s", piaddr (packet
-> client_addr
));
2372 if (!client
-> active
) {
2374 log_info ("DHCPNAK with no active lease.\n");
2379 /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
2380 * to indicate that we want all old bindings to be removed. (It
2381 * is possible that we may get a NAK while in the RENEW state,
2382 * so we might have bindings active at that time)
2384 script_init(client
, "EXPIRE", NULL
);
2385 script_write_params(client
, "old_", client
->active
);
2386 script_write_requested(client
);
2388 script_write_params(client
, "alias_", client
->alias
);
2391 destroy_client_lease (client
-> active
);
2392 client
-> active
= (struct client_lease
*)0;
2394 /* Stop sending DHCPREQUEST packets... */
2395 cancel_timeout (send_request
, client
);
2397 /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
2398 * down (this expunges any routes and arp cache). This makes the
2399 * interface unusable by state_init(), which we call next. So, we
2400 * need to 'PREINIT' the interface to bring it back up.
2402 script_init(client
, "PREINIT", NULL
);
2404 script_write_params(client
, "alias_", client
->alias
);
2407 client
-> state
= S_INIT
;
2408 state_init (client
);
2411 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
2412 one after the right interval has expired. If we don't get an offer by
2413 the time we reach the panic interval, call the panic function. */
2415 void send_discover (cpp
)
2418 struct client_state
*client
= cpp
;
2425 /* Figure out how long it's been since we started transmitting. */
2426 interval
= cur_time
- client
-> first_sending
;
2428 /* If we're past the panic timeout, call the script and tell it
2429 we haven't found anything for this interface yet. */
2430 if (interval
> client
-> config
-> timeout
) {
2431 state_panic (client
);
2435 /* If we're selecting media, try the whole list before doing
2436 the exponential backoff, but if we've already received an
2437 offer, stop looping, because we obviously have it right. */
2438 if (!client
-> offered_leases
&&
2439 client
-> config
-> media
) {
2442 if (client
-> medium
) {
2443 client
-> medium
= client
-> medium
-> next
;
2446 if (!client
-> medium
) {
2448 log_fatal ("No valid media types for %s!",
2449 client
-> interface
-> name
);
2451 client
-> config
-> media
;
2455 log_info ("Trying medium \"%s\" %d",
2456 client
-> medium
-> string
, increase
);
2457 script_init(client
, "MEDIUM", client
-> medium
);
2458 if (script_go(client
)) {
2464 /* If we're supposed to increase the interval, do so. If it's
2465 currently zero (i.e., we haven't sent any packets yet), set
2466 it to initial_interval; otherwise, add to it a random number
2467 between zero and two times itself. On average, this means
2468 that it will double with every transmission. */
2470 if (!client
->interval
)
2471 client
->interval
= client
->config
->initial_interval
;
2473 client
->interval
+= random() % (2 * client
->interval
);
2475 /* Don't backoff past cutoff. */
2476 if (client
->interval
> client
->config
->backoff_cutoff
)
2477 client
->interval
= (client
->config
->backoff_cutoff
/ 2)
2478 + (random() % client
->config
->backoff_cutoff
);
2479 } else if (!client
->interval
)
2480 client
->interval
= client
->config
->initial_interval
;
2482 /* If the backoff would take us to the panic timeout, just use that
2484 if (cur_time
+ client
-> interval
>
2485 client
-> first_sending
+ client
-> config
-> timeout
)
2486 client
-> interval
=
2487 (client
-> first_sending
+
2488 client
-> config
-> timeout
) - cur_time
+ 1;
2490 /* Record the number of seconds since we started sending. */
2491 if (interval
< 65536)
2492 client
-> packet
.secs
= htons (interval
);
2494 client
-> packet
.secs
= htons (65535);
2495 client
-> secs
= client
-> packet
.secs
;
2497 #if defined(DHCPv6) && defined(DHCP4o6)
2498 if (dhcpv4_over_dhcpv6
) {
2499 log_info ("DHCPDISCOVER interval %ld",
2500 (long)(client
-> interval
));
2503 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
2504 client
-> name
? client
-> name
: client
-> interface
-> name
,
2505 inet_ntoa (sockaddr_broadcast
.sin_addr
),
2506 ntohs (sockaddr_broadcast
.sin_port
), (long)(client
-> interval
));
2508 /* Send out a packet. */
2509 #if defined(DHCPv6) && defined(DHCP4o6)
2510 if (dhcpv4_over_dhcpv6
) {
2511 result
= send_dhcpv4_query(client
, 1);
2514 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
2515 client
->packet_length
, inaddr_any
,
2516 &sockaddr_broadcast
, NULL
);
2518 #if defined(DHCPv6) && defined(DHCP4o6)
2519 if (dhcpv4_over_dhcpv6
) {
2520 log_error("%s:%d: Failed to send %d byte long packet.",
2521 MDL
, client
->packet_length
);
2524 log_error("%s:%d: Failed to send %d byte long packet over %s "
2525 "interface.", MDL
, client
->packet_length
,
2526 client
->interface
->name
);
2530 * If we used 0 microseconds here, and there were other clients on the
2531 * same network with a synchronized local clock (ntp), and a similar
2532 * zero-microsecond-scheduler behavior, then we could be participating
2533 * in a sub-second DOS ttck.
2535 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->interval
;
2536 tv
.tv_usec
= client
->interval
> 1 ? random() % 1000000 : cur_tv
.tv_usec
;
2537 add_timeout(&tv
, send_discover
, client
, 0, 0);
2542 * \brief Remove leases from a list of leases which duplicate a given lease
2544 * Searches through a linked-list of leases, remove the first one matches the
2545 * given lease's address and value of is_static. The latter test is done
2546 * so we only remove leases that are from the same source (i.e server/lease file
2547 * vs config file). This ensures we do not discard "fallback" config file leases
2548 * that happen to match non-config file leases.
2550 * \param lease_list list of leases to clean
2551 * \param lease lease for which duplicates should be removed
2553 void discard_duplicate (struct client_lease
** lease_list
, struct client_lease
* lease
) {
2554 struct client_lease
*cur
, *prev
, *next
;
2556 if (!lease_list
|| !lease
) {
2560 prev
= (struct client_lease
*)0;
2561 for (cur
= *lease_list
; cur
; cur
= next
) {
2563 if ((cur
->is_static
== lease
->is_static
) &&
2564 (cur
->address
.len
== lease
->address
.len
&&
2565 !memcmp (cur
->address
.iabuf
, lease
->address
.iabuf
,
2566 lease
->address
.len
))) {
2572 destroy_client_lease (cur
);
2581 * \brief Add a given lease to the end of list of leases
2583 * Searches through a linked-list of leases, removing any that match the
2584 * given lease's address and value of is_static. The latter test is done
2585 * so we only remove leases that are from the same source (i.e server/lease file
2586 * vs config file). This ensures we do not discard "fallback" config file leases
2587 * that happen to match non-config file leases.
2589 * \param lease_list list of leases to clean
2590 * \param lease lease for which duplicates should be removed
2592 void add_to_tail(struct client_lease
** lease_list
,
2593 struct client_lease
* lease
)
2595 if (!lease_list
|| !lease
) {
2599 /* If there is already a lease for this address and
2600 * is_static value, toss discard it. This ensures
2601 * we only keep one dynamic and/or one static lease
2602 * for a given address. */
2603 discard_duplicate(lease_list
, lease
);
2606 struct client_lease
* tail
;
2607 for (tail
= *lease_list
; tail
&& tail
->next
; tail
= tail
->next
){};
2609 /* Ensure the tail points nowhere. */
2612 /* Add to the tail. */
2614 *lease_list
= lease
;
2621 void dbg_print_lease(char *text
, struct client_lease
* lease
) {
2623 log_debug("%s, lease is null", text
);
2625 log_debug ("%s: %p addr:%s expires:%ld :is_static? %d",
2626 text
, lease
, piaddr (lease
->address
),
2627 (lease
->expiry
- cur_time
),
2633 /* state_panic gets called if we haven't received any offers in a preset
2634 amount of time. When this happens, we try to use existing leases that
2635 haven't yet expired, and failing that, we call the client script and
2636 hope it can do something. */
2638 void state_panic (cpp
)
2641 struct client_state
*client
= cpp
;
2642 struct client_lease
*loop
;
2643 struct client_lease
*lp
;
2646 loop
= lp
= client
-> active
;
2648 log_info ("No DHCPOFFERS received.");
2650 /* We may not have an active lease, but we may have some
2651 predefined leases that we can try. */
2652 if (!client
-> active
&& client
-> leases
)
2655 /* Run through the list of leases and see if one can be used. */
2656 while (client
-> active
) {
2657 if (client
-> active
-> expiry
> cur_time
) {
2658 log_info ("Trying %s lease %s",
2659 (client
-> active
-> is_static
2660 ? "fallback" : "recorded"),
2661 piaddr (client
-> active
-> address
));
2662 /* Run the client script with the existing
2664 script_init(client
, "TIMEOUT",
2665 client
-> active
-> medium
);
2666 script_write_params(client
, "new_", client
-> active
);
2667 script_write_requested(client
);
2668 if (client
-> alias
)
2669 script_write_params(client
, "alias_",
2672 /* If the old lease is still good and doesn't
2673 yet need renewal, go into BOUND state and
2674 timeout at the renewal time. */
2675 if (!script_go(client
)) {
2676 if (cur_time
< client
-> active
-> renewal
) {
2677 client
-> state
= S_BOUND
;
2678 log_info ("bound: renewal in %ld %s.",
2679 (long)(client
-> active
-> renewal
-
2680 cur_time
), "seconds");
2681 tv
.tv_sec
= client
->active
->renewal
;
2682 tv
.tv_usec
= ((client
->active
->renewal
-
2684 random() % 1000000 :
2686 add_timeout(&tv
, state_bound
, client
, 0, 0);
2688 client
-> state
= S_BOUND
;
2689 log_info ("bound: immediate renewal.");
2690 state_bound (client
);
2692 reinitialize_interfaces ();
2698 /* If there are no other leases, give up. */
2699 if (!client
-> leases
) {
2700 client
-> leases
= client
-> active
;
2701 client
-> active
= (struct client_lease
*)0;
2706 /* Otherwise, put the active lease at the end of the
2707 lease list, and try another lease.. */
2708 add_to_tail(&client
->leases
, client
->active
);
2710 client
-> active
= client
-> leases
;
2711 client
-> leases
= client
-> leases
-> next
;
2713 /* If we already tried this lease, we've exhausted the
2714 set of leases, so we might as well give up for
2716 if (client
-> active
== loop
)
2719 loop
= client
-> active
;
2722 /* No leases were available, or what was available didn't work, so
2723 tell the shell script that we failed to allocate an address,
2724 and try again later. */
2727 log_info ("Unable to obtain a lease on first try.%s",
2731 #if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
2732 /* Let's call a script and we're done */
2733 script_init(client
, "FAIL", (struct string_list
*)0);
2739 log_info ("No working leases in persistent database - sleeping.");
2740 script_init(client
, "FAIL", (struct string_list
*)0);
2741 if (client
-> alias
)
2742 script_write_params(client
, "alias_", client
-> alias
);
2744 client
-> state
= S_INIT
;
2745 tv
.tv_sec
= cur_tv
.tv_sec
+ ((client
->config
->retry_interval
+ 1) / 2 +
2746 (random() % client
->config
->retry_interval
));
2747 tv
.tv_usec
= ((tv
.tv_sec
- cur_tv
.tv_sec
) > 1) ?
2748 random() % 1000000 : cur_tv
.tv_usec
;
2749 add_timeout(&tv
, state_init
, client
, 0, 0);
2753 void send_request (cpp
)
2756 struct client_state
*client
= cpp
;
2760 struct sockaddr_in destination
;
2761 struct in_addr from
;
2764 const char* rip_str
= "";
2766 /* Figure out how long it's been since we started transmitting. */
2767 interval
= cur_time
- client
-> first_sending
;
2769 /* If we're in the INIT-REBOOT or REQUESTING state and we're
2770 past the reboot timeout, go to INIT and see if we can
2771 DISCOVER an address... */
2772 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
2773 means either that we're on a network with no DHCP server,
2774 or that our server is down. In the latter case, assuming
2775 that there is a backup DHCP server, DHCPDISCOVER will get
2776 us a new address, but we could also have successfully
2777 reused our old address. In the former case, we're hosed
2778 anyway. This is not a win-prone situation. */
2779 if ((client
-> state
== S_REBOOTING
||
2780 client
-> state
== S_REQUESTING
) &&
2781 interval
> client
-> config
-> reboot_timeout
) {
2783 client
-> state
= S_INIT
;
2784 cancel_timeout (send_request
, client
);
2785 state_init (client
);
2789 /* If we're in the reboot state, make sure the media is set up
2791 if (client
-> state
== S_REBOOTING
&&
2792 !client
-> medium
&&
2793 client
-> active
-> medium
) {
2794 script_init(client
, "MEDIUM", client
-> active
-> medium
);
2796 /* If the medium we chose won't fly, go to INIT state. */
2797 if (script_go(client
))
2800 /* Record the medium. */
2801 client
-> medium
= client
-> active
-> medium
;
2804 /* If the lease has expired, relinquish the address and go back
2805 to the INIT state. */
2806 if (client
-> state
!= S_REQUESTING
&&
2807 cur_time
> client
-> active
-> expiry
) {
2808 /* Run the client script with the new parameters. */
2809 script_init(client
, "EXPIRE", (struct string_list
*)0);
2810 script_write_params(client
, "old_", client
-> active
);
2811 script_write_requested(client
);
2812 if (client
-> alias
)
2813 script_write_params(client
, "alias_",
2817 /* Now do a preinit on the interface so that we can
2818 discover a new address. */
2819 script_init(client
, "PREINIT", (struct string_list
*)0);
2820 if (client
-> alias
)
2821 script_write_params(client
, "alias_",
2825 client
-> state
= S_INIT
;
2826 state_init (client
);
2830 /* Do the exponential backoff... */
2831 if (!client
-> interval
)
2832 client
-> interval
= client
-> config
-> initial_interval
;
2834 client
-> interval
+= ((random () >> 2) %
2835 (2 * client
-> interval
));
2838 /* Don't backoff past cutoff. */
2839 if (client
-> interval
>
2840 client
-> config
-> backoff_cutoff
)
2841 client
-> interval
=
2842 ((client
-> config
-> backoff_cutoff
/ 2)
2843 + ((random () >> 2) %
2844 client
-> config
-> backoff_cutoff
));
2846 /* If the backoff would take us to the expiry time, just set the
2847 timeout to the expiry time. */
2848 if (client
-> state
!= S_REQUESTING
&&
2849 cur_time
+ client
-> interval
> client
-> active
-> expiry
)
2850 client
-> interval
=
2851 client
-> active
-> expiry
- cur_time
+ 1;
2853 /* If the lease T2 time has elapsed, or if we're not yet bound,
2854 broadcast the DHCPREQUEST rather than unicasting. */
2855 if (client
-> state
== S_REQUESTING
||
2856 client
-> state
== S_REBOOTING
||
2857 cur_time
> client
-> active
-> rebind
)
2858 destination
.sin_addr
= sockaddr_broadcast
.sin_addr
;
2860 memcpy (&destination
.sin_addr
.s_addr
,
2861 client
-> destination
.iabuf
,
2862 sizeof destination
.sin_addr
.s_addr
);
2863 destination
.sin_port
= remote_port
;
2864 destination
.sin_family
= AF_INET
;
2866 destination
.sin_len
= sizeof destination
;
2869 if (client
-> state
== S_RENEWING
||
2870 client
-> state
== S_REBINDING
)
2871 memcpy (&from
, client
-> active
-> address
.iabuf
,
2874 from
.s_addr
= INADDR_ANY
;
2876 /* Record the number of seconds since we started sending. */
2877 if (client
-> state
== S_REQUESTING
)
2878 client
-> packet
.secs
= client
-> secs
;
2880 if (interval
< 65536)
2881 client
-> packet
.secs
= htons (interval
);
2883 client
-> packet
.secs
= htons (65535);
2886 #if defined(DHCPv6) && defined(DHCP4o6)
2887 if (dhcpv4_over_dhcpv6
) {
2888 log_info ("DHCPREQUEST");
2891 memset(rip_buf
, 0x0, sizeof(rip_buf
));
2892 if (client
->state
== S_BOUND
|| client
->state
== S_RENEWING
||
2893 client
->state
== S_REBINDING
) {
2894 rip_str
= inet_ntoa(client
->packet
.ciaddr
);
2896 rip_str
= piaddr(client
->requested_address
);
2899 strncpy(rip_buf
, rip_str
, sizeof(rip_buf
)-1);
2900 log_info ("DHCPREQUEST for %s on %s to %s port %d", rip_buf
,
2901 client
->name
? client
->name
: client
->interface
->name
,
2902 inet_ntoa(destination
.sin_addr
),
2903 ntohs (destination
.sin_port
));
2905 #if defined(DHCPv6) && defined(DHCP4o6)
2906 if (dhcpv4_over_dhcpv6
) {
2908 if (destination
.sin_addr
.s_addr
== INADDR_BROADCAST
)
2910 result
= send_dhcpv4_query(client
, broadcast
);
2912 log_error("%s:%d: Failed to send %d byte long packet.",
2913 MDL
, client
->packet_length
);
2917 if (destination
.sin_addr
.s_addr
!= INADDR_BROADCAST
&&
2918 fallback_interface
) {
2919 result
= send_packet(fallback_interface
, NULL
, &client
->packet
,
2920 client
->packet_length
, from
, &destination
,
2923 log_error("%s:%d: Failed to send %d byte long packet "
2924 "over %s interface.", MDL
,
2925 client
->packet_length
,
2926 fallback_interface
->name
);
2930 /* Send out a packet. */
2931 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
2932 client
->packet_length
, from
, &destination
,
2935 log_error("%s:%d: Failed to send %d byte long packet"
2936 " over %s interface.", MDL
,
2937 client
->packet_length
,
2938 client
->interface
->name
);
2942 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->interval
;
2943 tv
.tv_usec
= ((tv
.tv_sec
- cur_tv
.tv_sec
) > 1) ?
2944 random() % 1000000 : cur_tv
.tv_usec
;
2945 add_timeout(&tv
, send_request
, client
, 0, 0);
2948 void send_decline (cpp
)
2951 struct client_state
*client
= cpp
;
2955 #if defined(DHCPv6) && defined(DHCP4o6)
2956 if (dhcpv4_over_dhcpv6
) {
2957 log_info ("DHCPDECLINE");
2960 log_info ("DHCPDECLINE of %s on %s to %s port %d",
2961 piaddr(client
->requested_address
),
2962 (client
->name
? client
->name
: client
->interface
->name
),
2963 inet_ntoa(sockaddr_broadcast
.sin_addr
),
2964 ntohs(sockaddr_broadcast
.sin_port
));
2966 /* Send out a packet. */
2967 #if defined(DHCPv6) && defined(DHCP4o6)
2968 if (dhcpv4_over_dhcpv6
) {
2969 result
= send_dhcpv4_query(client
, 1);
2972 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
2973 client
->packet_length
, inaddr_any
,
2974 &sockaddr_broadcast
, NULL
);
2976 #if defined(DHCPv6) && defined(DHCP4o6)
2977 if (dhcpv4_over_dhcpv6
) {
2978 log_error("%s:%d: Failed to send %d byte long packet.",
2979 MDL
, client
->packet_length
);
2982 log_error("%s:%d: Failed to send %d byte long packet over %s"
2983 " interface.", MDL
, client
->packet_length
,
2984 client
->interface
->name
);
2988 void send_release (cpp
)
2991 struct client_state
*client
= cpp
;
2994 struct sockaddr_in destination
;
2995 struct in_addr from
;
2997 memcpy (&from
, client
-> active
-> address
.iabuf
,
2999 memcpy (&destination
.sin_addr
.s_addr
,
3000 client
-> destination
.iabuf
,
3001 sizeof destination
.sin_addr
.s_addr
);
3002 destination
.sin_port
= remote_port
;
3003 destination
.sin_family
= AF_INET
;
3005 destination
.sin_len
= sizeof destination
;
3008 /* Set the lease to end now, so that we don't accidentally
3009 reuse it if we restart before the old expiry time. */
3010 client
-> active
-> expiry
=
3011 client
-> active
-> renewal
=
3012 client
-> active
-> rebind
= cur_time
;
3013 if (!write_client_lease (client
, client
-> active
, 1, 1)) {
3014 log_error ("Can't release lease: lease write failed.");
3018 #if defined(DHCPv6) && defined(DHCP4o6)
3019 if (dhcpv4_over_dhcpv6
) {
3020 log_info ("DHCPRELEASE");
3023 log_info ("DHCPRELEASE of %s on %s to %s port %d",
3024 piaddr(client
->active
->address
),
3025 client
->name
? client
->name
: client
->interface
->name
,
3026 inet_ntoa (destination
.sin_addr
),
3027 ntohs (destination
.sin_port
));
3029 #if defined(DHCPv6) && defined(DHCP4o6)
3030 if (dhcpv4_over_dhcpv6
) {
3032 if (destination
.sin_addr
.s_addr
== INADDR_BROADCAST
)
3034 result
= send_dhcpv4_query(client
, broadcast
);
3036 log_error("%s:%d: Failed to send %d byte long packet.",
3037 MDL
, client
->packet_length
);
3041 if (fallback_interface
) {
3042 result
= send_packet(fallback_interface
, NULL
, &client
->packet
,
3043 client
->packet_length
, from
, &destination
,
3046 log_error("%s:%d: Failed to send %d byte long packet"
3047 " over %s interface.", MDL
,
3048 client
->packet_length
,
3049 fallback_interface
->name
);
3052 /* Send out a packet. */
3053 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
3054 client
->packet_length
, from
, &destination
,
3057 log_error ("%s:%d: Failed to send %d byte long packet"
3058 " over %s interface.", MDL
,
3059 client
->packet_length
,
3060 client
->interface
->name
);
3066 #if defined(DHCPv6) && defined(DHCP4o6)
3068 * \brief Send a DHCPv4-query to the DHCPv6 client
3069 * (DHCPv4 client function)
3071 * The DHCPv4 client sends a DHCPv4-query to the DHCPv6 client over
3072 * the inter-process communication socket.
3074 * \param client the DHCPv4 client state
3075 * \param broadcast the broadcast flag
3076 * \return the sent byte count (-1 on error)
3078 static int send_dhcpv4_query(struct client_state
*client
, int broadcast
) {
3079 struct data_string ds
;
3080 struct dhcpv4_over_dhcpv6_packet
*query
;
3083 if (dhcp4o6_state
<= 0) {
3084 log_info("send_dhcpv4_query: not ready.");
3089 * Compute buffer length and allocate it.
3091 len
= ofs
= (int)(offsetof(struct dhcpv4_over_dhcpv6_packet
, options
));
3092 len
+= dhcpv6_universe
.tag_size
+ dhcpv6_universe
.length_size
;
3093 len
+= client
->packet_length
;
3094 memset(&ds
, 0, sizeof(ds
));
3095 if (!buffer_allocate(&ds
.buffer
, len
, MDL
)) {
3096 log_error("Unable to allocate memory for DHCPv4-query.");
3099 ds
.data
= ds
.buffer
->data
;
3105 query
= (struct dhcpv4_over_dhcpv6_packet
*)ds
.data
;
3106 query
->msg_type
= DHCPV6_DHCPV4_QUERY
;
3107 query
->flags
[0] = query
->flags
[1] = query
->flags
[2] = 0;
3109 query
->flags
[0] |= DHCP4O6_QUERY_UNICAST
;
3112 * Append DHCPv4 message.
3114 dhcpv6_universe
.store_tag(ds
.buffer
->data
+ ofs
, D6O_DHCPV4_MSG
);
3115 ofs
+= dhcpv6_universe
.tag_size
;
3116 dhcpv6_universe
.store_length(ds
.buffer
->data
+ ofs
,
3117 client
->packet_length
);
3118 ofs
+= dhcpv6_universe
.length_size
;
3119 memcpy(ds
.buffer
->data
+ ofs
, &client
->packet
, client
->packet_length
);
3122 * Send DHCPv6 message.
3124 cc
= send(dhcp4o6_fd
, ds
.data
, ds
.len
, 0);
3126 log_error("send_dhcpv4_query: send(): %m");
3128 data_string_forget(&ds
, MDL
);
3134 * \brief Forward a DHCPv4-query to all DHCPv4 over DHCPv6 server addresses.
3135 * (DHCPv6 client function)
3137 * \param raw the DHCPv6 DHCPv4-query message raw content
3139 static void forw_dhcpv4_query(struct data_string
*raw
) {
3140 struct interface_info
*ip
;
3141 struct client_state
*client
;
3142 struct dhc6_lease
*lease
;
3143 struct option_cache
*oc
;
3144 struct data_string addrs
;
3145 struct sockaddr_in6 sin6
;
3146 int i
, send_ret
, attempt
, success
;
3148 attempt
= success
= 0;
3149 memset(&sin6
, 0, sizeof(sin6
));
3150 sin6
.sin6_family
= AF_INET6
;
3151 sin6
.sin6_port
= remote_port
;
3153 sin6
.sin6_len
= sizeof(sin6
);
3155 memset(&addrs
, 0, sizeof(addrs
));
3156 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
3157 for (client
= ip
->client
; client
!= NULL
;
3158 client
= client
->next
) {
3159 if ((client
->state
!= S_BOUND
) &&
3160 (client
->state
!= S_RENEWING
) &&
3161 (client
->state
!= S_REBINDING
))
3163 lease
= client
->active_lease
;
3164 if ((lease
== NULL
) || lease
->released
)
3166 oc
= lookup_option(&dhcpv6_universe
,
3168 D6O_DHCP4_O_DHCP6_SERVER
);
3170 !evaluate_option_cache(&addrs
, NULL
, NULL
, NULL
,
3171 lease
->options
, NULL
,
3172 &global_scope
, oc
, MDL
) ||
3173 ((addrs
.len
% sizeof(sin6
.sin6_addr
)) != 0)) {
3174 data_string_forget(&addrs
, MDL
);
3177 if (addrs
.len
== 0) {
3178 /* note there is nothing to forget */
3180 All_DHCP_Relay_Agents_and_Servers
,
3183 send_ret
= send_packet6(ip
, raw
->data
,
3185 if (send_ret
== raw
->len
)
3189 for (i
= 0; i
< addrs
.len
;
3190 i
+= sizeof(sin6
.sin6_addr
)) {
3191 memcpy(&sin6
.sin6_addr
, addrs
.data
+ i
,
3192 sizeof(sin6
.sin6_addr
));
3194 send_ret
= send_packet6(ip
, raw
->data
,
3196 if (send_ret
== raw
->len
)
3199 data_string_forget(&addrs
, MDL
);
3203 log_info("forw_dhcpv4_query: sent(%d): %d/%d",
3204 raw
->len
, success
, attempt
);
3212 make_client_options(struct client_state
*client
, struct client_lease
*lease
,
3213 u_int8_t
*type
, struct option_cache
*sid
,
3214 struct iaddr
*rip
, struct option
**prl
,
3215 struct option_state
**op
)
3218 struct option_cache
*oc
;
3219 struct option
*option
= NULL
;
3220 struct buffer
*bp
= NULL
;
3222 /* If there are any leftover options, get rid of them. */
3224 option_state_dereference(op
, MDL
);
3226 /* Allocate space for options. */
3227 option_state_allocate(op
, MDL
);
3229 /* Send the server identifier if provided. */
3231 save_option(&dhcp_universe
, *op
, sid
);
3235 /* Send the requested address if provided. */
3237 client
->requested_address
= *rip
;
3238 i
= DHO_DHCP_REQUESTED_ADDRESS
;
3239 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
3241 make_const_option_cache(&oc
, NULL
, rip
->iabuf
, rip
->len
,
3243 log_error ("can't make requested address cache.");
3245 save_option(&dhcp_universe
, *op
, oc
);
3246 option_cache_dereference(&oc
, MDL
);
3248 option_dereference(&option
, MDL
);
3250 client
->requested_address
.len
= 0;
3253 i
= DHO_DHCP_MESSAGE_TYPE
;
3254 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
, &i
, 0,
3256 make_const_option_cache(&oc
, NULL
, type
, 1, option
, MDL
)))
3257 log_error("can't make message type.");
3259 save_option(&dhcp_universe
, *op
, oc
);
3260 option_cache_dereference(&oc
, MDL
);
3262 option_dereference(&option
, MDL
);
3267 /* Probe the length of the list. */
3269 for (i
= 0 ; prl
[i
] != NULL
; i
++)
3270 if (prl
[i
]->universe
== &dhcp_universe
)
3273 if (!buffer_allocate(&bp
, len
, MDL
))
3274 log_error("can't make parameter list buffer.");
3276 unsigned code
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
3279 for (i
= 0 ; prl
[i
] != NULL
; i
++)
3280 if (prl
[i
]->universe
== &dhcp_universe
)
3281 bp
->data
[len
++] = prl
[i
]->code
;
3283 if (!(option_code_hash_lookup(&option
,
3284 dhcp_universe
.code_hash
,
3286 make_const_option_cache(&oc
, &bp
, NULL
, len
,
3289 buffer_dereference(&bp
, MDL
);
3290 log_error ("can't make option cache");
3292 save_option(&dhcp_universe
, *op
, oc
);
3293 option_cache_dereference(&oc
, MDL
);
3295 option_dereference(&option
, MDL
);
3300 * If requested (duid_v4 == 1) add an RFC4361 compliant client-identifier
3301 * This can be overridden by including a client id in the configuration
3305 struct data_string client_identifier
;
3308 memset(&client_identifier
, 0, sizeof(client_identifier
));
3309 client_identifier
.len
= 1 + 4 + default_duid
.len
;
3310 if (!buffer_allocate(&client_identifier
.buffer
,
3311 client_identifier
.len
, MDL
))
3312 log_fatal("no memory for default DUID!");
3313 client_identifier
.data
= client_identifier
.buffer
->data
;
3315 i
= DHO_DHCP_CLIENT_IDENTIFIER
;
3317 /* Client-identifier type : 1 byte */
3318 *client_identifier
.buffer
->data
= 255;
3321 * we use the low 4 bytes from the interface address
3323 if (client
->interface
->hw_address
.hlen
> 4) {
3324 hw_idx
= client
->interface
->hw_address
.hlen
- 4;
3328 hw_len
= client
->interface
->hw_address
.hlen
;
3330 memcpy(&client_identifier
.buffer
->data
+ 5 - hw_len
,
3331 client
->interface
->hw_address
.hbuf
+ hw_idx
,
3334 /* Add the default duid */
3335 memcpy(&client_identifier
.buffer
->data
+(1+4),
3336 default_duid
.data
, default_duid
.len
);
3338 /* And save the option */
3339 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
3341 make_const_option_cache(&oc
, NULL
,
3342 (u_int8_t
*)client_identifier
.data
,
3343 client_identifier
.len
,
3345 log_error ("can't make requested client id cache..");
3347 save_option (&dhcp_universe
, *op
, oc
);
3348 option_cache_dereference (&oc
, MDL
);
3350 option_dereference(&option
, MDL
);
3353 /* Run statements that need to be run on transmission. */
3354 if (client
->config
->on_transmission
)
3355 execute_statements_in_scope(NULL
, NULL
, NULL
, client
,
3356 (lease
? lease
->options
: NULL
),
3358 client
->config
->on_transmission
,
3362 void make_discover (client
, lease
)
3363 struct client_state
*client
;
3364 struct client_lease
*lease
;
3366 unsigned char discover
= DHCPDISCOVER
;
3367 struct option_state
*options
= (struct option_state
*)0;
3369 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3371 make_client_options (client
,
3372 lease
, &discover
, (struct option_cache
*)0,
3373 lease
? &lease
-> address
: (struct iaddr
*)0,
3374 client
-> config
-> requested_options
,
3377 /* Set up the option buffer... */
3378 client
-> packet_length
=
3379 cons_options ((struct packet
*)0, &client
-> packet
,
3380 (struct lease
*)0, client
,
3381 /* maximum packet size */1500,
3382 (struct option_state
*)0,
3384 /* scope */ &global_scope
,
3388 (struct data_string
*)0,
3389 client
-> config
-> vendor_space_name
);
3391 option_state_dereference (&options
, MDL
);
3392 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3393 client
-> packet_length
= BOOTP_MIN_LEN
;
3395 client
-> packet
.op
= BOOTREQUEST
;
3396 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3397 /* Assumes hw_address is known, otherwise a random value may result */
3398 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3399 client
-> packet
.hops
= 0;
3400 client
-> packet
.xid
= random ();
3401 client
-> packet
.secs
= 0; /* filled in by send_discover. */
3403 if (can_receive_unicast_unconfigured (client
-> interface
))
3404 client
-> packet
.flags
= 0;
3406 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3408 memset (&(client
-> packet
.ciaddr
),
3409 0, sizeof client
-> packet
.ciaddr
);
3410 memset (&(client
-> packet
.yiaddr
),
3411 0, sizeof client
-> packet
.yiaddr
);
3412 memset (&(client
-> packet
.siaddr
),
3413 0, sizeof client
-> packet
.siaddr
);
3414 client
-> packet
.giaddr
= giaddr
;
3415 if (client
-> interface
-> hw_address
.hlen
> 0)
3416 memcpy (client
-> packet
.chaddr
,
3417 &client
-> interface
-> hw_address
.hbuf
[1],
3418 (unsigned)(client
-> interface
-> hw_address
.hlen
- 1));
3421 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3426 void make_request (client
, lease
)
3427 struct client_state
*client
;
3428 struct client_lease
*lease
;
3430 unsigned char request
= DHCPREQUEST
;
3431 struct option_cache
*oc
;
3433 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3435 if (client
-> state
== S_REQUESTING
)
3436 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3437 DHO_DHCP_SERVER_IDENTIFIER
);
3439 oc
= (struct option_cache
*)0;
3441 if (client
-> sent_options
)
3442 option_state_dereference (&client
-> sent_options
, MDL
);
3444 make_client_options (client
, lease
, &request
, oc
,
3445 ((client
-> state
== S_REQUESTING
||
3446 client
-> state
== S_REBOOTING
)
3448 : (struct iaddr
*)0),
3449 client
-> config
-> requested_options
,
3450 &client
-> sent_options
);
3452 /* Set up the option buffer... */
3453 client
-> packet_length
=
3454 cons_options ((struct packet
*)0, &client
-> packet
,
3455 (struct lease
*)0, client
,
3456 /* maximum packet size */1500,
3457 (struct option_state
*)0,
3458 client
-> sent_options
,
3459 /* scope */ &global_scope
,
3463 (struct data_string
*)0,
3464 client
-> config
-> vendor_space_name
);
3466 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3467 client
-> packet_length
= BOOTP_MIN_LEN
;
3469 client
-> packet
.op
= BOOTREQUEST
;
3470 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3471 /* Assumes hw_address is known, otherwise a random value may result */
3472 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3473 client
-> packet
.hops
= 0;
3474 client
-> packet
.xid
= client
-> xid
;
3475 client
-> packet
.secs
= 0; /* Filled in by send_request. */
3477 /* If we own the address we're requesting, put it in ciaddr;
3478 otherwise set ciaddr to zero. */
3479 if (client
-> state
== S_BOUND
||
3480 client
-> state
== S_RENEWING
||
3481 client
-> state
== S_REBINDING
) {
3482 memcpy (&client
-> packet
.ciaddr
,
3483 lease
-> address
.iabuf
, lease
-> address
.len
);
3484 client
-> packet
.flags
= 0;
3486 memset (&client
-> packet
.ciaddr
, 0,
3487 sizeof client
-> packet
.ciaddr
);
3488 if (can_receive_unicast_unconfigured (client
-> interface
))
3489 client
-> packet
.flags
= 0;
3491 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3494 memset (&client
-> packet
.yiaddr
, 0,
3495 sizeof client
-> packet
.yiaddr
);
3496 memset (&client
-> packet
.siaddr
, 0,
3497 sizeof client
-> packet
.siaddr
);
3498 if (client
-> state
!= S_BOUND
&&
3499 client
-> state
!= S_RENEWING
)
3500 client
-> packet
.giaddr
= giaddr
;
3502 memset (&client
-> packet
.giaddr
, 0,
3503 sizeof client
-> packet
.giaddr
);
3504 if (client
-> interface
-> hw_address
.hlen
> 0)
3505 memcpy (client
-> packet
.chaddr
,
3506 &client
-> interface
-> hw_address
.hbuf
[1],
3507 (unsigned)(client
-> interface
-> hw_address
.hlen
- 1));
3510 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3514 void make_decline (client
, lease
)
3515 struct client_state
*client
;
3516 struct client_lease
*lease
;
3518 unsigned char decline
= DHCPDECLINE
;
3519 struct option_cache
*oc
;
3521 struct option_state
*options
= (struct option_state
*)0;
3523 /* Create the options cache. */
3524 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3525 DHO_DHCP_SERVER_IDENTIFIER
);
3526 make_client_options(client
, lease
, &decline
, oc
, &lease
->address
,
3529 /* Consume the options cache into the option buffer. */
3530 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3531 client
-> packet_length
=
3532 cons_options ((struct packet
*)0, &client
-> packet
,
3533 (struct lease
*)0, client
, 0,
3534 (struct option_state
*)0, options
,
3535 &global_scope
, 0, 0, 0, (struct data_string
*)0,
3536 client
-> config
-> vendor_space_name
);
3538 /* Destroy the options cache. */
3539 option_state_dereference (&options
, MDL
);
3541 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3542 client
-> packet_length
= BOOTP_MIN_LEN
;
3544 client
-> packet
.op
= BOOTREQUEST
;
3545 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3546 /* Assumes hw_address is known, otherwise a random value may result */
3547 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3548 client
-> packet
.hops
= 0;
3549 client
-> packet
.xid
= client
-> xid
;
3550 client
-> packet
.secs
= 0; /* Filled in by send_request. */
3551 if (can_receive_unicast_unconfigured (client
-> interface
))
3552 client
-> packet
.flags
= 0;
3554 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3556 /* ciaddr must always be zero. */
3557 memset (&client
-> packet
.ciaddr
, 0,
3558 sizeof client
-> packet
.ciaddr
);
3559 memset (&client
-> packet
.yiaddr
, 0,
3560 sizeof client
-> packet
.yiaddr
);
3561 memset (&client
-> packet
.siaddr
, 0,
3562 sizeof client
-> packet
.siaddr
);
3563 client
-> packet
.giaddr
= giaddr
;
3564 memcpy (client
-> packet
.chaddr
,
3565 &client
-> interface
-> hw_address
.hbuf
[1],
3566 client
-> interface
-> hw_address
.hlen
);
3569 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3573 void make_release (client
, lease
)
3574 struct client_state
*client
;
3575 struct client_lease
*lease
;
3577 unsigned char request
= DHCPRELEASE
;
3578 struct option_cache
*oc
;
3580 struct option_state
*options
= (struct option_state
*)0;
3582 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3584 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3585 DHO_DHCP_SERVER_IDENTIFIER
);
3586 make_client_options(client
, lease
, &request
, oc
, NULL
, NULL
, &options
);
3588 /* Set up the option buffer... */
3589 client
-> packet_length
=
3590 cons_options ((struct packet
*)0, &client
-> packet
,
3591 (struct lease
*)0, client
,
3592 /* maximum packet size */1500,
3593 (struct option_state
*)0,
3595 /* scope */ &global_scope
,
3599 (struct data_string
*)0,
3600 client
-> config
-> vendor_space_name
);
3602 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3603 client
-> packet_length
= BOOTP_MIN_LEN
;
3604 option_state_dereference (&options
, MDL
);
3606 client
-> packet
.op
= BOOTREQUEST
;
3607 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3608 /* Assumes hw_address is known, otherwise a random value may result */
3609 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3610 client
-> packet
.hops
= 0;
3611 client
-> packet
.xid
= random ();
3612 client
-> packet
.secs
= 0;
3613 client
-> packet
.flags
= 0;
3614 memcpy (&client
-> packet
.ciaddr
,
3615 lease
-> address
.iabuf
, lease
-> address
.len
);
3616 memset (&client
-> packet
.yiaddr
, 0,
3617 sizeof client
-> packet
.yiaddr
);
3618 memset (&client
-> packet
.siaddr
, 0,
3619 sizeof client
-> packet
.siaddr
);
3620 client
-> packet
.giaddr
= giaddr
;
3621 memcpy (client
-> packet
.chaddr
,
3622 &client
-> interface
-> hw_address
.hbuf
[1],
3623 client
-> interface
-> hw_address
.hlen
);
3626 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3630 void destroy_client_lease (lease
)
3631 struct client_lease
*lease
;
3633 if (lease
-> server_name
)
3634 dfree (lease
-> server_name
, MDL
);
3635 if (lease
-> filename
)
3636 dfree (lease
-> filename
, MDL
);
3637 option_state_dereference (&lease
-> options
, MDL
);
3638 free_client_lease (lease
, MDL
);
3641 FILE *leaseFile
= NULL
;
3642 int leases_written
= 0;
3644 void rewrite_client_leases ()
3646 struct interface_info
*ip
;
3647 struct client_state
*client
;
3648 struct client_lease
*lp
;
3650 if (leaseFile
!= NULL
)
3652 leaseFile
= fopen (path_dhclient_db
, "w");
3653 if (leaseFile
== NULL
) {
3654 log_error ("can't create %s: %m", path_dhclient_db
);
3658 /* If there is a default duid, write it out. */
3659 if (default_duid
.len
!= 0)
3660 write_duid(&default_duid
);
3662 /* Write out all the leases attached to configured interfaces that
3664 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
3665 for (client
= ip
-> client
; client
; client
= client
-> next
) {
3666 for (lp
= client
-> leases
; lp
; lp
= lp
-> next
) {
3667 write_client_lease (client
, lp
, 1, 0);
3669 if (client
-> active
)
3670 write_client_lease (client
,
3671 client
-> active
, 1, 0);
3673 if (client
->active_lease
!= NULL
)
3674 write_client6_lease(client
,
3675 client
->active_lease
,
3678 /* Reset last_write after rewrites. */
3679 client
->last_write
= 0;
3683 /* Write out any leases that are attached to interfaces that aren't
3684 currently configured. */
3685 for (ip
= dummy_interfaces
; ip
; ip
= ip
-> next
) {
3686 for (client
= ip
-> client
; client
; client
= client
-> next
) {
3687 for (lp
= client
-> leases
; lp
; lp
= lp
-> next
) {
3688 write_client_lease (client
, lp
, 1, 0);
3690 if (client
-> active
)
3691 write_client_lease (client
,
3692 client
-> active
, 1, 0);
3694 if (client
->active_lease
!= NULL
)
3695 write_client6_lease(client
,
3696 client
->active_lease
,
3699 /* Reset last_write after rewrites. */
3700 client
->last_write
= 0;
3706 void write_lease_option (struct option_cache
*oc
,
3707 struct packet
*packet
, struct lease
*lease
,
3708 struct client_state
*client_state
,
3709 struct option_state
*in_options
,
3710 struct option_state
*cfg_options
,
3711 struct binding_scope
**scope
,
3712 struct universe
*u
, void *stuff
)
3714 const char *name
, *dot
;
3715 struct data_string ds
;
3716 char *preamble
= stuff
;
3718 memset (&ds
, 0, sizeof ds
);
3720 if (u
!= &dhcp_universe
) {
3727 if (evaluate_option_cache (&ds
, packet
, lease
, client_state
,
3728 in_options
, cfg_options
, scope
, oc
, MDL
)) {
3729 /* The option name */
3730 fprintf(leaseFile
, "%soption %s%s%s", preamble
,
3731 name
, dot
, oc
->option
->name
);
3733 /* The option value if there is one */
3734 if ((oc
->option
->format
== NULL
) ||
3735 (oc
->option
->format
[0] != 'Z')) {
3736 fprintf(leaseFile
, " %s",
3737 pretty_print_option(oc
->option
, ds
.data
,
3741 /* The closing semi-colon and newline */
3742 fprintf(leaseFile
, ";\n");
3744 data_string_forget (&ds
, MDL
);
3748 /* Write an option cache to the lease store. */
3750 write_options(struct client_state
*client
, struct option_state
*options
,
3751 const char *preamble
)
3755 for (i
= 0; i
< options
->universe_count
; i
++) {
3756 option_space_foreach(NULL
, NULL
, client
, NULL
, options
,
3757 &global_scope
, universes
[i
],
3758 (char *)preamble
, write_lease_option
);
3763 * The "best" default DUID, since we cannot predict any information
3764 * about the system (such as whether or not the hardware addresses are
3765 * integrated into the motherboard or similar), is the "LLT", link local
3766 * plus time, DUID. For real stateless "LL" is better.
3768 * Once generated, this duid is stored into the state database, and
3769 * retained across restarts.
3771 * For the time being, there is probably a different state database for
3772 * every daemon, so this winds up being a per-interface identifier...which
3773 * is not how it is intended. Upcoming rearchitecting the client should
3774 * address this "one daemon model."
3777 form_duid(struct data_string
*duid
, const char *file
, int line
)
3779 struct interface_info
*ip
;
3783 /* For now, just use the first interface on the list. */
3787 log_fatal("Impossible condition at %s:%d.", MDL
);
3789 if ((ip
->hw_address
.hlen
== 0) ||
3790 (ip
->hw_address
.hlen
> sizeof(ip
->hw_address
.hbuf
)))
3791 log_fatal("Impossible hardware address length at %s:%d.", MDL
);
3794 duid_type
= stateless
? DUID_LL
: DUID_LLT
;
3797 * 2 bytes for the 'duid type' field.
3798 * 2 bytes for the 'htype' field.
3799 * (DUID_LLT) 4 bytes for the 'current time'.
3800 * enough bytes for the hardware address (note that hw_address has
3801 * the 'htype' on byte zero).
3803 len
= 4 + (ip
->hw_address
.hlen
- 1);
3804 if (duid_type
== DUID_LLT
)
3806 if (!buffer_allocate(&duid
->buffer
, len
, MDL
))
3807 log_fatal("no memory for default DUID!");
3808 duid
->data
= duid
->buffer
->data
;
3811 /* Basic Link Local Address type of DUID. */
3812 if (duid_type
== DUID_LLT
) {
3813 putUShort(duid
->buffer
->data
, DUID_LLT
);
3814 putUShort(duid
->buffer
->data
+ 2, ip
->hw_address
.hbuf
[0]);
3815 putULong(duid
->buffer
->data
+ 4, cur_time
- DUID_TIME_EPOCH
);
3816 memcpy(duid
->buffer
->data
+ 8, ip
->hw_address
.hbuf
+ 1,
3817 ip
->hw_address
.hlen
- 1);
3819 putUShort(duid
->buffer
->data
, DUID_LL
);
3820 putUShort(duid
->buffer
->data
+ 2, ip
->hw_address
.hbuf
[0]);
3821 memcpy(duid
->buffer
->data
+ 4, ip
->hw_address
.hbuf
+ 1,
3822 ip
->hw_address
.hlen
- 1);
3825 /* Now format the output based on lease-id-format */
3826 str
= format_lease_id(duid
->data
, duid
->len
,
3827 top_level_config
.lease_id_format
, MDL
);
3829 log_info("form_duid: Couldn't allocate memory to log duid!");
3831 log_info("Created duid %s.", str
);
3836 /* Write the default DUID to the lease store. */
3838 write_duid(struct data_string
*duid
)
3843 if ((duid
== NULL
) || (duid
->len
<= 2))
3844 return DHCP_R_INVALIDARG
;
3846 if (leaseFile
== NULL
) { /* XXX? */
3847 leaseFile
= fopen(path_dhclient_db
, "w");
3848 if (leaseFile
== NULL
) {
3849 log_error("can't create %s: %m", path_dhclient_db
);
3850 return ISC_R_IOERROR
;
3854 /* Generate a formatted duid string per lease-id-format */
3855 str
= format_lease_id(duid
->data
, duid
->len
,
3856 top_level_config
.lease_id_format
, MDL
);
3858 return ISC_R_NOMEMORY
;
3860 stat
= fprintf(leaseFile
, "default-duid %s;\n", str
);
3863 return ISC_R_IOERROR
;
3865 if (fflush(leaseFile
) != 0)
3866 return ISC_R_IOERROR
;
3868 return ISC_R_SUCCESS
;
3871 /* Write a DHCPv6 lease to the store. */
3873 write_client6_lease(struct client_state
*client
, struct dhc6_lease
*lease
,
3874 int rewrite
, int sync
)
3877 struct dhc6_addr
*addr
;
3881 /* This should include the current lease. */
3882 if (!rewrite
&& (leases_written
++ > 20)) {
3883 rewrite_client_leases();
3885 return ISC_R_SUCCESS
;
3888 if (client
== NULL
|| lease
== NULL
)
3889 return DHCP_R_INVALIDARG
;
3891 if (leaseFile
== NULL
) { /* XXX? */
3892 leaseFile
= fopen(path_dhclient_db
, "w");
3893 if (leaseFile
== NULL
) {
3894 log_error("can't create %s: %m", path_dhclient_db
);
3895 return ISC_R_IOERROR
;
3899 stat
= fprintf(leaseFile
, "lease6 {\n");
3901 return ISC_R_IOERROR
;
3903 stat
= fprintf(leaseFile
, " interface \"%s\";\n",
3904 client
->interface
->name
);
3906 return ISC_R_IOERROR
;
3908 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
3909 switch (ia
->ia_type
) {
3922 /* For some reason IAID was never octal or hex, but string or
3923 * hex. Go figure. So for compatibilty's sake we will either
3924 * do hex or "legacy" i.e string rather than octal. What a
3926 switch(top_level_config
.lease_id_format
) {
3928 char* iaid_str
= format_lease_id(
3929 (const unsigned char *) &ia
->iaid
, 4,
3930 top_level_config
.lease_id_format
, MDL
);
3933 log_error("Can't format iaid");
3934 return ISC_R_IOERROR
;
3937 stat
= fprintf(leaseFile
, " %s %s {\n",
3939 dfree(iaid_str
, MDL
);
3945 stat
= fprintf(leaseFile
, " %s %s {\n", ianame
,
3946 print_hex_1(4, ia
->iaid
, 12));
3951 return ISC_R_IOERROR
;
3953 if (ia
->ia_type
!= D6O_IA_TA
)
3954 stat
= fprintf(leaseFile
, " starts %d;\n"
3957 (int)ia
->starts
, ia
->renew
, ia
->rebind
);
3959 stat
= fprintf(leaseFile
, " starts %d;\n",
3962 return ISC_R_IOERROR
;
3964 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
3965 if (ia
->ia_type
!= D6O_IA_PD
)
3966 stat
= fprintf(leaseFile
,
3968 piaddr(addr
->address
));
3970 stat
= fprintf(leaseFile
,
3971 " iaprefix %s/%d {\n",
3972 piaddr(addr
->address
),
3975 return ISC_R_IOERROR
;
3977 stat
= fprintf(leaseFile
, " starts %d;\n"
3978 " preferred-life %u;\n"
3980 (int)addr
->starts
, addr
->preferred_life
,
3983 return ISC_R_IOERROR
;
3985 if (addr
->options
!= NULL
)
3986 write_options(client
, addr
->options
, " ");
3988 stat
= fprintf(leaseFile
, " }\n");
3990 return ISC_R_IOERROR
;
3993 if (ia
->options
!= NULL
)
3994 write_options(client
, ia
->options
, " ");
3996 stat
= fprintf(leaseFile
, " }\n");
3998 return ISC_R_IOERROR
;
4001 if (lease
->released
) {
4002 stat
= fprintf(leaseFile
, " released;\n");
4004 return ISC_R_IOERROR
;
4007 if (lease
->options
!= NULL
)
4008 write_options(client
, lease
->options
, " ");
4010 stat
= fprintf(leaseFile
, "}\n");
4012 return ISC_R_IOERROR
;
4014 if (fflush(leaseFile
) != 0)
4015 return ISC_R_IOERROR
;
4018 if (fsync(fileno(leaseFile
)) < 0) {
4019 log_error("write_client_lease: fsync(): %m");
4020 return ISC_R_IOERROR
;
4024 return ISC_R_SUCCESS
;
4027 int write_client_lease (client
, lease
, rewrite
, makesure
)
4028 struct client_state
*client
;
4029 struct client_lease
*lease
;
4033 struct data_string ds
;
4039 if (leases_written
++ > 20) {
4040 rewrite_client_leases ();
4045 /* If the lease came from the config file, we don't need to stash
4046 a copy in the lease database. */
4047 if (lease
-> is_static
)
4050 if (leaseFile
== NULL
) { /* XXX */
4051 leaseFile
= fopen (path_dhclient_db
, "w");
4052 if (leaseFile
== NULL
) {
4053 log_error ("can't create %s: %m", path_dhclient_db
);
4059 fprintf (leaseFile
, "lease {\n");
4060 if (lease
-> is_bootp
) {
4061 fprintf (leaseFile
, " bootp;\n");
4067 fprintf (leaseFile
, " interface \"%s\";\n",
4068 client
-> interface
-> name
);
4073 if (client
-> name
) {
4074 fprintf (leaseFile
, " name \"%s\";\n", client
-> name
);
4080 fprintf (leaseFile
, " fixed-address %s;\n",
4081 piaddr (lease
-> address
));
4086 if (lease
-> filename
) {
4087 s
= quotify_string (lease
-> filename
, MDL
);
4089 fprintf (leaseFile
, " filename \"%s\";\n", s
);
4099 if (lease
->server_name
!= NULL
) {
4100 s
= quotify_string(lease
->server_name
, MDL
);
4102 fprintf(leaseFile
, " server-name \"%s\";\n", s
);
4111 if (lease
-> medium
) {
4112 s
= quotify_string (lease
-> medium
-> string
, MDL
);
4114 fprintf (leaseFile
, " medium \"%s\";\n", s
);
4128 memset (&ds
, 0, sizeof ds
);
4130 write_options(client
, lease
->options
, " ");
4132 tval
= print_time(lease
->renewal
);
4134 fprintf(leaseFile
, " renew %s\n", tval
) < 0)
4137 tval
= print_time(lease
->rebind
);
4139 fprintf(leaseFile
, " rebind %s\n", tval
) < 0)
4142 tval
= print_time(lease
->expiry
);
4144 fprintf(leaseFile
, " expire %s\n", tval
) < 0)
4147 if (fprintf(leaseFile
, "}\n") < 0)
4150 if (fflush(leaseFile
) != 0)
4153 client
->last_write
= cur_time
;
4155 if (!errors
&& makesure
) {
4156 if (fsync (fileno (leaseFile
)) < 0) {
4157 log_info ("write_client_lease: %m");
4162 return errors
? 0 : 1;
4165 /* Variables holding name of script and file pointer for writing to
4166 script. Needless to say, this is not reentrant - only one script
4167 can be invoked at a time. */
4168 char scriptName
[256];
4172 * @brief Initializes basic variables for a script
4174 * This function is called as an initial preparation for calling a script.
4175 * It sets up a number of common env. variables that will be passed to
4176 * the script. For actual script calling, see @ref script_go .
4178 * @param client variables will be stored here (if null, the whole function
4180 * @param reason specified the reason for calling a script (must be non-null)
4181 * @param medium if specified, defines medium type (may be null)
4183 void script_init(struct client_state
*client
, const char *reason
,
4184 struct string_list
*medium
)
4186 struct string_list
*sl
, *next
;
4189 for (sl
= client
-> env
; sl
; sl
= next
) {
4193 client
-> env
= (struct string_list
*)0;
4196 if (client
-> interface
) {
4197 client_envadd (client
, "", "interface", "%s",
4198 client
-> interface
-> name
);
4201 client_envadd (client
,
4202 "", "client", "%s", client
-> name
);
4204 client_envadd (client
,
4205 "", "medium", "%s", medium
-> string
);
4207 client_envadd (client
, "", "reason", "%s", reason
);
4208 client_envadd (client
, "", "pid", "%ld", (long int)getpid ());
4210 client_envadd (client
, "", "dad_wait_time", "%ld",
4211 (long int)dad_wait_time
);
4216 void client_option_envadd (struct option_cache
*oc
,
4217 struct packet
*packet
, struct lease
*lease
,
4218 struct client_state
*client_state
,
4219 struct option_state
*in_options
,
4220 struct option_state
*cfg_options
,
4221 struct binding_scope
**scope
,
4222 struct universe
*u
, void *stuff
)
4224 struct envadd_state
*es
= stuff
;
4225 struct data_string data
;
4226 memset (&data
, 0, sizeof data
);
4228 if (evaluate_option_cache (&data
, packet
, lease
, client_state
,
4229 in_options
, cfg_options
, scope
, oc
, MDL
)) {
4232 if (dhcp_option_ev_name (name
, sizeof name
,
4236 value
= pretty_print_option(oc
->option
,
4239 length
= strlen(value
);
4241 if (check_option_values(oc
->option
->universe
,
4243 value
, length
) == 0) {
4244 client_envadd(es
->client
, es
->prefix
,
4247 log_error("suspect value in %s "
4248 "option - discarded",
4254 data_string_forget (&data
, MDL
);
4259 * @brief Adds parameters to environment variables for a script
4261 * This function add details of specified lease to a list of env. variables
4262 * to be passed to a script. The lease details will be prepended with
4263 * specified prefix (e.g. "old_") and added to the list stored in client.
4264 * Following variables may be set:
4268 * - broadcast_address
4273 * @param client env. variables will be stored here
4274 * @param prefix textual prefix to be added to each variable (e.g. "old_")
4275 * @param lease lease details will be extracted from here
4277 void script_write_params(struct client_state
*client
, const char *prefix
,
4278 struct client_lease
*lease
)
4281 struct data_string data
;
4282 struct option_cache
*oc
;
4283 struct envadd_state es
;
4288 client_envadd (client
,
4289 prefix
, "ip_address", "%s", piaddr (lease
-> address
));
4291 /* If we've set the next server address in the lease structure
4292 put it into an environment variable for the script */
4293 if (lease
->next_srv_addr
.len
!= 0) {
4294 client_envadd(client
, prefix
, "next_server", "%s",
4295 piaddr(lease
->next_srv_addr
));
4298 /* For the benefit of Linux (and operating systems which may
4299 have similar needs), compute the network address based on
4300 the supplied ip address and netmask, if provided. Also
4301 compute the broadcast address (the host address all ones
4302 broadcast address, not the host address all zeroes
4303 broadcast address). */
4305 memset (&data
, 0, sizeof data
);
4306 oc
= lookup_option (&dhcp_universe
, lease
-> options
, DHO_SUBNET_MASK
);
4307 if (oc
&& evaluate_option_cache (&data
, (struct packet
*)0,
4308 (struct lease
*)0, client
,
4309 (struct option_state
*)0,
4311 &global_scope
, oc
, MDL
)) {
4313 struct iaddr netmask
, subnet
, broadcast
;
4316 * No matter the length of the subnet-mask option,
4317 * use only the first four octets. Note that
4318 * subnet-mask options longer than 4 octets are not
4319 * in conformance with RFC 2132, but servers with this
4322 memcpy(netmask
.iabuf
, data
.data
, 4);
4324 data_string_forget (&data
, MDL
);
4326 subnet
= subnet_number (lease
-> address
, netmask
);
4328 client_envadd (client
, prefix
, "network_number",
4329 "%s", piaddr (subnet
));
4331 oc
= lookup_option (&dhcp_universe
,
4333 DHO_BROADCAST_ADDRESS
);
4335 !(evaluate_option_cache
4336 (&data
, (struct packet
*)0,
4337 (struct lease
*)0, client
,
4338 (struct option_state
*)0,
4340 &global_scope
, oc
, MDL
))) {
4341 broadcast
= broadcast_addr (subnet
, netmask
);
4342 if (broadcast
.len
) {
4343 client_envadd (client
,
4344 prefix
, "broadcast_address",
4345 "%s", piaddr (broadcast
));
4350 data_string_forget (&data
, MDL
);
4353 if (lease
->filename
) {
4354 if (check_option_values(NULL
, DHO_ROOT_PATH
,
4356 strlen(lease
->filename
)) == 0) {
4357 client_envadd(client
, prefix
, "filename",
4358 "%s", lease
->filename
);
4360 log_error("suspect value in %s "
4361 "option - discarded",
4366 if (lease
->server_name
) {
4367 if (check_option_values(NULL
, DHO_HOST_NAME
,
4369 strlen(lease
->server_name
)) == 0 ) {
4370 client_envadd (client
, prefix
, "server_name",
4371 "%s", lease
->server_name
);
4373 log_error("suspect value in %s "
4374 "option - discarded",
4375 lease
->server_name
);
4379 for (i
= 0; i
< lease
-> options
-> universe_count
; i
++) {
4380 option_space_foreach ((struct packet
*)0, (struct lease
*)0,
4381 client
, (struct option_state
*)0,
4382 lease
-> options
, &global_scope
,
4384 &es
, client_option_envadd
);
4387 client_envadd (client
, prefix
, "expiry", "%lu",
4388 (unsigned long)(lease
-> expiry
));
4392 * @brief Write out the environent variable the client requested.
4393 * Write out the environment variables for the objects that the
4394 * client requested. If the object was requested the variable will be:
4395 * requested_<option_name>=1
4396 * If it wasn't requested there won't be a variable.
4398 * @param client client structure
4400 void script_write_requested(struct client_state
*client
)
4403 struct option
**req
;
4405 req
= client
->config
->requested_options
;
4410 for (i
= 0 ; req
[i
] != NULL
; i
++) {
4411 if ((req
[i
]->universe
== &dhcp_universe
) &&
4412 dhcp_option_ev_name(name
, sizeof(name
), req
[i
])) {
4413 client_envadd(client
, "requested_", name
, "%d", 1);
4419 * @brief Calls external script.
4421 * External script is specified either using -sf command line or
4422 * script parameter in the configuration file.
4424 * @param client specifies client information (environment variables,
4425 * and other parameters will be extracted and passed to the script.
4426 * @return If positive, it contains exit code of the process running script.
4427 * If negative, returns the signal number that cause the script process
4430 int script_go(struct client_state
*client
)
4435 char reason
[] = "REASON=NBI";
4436 static char client_path
[] = CLIENT_PATH
;
4438 struct string_list
*sp
, *next
;
4439 int pid
, wpid
, wstatus
;
4442 scriptName
= client
-> config
-> script_name
;
4444 scriptName
= top_level_config
.script_name
;
4446 envp
= dmalloc (((client
? client
-> envc
: 2) +
4447 client_env_count
+ 2) * sizeof (char *), MDL
);
4449 log_error ("No memory for client script environment.");
4453 /* Copy out the environment specified on the command line,
4455 for (sp
= client_env
; sp
; sp
= sp
-> next
) {
4456 envp
[i
++] = sp
-> string
;
4458 /* Copy out the environment specified by dhclient. */
4460 for (sp
= client
-> env
; sp
; sp
= sp
-> next
) {
4461 envp
[i
++] = sp
-> string
;
4464 envp
[i
++] = reason
;
4467 envp
[i
++] = client_path
;
4468 envp
[i
] = (char *)0;
4470 argv
[0] = scriptName
;
4471 argv
[1] = (char *)0;
4475 log_error ("fork: %m");
4479 wpid
= wait (&wstatus
);
4480 } while (wpid
!= pid
&& wpid
> 0);
4482 log_error ("wait: %m");
4486 /* We don't want to pass an open file descriptor for
4487 * dhclient.leases when executing dhclient-script.
4489 if (leaseFile
!= NULL
)
4491 execve (scriptName
, argv
, envp
);
4492 log_error ("execve (%s, ...): %m", scriptName
);
4497 for (sp
= client
-> env
; sp
; sp
= next
) {
4501 client
-> env
= (struct string_list
*)0;
4505 gettimeofday(&cur_tv
, NULL
);
4506 return (WIFEXITED (wstatus
) ?
4507 WEXITSTATUS (wstatus
) : -WTERMSIG (wstatus
));
4510 void client_envadd (struct client_state
*client
,
4511 const char *prefix
, const char *name
, const char *fmt
, ...)
4516 struct string_list
*val
;
4519 va_start (list
, fmt
);
4520 len
= vsnprintf (spbuf
, sizeof spbuf
, fmt
, list
);
4523 val
= dmalloc (strlen (prefix
) + strlen (name
) + 1 /* = */ +
4524 len
+ sizeof *val
, MDL
);
4526 log_error ("client_envadd: cannot allocate space for variable");
4535 if (len
>= sizeof spbuf
) {
4536 va_start (list
, fmt
);
4537 vsnprintf (s
, len
+ 1, fmt
, list
);
4543 val
-> next
= client
-> env
;
4544 client
-> env
= val
;
4548 int dhcp_option_ev_name (buf
, buflen
, option
)
4551 struct option
*option
;
4557 if (option
-> universe
!= &dhcp_universe
) {
4558 s
= option
-> universe
-> name
;
4567 if (j
+ 1 == buflen
)
4577 if (j
+ 1 == buflen
)
4588 void finish (char ret
)
4590 if (no_daemon
|| dfd
[0] == -1 || dfd
[1] == -1)
4592 if (write(dfd
[1], &ret
, 1) != 1)
4593 log_fatal("write to parent: %m");
4594 (void) close(dfd
[1]);
4595 dfd
[0] = dfd
[1] = -1;
4603 /* Don't become a daemon if the user requested otherwise. */
4605 write_client_pid_file ();
4609 /* Only do it once. */
4610 if (dfd
[0] == -1 || dfd
[1] == -1)
4613 /* Signal parent we started successfully. */
4614 if (write(dfd
[1], &buf
, 1) != 1)
4615 log_fatal("write to parent: %m");
4616 (void) close(dfd
[1]);
4617 dfd
[0] = dfd
[1] = -1;
4619 /* Stop logging to stderr... */
4622 /* Become session leader and get pid... */
4625 /* Close standard I/O descriptors. */
4630 /* Reopen them on /dev/null. */
4631 (void) open("/dev/null", O_RDWR
);
4632 (void) open("/dev/null", O_RDWR
);
4633 (void) open("/dev/null", O_RDWR
);
4635 write_client_pid_file ();
4637 IGNORE_RET (chdir("/"));
4641 void write_client_pid_file ()
4646 /* nothing to do if the user doesn't want a pid file */
4647 if (no_pid_file
== ISC_TRUE
) {
4651 pfdesc
= open (path_dhclient_pid
, O_CREAT
| O_TRUNC
| O_WRONLY
, 0644);
4654 log_error ("Can't create %s: %m", path_dhclient_pid
);
4658 pf
= fdopen (pfdesc
, "w");
4661 log_error ("Can't fdopen %s: %m", path_dhclient_pid
);
4663 fprintf (pf
, "%ld\n", (long)getpid ());
4668 void client_location_changed ()
4670 struct interface_info
*ip
;
4671 struct client_state
*client
;
4673 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4674 for (client
= ip
-> client
; client
; client
= client
-> next
) {
4675 switch (client
-> state
) {
4677 cancel_timeout (send_discover
, client
);
4681 cancel_timeout (state_bound
, client
);
4687 cancel_timeout (send_request
, client
);
4697 client
-> state
= S_INIT
;
4698 state_reboot (client
);
4703 void do_release(client
)
4704 struct client_state
*client
;
4706 struct data_string ds
;
4707 struct option_cache
*oc
;
4709 #if defined(DHCPv6) && defined(DHCP4o6)
4710 if (dhcpv4_over_dhcpv6
&& (dhcp4o6_state
<= 0)) {
4711 if (dhcp4o6_state
< 0)
4713 client
->pending
= P_RELEASE
;
4718 /* Pick a random xid. */
4719 client
-> xid
= random ();
4721 /* is there even a lease to release? */
4722 if (client
-> active
) {
4723 /* Make a DHCPRELEASE packet, and set appropriate per-interface
4725 make_release (client
, client
-> active
);
4727 memset (&ds
, 0, sizeof ds
);
4728 oc
= lookup_option (&dhcp_universe
,
4729 client
-> active
-> options
,
4730 DHO_DHCP_SERVER_IDENTIFIER
);
4732 evaluate_option_cache (&ds
, (struct packet
*)0,
4733 (struct lease
*)0, client
,
4734 (struct option_state
*)0,
4735 client
-> active
-> options
,
4736 &global_scope
, oc
, MDL
)) {
4738 memcpy (client
-> destination
.iabuf
,
4740 client
-> destination
.len
= 4;
4742 client
-> destination
= iaddr_broadcast
;
4744 data_string_forget (&ds
, MDL
);
4746 client
-> destination
= iaddr_broadcast
;
4747 client
-> first_sending
= cur_time
;
4748 client
-> interval
= client
-> config
-> initial_interval
;
4750 /* Zap the medium list... */
4751 client
-> medium
= (struct string_list
*)0;
4753 /* Send out the first and only DHCPRELEASE packet. */
4754 send_release (client
);
4756 /* Do the client script RELEASE operation. */
4757 script_init (client
,
4758 "RELEASE", (struct string_list
*)0);
4759 if (client
-> alias
)
4760 script_write_params(client
, "alias_",
4762 script_write_params(client
, "old_", client
-> active
);
4763 script_write_requested(client
);
4767 /* Cancel any timeouts. */
4768 cancel_timeout (state_bound
, client
);
4769 cancel_timeout (send_discover
, client
);
4770 cancel_timeout (state_init
, client
);
4771 cancel_timeout (send_request
, client
);
4772 cancel_timeout (state_reboot
, client
);
4773 cancel_timeout (finish_v6only
, client
);
4774 client
-> state
= S_STOPPED
;
4776 #if defined(DHCPv6) && defined(DHCP4o6)
4777 if (dhcpv4_over_dhcpv6
)
4782 int dhclient_interface_shutdown_hook (struct interface_info
*interface
)
4784 do_release (interface
-> client
);
4789 int dhclient_interface_discovery_hook (struct interface_info
*tmp
)
4791 struct interface_info
*last
, *ip
;
4792 /* See if we can find the client from dummy_interfaces */
4794 for (ip
= dummy_interfaces
; ip
; ip
= ip
-> next
) {
4795 if (!strcmp (ip
-> name
, tmp
-> name
)) {
4796 /* Remove from dummy_interfaces */
4798 ip
= (struct interface_info
*)0;
4799 interface_reference (&ip
, last
-> next
, MDL
);
4800 interface_dereference (&last
-> next
, MDL
);
4802 interface_reference (&last
-> next
,
4804 interface_dereference (&ip
-> next
,
4808 ip
= (struct interface_info
*)0;
4809 interface_reference (&ip
,
4810 dummy_interfaces
, MDL
);
4811 interface_dereference (&dummy_interfaces
, MDL
);
4813 interface_reference (&dummy_interfaces
,
4815 interface_dereference (&ip
-> next
,
4819 /* Copy "client" to tmp */
4821 tmp
-> client
= ip
-> client
;
4822 tmp
-> client
-> interface
= tmp
;
4824 interface_dereference (&ip
, MDL
);
4832 isc_result_t
dhclient_interface_startup_hook (struct interface_info
*interface
)
4834 struct interface_info
*ip
;
4835 struct client_state
*client
;
4837 /* This code needs some rethinking. It doesn't test against
4838 a signal name, and it just kind of bulls into doing something
4839 that may or may not be appropriate. */
4842 interface_reference (&interface
-> next
, interfaces
, MDL
);
4843 interface_dereference (&interfaces
, MDL
);
4845 interface_reference (&interfaces
, interface
, MDL
);
4847 discover_interfaces (DISCOVER_UNCONFIGURED
);
4849 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4850 /* If interfaces were specified, don't configure
4851 interfaces that weren't specified! */
4852 if (ip
-> flags
& INTERFACE_RUNNING
||
4853 (ip
-> flags
& (INTERFACE_REQUESTED
|
4854 INTERFACE_AUTOMATIC
)) !=
4855 INTERFACE_REQUESTED
)
4857 script_init (ip
-> client
,
4858 "PREINIT", (struct string_list
*)0);
4859 if (ip
-> client
-> alias
)
4860 script_write_params(ip
-> client
, "alias_",
4861 ip
-> client
-> alias
);
4862 script_go(ip
-> client
);
4865 discover_interfaces (interfaces_requested
!= 0
4866 ? DISCOVER_REQUESTED
4867 : DISCOVER_RUNNING
);
4869 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4870 if (ip
-> flags
& INTERFACE_RUNNING
)
4872 ip
-> flags
|= INTERFACE_RUNNING
;
4873 for (client
= ip
->client
; client
; client
= client
->next
) {
4874 client
->state
= S_INIT
;
4875 state_reboot(client
);
4878 return ISC_R_SUCCESS
;
4881 /* The client should never receive a relay agent information option,
4882 so if it does, log it and discard it. */
4884 int parse_agent_information_option (packet
, len
, data
)
4885 struct packet
*packet
;
4892 /* The client never sends relay agent information options. */
4894 unsigned cons_agent_information_options (cfg_options
, outpacket
,
4896 struct option_state
*cfg_options
;
4897 struct dhcp_packet
*outpacket
;
4904 static void shutdown_exit (void *foo
)
4906 /* get rid of the pid if we can */
4907 if (no_pid_file
== ISC_FALSE
)
4908 (void) unlink(path_dhclient_pid
);
4912 #if defined (NSUPDATE)
4914 * If the first query fails, the updater MUST NOT delete the DNS name. It
4915 * may be that the host whose lease on the server has expired has moved
4916 * to another network and obtained a lease from a different server,
4917 * which has caused the client's A RR to be replaced. It may also be
4918 * that some other client has been configured with a name that matches
4919 * the name of the DHCP client, and the policy was that the last client
4920 * to specify the name would get the name. In this case, the DHCID RR
4921 * will no longer match the updater's notion of the client-identity of
4922 * the host pointed to by the DNS name.
4923 * -- "Interaction between DHCP and DNS"
4926 /* The first and second stages are pretty similar so we combine them */
4928 client_dns_remove_action(dhcp_ddns_cb_t
*ddns_cb
,
4929 isc_result_t eresult
)
4932 isc_result_t result
;
4934 if ((eresult
== ISC_R_SUCCESS
) &&
4935 (ddns_cb
->state
== DDNS_STATE_REM_FW_YXDHCID
)) {
4936 /* Do the second stage of the FWD removal */
4937 ddns_cb
->state
= DDNS_STATE_REM_FW_NXRR
;
4939 result
= ddns_modify_fwd(ddns_cb
, MDL
);
4940 if (result
== ISC_R_SUCCESS
) {
4945 /* If we are done or have an error clean up */
4946 dhclient_ddns_cb_free(ddns_cb
, MDL
);
4951 client_dns_remove(struct client_state
*client
,
4954 dhcp_ddns_cb_t
*ddns_cb
;
4955 isc_result_t result
;
4957 /* if we have an old ddns request for this client, cancel it */
4958 if (client
->ddns_cb
!= NULL
) {
4959 ddns_cancel(client
->ddns_cb
, MDL
);
4960 client
->ddns_cb
= NULL
;
4963 ddns_cb
= ddns_cb_alloc(MDL
);
4964 if (ddns_cb
!= NULL
) {
4965 ddns_cb
->address
= *addr
;
4966 ddns_cb
->timeout
= 0;
4968 ddns_cb
->state
= DDNS_STATE_REM_FW_YXDHCID
;
4969 ddns_cb
->flags
= DDNS_UPDATE_ADDR
;
4970 ddns_cb
->cur_func
= client_dns_remove_action
;
4972 result
= client_dns_update(client
, ddns_cb
);
4974 if (result
!= ISC_R_TIMEDOUT
) {
4975 dhclient_ddns_cb_free(ddns_cb
, MDL
);
4979 #endif /* defined NSUPDATE */
4982 isc_result_t
dhcp_set_control_state (control_object_state_t oldstate
,
4983 control_object_state_t newstate
)
4985 struct interface_info
*ip
;
4986 struct client_state
*client
;
4989 if (newstate
== server_shutdown
) {
4991 if (shutdown_signal
== SIGUSR1
)
4992 return ISC_R_SUCCESS
;
4993 /* Log shutdown on signal. */
4994 if ((shutdown_signal
== SIGINT
) ||
4995 (shutdown_signal
== SIGTERM
)) {
4996 log_info("Received signal %d, initiating shutdown.",
4999 /* Mark it was called. */
5000 shutdown_signal
= SIGUSR1
;
5003 /* Do the right thing for each interface. */
5004 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
5005 for (client
= ip
-> client
; client
; client
= client
-> next
) {
5007 case server_startup
:
5008 return ISC_R_SUCCESS
;
5010 case server_running
:
5011 return ISC_R_SUCCESS
;
5013 case server_shutdown
:
5014 if (client
-> active
&&
5015 client
-> active
-> expiry
> cur_time
) {
5016 #if defined (NSUPDATE)
5017 if (client
->config
->do_forward_update
) {
5018 client_dns_remove(client
,
5019 &client
->active
->address
);
5021 #endif /* defined NSUPDATE */
5023 do_release (client
);
5027 case server_hibernate
:
5028 state_stop (client
);
5032 state_reboot (client
);
5038 if (newstate
== server_shutdown
) {
5039 tv
.tv_sec
= cur_tv
.tv_sec
;
5040 tv
.tv_usec
= cur_tv
.tv_usec
+ 1;
5041 add_timeout(&tv
, shutdown_exit
, 0, 0, 0);
5043 return ISC_R_SUCCESS
;
5046 #if defined (NSUPDATE)
5048 * Called after a timeout if the DNS update failed on the previous try.
5049 * Starts the retry process. If the retry times out it will schedule
5050 * this routine to run again after a 10x wait.
5053 client_dns_update_timeout (void *cp
)
5055 dhcp_ddns_cb_t
*ddns_cb
= (dhcp_ddns_cb_t
*)cp
;
5056 struct client_state
*client
= (struct client_state
*)ddns_cb
->lease
;
5057 isc_result_t status
= ISC_R_FAILURE
;
5059 if ((client
!= NULL
) &&
5060 ((client
->active
!= NULL
) ||
5061 (client
->active_lease
!= NULL
)))
5062 status
= client_dns_update(client
, ddns_cb
);
5065 * A status of timedout indicates that we started the update and
5066 * have released control of the control block. Any other status
5067 * indicates that we should clean up the control block. We either
5068 * got a success which indicates that we didn't really need to
5069 * send an update or some other error in which case we weren't able
5070 * to start the update process. In both cases we still own
5071 * the control block and should free it.
5073 if (status
!= ISC_R_TIMEDOUT
) {
5074 dhclient_ddns_cb_free(ddns_cb
, MDL
);
5079 * If the first query succeeds, the updater can conclude that it
5080 * has added a new name whose only RRs are the A and DHCID RR records.
5081 * The A RR update is now complete (and a client updater is finished,
5082 * while a server might proceed to perform a PTR RR update).
5083 * -- "Interaction between DHCP and DNS"
5085 * If the second query succeeds, the updater can conclude that the current
5086 * client was the last client associated with the domain name, and that
5087 * the name now contains the updated A RR. The A RR update is now
5088 * complete (and a client updater is finished, while a server would
5089 * then proceed to perform a PTR RR update).
5090 * -- "Interaction between DHCP and DNS"
5092 * If the second query fails with NXRRSET, the updater must conclude
5093 * that the client's desired name is in use by another host. At this
5094 * juncture, the updater can decide (based on some administrative
5095 * configuration outside of the scope of this document) whether to let
5096 * the existing owner of the name keep that name, and to (possibly)
5097 * perform some name disambiguation operation on behalf of the current
5098 * client, or to replace the RRs on the name with RRs that represent
5099 * the current client. If the configured policy allows replacement of
5100 * existing records, the updater submits a query that deletes the
5101 * existing A RR and the existing DHCID RR, adding A and DHCID RRs that
5102 * represent the IP address and client-identity of the new client.
5103 * -- "Interaction between DHCP and DNS"
5106 /* The first and second stages are pretty similar so we combine them */
5108 client_dns_update_action(dhcp_ddns_cb_t
*ddns_cb
,
5109 isc_result_t eresult
)
5111 isc_result_t result
;
5117 /* Either we succeeded or broke in a bad way, clean up */
5122 * This is the only difference between the two stages,
5123 * check to see if it is the first stage, in which case
5124 * start the second stage
5126 if (ddns_cb
->state
== DDNS_STATE_ADD_FW_NXDOMAIN
) {
5127 ddns_cb
->state
= DDNS_STATE_ADD_FW_YXDHCID
;
5128 ddns_cb
->cur_func
= client_dns_update_action
;
5130 result
= ddns_modify_fwd(ddns_cb
, MDL
);
5131 if (result
== ISC_R_SUCCESS
) {
5137 case ISC_R_TIMEDOUT
:
5139 * We got a timeout response from the DNS module. Schedule
5140 * another attempt for later. We forget the name, dhcid and
5141 * zone so if it gets changed we will get the new information.
5143 data_string_forget(&ddns_cb
->fwd_name
, MDL
);
5144 data_string_forget(&ddns_cb
->dhcid
, MDL
);
5145 if (ddns_cb
->zone
!= NULL
) {
5146 forget_zone((struct dns_zone
**)&ddns_cb
->zone
);
5149 /* Reset to doing the first stage */
5150 ddns_cb
->state
= DDNS_STATE_ADD_FW_NXDOMAIN
;
5151 ddns_cb
->cur_func
= client_dns_update_action
;
5153 /* and update our timer */
5154 if (ddns_cb
->timeout
< 3600)
5155 ddns_cb
->timeout
*= 10;
5156 tv
.tv_sec
= cur_tv
.tv_sec
+ ddns_cb
->timeout
;
5157 tv
.tv_usec
= cur_tv
.tv_usec
;
5158 add_timeout(&tv
, client_dns_update_timeout
,
5159 ddns_cb
, NULL
, NULL
);
5163 dhclient_ddns_cb_free(ddns_cb
, MDL
);
5167 /* See if we should do a DNS update, and if so, do it. */
5170 client_dns_update(struct client_state
*client
, dhcp_ddns_cb_t
*ddns_cb
)
5172 struct data_string client_identifier
;
5173 struct option_cache
*oc
;
5179 /* If we didn't send an FQDN option, we certainly aren't going to
5180 be doing an update. */
5181 if (!client
-> sent_options
)
5182 return ISC_R_SUCCESS
;
5184 /* If we don't have a lease, we can't do an update. */
5185 if ((client
->active
== NULL
) && (client
->active_lease
== NULL
))
5186 return ISC_R_SUCCESS
;
5188 /* If we set the no client update flag, don't do the update. */
5189 if ((oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5190 FQDN_NO_CLIENT_UPDATE
)) &&
5191 evaluate_boolean_option_cache (&ignorep
, (struct packet
*)0,
5192 (struct lease
*)0, client
,
5193 client
-> sent_options
,
5194 (struct option_state
*)0,
5195 &global_scope
, oc
, MDL
))
5196 return ISC_R_SUCCESS
;
5198 /* If we set the "server, please update" flag, or didn't set it
5199 to false, don't do the update. */
5200 if (!(oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5201 FQDN_SERVER_UPDATE
)) ||
5202 evaluate_boolean_option_cache (&ignorep
, (struct packet
*)0,
5203 (struct lease
*)0, client
,
5204 client
-> sent_options
,
5205 (struct option_state
*)0,
5206 &global_scope
, oc
, MDL
))
5207 return ISC_R_SUCCESS
;
5209 /* If no FQDN option was supplied, don't do the update. */
5210 if (!(oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5212 !evaluate_option_cache (&ddns_cb
->fwd_name
, (struct packet
*)0,
5213 (struct lease
*)0, client
,
5214 client
-> sent_options
,
5215 (struct option_state
*)0,
5216 &global_scope
, oc
, MDL
))
5217 return ISC_R_SUCCESS
;
5220 * Construct the DHCID value for use in the DDNS update process
5221 * We have the newer standard version and the older interim version
5222 * chosen by the '-I' option. The interim version is left as is
5223 * for backwards compatibility. The standard version is based on
5224 * RFC 4701 section 3.3
5229 memset(&client_identifier
, 0, sizeof(client_identifier
));
5231 if (std_dhcid
== 1) {
5232 /* standard style */
5233 ddns_cb
->dhcid_class
= dns_rdatatype_dhcid
;
5237 ddns_cb
->dhcid_class
= dns_rdatatype_txt
;
5238 /* for backwards compatibility */
5239 ddns_v4_type
= DHO_DHCP_CLIENT_IDENTIFIER
;
5241 if (client
->active_lease
!= NULL
) {
5242 /* V6 request, get the client identifier, then
5243 * construct the dhcid for either standard
5245 if (((oc
= lookup_option(&dhcpv6_universe
,
5246 client
->sent_options
,
5247 D6O_CLIENTID
)) != NULL
) &&
5248 evaluate_option_cache(&client_identifier
, NULL
,
5250 client
->sent_options
, NULL
,
5251 &global_scope
, oc
, MDL
)) {
5252 result
= get_dhcid(ddns_cb
, 2,
5253 client_identifier
.data
,
5254 client_identifier
.len
);
5255 data_string_forget(&client_identifier
, MDL
);
5257 log_fatal("Impossible condition at %s:%d.", MDL
);
5260 * V4 request, use the client id if there is one or the
5261 * mac address if there isn't. If we have a client id
5262 * we check to see if it is an embedded DUID.
5264 if (((oc
= lookup_option(&dhcp_universe
,
5265 client
->sent_options
,
5266 DHO_DHCP_CLIENT_IDENTIFIER
)) != NULL
) &&
5267 evaluate_option_cache(&client_identifier
, NULL
,
5269 client
->sent_options
, NULL
,
5270 &global_scope
, oc
, MDL
)) {
5271 if ((std_dhcid
== 1) && (duid_v4
== 1) &&
5272 (client_identifier
.data
[0] == 255)) {
5274 * This appears to be an embedded DUID,
5275 * extract it and treat it as such
5277 if (client_identifier
.len
<= 5)
5278 log_fatal("Impossible condition at %s:%d.",
5280 result
= get_dhcid(ddns_cb
, 2,
5281 client_identifier
.data
+ 5,
5282 client_identifier
.len
- 5);
5284 result
= get_dhcid(ddns_cb
, ddns_v4_type
,
5285 client_identifier
.data
,
5286 client_identifier
.len
);
5288 data_string_forget(&client_identifier
, MDL
);
5290 result
= get_dhcid(ddns_cb
, 0,
5291 client
->interface
->hw_address
.hbuf
,
5292 client
->interface
->hw_address
.hlen
);
5296 return ISC_R_SUCCESS
;
5302 if (ddns_cb
->fwd_name
.len
&& ddns_cb
->dhcid
.len
) {
5303 rcode
= ddns_modify_fwd(ddns_cb
, MDL
);
5305 rcode
= ISC_R_FAILURE
;
5308 * A success from the modify routine means we are performing
5309 * async processing, for which we use the timedout error message.
5311 if (rcode
== ISC_R_SUCCESS
) {
5312 rcode
= ISC_R_TIMEDOUT
;
5320 * Schedule the first update. They will continue to retry occasionally
5321 * until they no longer time out (or fail).
5324 dhclient_schedule_updates(struct client_state
*client
,
5328 dhcp_ddns_cb_t
*ddns_cb
;
5331 if (!client
->config
->do_forward_update
)
5334 /* cancel any outstanding ddns requests */
5335 if (client
->ddns_cb
!= NULL
) {
5336 ddns_cancel(client
->ddns_cb
, MDL
);
5337 client
->ddns_cb
= NULL
;
5340 ddns_cb
= ddns_cb_alloc(MDL
);
5342 if (ddns_cb
!= NULL
) {
5343 ddns_cb
->lease
= (void *)client
;
5344 ddns_cb
->address
= *addr
;
5345 ddns_cb
->timeout
= 1;
5348 * XXX: DNS TTL is a problem we need to solve properly.
5349 * Until that time, 300 is a placeholder default for
5350 * something that is less insane than a value scaled
5355 ddns_cb
->state
= DDNS_STATE_ADD_FW_NXDOMAIN
;
5356 ddns_cb
->cur_func
= client_dns_update_action
;
5357 ddns_cb
->flags
= DDNS_UPDATE_ADDR
| DDNS_INCLUDE_RRSET
;
5359 client
->ddns_cb
= ddns_cb
;
5360 tv
.tv_sec
= cur_tv
.tv_sec
+ offset
;
5361 tv
.tv_usec
= cur_tv
.tv_usec
;
5362 add_timeout(&tv
, client_dns_update_timeout
,
5363 ddns_cb
, NULL
, NULL
);
5365 log_error("Unable to allocate dns update state for %s",
5369 #endif /* defined NSUPDATE */
5372 dhcpv4_client_assignments(void)
5374 struct servent
*ent
;
5376 if (path_dhclient_pid
== NULL
)
5377 path_dhclient_pid
= _PATH_DHCLIENT_PID
;
5378 if (path_dhclient_db
== NULL
)
5379 path_dhclient_db
= _PATH_DHCLIENT_DB
;
5381 /* Default to the DHCP/BOOTP port. */
5383 /* If we're faking a relay agent, and we're not using loopback,
5384 use the server port, not the client port. */
5385 if (mockup_relay
&& giaddr
.s_addr
!= htonl(INADDR_LOOPBACK
)) {
5386 local_port
= htons(67);
5388 ent
= getservbyname("dhcpc", "udp");
5390 ent
= getservbyname("bootpc", "udp");
5392 local_port
= htons(68);
5394 local_port
= ent
->s_port
;
5395 #ifndef __CYGWIN32__
5401 /* If we're faking a relay agent, and we're not using loopback,
5402 we're using the server port, not the client port. */
5403 if (mockup_relay
&& giaddr
.s_addr
!= htonl(INADDR_LOOPBACK
)) {
5404 remote_port
= local_port
;
5406 remote_port
= htons(ntohs(local_port
) - 1); /* XXX */
5410 * The following routines are used to check that certain
5411 * strings are reasonable before we pass them to the scripts.
5412 * This avoids some problems with scripts treating the strings
5413 * as commands - see ticket 23722
5414 * The domain checking code should be done as part of assembling
5415 * the string but we are doing it here for now due to time
5419 static int check_domain_name(const char *ptr
, size_t len
, int dots
)
5423 /* not empty or complete length not over 255 characters */
5424 if ((len
== 0) || (len
> 256))
5427 /* consists of [[:alnum:]-]+ labels separated by [.] */
5428 /* a [_] is against RFC but seems to be "widely used"... */
5429 for (p
=ptr
; (*p
!= 0) && (len
-- > 0); p
++) {
5430 if ((*p
== '-') || (*p
== '_')) {
5431 /* not allowed at begin or end of a label */
5432 if (((p
- ptr
) == 0) || (len
== 0) || (p
[1] == '.'))
5434 } else if (*p
== '.') {
5435 /* each label has to be 1-63 characters;
5436 we allow [.] at the end ('foo.bar.') */
5438 if ((d
<= 0) || (d
>= 64))
5440 ptr
= p
+ 1; /* jump to the next label */
5441 if ((dots
> 0) && (len
> 0))
5443 } else if (isalnum((unsigned char)*p
) == 0) {
5444 /* also numbers at the begin are fine */
5448 return(dots
? -1 : 0);
5451 static int check_domain_name_list(const char *ptr
, size_t len
, int dots
)
5454 int ret
= -1; /* at least one needed */
5456 if ((ptr
== NULL
) || (len
== 0))
5459 for (p
=ptr
; (*p
!= 0) && (len
> 0); p
++, len
--) {
5463 if (check_domain_name(ptr
, p
- ptr
, dots
) != 0)
5470 return(check_domain_name(ptr
, p
- ptr
, dots
));
5475 static int check_option_values(struct universe
*universe
,
5483 /* just reject options we want to protect, will be escaped anyway */
5484 if ((universe
== NULL
) || (universe
== &dhcp_universe
)) {
5486 case DHO_DOMAIN_NAME
:
5487 #ifdef ACCEPT_LIST_IN_DOMAIN_NAME
5488 return check_domain_name_list(ptr
, len
, 0);
5490 return check_domain_name(ptr
, len
, 0);
5493 case DHO_NIS_DOMAIN
:
5494 case DHO_NETBIOS_SCOPE
:
5495 return check_domain_name(ptr
, len
, 0);
5497 case DHO_DOMAIN_SEARCH
:
5498 return check_domain_name_list(ptr
, len
, 0);
5503 for (; (*ptr
!= 0) && (len
-- > 0); ptr
++) {
5504 if(!(isalnum((unsigned char)*ptr
) ||
5505 *ptr
== '#' || *ptr
== '%' ||
5506 *ptr
== '+' || *ptr
== '-' ||
5507 *ptr
== '_' || *ptr
== ':' ||
5508 *ptr
== '.' || *ptr
== ',' ||
5509 *ptr
== '@' || *ptr
== '~' ||
5510 *ptr
== '\\' || *ptr
== '/' ||
5511 *ptr
== '[' || *ptr
== ']' ||
5512 *ptr
== '=' || *ptr
== ' '))
5521 if (universe
== &dhcpv6_universe
) {
5523 case D6O_SIP_SERVERS_DNS
:
5524 case D6O_DOMAIN_SEARCH
:
5525 case D6O_NIS_DOMAIN_NAME
:
5526 case D6O_NISP_DOMAIN_NAME
:
5527 return check_domain_name_list(ptr
, len
, 0);
5537 add_reject(struct packet
*packet
) {
5538 struct iaddrmatchlist
*list
;
5540 list
= dmalloc(sizeof(struct iaddrmatchlist
), MDL
);
5542 log_fatal ("no memory for reject list!");
5545 * client_addr is misleading - it is set to source address in common
5548 list
->match
.addr
= packet
->client_addr
;
5549 /* Set mask to indicate host address. */
5550 list
->match
.mask
.len
= list
->match
.addr
.len
;
5551 memset(list
->match
.mask
.iabuf
, 0xff, sizeof(list
->match
.mask
.iabuf
));
5553 /* Append to reject list for the source interface. */
5554 list
->next
= packet
->interface
->client
->config
->reject_list
;
5555 packet
->interface
->client
->config
->reject_list
= list
;
5558 * We should inform user that we won't be accepting this server
5561 log_info("Server added to list of rejected servers.");
5564 #if defined(NSUPDATE)
5565 /* Wrapper function around common ddns_cb_free function that ensures
5566 * we set the client_state pointer to the control block to NULL. */
5568 dhclient_ddns_cb_free(dhcp_ddns_cb_t
*ddns_cb
, char* file
, int line
) {
5570 struct client_state
*client
= (struct client_state
*)ddns_cb
->lease
;
5571 if (client
!= NULL
) {
5572 client
->ddns_cb
= NULL
;
5575 ddns_cb_free(ddns_cb
, file
, line
);
5578 #endif /* defined NSUPDATE */
5580 #if defined(DHCPv6) && defined(DHCP4o6)
5582 * \brief Omapi I/O handler
5584 * The inter-process communication receive handler.
5586 * On the DHCPv6 side, the message is either a POLL (which is answered
5587 * by a START or a STOP) or a DHCPv4-QUERY (which is forwarded to
5588 * DHCPv4 over DHCPv6 servers by forw_dhcpv4_query()).
5590 * On the DHCPv4 side, the message is either a START, a STOP
5591 * (both for the DHCP4 over DHCPv6 state machine) or a DHCPv4-RESPONSE
5592 * (which is processed by recv_dhcpv4_response()).
5594 * \param h the OMAPI object
5595 * \return a result for I/O success or error (used by the I/O subsystem)
5597 isc_result_t
dhcpv4o6_handler(omapi_object_t
*h
) {
5599 char start_msg
[5] = { 'S', 'T', 'A', 'R', 'T' };
5600 char stop_msg
[4] = { 'S', 'T', 'O', 'P' };
5601 char poll_msg
[4] = { 'P', 'O', 'L', 'L' };
5602 struct data_string raw
;
5605 if (h
->type
!= dhcp4o6_type
)
5606 return DHCP_R_INVALIDARG
;
5608 cc
= recv(dhcp4o6_fd
, buf
, sizeof(buf
), 0);
5610 return ISC_R_UNEXPECTED
;
5612 if (local_family
== AF_INET6
) {
5614 (memcmp(buf
, poll_msg
, sizeof(poll_msg
)) == 0)) {
5615 log_info("RCV: POLL");
5616 if (dhcp4o6_state
< 0)
5617 cc
= send(dhcp4o6_fd
, stop_msg
,
5618 sizeof(stop_msg
), 0);
5620 cc
= send(dhcp4o6_fd
, start_msg
,
5621 sizeof(start_msg
), 0);
5623 log_error("dhcpv4o6_handler: send(): %m");
5624 return ISC_R_IOERROR
;
5627 if (cc
< DHCP_FIXED_NON_UDP
+ 8)
5628 return ISC_R_UNEXPECTED
;
5629 memset(&raw
, 0, sizeof(raw
));
5630 if (!buffer_allocate(&raw
.buffer
, cc
, MDL
)) {
5631 log_error("dhcpv4o6_handler: "
5632 "no memory buffer.");
5633 return ISC_R_NOMEMORY
;
5635 raw
.data
= raw
.buffer
->data
;
5637 memcpy(raw
.buffer
->data
, buf
, cc
);
5639 forw_dhcpv4_query(&raw
);
5641 data_string_forget(&raw
, MDL
);
5645 (memcmp(buf
, stop_msg
, sizeof(stop_msg
)) == 0)) {
5646 log_info("RCV: STOP");
5647 if (dhcp4o6_state
> 0) {
5651 } else if ((cc
== 5) &&
5652 (memcmp(buf
, start_msg
, sizeof(start_msg
)) == 0)) {
5653 log_info("RCV: START");
5654 if (dhcp4o6_state
== 0)
5655 cancel_timeout(dhcp4o6_poll
, NULL
);
5659 if (cc
< DHCP_FIXED_NON_UDP
+ 16)
5660 return ISC_R_UNEXPECTED
;
5661 memset(&raw
, 0, sizeof(raw
));
5662 if (!buffer_allocate(&raw
.buffer
, cc
, MDL
)) {
5663 log_error("dhcpv4o6_handler: "
5664 "no memory buffer.");
5665 return ISC_R_NOMEMORY
;
5667 raw
.data
= raw
.buffer
->data
;
5669 memcpy(raw
.buffer
->data
, buf
, cc
);
5671 recv_dhcpv4_response(&raw
);
5673 data_string_forget(&raw
, MDL
);
5677 return ISC_R_SUCCESS
;
5681 * \brief Poll the DHCPv6 client
5682 * (DHCPv4 client function)
5684 * A POLL message is sent to the DHCPv6 client periodically to check
5685 * if the DHCPv6 is ready (i.e., has a valid DHCPv4-over-DHCPv6 server
5688 static void dhcp4o6_poll(void *dummy
) {
5689 char msg
[4] = { 'P', 'O', 'L', 'L' };
5693 IGNORE_UNUSED(dummy
);
5695 if (dhcp4o6_state
< 0)
5700 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5702 log_error("dhcp4o6_poll: send(): %m");
5704 tv
.tv_sec
= cur_time
+ 60;
5705 tv
.tv_usec
= random() % 1000000;
5707 add_timeout(&tv
, dhcp4o6_poll
, NULL
, 0, 0);
5711 * \brief Resume pending operations
5712 * (DHCPv4 client function)
5714 * A START message was received from the DHCPv6 client so pending
5715 * operations (RELEASE or REBOOT) must be resumed.
5717 static void dhcp4o6_resume() {
5718 struct interface_info
*ip
;
5719 struct client_state
*client
;
5721 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
5722 for (client
= ip
->client
; client
!= NULL
;
5723 client
= client
->next
) {
5724 if (client
->pending
== P_RELEASE
)
5726 else if (client
->pending
== P_REBOOT
)
5727 state_reboot(client
);
5733 * \brief Send a START to the DHCPv4 client
5734 * (DHCPv6 client function)
5736 * First check if there is a valid DHCPv4-over-DHCPv6 server address option,
5737 * and when found go UP and on a transition from another state send
5738 * a START message to the DHCPv4 client.
5740 void dhcp4o6_start() {
5741 struct interface_info
*ip
;
5742 struct client_state
*client
;
5743 struct dhc6_lease
*lease
;
5744 struct option_cache
*oc
;
5745 struct data_string addrs
;
5746 char msg
[5] = { 'S', 'T', 'A', 'R', 'T' };
5749 memset(&addrs
, 0, sizeof(addrs
));
5750 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
5751 for (client
= ip
->client
; client
!= NULL
;
5752 client
= client
->next
) {
5753 if ((client
->state
!= S_BOUND
) &&
5754 (client
->state
!= S_RENEWING
) &&
5755 (client
->state
!= S_REBINDING
))
5757 lease
= client
->active_lease
;
5758 if ((lease
== NULL
) || lease
->released
)
5760 oc
= lookup_option(&dhcpv6_universe
,
5762 D6O_DHCP4_O_DHCP6_SERVER
);
5764 !evaluate_option_cache(&addrs
, NULL
, NULL
, NULL
,
5765 lease
->options
, NULL
,
5766 &global_scope
, oc
, MDL
))
5768 if ((addrs
.len
% 16) != 0) {
5769 data_string_forget(&addrs
, MDL
);
5772 data_string_forget(&addrs
, MDL
);
5776 log_info("dhcp4o6_start: failed");
5781 if (dhcp4o6_state
== 1)
5783 log_info("dhcp4o6_start: go to UP");
5786 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5788 log_info("dhcp4o6_start: send(): %m");
5792 * Send a STOP to the DHCPv4 client
5793 * (DHCPv6 client function)
5795 * Go DOWN and on a transition from another state send a STOP message
5796 * to the DHCPv4 client.
5798 static void dhcp4o6_stop() {
5799 char msg
[4] = { 'S', 'T', 'O', 'P' };
5802 if (dhcp4o6_state
== -1)
5805 log_info("dhcp4o6_stop: go to DOWN");
5808 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5810 log_error("dhcp4o6_stop: send(): %m");
5812 #endif /* DHCPv6 && DHCP4o6 */