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 /* check_v6only is called by dhcpoffer and dhcpack. It checks if a
1246 * requested v6-only-preferred option is present and returned the
1247 * V6ONLY_WAIT delay to suspend DHCPv4. */
1249 uint32_t check_v6only(packet
, client
)
1250 struct packet
*packet
;
1251 struct client_state
*client
;
1254 struct option
**req
;
1255 isc_boolean_t found
= ISC_FALSE
;
1256 struct option_cache
*oc
;
1257 struct data_string data
;
1258 uint32_t v6only_wait
= 0;
1260 /* Check if the v6-only-preferred was requested. */
1261 req
= client
->config
->requested_options
;
1266 for (i
= 0 ; req
[i
] != NULL
; i
++) {
1267 if ((req
[i
]->universe
== &dhcp_universe
) &&
1268 (req
[i
]->code
== DHO_V6_ONLY_PREFERRED
)) {
1274 if (found
== ISC_FALSE
)
1277 /* Get the V6ONLY_WAIT timer. */
1278 oc
= lookup_option(&dhcp_universe
, packet
->options
,
1279 DHO_V6_ONLY_PREFERRED
);
1283 memset(&data
, 0, sizeof(data
));
1285 if (evaluate_option_cache(&data
, packet
, (struct lease
*)0, client
,
1286 packet
->options
, (struct option_state
*)0,
1287 &global_scope
, oc
, MDL
)) {
1289 v6only_wait
= getULong(data
.data
);
1290 if (v6only_wait
< MIN_V6ONLY_WAIT
)
1291 v6only_wait
= MIN_V6ONLY_WAIT
;
1293 data_string_forget(&data
, MDL
);
1296 return (v6only_wait
);
1299 /* finish_v6only is called when the V6ONLY_WAIT timer expired. */
1301 void finish_v6only(cpp
)
1304 struct client_state
*client
= cpp
;
1306 cancel_timeout(finish_v6only
, client
);
1307 client
->state
= S_INIT
;
1312 * start_v6only is called when a requested v6-only-preferred option was
1313 * returned by the server. */
1315 void start_v6only(client
, v6only_wait
)
1316 struct client_state
*client
;
1317 uint32_t v6only_wait
;
1321 /* Enter V6ONLY state. */
1323 client
->state
= S_V6ONLY
;
1325 /* Run the client script. */
1326 script_init(client
, "V6ONLY", NULL
);
1327 if (client
->active
) {
1328 script_write_params(client
, "old_", client
->active
);
1329 destroy_client_lease(client
->active
);
1330 client
->active
= NULL
;
1332 script_write_requested(client
);
1333 client_envadd(client
, "", "v6-only-preferred", "%lu",
1334 (long unsigned)v6only_wait
);
1337 /* Trigger finish_v6only after V6ONLY_WAIT seconds. */
1338 tv
.tv_sec
= cur_tv
.tv_sec
+ v6only_wait
;
1339 tv
.tv_usec
= cur_tv
.tv_usec
;
1341 add_timeout(&tv
, finish_v6only
, client
, 0, 0);
1345 * state_selecting is called when one or more DHCPOFFER packets have been
1346 * received and a configurable period of time has passed.
1349 void state_selecting (cpp
)
1352 struct client_state
*client
= cpp
;
1353 struct client_lease
*lp
, *next
, *picked
;
1356 ASSERT_STATE(state
, S_SELECTING
);
1359 * Cancel state_selecting and send_discover timeouts, since either
1360 * one could have got us here.
1362 cancel_timeout (state_selecting
, client
);
1363 cancel_timeout (send_discover
, client
);
1366 * We have received one or more DHCPOFFER packets. Currently,
1367 * the only criterion by which we judge leases is whether or
1368 * not we get a response when we arp for them.
1371 for (lp
= client
-> offered_leases
; lp
; lp
= next
) {
1375 * Check to see if we got an ARPREPLY for the address
1376 * in this particular lease.
1380 picked
-> next
= NULL
;
1382 destroy_client_lease (lp
);
1385 client
-> offered_leases
= NULL
;
1388 * If we just tossed all the leases we were offered, go back
1392 client
-> state
= S_INIT
;
1393 state_init (client
);
1397 /* If it was a BOOTREPLY, we can just take the address right now. */
1398 if (picked
-> is_bootp
) {
1399 client
-> new = picked
;
1401 /* Make up some lease expiry times
1402 XXX these should be configurable. */
1403 client
-> new -> expiry
= cur_time
+ 12000;
1404 client
-> new -> renewal
+= cur_time
+ 8000;
1405 client
-> new -> rebind
+= cur_time
+ 10000;
1407 client
-> state
= S_REQUESTING
;
1409 /* Bind to the address we received. */
1410 bind_lease (client
);
1414 /* Go to the REQUESTING state. */
1415 client
-> destination
= iaddr_broadcast
;
1416 client
-> state
= S_REQUESTING
;
1417 client
-> first_sending
= cur_time
;
1418 client
-> interval
= client
-> config
-> initial_interval
;
1420 /* Make a DHCPREQUEST packet from the lease we picked. */
1421 make_request (client
, picked
);
1422 client
-> xid
= client
-> packet
.xid
;
1424 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
1425 destroy_client_lease (picked
);
1427 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
1428 send_request (client
);
1431 /* state_requesting is called when we receive a DHCPACK message after
1432 having sent out one or more DHCPREQUEST packets. */
1434 void dhcpack (packet
)
1435 struct packet
*packet
;
1437 struct interface_info
*ip
= packet
-> interface
;
1438 struct client_state
*client
;
1439 uint32_t v6only_wait
;
1440 struct client_lease
*lease
;
1441 struct option_cache
*oc
;
1442 struct data_string ds
;
1444 /* If we're not receptive to an offer right now, or if the offer
1445 has an unrecognizable transaction id, then just drop it. */
1446 for (client
= ip
-> client
; client
; client
= client
-> next
) {
1447 if (client
-> xid
== packet
-> raw
-> xid
)
1451 (packet
-> interface
-> hw_address
.hlen
- 1 !=
1452 packet
-> raw
-> hlen
) ||
1453 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
1454 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
1456 log_debug ("DHCPACK in wrong transaction.");
1461 if (client
-> state
!= S_REBOOTING
&&
1462 client
-> state
!= S_REQUESTING
&&
1463 client
-> state
!= S_RENEWING
&&
1464 client
-> state
!= S_REBINDING
) {
1466 log_debug ("DHCPACK in wrong state.");
1471 log_info ("DHCPACK of %s from %s",
1472 inet_ntoa(packet
->raw
->yiaddr
),
1473 piaddr (packet
->client_addr
));
1475 /* Check v6only first. */
1476 v6only_wait
= check_v6only(packet
, client
);
1477 if (v6only_wait
> 0) {
1478 log_info("v6 only preferred for %lu.",
1479 (long unsigned)v6only_wait
);
1480 cancel_timeout(send_request
, client
);
1481 start_v6only(client
, v6only_wait
);
1485 lease
= packet_to_lease (packet
, client
);
1487 log_info ("packet_to_lease failed.");
1491 client
-> new = lease
;
1493 /* Stop resending DHCPREQUEST. */
1494 cancel_timeout (send_request
, client
);
1496 /* Figure out the lease time. */
1497 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1498 DHO_DHCP_LEASE_TIME
);
1499 memset (&ds
, 0, sizeof ds
);
1501 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1502 packet
-> options
, client
-> new -> options
,
1503 &global_scope
, oc
, MDL
)) {
1505 client
-> new -> expiry
= getULong (ds
.data
);
1507 client
-> new -> expiry
= 0;
1508 data_string_forget (&ds
, MDL
);
1510 client
-> new -> expiry
= 0;
1512 if (client
->new->expiry
== 0) {
1515 log_error ("no expiry time on offered lease.");
1517 /* Quench this (broken) server. Return to INIT to reselect. */
1520 /* 1/2 second delay to restart at INIT. */
1521 tv
.tv_sec
= cur_tv
.tv_sec
;
1522 tv
.tv_usec
= cur_tv
.tv_usec
+ 500000;
1524 if (tv
.tv_usec
>= 1000000) {
1526 tv
.tv_usec
-= 1000000;
1529 add_timeout(&tv
, state_init
, client
, 0, 0);
1534 * A number that looks negative here is really just very large,
1535 * because the lease expiry offset is unsigned.
1537 if (client
->new->expiry
< 0)
1538 client
->new->expiry
= TIME_MAX
;
1540 /* Take the server-provided renewal time if there is one. */
1541 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1542 DHO_DHCP_RENEWAL_TIME
);
1544 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1545 packet
-> options
, client
-> new -> options
,
1546 &global_scope
, oc
, MDL
)) {
1548 client
-> new -> renewal
= getULong (ds
.data
);
1550 client
-> new -> renewal
= 0;
1551 data_string_forget (&ds
, MDL
);
1553 client
-> new -> renewal
= 0;
1555 /* If it wasn't specified by the server, calculate it. */
1556 if (!client
-> new -> renewal
)
1557 client
-> new -> renewal
= client
-> new -> expiry
/ 2 + 1;
1559 if (client
-> new -> renewal
<= 0)
1560 client
-> new -> renewal
= TIME_MAX
;
1562 /* Now introduce some randomness to the renewal time: */
1563 if (client
->new->renewal
<= ((TIME_MAX
/ 3) - 3))
1564 client
->new->renewal
= (((client
->new->renewal
* 3) + 3) / 4) +
1565 (((random() % client
->new->renewal
) + 3) / 4);
1567 /* Same deal with the rebind time. */
1568 oc
= lookup_option (&dhcp_universe
, client
-> new -> options
,
1569 DHO_DHCP_REBINDING_TIME
);
1571 evaluate_option_cache (&ds
, packet
, (struct lease
*)0, client
,
1572 packet
-> options
, client
-> new -> options
,
1573 &global_scope
, oc
, MDL
)) {
1575 client
-> new -> rebind
= getULong (ds
.data
);
1577 client
-> new -> rebind
= 0;
1578 data_string_forget (&ds
, MDL
);
1580 client
-> new -> rebind
= 0;
1582 if (client
-> new -> rebind
<= 0) {
1583 if (client
-> new -> expiry
<= TIME_MAX
/ 7)
1584 client
-> new -> rebind
=
1585 client
-> new -> expiry
* 7 / 8;
1587 client
-> new -> rebind
=
1588 client
-> new -> expiry
/ 8 * 7;
1591 /* Make sure our randomness didn't run the renewal time past the
1593 if (client
-> new -> renewal
> client
-> new -> rebind
) {
1594 if (client
-> new -> rebind
<= TIME_MAX
/ 3)
1595 client
-> new -> renewal
=
1596 client
-> new -> rebind
* 3 / 4;
1598 client
-> new -> renewal
=
1599 client
-> new -> rebind
/ 4 * 3;
1602 client
-> new -> expiry
+= cur_time
;
1603 /* Lease lengths can never be negative. */
1604 if (client
-> new -> expiry
< cur_time
)
1605 client
-> new -> expiry
= TIME_MAX
;
1606 client
-> new -> renewal
+= cur_time
;
1607 if (client
-> new -> renewal
< cur_time
)
1608 client
-> new -> renewal
= TIME_MAX
;
1609 client
-> new -> rebind
+= cur_time
;
1610 if (client
-> new -> rebind
< cur_time
)
1611 client
-> new -> rebind
= TIME_MAX
;
1613 bind_lease (client
);
1616 void bind_lease (client
)
1617 struct client_state
*client
;
1621 /* Remember the medium. */
1622 client
->new->medium
= client
->medium
;
1624 /* Run the client script with the new parameters. */
1625 script_init(client
, (client
->state
== S_REQUESTING
? "BOUND" :
1626 (client
->state
== S_RENEWING
? "RENEW" :
1627 (client
->state
== S_REBOOTING
? "REBOOT" :
1629 client
->new->medium
);
1630 if (client
->active
&& client
->state
!= S_REBOOTING
)
1631 script_write_params(client
, "old_", client
->active
);
1632 script_write_params(client
, "new_", client
->new);
1633 script_write_requested(client
);
1635 script_write_params(client
, "alias_", client
->alias
);
1637 /* If the BOUND/RENEW code detects another machine using the
1638 offered address, it exits nonzero. We need to send a
1639 DHCPDECLINE and toss the lease. */
1640 if (script_go(client
)) {
1641 make_decline(client
, client
->new);
1642 send_decline(client
);
1643 destroy_client_lease(client
->new);
1647 log_info("Unable to obtain a lease on first "
1648 "try (declined). Exiting.");
1651 #if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
1652 /* Let's call a script and we're done */
1653 script_init(client
, "FAIL", (struct string_list
*)0);
1659 tv
.tv_sec
= cur_tv
.tv_sec
+ decline_wait_time
;
1660 tv
.tv_usec
= cur_tv
.tv_usec
;
1661 add_timeout(&tv
, state_init
, client
, 0, 0);
1666 /* Write out the new lease if it has been long enough. */
1667 if (!client
->last_write
||
1668 (cur_time
- client
->last_write
) >= MIN_LEASE_WRITE
)
1669 write_client_lease(client
, client
->new, 0, 1);
1671 /* Replace the old active lease with the new one. */
1672 if (client
->active
) {
1673 if (client
->active
->is_static
) {
1674 // We need to preserve the fallback lease in case
1675 // we lose DHCP service again.
1676 add_to_tail(&client
->leases
, client
->active
);
1678 destroy_client_lease(client
->active
);
1682 client
->active
= client
->new;
1685 /* Set up a timeout to start the renewal process. */
1686 tv
.tv_sec
= client
->active
->renewal
;
1687 tv
.tv_usec
= ((client
->active
->renewal
- cur_tv
.tv_sec
) > 1) ?
1688 random() % 1000000 : cur_tv
.tv_usec
;
1689 add_timeout(&tv
, state_bound
, client
, 0, 0);
1691 log_info("bound to %s -- renewal in %ld seconds.",
1692 piaddr(client
->active
->address
),
1693 (long)(client
->active
->renewal
- cur_time
));
1694 client
->state
= S_BOUND
;
1695 reinitialize_interfaces();
1697 #if defined (NSUPDATE)
1698 if (client
->config
->do_forward_update
)
1699 dhclient_schedule_updates(client
, &client
->active
->address
, 1);
1700 #endif /* defined NSUPDATE */
1704 /* state_bound is called when we've successfully bound to a particular
1705 lease, but the renewal time on that lease has expired. We are
1706 expected to unicast a DHCPREQUEST to the server that gave us our
1709 void state_bound (cpp
)
1712 struct client_state
*client
= cpp
;
1713 struct option_cache
*oc
;
1714 struct data_string ds
;
1716 ASSERT_STATE(state
, S_BOUND
);
1718 /* T1 has expired. */
1719 make_request (client
, client
-> active
);
1720 client
-> xid
= client
-> packet
.xid
;
1722 memset (&ds
, 0, sizeof ds
);
1723 oc
= lookup_option (&dhcp_universe
, client
-> active
-> options
,
1724 DHO_DHCP_SERVER_IDENTIFIER
);
1726 evaluate_option_cache (&ds
, (struct packet
*)0, (struct lease
*)0,
1727 client
, (struct option_state
*)0,
1728 client
-> active
-> options
,
1729 &global_scope
, oc
, MDL
)) {
1731 memcpy (client
-> destination
.iabuf
, ds
.data
, 4);
1732 client
-> destination
.len
= 4;
1734 client
-> destination
= iaddr_broadcast
;
1736 data_string_forget (&ds
, MDL
);
1738 client
-> destination
= iaddr_broadcast
;
1740 client
-> first_sending
= cur_time
;
1741 client
-> interval
= client
-> config
-> initial_interval
;
1742 client
-> state
= S_RENEWING
;
1744 /* Send the first packet immediately. */
1745 send_request (client
);
1748 /* state_stop is called when we've been told to shut down. We unconfigure
1749 the interfaces, and then stop operating until told otherwise. */
1751 void state_stop (cpp
)
1754 struct client_state
*client
= cpp
;
1756 client
->pending
= P_NONE
;
1758 /* Cancel all timeouts. */
1759 cancel_timeout(state_selecting
, client
);
1760 cancel_timeout(send_discover
, client
);
1761 cancel_timeout(send_request
, client
);
1762 cancel_timeout(state_bound
, client
);
1763 cancel_timeout(finish_v6only
, client
);
1765 /* If we have an address, unconfigure it. */
1766 if (client
->active
) {
1767 script_init(client
, "STOP", client
->active
->medium
);
1768 script_write_params(client
, "old_", client
->active
);
1769 script_write_requested(client
);
1771 script_write_params(client
, "alias_", client
->alias
);
1776 int commit_leases ()
1781 int write_lease (lease
)
1782 struct lease
*lease
;
1787 int write_host (host
)
1788 struct host_decl
*host
;
1793 void db_startup (testp
)
1799 struct packet
*packet
;
1801 struct iaddrmatchlist
*ap
;
1805 if (packet
-> raw
-> op
!= BOOTREPLY
)
1808 /* If there's a reject list, make sure this packet's sender isn't
1810 for (ap
= packet
-> interface
-> client
-> config
-> reject_list
;
1811 ap
; ap
= ap
-> next
) {
1812 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1814 /* piaddr() returns its result in a static
1815 buffer sized 4*16 (see common/inet.c). */
1817 strcpy(addrbuf
, piaddr(ap
->match
.addr
));
1818 strcpy(maskbuf
, piaddr(ap
->match
.mask
));
1820 log_info("BOOTREPLY from %s rejected by rule %s "
1821 "mask %s.", piaddr(packet
->client_addr
),
1832 struct packet
*packet
;
1834 struct iaddrmatchlist
*ap
;
1835 void (*handler
) (struct packet
*);
1840 switch (packet
-> packet_type
) {
1842 handler
= dhcpoffer
;
1860 /* If there's a reject list, make sure this packet's sender isn't
1862 for (ap
= packet
-> interface
-> client
-> config
-> reject_list
;
1863 ap
; ap
= ap
-> next
) {
1864 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1866 /* piaddr() returns its result in a static
1867 buffer sized 4*16 (see common/inet.c). */
1869 strcpy(addrbuf
, piaddr(ap
->match
.addr
));
1870 strcpy(maskbuf
, piaddr(ap
->match
.mask
));
1872 log_info("%s from %s rejected by rule %s mask %s.",
1873 type
, piaddr(packet
->client_addr
),
1878 (*handler
) (packet
);
1883 dhcpv6(struct packet
*packet
) {
1884 struct iaddrmatchlist
*ap
;
1885 struct client_state
*client
;
1886 char addrbuf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
1888 /* Silently drop bogus messages. */
1889 if (packet
->dhcpv6_msg_type
>= dhcpv6_type_name_max
)
1892 /* Discard, with log, packets from quenched sources. */
1893 for (ap
= packet
->interface
->client
->config
->reject_list
;
1894 ap
; ap
= ap
->next
) {
1895 if (addr_match(&packet
->client_addr
, &ap
->match
)) {
1896 strcpy(addrbuf
, piaddr(packet
->client_addr
));
1897 log_info("%s from %s rejected by rule %s",
1898 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1900 piaddrmask(&ap
->match
.addr
, &ap
->match
.mask
));
1905 /* Screen out nonsensical messages. */
1906 switch(packet
->dhcpv6_msg_type
) {
1908 case DHCPV6_DHCPV4_RESPONSE
:
1909 if (dhcpv4_over_dhcpv6
) {
1910 log_info("RCV: %s message on %s from %s.",
1911 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1912 packet
->interface
->name
,
1913 piaddr(packet
->client_addr
));
1914 forw_dhcpv4_response(packet
);
1918 case DHCPV6_ADVERTISE
:
1919 case DHCPV6_RECONFIGURE
:
1924 log_info("RCV: %s message on %s from %s.",
1925 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
1926 packet
->interface
->name
, piaddr(packet
->client_addr
));
1933 /* Find a client state that matches the incoming XID. */
1934 for (client
= packet
->interface
->client
; client
;
1935 client
= client
->next
) {
1936 if (memcmp(&client
->dhcpv6_transaction_id
,
1937 packet
->dhcpv6_transaction_id
, 3) == 0) {
1938 client
->v6_handler(packet
, client
);
1943 /* XXX: temporary log for debugging */
1944 log_info("Packet received, but nothing done with it.");
1949 * \brief Forward a DHCPv4-response to the DHCPv4 client.
1950 * (DHCPv6 client function)
1952 * The DHCPv6 client receives a DHCPv4-response which is forwarded
1953 * to the DHCPv4 client.
1954 * Format: address:16 + DHCPv4 message content
1955 * (we have no state to keep the address so it is transported in
1956 * DHCPv6 <-> DHCPv6 inter-process messages)
1958 * \param packet the DHCPv4-response packet
1960 static void forw_dhcpv4_response(struct packet
*packet
)
1962 struct option_cache
*oc
;
1963 struct data_string enc_opt_data
;
1964 struct data_string ds
;
1968 * Discard if relay is not ready.
1970 if (dhcp4o6_state
== -1) {
1971 log_info("forw_dhcpv4_response: not ready.");
1975 if (packet
->client_addr
.len
!= 16) {
1976 log_error("forw_dhcpv4_response: bad address");
1981 * Get our encapsulated DHCPv4 message.
1983 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_DHCPV4_MSG
);
1985 log_info("DHCPv4-response from %s missing "
1986 "DHCPv4 Message option.",
1987 piaddr(packet
->client_addr
));
1991 memset(&enc_opt_data
, 0, sizeof(enc_opt_data
));
1992 if (!evaluate_option_cache(&enc_opt_data
, NULL
, NULL
, NULL
,
1993 NULL
, NULL
, &global_scope
, oc
, MDL
)) {
1994 log_error("forw_dhcpv4_response: error evaluating "
1996 data_string_forget(&enc_opt_data
, MDL
);
2000 if (enc_opt_data
.len
< DHCP_FIXED_NON_UDP
) {
2001 log_error("forw_dhcpv4_response: "
2002 "no memory for encapsulated packet.");
2003 data_string_forget(&enc_opt_data
, MDL
);
2010 memset(&ds
, 0, sizeof(ds
));
2011 if (!buffer_allocate(&ds
.buffer
, enc_opt_data
.len
+ 16, MDL
)) {
2012 log_error("forw_dhcpv4_response: no memory buffer.");
2013 data_string_forget(&enc_opt_data
, MDL
);
2016 ds
.data
= ds
.buffer
->data
;
2017 ds
.len
= enc_opt_data
.len
+ 16;
2018 memcpy(ds
.buffer
->data
, enc_opt_data
.data
, enc_opt_data
.len
);
2019 memcpy(ds
.buffer
->data
+ enc_opt_data
.len
,
2020 packet
->client_addr
.iabuf
, 16);
2021 data_string_forget(&enc_opt_data
, MDL
);
2026 cc
= send(dhcp4o6_fd
, ds
.data
, ds
.len
, 0);
2028 log_error("forw_dhcpv4_response: send(): %m");
2030 data_string_forget(&ds
, MDL
);
2034 * \brief Receive a DHCPv4-response from the DHCPv6 client.
2035 * (DHCPv4 client function)
2037 * The DHCPv4 client receives a DHCPv4-response forwarded
2038 * by the DHCPv6 client (using \ref forw_dhcpv4_response())
2040 * \param raw the DHCPv4-response raw packet
2042 static void recv_dhcpv4_response(struct data_string
*raw
)
2044 struct packet
*packet
;
2047 if (interfaces
== NULL
) {
2048 log_error("recv_dhcpv4_response: no interfaces.");
2053 memcpy(from
.iabuf
, raw
->data
+ (raw
->len
- 16), 16);
2056 * Build a packet structure.
2059 if (!packet_allocate(&packet
, MDL
)) {
2060 log_error("recv_dhcpv4_response: no memory for packet.");
2064 packet
->raw
= (struct dhcp_packet
*) raw
->data
;
2065 packet
->packet_length
= raw
->len
- 16;
2066 packet
->client_port
= remote_port
;
2067 packet
->client_addr
= from
;
2068 interface_reference(&packet
->interface
, interfaces
, MDL
);
2070 /* Allocate packet->options now so it is non-null for all packets */
2071 if (!option_state_allocate (&packet
->options
, MDL
)) {
2072 log_error("recv_dhcpv4_response: no memory for options.");
2073 packet_dereference (&packet
, MDL
);
2077 /* If there's an option buffer, try to parse it. */
2078 if (packet
->packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
2079 struct option_cache
*op
;
2080 if (!parse_options(packet
)) {
2081 if (packet
->options
)
2082 option_state_dereference
2083 (&packet
->options
, MDL
);
2084 packet_dereference (&packet
, MDL
);
2088 if (packet
->options_valid
&&
2089 (op
= lookup_option(&dhcp_universe
,
2091 DHO_DHCP_MESSAGE_TYPE
))) {
2092 struct data_string dp
;
2093 memset(&dp
, 0, sizeof dp
);
2094 evaluate_option_cache(&dp
, packet
, NULL
, NULL
,
2095 packet
->options
, NULL
,
2098 packet
->packet_type
= dp
.data
[0];
2100 packet
->packet_type
= 0;
2101 data_string_forget(&dp
, MDL
);
2105 if (validate_packet(packet
) != 0) {
2106 if (packet
->packet_type
)
2112 /* If the caller kept the packet, they'll have upped the refcnt. */
2113 packet_dereference(&packet
, MDL
);
2115 #endif /* DHCP4o6 */
2118 void dhcpoffer (packet
)
2119 struct packet
*packet
;
2121 struct interface_info
*ip
= packet
-> interface
;
2122 struct client_state
*client
;
2123 uint32_t v6only_wait
;
2124 struct client_lease
*lease
, *lp
;
2125 struct option
**req
;
2128 const char *name
= packet
-> packet_type
? "DHCPOFFER" : "BOOTREPLY";
2133 dump_packet (packet
);
2136 /* Find a client state that matches the xid... */
2137 for (client
= ip
-> client
; client
; client
= client
-> next
)
2138 if (client
-> xid
== packet
-> raw
-> xid
)
2141 /* If we're not receptive to an offer right now, or if the offer
2142 has an unrecognizable transaction id, then just drop it. */
2144 client
-> state
!= S_SELECTING
||
2145 (packet
-> interface
-> hw_address
.hlen
- 1 !=
2146 packet
-> raw
-> hlen
) ||
2147 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
2148 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
2150 log_debug ("%s in wrong transaction.", name
);
2155 sprintf (obuf
, "%s of %s from %s", name
,
2156 inet_ntoa(packet
->raw
->yiaddr
),
2157 piaddr(packet
->client_addr
));
2159 /* Check v6only first. */
2160 v6only_wait
= check_v6only(packet
, client
);
2161 if (v6only_wait
> 0) {
2162 log_info("%s: v6 only preferred for %lu.", obuf
,
2163 (long unsigned)v6only_wait
);
2164 cancel_timeout(send_discover
, client
);
2165 start_v6only(client
, v6only_wait
);
2169 /* If this lease doesn't supply the minimum required DHCPv4 parameters,
2172 req
= client
->config
->required_options
;
2174 for (i
= 0 ; req
[i
] != NULL
; i
++) {
2175 if ((req
[i
]->universe
== &dhcp_universe
) &&
2176 !lookup_option(&dhcp_universe
, packet
->options
,
2178 struct option
*option
= NULL
;
2179 unsigned code
= req
[i
]->code
;
2181 option_code_hash_lookup(&option
,
2182 dhcp_universe
.code_hash
,
2186 log_info("%s: no %s option.", obuf
,
2189 log_info("%s: no unknown-%u option.",
2192 option_dereference(&option
, MDL
);
2199 /* If we've already seen this lease, don't record it again. */
2200 for (lease
= client
-> offered_leases
; lease
; lease
= lease
-> next
) {
2201 if (lease
-> address
.len
== sizeof packet
-> raw
-> yiaddr
&&
2202 !memcmp (lease
-> address
.iabuf
,
2203 &packet
-> raw
-> yiaddr
, lease
-> address
.len
)) {
2204 log_debug ("%s: already seen.", obuf
);
2209 lease
= packet_to_lease (packet
, client
);
2211 log_info ("%s: packet_to_lease failed.", obuf
);
2215 /* log it now, so it emits before the request goes out */
2216 log_info("%s", obuf
);
2218 /* If this lease was acquired through a BOOTREPLY, record that
2220 if (!packet
-> options_valid
|| !packet
-> packet_type
)
2221 lease
-> is_bootp
= 1;
2223 /* Record the medium under which this lease was offered. */
2224 lease
-> medium
= client
-> medium
;
2226 /* Figure out when we're supposed to stop selecting. */
2227 stop_selecting
= (client
-> first_sending
+
2228 client
-> config
-> select_interval
);
2230 /* If this is the lease we asked for, put it at the head of the
2231 list, and don't mess with the arp request timeout. */
2232 if (lease
-> address
.len
== client
-> requested_address
.len
&&
2233 !memcmp (lease
-> address
.iabuf
,
2234 client
-> requested_address
.iabuf
,
2235 client
-> requested_address
.len
)) {
2236 lease
-> next
= client
-> offered_leases
;
2237 client
-> offered_leases
= lease
;
2239 /* Put the lease at the end of the list. */
2240 lease
-> next
= (struct client_lease
*)0;
2241 if (!client
-> offered_leases
)
2242 client
-> offered_leases
= lease
;
2244 for (lp
= client
-> offered_leases
; lp
-> next
;
2251 /* If the selecting interval has expired, go immediately to
2252 state_selecting(). Otherwise, time out into
2253 state_selecting at the select interval. */
2254 if (stop_selecting
<= cur_tv
.tv_sec
)
2255 state_selecting (client
);
2257 tv
.tv_sec
= stop_selecting
;
2258 tv
.tv_usec
= cur_tv
.tv_usec
;
2259 add_timeout(&tv
, state_selecting
, client
, 0, 0);
2260 cancel_timeout(send_discover
, client
);
2264 /* Allocate a client_lease structure and initialize it from the parameters
2265 in the specified packet. */
2267 struct client_lease
*packet_to_lease (packet
, client
)
2268 struct packet
*packet
;
2269 struct client_state
*client
;
2271 struct client_lease
*lease
;
2273 struct option_cache
*oc
;
2274 struct option
*option
= NULL
;
2275 struct data_string data
;
2277 lease
= (struct client_lease
*)new_client_lease (MDL
);
2280 log_error("packet_to_lease: no memory to record lease.\n");
2284 memset(lease
, 0, sizeof(*lease
));
2286 /* Copy the lease options. */
2287 option_state_reference(&lease
->options
, packet
->options
, MDL
);
2289 lease
->address
.len
= sizeof(packet
->raw
->yiaddr
);
2290 memcpy(lease
->address
.iabuf
, &packet
->raw
->yiaddr
,
2291 lease
->address
.len
);
2293 lease
->next_srv_addr
.len
= sizeof(packet
->raw
->siaddr
);
2294 memcpy(lease
->next_srv_addr
.iabuf
, &packet
->raw
->siaddr
,
2295 lease
->next_srv_addr
.len
);
2297 memset(&data
, 0, sizeof(data
));
2299 if (client
-> config
-> vendor_space_name
) {
2300 i
= DHO_VENDOR_ENCAPSULATED_OPTIONS
;
2302 /* See if there was a vendor encapsulation option. */
2303 oc
= lookup_option (&dhcp_universe
, lease
-> options
, i
);
2305 client
-> config
-> vendor_space_name
&&
2306 evaluate_option_cache (&data
, packet
,
2307 (struct lease
*)0, client
,
2308 packet
-> options
, lease
-> options
,
2309 &global_scope
, oc
, MDL
)) {
2311 if (!option_code_hash_lookup(&option
,
2312 dhcp_universe
.code_hash
,
2314 log_fatal("Unable to find VENDOR "
2315 "option (%s:%d).", MDL
);
2316 parse_encapsulated_suboptions
2317 (packet
-> options
, option
,
2318 data
.data
, data
.len
, &dhcp_universe
,
2319 client
-> config
-> vendor_space_name
2322 option_dereference(&option
, MDL
);
2324 data_string_forget (&data
, MDL
);
2329 /* Figure out the overload flag. */
2330 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
2331 DHO_DHCP_OPTION_OVERLOAD
);
2333 evaluate_option_cache (&data
, packet
, (struct lease
*)0, client
,
2334 packet
-> options
, lease
-> options
,
2335 &global_scope
, oc
, MDL
)) {
2340 data_string_forget (&data
, MDL
);
2344 /* If the server name was filled out, copy it. */
2345 if (!(i
& 2) && packet
-> raw
-> sname
[0]) {
2347 /* Don't count on the NUL terminator. */
2348 for (len
= 0; len
< DHCP_SNAME_LEN
; len
++)
2349 if (!packet
-> raw
-> sname
[len
])
2351 lease
-> server_name
= dmalloc (len
+ 1, MDL
);
2352 if (!lease
-> server_name
) {
2353 log_error ("dhcpoffer: no memory for server name.\n");
2354 destroy_client_lease (lease
);
2355 return (struct client_lease
*)0;
2357 memcpy (lease
-> server_name
,
2358 packet
-> raw
-> sname
, len
);
2359 lease
-> server_name
[len
] = 0;
2363 /* Ditto for the filename. */
2364 if (!(i
& 1) && packet
-> raw
-> file
[0]) {
2366 /* Don't count on the NUL terminator. */
2367 for (len
= 0; len
< DHCP_FILE_LEN
; len
++)
2368 if (!packet
-> raw
-> file
[len
])
2370 lease
-> filename
= dmalloc (len
+ 1, MDL
);
2371 if (!lease
-> filename
) {
2372 log_error ("dhcpoffer: no memory for filename.\n");
2373 destroy_client_lease (lease
);
2374 return (struct client_lease
*)0;
2376 memcpy (lease
-> filename
,
2377 packet
-> raw
-> file
, len
);
2378 lease
-> filename
[len
] = 0;
2382 execute_statements_in_scope(NULL
, (struct packet
*)packet
, NULL
,
2383 client
, lease
->options
, lease
->options
,
2384 &global_scope
, client
->config
->on_receipt
,
2390 void dhcpnak (packet
)
2391 struct packet
*packet
;
2393 struct interface_info
*ip
= packet
-> interface
;
2394 struct client_state
*client
;
2396 /* Find a client state that matches the xid... */
2397 for (client
= ip
-> client
; client
; client
= client
-> next
)
2398 if (client
-> xid
== packet
-> raw
-> xid
)
2401 /* If we're not receptive to an offer right now, or if the offer
2402 has an unrecognizable transaction id, then just drop it. */
2404 (packet
-> interface
-> hw_address
.hlen
- 1 !=
2405 packet
-> raw
-> hlen
) ||
2406 (memcmp (&packet
-> interface
-> hw_address
.hbuf
[1],
2407 packet
-> raw
-> chaddr
, packet
-> raw
-> hlen
))) {
2409 log_debug ("DHCPNAK in wrong transaction.");
2414 if (client
-> state
!= S_REBOOTING
&&
2415 client
-> state
!= S_REQUESTING
&&
2416 client
-> state
!= S_RENEWING
&&
2417 client
-> state
!= S_REBINDING
) {
2419 log_debug ("DHCPNAK in wrong state.");
2424 log_info ("DHCPNAK from %s", piaddr (packet
-> client_addr
));
2426 if (!client
-> active
) {
2428 log_info ("DHCPNAK with no active lease.\n");
2433 /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
2434 * to indicate that we want all old bindings to be removed. (It
2435 * is possible that we may get a NAK while in the RENEW state,
2436 * so we might have bindings active at that time)
2438 script_init(client
, "EXPIRE", NULL
);
2439 script_write_params(client
, "old_", client
->active
);
2440 script_write_requested(client
);
2442 script_write_params(client
, "alias_", client
->alias
);
2445 destroy_client_lease (client
-> active
);
2446 client
-> active
= (struct client_lease
*)0;
2448 /* Stop sending DHCPREQUEST packets... */
2449 cancel_timeout (send_request
, client
);
2451 /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
2452 * down (this expunges any routes and arp cache). This makes the
2453 * interface unusable by state_init(), which we call next. So, we
2454 * need to 'PREINIT' the interface to bring it back up.
2456 script_init(client
, "PREINIT", NULL
);
2458 script_write_params(client
, "alias_", client
->alias
);
2461 client
-> state
= S_INIT
;
2462 state_init (client
);
2465 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
2466 one after the right interval has expired. If we don't get an offer by
2467 the time we reach the panic interval, call the panic function. */
2469 void send_discover (cpp
)
2472 struct client_state
*client
= cpp
;
2479 /* Figure out how long it's been since we started transmitting. */
2480 interval
= cur_time
- client
-> first_sending
;
2482 /* If we're past the panic timeout, call the script and tell it
2483 we haven't found anything for this interface yet. */
2484 if (interval
> client
-> config
-> timeout
) {
2485 state_panic (client
);
2489 /* If we're selecting media, try the whole list before doing
2490 the exponential backoff, but if we've already received an
2491 offer, stop looping, because we obviously have it right. */
2492 if (!client
-> offered_leases
&&
2493 client
-> config
-> media
) {
2496 if (client
-> medium
) {
2497 client
-> medium
= client
-> medium
-> next
;
2500 if (!client
-> medium
) {
2502 log_fatal ("No valid media types for %s!",
2503 client
-> interface
-> name
);
2505 client
-> config
-> media
;
2509 log_info ("Trying medium \"%s\" %d",
2510 client
-> medium
-> string
, increase
);
2511 script_init(client
, "MEDIUM", client
-> medium
);
2512 if (script_go(client
)) {
2518 /* If we're supposed to increase the interval, do so. If it's
2519 currently zero (i.e., we haven't sent any packets yet), set
2520 it to initial_interval; otherwise, add to it a random number
2521 between zero and two times itself. On average, this means
2522 that it will double with every transmission. */
2524 if (!client
->interval
)
2525 client
->interval
= client
->config
->initial_interval
;
2527 client
->interval
+= random() % (2 * client
->interval
);
2529 /* Don't backoff past cutoff. */
2530 if (client
->interval
> client
->config
->backoff_cutoff
)
2531 client
->interval
= (client
->config
->backoff_cutoff
/ 2)
2532 + (random() % client
->config
->backoff_cutoff
);
2533 } else if (!client
->interval
)
2534 client
->interval
= client
->config
->initial_interval
;
2536 /* If the backoff would take us to the panic timeout, just use that
2538 if (cur_time
+ client
-> interval
>
2539 client
-> first_sending
+ client
-> config
-> timeout
)
2540 client
-> interval
=
2541 (client
-> first_sending
+
2542 client
-> config
-> timeout
) - cur_time
+ 1;
2544 /* Record the number of seconds since we started sending. */
2545 if (interval
< 65536)
2546 client
-> packet
.secs
= htons (interval
);
2548 client
-> packet
.secs
= htons (65535);
2549 client
-> secs
= client
-> packet
.secs
;
2551 #if defined(DHCPv6) && defined(DHCP4o6)
2552 if (dhcpv4_over_dhcpv6
) {
2553 log_info ("DHCPDISCOVER interval %ld",
2554 (long)(client
-> interval
));
2557 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
2558 client
-> name
? client
-> name
: client
-> interface
-> name
,
2559 inet_ntoa (sockaddr_broadcast
.sin_addr
),
2560 ntohs (sockaddr_broadcast
.sin_port
), (long)(client
-> interval
));
2562 /* Send out a packet. */
2563 #if defined(DHCPv6) && defined(DHCP4o6)
2564 if (dhcpv4_over_dhcpv6
) {
2565 result
= send_dhcpv4_query(client
, 1);
2568 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
2569 client
->packet_length
, inaddr_any
,
2570 &sockaddr_broadcast
, NULL
);
2572 #if defined(DHCPv6) && defined(DHCP4o6)
2573 if (dhcpv4_over_dhcpv6
) {
2574 log_error("%s:%d: Failed to send %d byte long packet.",
2575 MDL
, client
->packet_length
);
2578 log_error("%s:%d: Failed to send %d byte long packet over %s "
2579 "interface.", MDL
, client
->packet_length
,
2580 client
->interface
->name
);
2584 * If we used 0 microseconds here, and there were other clients on the
2585 * same network with a synchronized local clock (ntp), and a similar
2586 * zero-microsecond-scheduler behavior, then we could be participating
2587 * in a sub-second DOS ttck.
2589 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->interval
;
2590 tv
.tv_usec
= client
->interval
> 1 ? random() % 1000000 : cur_tv
.tv_usec
;
2591 add_timeout(&tv
, send_discover
, client
, 0, 0);
2596 * \brief Remove leases from a list of leases which duplicate a given lease
2598 * Searches through a linked-list of leases, remove the first one matches the
2599 * given lease's address and value of is_static. The latter test is done
2600 * so we only remove leases that are from the same source (i.e server/lease file
2601 * vs config file). This ensures we do not discard "fallback" config file leases
2602 * that happen to match non-config file leases.
2604 * \param lease_list list of leases to clean
2605 * \param lease lease for which duplicates should be removed
2607 void discard_duplicate (struct client_lease
** lease_list
, struct client_lease
* lease
) {
2608 struct client_lease
*cur
, *prev
, *next
;
2610 if (!lease_list
|| !lease
) {
2614 prev
= (struct client_lease
*)0;
2615 for (cur
= *lease_list
; cur
; cur
= next
) {
2617 if ((cur
->is_static
== lease
->is_static
) &&
2618 (cur
->address
.len
== lease
->address
.len
&&
2619 !memcmp (cur
->address
.iabuf
, lease
->address
.iabuf
,
2620 lease
->address
.len
))) {
2626 destroy_client_lease (cur
);
2635 * \brief Add a given lease to the end of list of leases
2637 * Searches through a linked-list of leases, removing any that match the
2638 * given lease's address and value of is_static. The latter test is done
2639 * so we only remove leases that are from the same source (i.e server/lease file
2640 * vs config file). This ensures we do not discard "fallback" config file leases
2641 * that happen to match non-config file leases.
2643 * \param lease_list list of leases to clean
2644 * \param lease lease for which duplicates should be removed
2646 void add_to_tail(struct client_lease
** lease_list
,
2647 struct client_lease
* lease
)
2649 if (!lease_list
|| !lease
) {
2653 /* If there is already a lease for this address and
2654 * is_static value, toss discard it. This ensures
2655 * we only keep one dynamic and/or one static lease
2656 * for a given address. */
2657 discard_duplicate(lease_list
, lease
);
2660 struct client_lease
* tail
;
2661 for (tail
= *lease_list
; tail
&& tail
->next
; tail
= tail
->next
){};
2663 /* Ensure the tail points nowhere. */
2666 /* Add to the tail. */
2668 *lease_list
= lease
;
2675 void dbg_print_lease(char *text
, struct client_lease
* lease
) {
2677 log_debug("%s, lease is null", text
);
2679 log_debug ("%s: %p addr:%s expires:%ld :is_static? %d",
2680 text
, lease
, piaddr (lease
->address
),
2681 (lease
->expiry
- cur_time
),
2687 /* state_panic gets called if we haven't received any offers in a preset
2688 amount of time. When this happens, we try to use existing leases that
2689 haven't yet expired, and failing that, we call the client script and
2690 hope it can do something. */
2692 void state_panic (cpp
)
2695 struct client_state
*client
= cpp
;
2696 struct client_lease
*loop
;
2697 struct client_lease
*lp
;
2700 loop
= lp
= client
-> active
;
2702 log_info ("No DHCPOFFERS received.");
2704 /* We may not have an active lease, but we may have some
2705 predefined leases that we can try. */
2706 if (!client
-> active
&& client
-> leases
)
2709 /* Run through the list of leases and see if one can be used. */
2710 while (client
-> active
) {
2711 if (client
-> active
-> expiry
> cur_time
) {
2712 log_info ("Trying %s lease %s",
2713 (client
-> active
-> is_static
2714 ? "fallback" : "recorded"),
2715 piaddr (client
-> active
-> address
));
2716 /* Run the client script with the existing
2718 script_init(client
, "TIMEOUT",
2719 client
-> active
-> medium
);
2720 script_write_params(client
, "new_", client
-> active
);
2721 script_write_requested(client
);
2722 if (client
-> alias
)
2723 script_write_params(client
, "alias_",
2726 /* If the old lease is still good and doesn't
2727 yet need renewal, go into BOUND state and
2728 timeout at the renewal time. */
2729 if (!script_go(client
)) {
2730 if (cur_time
< client
-> active
-> renewal
) {
2731 client
-> state
= S_BOUND
;
2732 log_info ("bound: renewal in %ld %s.",
2733 (long)(client
-> active
-> renewal
-
2734 cur_time
), "seconds");
2735 tv
.tv_sec
= client
->active
->renewal
;
2736 tv
.tv_usec
= ((client
->active
->renewal
-
2738 random() % 1000000 :
2740 add_timeout(&tv
, state_bound
, client
, 0, 0);
2742 client
-> state
= S_BOUND
;
2743 log_info ("bound: immediate renewal.");
2744 state_bound (client
);
2746 reinitialize_interfaces ();
2752 /* If there are no other leases, give up. */
2753 if (!client
-> leases
) {
2754 client
-> leases
= client
-> active
;
2755 client
-> active
= (struct client_lease
*)0;
2760 /* Otherwise, put the active lease at the end of the
2761 lease list, and try another lease.. */
2762 add_to_tail(&client
->leases
, client
->active
);
2764 client
-> active
= client
-> leases
;
2765 client
-> leases
= client
-> leases
-> next
;
2767 /* If we already tried this lease, we've exhausted the
2768 set of leases, so we might as well give up for
2770 if (client
-> active
== loop
)
2773 loop
= client
-> active
;
2776 /* No leases were available, or what was available didn't work, so
2777 tell the shell script that we failed to allocate an address,
2778 and try again later. */
2781 log_info ("Unable to obtain a lease on first try.%s",
2785 #if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
2786 /* Let's call a script and we're done */
2787 script_init(client
, "FAIL", (struct string_list
*)0);
2793 log_info ("No working leases in persistent database - sleeping.");
2794 script_init(client
, "FAIL", (struct string_list
*)0);
2795 if (client
-> alias
)
2796 script_write_params(client
, "alias_", client
-> alias
);
2798 client
-> state
= S_INIT
;
2799 tv
.tv_sec
= cur_tv
.tv_sec
+ ((client
->config
->retry_interval
+ 1) / 2 +
2800 (random() % client
->config
->retry_interval
));
2801 tv
.tv_usec
= ((tv
.tv_sec
- cur_tv
.tv_sec
) > 1) ?
2802 random() % 1000000 : cur_tv
.tv_usec
;
2803 add_timeout(&tv
, state_init
, client
, 0, 0);
2807 void send_request (cpp
)
2810 struct client_state
*client
= cpp
;
2814 struct sockaddr_in destination
;
2815 struct in_addr from
;
2818 const char* rip_str
= "";
2820 /* Figure out how long it's been since we started transmitting. */
2821 interval
= cur_time
- client
-> first_sending
;
2823 /* If we're in the INIT-REBOOT or REQUESTING state and we're
2824 past the reboot timeout, go to INIT and see if we can
2825 DISCOVER an address... */
2826 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
2827 means either that we're on a network with no DHCP server,
2828 or that our server is down. In the latter case, assuming
2829 that there is a backup DHCP server, DHCPDISCOVER will get
2830 us a new address, but we could also have successfully
2831 reused our old address. In the former case, we're hosed
2832 anyway. This is not a win-prone situation. */
2833 if ((client
-> state
== S_REBOOTING
||
2834 client
-> state
== S_REQUESTING
) &&
2835 interval
> client
-> config
-> reboot_timeout
) {
2837 client
-> state
= S_INIT
;
2838 cancel_timeout (send_request
, client
);
2839 state_init (client
);
2843 /* If we're in the reboot state, make sure the media is set up
2845 if (client
-> state
== S_REBOOTING
&&
2846 !client
-> medium
&&
2847 client
-> active
-> medium
) {
2848 script_init(client
, "MEDIUM", client
-> active
-> medium
);
2850 /* If the medium we chose won't fly, go to INIT state. */
2851 if (script_go(client
))
2854 /* Record the medium. */
2855 client
-> medium
= client
-> active
-> medium
;
2858 /* If the lease has expired, relinquish the address and go back
2859 to the INIT state. */
2860 if (client
-> state
!= S_REQUESTING
&&
2861 cur_time
> client
-> active
-> expiry
) {
2862 /* Run the client script with the new parameters. */
2863 script_init(client
, "EXPIRE", (struct string_list
*)0);
2864 script_write_params(client
, "old_", client
-> active
);
2865 script_write_requested(client
);
2866 if (client
-> alias
)
2867 script_write_params(client
, "alias_",
2871 /* Now do a preinit on the interface so that we can
2872 discover a new address. */
2873 script_init(client
, "PREINIT", (struct string_list
*)0);
2874 if (client
-> alias
)
2875 script_write_params(client
, "alias_",
2879 client
-> state
= S_INIT
;
2880 state_init (client
);
2884 /* Do the exponential backoff... */
2885 if (!client
-> interval
)
2886 client
-> interval
= client
-> config
-> initial_interval
;
2888 client
-> interval
+= ((random () >> 2) %
2889 (2 * client
-> interval
));
2892 /* Don't backoff past cutoff. */
2893 if (client
-> interval
>
2894 client
-> config
-> backoff_cutoff
)
2895 client
-> interval
=
2896 ((client
-> config
-> backoff_cutoff
/ 2)
2897 + ((random () >> 2) %
2898 client
-> config
-> backoff_cutoff
));
2900 /* If the backoff would take us to the expiry time, just set the
2901 timeout to the expiry time. */
2902 if (client
-> state
!= S_REQUESTING
&&
2903 cur_time
+ client
-> interval
> client
-> active
-> expiry
)
2904 client
-> interval
=
2905 client
-> active
-> expiry
- cur_time
+ 1;
2907 /* If the lease T2 time has elapsed, or if we're not yet bound,
2908 broadcast the DHCPREQUEST rather than unicasting. */
2909 if (client
-> state
== S_REQUESTING
||
2910 client
-> state
== S_REBOOTING
||
2911 cur_time
> client
-> active
-> rebind
)
2912 destination
.sin_addr
= sockaddr_broadcast
.sin_addr
;
2914 memcpy (&destination
.sin_addr
.s_addr
,
2915 client
-> destination
.iabuf
,
2916 sizeof destination
.sin_addr
.s_addr
);
2917 destination
.sin_port
= remote_port
;
2918 destination
.sin_family
= AF_INET
;
2920 destination
.sin_len
= sizeof destination
;
2923 if (client
-> state
== S_RENEWING
||
2924 client
-> state
== S_REBINDING
)
2925 memcpy (&from
, client
-> active
-> address
.iabuf
,
2928 from
.s_addr
= INADDR_ANY
;
2930 /* Record the number of seconds since we started sending. */
2931 if (client
-> state
== S_REQUESTING
)
2932 client
-> packet
.secs
= client
-> secs
;
2934 if (interval
< 65536)
2935 client
-> packet
.secs
= htons (interval
);
2937 client
-> packet
.secs
= htons (65535);
2940 #if defined(DHCPv6) && defined(DHCP4o6)
2941 if (dhcpv4_over_dhcpv6
) {
2942 log_info ("DHCPREQUEST");
2945 memset(rip_buf
, 0x0, sizeof(rip_buf
));
2946 if (client
->state
== S_BOUND
|| client
->state
== S_RENEWING
||
2947 client
->state
== S_REBINDING
) {
2948 rip_str
= inet_ntoa(client
->packet
.ciaddr
);
2950 rip_str
= piaddr(client
->requested_address
);
2953 strncpy(rip_buf
, rip_str
, sizeof(rip_buf
)-1);
2954 log_info ("DHCPREQUEST for %s on %s to %s port %d", rip_buf
,
2955 client
->name
? client
->name
: client
->interface
->name
,
2956 inet_ntoa(destination
.sin_addr
),
2957 ntohs (destination
.sin_port
));
2959 #if defined(DHCPv6) && defined(DHCP4o6)
2960 if (dhcpv4_over_dhcpv6
) {
2962 if (destination
.sin_addr
.s_addr
== INADDR_BROADCAST
)
2964 result
= send_dhcpv4_query(client
, broadcast
);
2966 log_error("%s:%d: Failed to send %d byte long packet.",
2967 MDL
, client
->packet_length
);
2971 if (destination
.sin_addr
.s_addr
!= INADDR_BROADCAST
&&
2972 fallback_interface
) {
2973 result
= send_packet(fallback_interface
, NULL
, &client
->packet
,
2974 client
->packet_length
, from
, &destination
,
2977 log_error("%s:%d: Failed to send %d byte long packet "
2978 "over %s interface.", MDL
,
2979 client
->packet_length
,
2980 fallback_interface
->name
);
2984 /* Send out a packet. */
2985 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
2986 client
->packet_length
, from
, &destination
,
2989 log_error("%s:%d: Failed to send %d byte long packet"
2990 " over %s interface.", MDL
,
2991 client
->packet_length
,
2992 client
->interface
->name
);
2996 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->interval
;
2997 tv
.tv_usec
= ((tv
.tv_sec
- cur_tv
.tv_sec
) > 1) ?
2998 random() % 1000000 : cur_tv
.tv_usec
;
2999 add_timeout(&tv
, send_request
, client
, 0, 0);
3002 void send_decline (cpp
)
3005 struct client_state
*client
= cpp
;
3009 #if defined(DHCPv6) && defined(DHCP4o6)
3010 if (dhcpv4_over_dhcpv6
) {
3011 log_info ("DHCPDECLINE");
3014 log_info ("DHCPDECLINE of %s on %s to %s port %d",
3015 piaddr(client
->requested_address
),
3016 (client
->name
? client
->name
: client
->interface
->name
),
3017 inet_ntoa(sockaddr_broadcast
.sin_addr
),
3018 ntohs(sockaddr_broadcast
.sin_port
));
3020 /* Send out a packet. */
3021 #if defined(DHCPv6) && defined(DHCP4o6)
3022 if (dhcpv4_over_dhcpv6
) {
3023 result
= send_dhcpv4_query(client
, 1);
3026 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
3027 client
->packet_length
, inaddr_any
,
3028 &sockaddr_broadcast
, NULL
);
3030 #if defined(DHCPv6) && defined(DHCP4o6)
3031 if (dhcpv4_over_dhcpv6
) {
3032 log_error("%s:%d: Failed to send %d byte long packet.",
3033 MDL
, client
->packet_length
);
3036 log_error("%s:%d: Failed to send %d byte long packet over %s"
3037 " interface.", MDL
, client
->packet_length
,
3038 client
->interface
->name
);
3042 void send_release (cpp
)
3045 struct client_state
*client
= cpp
;
3048 struct sockaddr_in destination
;
3049 struct in_addr from
;
3051 memcpy (&from
, client
-> active
-> address
.iabuf
,
3053 memcpy (&destination
.sin_addr
.s_addr
,
3054 client
-> destination
.iabuf
,
3055 sizeof destination
.sin_addr
.s_addr
);
3056 destination
.sin_port
= remote_port
;
3057 destination
.sin_family
= AF_INET
;
3059 destination
.sin_len
= sizeof destination
;
3062 /* Set the lease to end now, so that we don't accidentally
3063 reuse it if we restart before the old expiry time. */
3064 client
-> active
-> expiry
=
3065 client
-> active
-> renewal
=
3066 client
-> active
-> rebind
= cur_time
;
3067 if (!write_client_lease (client
, client
-> active
, 1, 1)) {
3068 log_error ("Can't release lease: lease write failed.");
3072 #if defined(DHCPv6) && defined(DHCP4o6)
3073 if (dhcpv4_over_dhcpv6
) {
3074 log_info ("DHCPRELEASE");
3077 log_info ("DHCPRELEASE of %s on %s to %s port %d",
3078 piaddr(client
->active
->address
),
3079 client
->name
? client
->name
: client
->interface
->name
,
3080 inet_ntoa (destination
.sin_addr
),
3081 ntohs (destination
.sin_port
));
3083 #if defined(DHCPv6) && defined(DHCP4o6)
3084 if (dhcpv4_over_dhcpv6
) {
3086 if (destination
.sin_addr
.s_addr
== INADDR_BROADCAST
)
3088 result
= send_dhcpv4_query(client
, broadcast
);
3090 log_error("%s:%d: Failed to send %d byte long packet.",
3091 MDL
, client
->packet_length
);
3095 if (fallback_interface
) {
3096 result
= send_packet(fallback_interface
, NULL
, &client
->packet
,
3097 client
->packet_length
, from
, &destination
,
3100 log_error("%s:%d: Failed to send %d byte long packet"
3101 " over %s interface.", MDL
,
3102 client
->packet_length
,
3103 fallback_interface
->name
);
3106 /* Send out a packet. */
3107 result
= send_packet(client
->interface
, NULL
, &client
->packet
,
3108 client
->packet_length
, from
, &destination
,
3111 log_error ("%s:%d: Failed to send %d byte long packet"
3112 " over %s interface.", MDL
,
3113 client
->packet_length
,
3114 client
->interface
->name
);
3120 #if defined(DHCPv6) && defined(DHCP4o6)
3122 * \brief Send a DHCPv4-query to the DHCPv6 client
3123 * (DHCPv4 client function)
3125 * The DHCPv4 client sends a DHCPv4-query to the DHCPv6 client over
3126 * the inter-process communication socket.
3128 * \param client the DHCPv4 client state
3129 * \param broadcast the broadcast flag
3130 * \return the sent byte count (-1 on error)
3132 static int send_dhcpv4_query(struct client_state
*client
, int broadcast
) {
3133 struct data_string ds
;
3134 struct dhcpv4_over_dhcpv6_packet
*query
;
3137 if (dhcp4o6_state
<= 0) {
3138 log_info("send_dhcpv4_query: not ready.");
3143 * Compute buffer length and allocate it.
3145 len
= ofs
= (int)(offsetof(struct dhcpv4_over_dhcpv6_packet
, options
));
3146 len
+= dhcpv6_universe
.tag_size
+ dhcpv6_universe
.length_size
;
3147 len
+= client
->packet_length
;
3148 memset(&ds
, 0, sizeof(ds
));
3149 if (!buffer_allocate(&ds
.buffer
, len
, MDL
)) {
3150 log_error("Unable to allocate memory for DHCPv4-query.");
3153 ds
.data
= ds
.buffer
->data
;
3159 query
= (struct dhcpv4_over_dhcpv6_packet
*)ds
.data
;
3160 query
->msg_type
= DHCPV6_DHCPV4_QUERY
;
3161 query
->flags
[0] = query
->flags
[1] = query
->flags
[2] = 0;
3163 query
->flags
[0] |= DHCP4O6_QUERY_UNICAST
;
3166 * Append DHCPv4 message.
3168 dhcpv6_universe
.store_tag(ds
.buffer
->data
+ ofs
, D6O_DHCPV4_MSG
);
3169 ofs
+= dhcpv6_universe
.tag_size
;
3170 dhcpv6_universe
.store_length(ds
.buffer
->data
+ ofs
,
3171 client
->packet_length
);
3172 ofs
+= dhcpv6_universe
.length_size
;
3173 memcpy(ds
.buffer
->data
+ ofs
, &client
->packet
, client
->packet_length
);
3176 * Send DHCPv6 message.
3178 cc
= send(dhcp4o6_fd
, ds
.data
, ds
.len
, 0);
3180 log_error("send_dhcpv4_query: send(): %m");
3182 data_string_forget(&ds
, MDL
);
3188 * \brief Forward a DHCPv4-query to all DHCPv4 over DHCPv6 server addresses.
3189 * (DHCPv6 client function)
3191 * \param raw the DHCPv6 DHCPv4-query message raw content
3193 static void forw_dhcpv4_query(struct data_string
*raw
) {
3194 struct interface_info
*ip
;
3195 struct client_state
*client
;
3196 struct dhc6_lease
*lease
;
3197 struct option_cache
*oc
;
3198 struct data_string addrs
;
3199 struct sockaddr_in6 sin6
;
3200 int i
, send_ret
, attempt
, success
;
3202 attempt
= success
= 0;
3203 memset(&sin6
, 0, sizeof(sin6
));
3204 sin6
.sin6_family
= AF_INET6
;
3205 sin6
.sin6_port
= remote_port
;
3207 sin6
.sin6_len
= sizeof(sin6
);
3209 memset(&addrs
, 0, sizeof(addrs
));
3210 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
3211 for (client
= ip
->client
; client
!= NULL
;
3212 client
= client
->next
) {
3213 if ((client
->state
!= S_BOUND
) &&
3214 (client
->state
!= S_RENEWING
) &&
3215 (client
->state
!= S_REBINDING
))
3217 lease
= client
->active_lease
;
3218 if ((lease
== NULL
) || lease
->released
)
3220 oc
= lookup_option(&dhcpv6_universe
,
3222 D6O_DHCP4_O_DHCP6_SERVER
);
3224 !evaluate_option_cache(&addrs
, NULL
, NULL
, NULL
,
3225 lease
->options
, NULL
,
3226 &global_scope
, oc
, MDL
) ||
3227 ((addrs
.len
% sizeof(sin6
.sin6_addr
)) != 0)) {
3228 data_string_forget(&addrs
, MDL
);
3231 if (addrs
.len
== 0) {
3232 /* note there is nothing to forget */
3234 All_DHCP_Relay_Agents_and_Servers
,
3237 send_ret
= send_packet6(ip
, raw
->data
,
3239 if (send_ret
== raw
->len
)
3243 for (i
= 0; i
< addrs
.len
;
3244 i
+= sizeof(sin6
.sin6_addr
)) {
3245 memcpy(&sin6
.sin6_addr
, addrs
.data
+ i
,
3246 sizeof(sin6
.sin6_addr
));
3248 send_ret
= send_packet6(ip
, raw
->data
,
3250 if (send_ret
== raw
->len
)
3253 data_string_forget(&addrs
, MDL
);
3257 log_info("forw_dhcpv4_query: sent(%d): %d/%d",
3258 raw
->len
, success
, attempt
);
3266 make_client_options(struct client_state
*client
, struct client_lease
*lease
,
3267 u_int8_t
*type
, struct option_cache
*sid
,
3268 struct iaddr
*rip
, struct option
**prl
,
3269 struct option_state
**op
)
3272 struct option_cache
*oc
;
3273 struct option
*option
= NULL
;
3274 struct buffer
*bp
= NULL
;
3276 /* If there are any leftover options, get rid of them. */
3278 option_state_dereference(op
, MDL
);
3280 /* Allocate space for options. */
3281 option_state_allocate(op
, MDL
);
3283 /* Send the server identifier if provided. */
3285 save_option(&dhcp_universe
, *op
, sid
);
3289 /* Send the requested address if provided. */
3291 client
->requested_address
= *rip
;
3292 i
= DHO_DHCP_REQUESTED_ADDRESS
;
3293 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
3295 make_const_option_cache(&oc
, NULL
, rip
->iabuf
, rip
->len
,
3297 log_error ("can't make requested address cache.");
3299 save_option(&dhcp_universe
, *op
, oc
);
3300 option_cache_dereference(&oc
, MDL
);
3302 option_dereference(&option
, MDL
);
3304 client
->requested_address
.len
= 0;
3307 i
= DHO_DHCP_MESSAGE_TYPE
;
3308 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
, &i
, 0,
3310 make_const_option_cache(&oc
, NULL
, type
, 1, option
, MDL
)))
3311 log_error("can't make message type.");
3313 save_option(&dhcp_universe
, *op
, oc
);
3314 option_cache_dereference(&oc
, MDL
);
3316 option_dereference(&option
, MDL
);
3321 /* Probe the length of the list. */
3323 for (i
= 0 ; prl
[i
] != NULL
; i
++)
3324 if (prl
[i
]->universe
== &dhcp_universe
)
3327 if (!buffer_allocate(&bp
, len
, MDL
))
3328 log_error("can't make parameter list buffer.");
3330 unsigned code
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
3333 for (i
= 0 ; prl
[i
] != NULL
; i
++)
3334 if (prl
[i
]->universe
== &dhcp_universe
)
3335 bp
->data
[len
++] = prl
[i
]->code
;
3337 if (!(option_code_hash_lookup(&option
,
3338 dhcp_universe
.code_hash
,
3340 make_const_option_cache(&oc
, &bp
, NULL
, len
,
3343 buffer_dereference(&bp
, MDL
);
3344 log_error ("can't make option cache");
3346 save_option(&dhcp_universe
, *op
, oc
);
3347 option_cache_dereference(&oc
, MDL
);
3349 option_dereference(&option
, MDL
);
3354 * If requested (duid_v4 == 1) add an RFC4361 compliant client-identifier
3355 * This can be overridden by including a client id in the configuration
3359 struct data_string client_identifier
;
3362 memset(&client_identifier
, 0, sizeof(client_identifier
));
3363 client_identifier
.len
= 1 + 4 + default_duid
.len
;
3364 if (!buffer_allocate(&client_identifier
.buffer
,
3365 client_identifier
.len
, MDL
))
3366 log_fatal("no memory for default DUID!");
3367 client_identifier
.data
= client_identifier
.buffer
->data
;
3369 i
= DHO_DHCP_CLIENT_IDENTIFIER
;
3371 /* Client-identifier type : 1 byte */
3372 *client_identifier
.buffer
->data
= 255;
3375 * we use the low 4 bytes from the interface address
3377 if (client
->interface
->hw_address
.hlen
> 4) {
3378 hw_idx
= client
->interface
->hw_address
.hlen
- 4;
3382 hw_len
= client
->interface
->hw_address
.hlen
;
3384 memcpy(&client_identifier
.buffer
->data
+ 5 - hw_len
,
3385 client
->interface
->hw_address
.hbuf
+ hw_idx
,
3388 /* Add the default duid */
3389 memcpy(&client_identifier
.buffer
->data
+(1+4),
3390 default_duid
.data
, default_duid
.len
);
3392 /* And save the option */
3393 if (!(option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
3395 make_const_option_cache(&oc
, NULL
,
3396 (u_int8_t
*)client_identifier
.data
,
3397 client_identifier
.len
,
3399 log_error ("can't make requested client id cache..");
3401 save_option (&dhcp_universe
, *op
, oc
);
3402 option_cache_dereference (&oc
, MDL
);
3404 option_dereference(&option
, MDL
);
3407 /* Run statements that need to be run on transmission. */
3408 if (client
->config
->on_transmission
)
3409 execute_statements_in_scope(NULL
, NULL
, NULL
, client
,
3410 (lease
? lease
->options
: NULL
),
3412 client
->config
->on_transmission
,
3416 void make_discover (client
, lease
)
3417 struct client_state
*client
;
3418 struct client_lease
*lease
;
3420 unsigned char discover
= DHCPDISCOVER
;
3421 struct option_state
*options
= (struct option_state
*)0;
3423 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3425 make_client_options (client
,
3426 lease
, &discover
, (struct option_cache
*)0,
3427 lease
? &lease
-> address
: (struct iaddr
*)0,
3428 client
-> config
-> requested_options
,
3431 /* Set up the option buffer... */
3432 client
-> packet_length
=
3433 cons_options ((struct packet
*)0, &client
-> packet
,
3434 (struct lease
*)0, client
,
3435 /* maximum packet size */1500,
3436 (struct option_state
*)0,
3438 /* scope */ &global_scope
,
3442 (struct data_string
*)0,
3443 client
-> config
-> vendor_space_name
);
3445 option_state_dereference (&options
, MDL
);
3446 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3447 client
-> packet_length
= BOOTP_MIN_LEN
;
3449 client
-> packet
.op
= BOOTREQUEST
;
3450 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3451 /* Assumes hw_address is known, otherwise a random value may result */
3452 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3453 client
-> packet
.hops
= 0;
3454 client
-> packet
.xid
= random ();
3455 client
-> packet
.secs
= 0; /* filled in by send_discover. */
3457 if (can_receive_unicast_unconfigured (client
-> interface
))
3458 client
-> packet
.flags
= 0;
3460 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3462 memset (&(client
-> packet
.ciaddr
),
3463 0, sizeof client
-> packet
.ciaddr
);
3464 memset (&(client
-> packet
.yiaddr
),
3465 0, sizeof client
-> packet
.yiaddr
);
3466 memset (&(client
-> packet
.siaddr
),
3467 0, sizeof client
-> packet
.siaddr
);
3468 client
-> packet
.giaddr
= giaddr
;
3469 if (client
-> interface
-> hw_address
.hlen
> 0)
3470 memcpy (client
-> packet
.chaddr
,
3471 &client
-> interface
-> hw_address
.hbuf
[1],
3472 (unsigned)(client
-> interface
-> hw_address
.hlen
- 1));
3475 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3480 void make_request (client
, lease
)
3481 struct client_state
*client
;
3482 struct client_lease
*lease
;
3484 unsigned char request
= DHCPREQUEST
;
3485 struct option_cache
*oc
;
3487 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3489 if (client
-> state
== S_REQUESTING
)
3490 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3491 DHO_DHCP_SERVER_IDENTIFIER
);
3493 oc
= (struct option_cache
*)0;
3495 if (client
-> sent_options
)
3496 option_state_dereference (&client
-> sent_options
, MDL
);
3498 make_client_options (client
, lease
, &request
, oc
,
3499 ((client
-> state
== S_REQUESTING
||
3500 client
-> state
== S_REBOOTING
)
3502 : (struct iaddr
*)0),
3503 client
-> config
-> requested_options
,
3504 &client
-> sent_options
);
3506 /* Set up the option buffer... */
3507 client
-> packet_length
=
3508 cons_options ((struct packet
*)0, &client
-> packet
,
3509 (struct lease
*)0, client
,
3510 /* maximum packet size */1500,
3511 (struct option_state
*)0,
3512 client
-> sent_options
,
3513 /* scope */ &global_scope
,
3517 (struct data_string
*)0,
3518 client
-> config
-> vendor_space_name
);
3520 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3521 client
-> packet_length
= BOOTP_MIN_LEN
;
3523 client
-> packet
.op
= BOOTREQUEST
;
3524 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3525 /* Assumes hw_address is known, otherwise a random value may result */
3526 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3527 client
-> packet
.hops
= 0;
3528 client
-> packet
.xid
= client
-> xid
;
3529 client
-> packet
.secs
= 0; /* Filled in by send_request. */
3531 /* If we own the address we're requesting, put it in ciaddr;
3532 otherwise set ciaddr to zero. */
3533 if (client
-> state
== S_BOUND
||
3534 client
-> state
== S_RENEWING
||
3535 client
-> state
== S_REBINDING
) {
3536 memcpy (&client
-> packet
.ciaddr
,
3537 lease
-> address
.iabuf
, lease
-> address
.len
);
3538 client
-> packet
.flags
= 0;
3540 memset (&client
-> packet
.ciaddr
, 0,
3541 sizeof client
-> packet
.ciaddr
);
3542 if (can_receive_unicast_unconfigured (client
-> interface
))
3543 client
-> packet
.flags
= 0;
3545 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3548 memset (&client
-> packet
.yiaddr
, 0,
3549 sizeof client
-> packet
.yiaddr
);
3550 memset (&client
-> packet
.siaddr
, 0,
3551 sizeof client
-> packet
.siaddr
);
3552 if (client
-> state
!= S_BOUND
&&
3553 client
-> state
!= S_RENEWING
)
3554 client
-> packet
.giaddr
= giaddr
;
3556 memset (&client
-> packet
.giaddr
, 0,
3557 sizeof client
-> packet
.giaddr
);
3558 if (client
-> interface
-> hw_address
.hlen
> 0)
3559 memcpy (client
-> packet
.chaddr
,
3560 &client
-> interface
-> hw_address
.hbuf
[1],
3561 (unsigned)(client
-> interface
-> hw_address
.hlen
- 1));
3564 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3568 void make_decline (client
, lease
)
3569 struct client_state
*client
;
3570 struct client_lease
*lease
;
3572 unsigned char decline
= DHCPDECLINE
;
3573 struct option_cache
*oc
;
3575 struct option_state
*options
= (struct option_state
*)0;
3577 /* Create the options cache. */
3578 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3579 DHO_DHCP_SERVER_IDENTIFIER
);
3580 make_client_options(client
, lease
, &decline
, oc
, &lease
->address
,
3583 /* Consume the options cache into the option buffer. */
3584 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3585 client
-> packet_length
=
3586 cons_options ((struct packet
*)0, &client
-> packet
,
3587 (struct lease
*)0, client
, 0,
3588 (struct option_state
*)0, options
,
3589 &global_scope
, 0, 0, 0, (struct data_string
*)0,
3590 client
-> config
-> vendor_space_name
);
3592 /* Destroy the options cache. */
3593 option_state_dereference (&options
, MDL
);
3595 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3596 client
-> packet_length
= BOOTP_MIN_LEN
;
3598 client
-> packet
.op
= BOOTREQUEST
;
3599 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3600 /* Assumes hw_address is known, otherwise a random value may result */
3601 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3602 client
-> packet
.hops
= 0;
3603 client
-> packet
.xid
= client
-> xid
;
3604 client
-> packet
.secs
= 0; /* Filled in by send_request. */
3605 if (can_receive_unicast_unconfigured (client
-> interface
))
3606 client
-> packet
.flags
= 0;
3608 client
-> packet
.flags
= htons (BOOTP_BROADCAST
);
3610 /* ciaddr must always be zero. */
3611 memset (&client
-> packet
.ciaddr
, 0,
3612 sizeof client
-> packet
.ciaddr
);
3613 memset (&client
-> packet
.yiaddr
, 0,
3614 sizeof client
-> packet
.yiaddr
);
3615 memset (&client
-> packet
.siaddr
, 0,
3616 sizeof client
-> packet
.siaddr
);
3617 client
-> packet
.giaddr
= giaddr
;
3618 memcpy (client
-> packet
.chaddr
,
3619 &client
-> interface
-> hw_address
.hbuf
[1],
3620 client
-> interface
-> hw_address
.hlen
);
3623 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3627 void make_release (client
, lease
)
3628 struct client_state
*client
;
3629 struct client_lease
*lease
;
3631 unsigned char request
= DHCPRELEASE
;
3632 struct option_cache
*oc
;
3634 struct option_state
*options
= (struct option_state
*)0;
3636 memset (&client
-> packet
, 0, sizeof (client
-> packet
));
3638 oc
= lookup_option (&dhcp_universe
, lease
-> options
,
3639 DHO_DHCP_SERVER_IDENTIFIER
);
3640 make_client_options(client
, lease
, &request
, oc
, NULL
, NULL
, &options
);
3642 /* Set up the option buffer... */
3643 client
-> packet_length
=
3644 cons_options ((struct packet
*)0, &client
-> packet
,
3645 (struct lease
*)0, client
,
3646 /* maximum packet size */1500,
3647 (struct option_state
*)0,
3649 /* scope */ &global_scope
,
3653 (struct data_string
*)0,
3654 client
-> config
-> vendor_space_name
);
3656 if (client
-> packet_length
< BOOTP_MIN_LEN
)
3657 client
-> packet_length
= BOOTP_MIN_LEN
;
3658 option_state_dereference (&options
, MDL
);
3660 client
-> packet
.op
= BOOTREQUEST
;
3661 client
-> packet
.htype
= client
-> interface
-> hw_address
.hbuf
[0];
3662 /* Assumes hw_address is known, otherwise a random value may result */
3663 client
-> packet
.hlen
= client
-> interface
-> hw_address
.hlen
- 1;
3664 client
-> packet
.hops
= 0;
3665 client
-> packet
.xid
= random ();
3666 client
-> packet
.secs
= 0;
3667 client
-> packet
.flags
= 0;
3668 memcpy (&client
-> packet
.ciaddr
,
3669 lease
-> address
.iabuf
, lease
-> address
.len
);
3670 memset (&client
-> packet
.yiaddr
, 0,
3671 sizeof client
-> packet
.yiaddr
);
3672 memset (&client
-> packet
.siaddr
, 0,
3673 sizeof client
-> packet
.siaddr
);
3674 client
-> packet
.giaddr
= giaddr
;
3675 memcpy (client
-> packet
.chaddr
,
3676 &client
-> interface
-> hw_address
.hbuf
[1],
3677 client
-> interface
-> hw_address
.hlen
);
3680 dump_raw ((unsigned char *)&client
-> packet
, client
-> packet_length
);
3684 void destroy_client_lease (lease
)
3685 struct client_lease
*lease
;
3687 if (lease
-> server_name
)
3688 dfree (lease
-> server_name
, MDL
);
3689 if (lease
-> filename
)
3690 dfree (lease
-> filename
, MDL
);
3691 option_state_dereference (&lease
-> options
, MDL
);
3692 free_client_lease (lease
, MDL
);
3695 FILE *leaseFile
= NULL
;
3696 int leases_written
= 0;
3698 void rewrite_client_leases ()
3700 struct interface_info
*ip
;
3701 struct client_state
*client
;
3702 struct client_lease
*lp
;
3704 if (leaseFile
!= NULL
)
3706 leaseFile
= fopen (path_dhclient_db
, "w");
3707 if (leaseFile
== NULL
) {
3708 log_error ("can't create %s: %m", path_dhclient_db
);
3712 /* If there is a default duid, write it out. */
3713 if (default_duid
.len
!= 0)
3714 write_duid(&default_duid
);
3716 /* Write out all the leases attached to configured interfaces that
3718 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
3719 for (client
= ip
-> client
; client
; client
= client
-> next
) {
3720 for (lp
= client
-> leases
; lp
; lp
= lp
-> next
) {
3721 write_client_lease (client
, lp
, 1, 0);
3723 if (client
-> active
)
3724 write_client_lease (client
,
3725 client
-> active
, 1, 0);
3727 if (client
->active_lease
!= NULL
)
3728 write_client6_lease(client
,
3729 client
->active_lease
,
3732 /* Reset last_write after rewrites. */
3733 client
->last_write
= 0;
3737 /* Write out any leases that are attached to interfaces that aren't
3738 currently configured. */
3739 for (ip
= dummy_interfaces
; ip
; ip
= ip
-> next
) {
3740 for (client
= ip
-> client
; client
; client
= client
-> next
) {
3741 for (lp
= client
-> leases
; lp
; lp
= lp
-> next
) {
3742 write_client_lease (client
, lp
, 1, 0);
3744 if (client
-> active
)
3745 write_client_lease (client
,
3746 client
-> active
, 1, 0);
3748 if (client
->active_lease
!= NULL
)
3749 write_client6_lease(client
,
3750 client
->active_lease
,
3753 /* Reset last_write after rewrites. */
3754 client
->last_write
= 0;
3760 void write_lease_option (struct option_cache
*oc
,
3761 struct packet
*packet
, struct lease
*lease
,
3762 struct client_state
*client_state
,
3763 struct option_state
*in_options
,
3764 struct option_state
*cfg_options
,
3765 struct binding_scope
**scope
,
3766 struct universe
*u
, void *stuff
)
3768 const char *name
, *dot
;
3769 struct data_string ds
;
3770 char *preamble
= stuff
;
3772 memset (&ds
, 0, sizeof ds
);
3774 if (u
!= &dhcp_universe
) {
3781 if (evaluate_option_cache (&ds
, packet
, lease
, client_state
,
3782 in_options
, cfg_options
, scope
, oc
, MDL
)) {
3783 /* The option name */
3784 fprintf(leaseFile
, "%soption %s%s%s", preamble
,
3785 name
, dot
, oc
->option
->name
);
3787 /* The option value if there is one */
3788 if ((oc
->option
->format
== NULL
) ||
3789 (oc
->option
->format
[0] != 'Z')) {
3790 fprintf(leaseFile
, " %s",
3791 pretty_print_option(oc
->option
, ds
.data
,
3795 /* The closing semi-colon and newline */
3796 fprintf(leaseFile
, ";\n");
3798 data_string_forget (&ds
, MDL
);
3802 /* Write an option cache to the lease store. */
3804 write_options(struct client_state
*client
, struct option_state
*options
,
3805 const char *preamble
)
3809 for (i
= 0; i
< options
->universe_count
; i
++) {
3810 option_space_foreach(NULL
, NULL
, client
, NULL
, options
,
3811 &global_scope
, universes
[i
],
3812 (char *)preamble
, write_lease_option
);
3817 * The "best" default DUID, since we cannot predict any information
3818 * about the system (such as whether or not the hardware addresses are
3819 * integrated into the motherboard or similar), is the "LLT", link local
3820 * plus time, DUID. For real stateless "LL" is better.
3822 * Once generated, this duid is stored into the state database, and
3823 * retained across restarts.
3825 * For the time being, there is probably a different state database for
3826 * every daemon, so this winds up being a per-interface identifier...which
3827 * is not how it is intended. Upcoming rearchitecting the client should
3828 * address this "one daemon model."
3831 form_duid(struct data_string
*duid
, const char *file
, int line
)
3833 struct interface_info
*ip
;
3837 /* For now, just use the first interface on the list. */
3841 log_fatal("Impossible condition at %s:%d.", MDL
);
3843 if ((ip
->hw_address
.hlen
== 0) ||
3844 (ip
->hw_address
.hlen
> sizeof(ip
->hw_address
.hbuf
)))
3845 log_fatal("Impossible hardware address length at %s:%d.", MDL
);
3848 duid_type
= stateless
? DUID_LL
: DUID_LLT
;
3851 * 2 bytes for the 'duid type' field.
3852 * 2 bytes for the 'htype' field.
3853 * (DUID_LLT) 4 bytes for the 'current time'.
3854 * enough bytes for the hardware address (note that hw_address has
3855 * the 'htype' on byte zero).
3857 len
= 4 + (ip
->hw_address
.hlen
- 1);
3858 if (duid_type
== DUID_LLT
)
3860 if (!buffer_allocate(&duid
->buffer
, len
, MDL
))
3861 log_fatal("no memory for default DUID!");
3862 duid
->data
= duid
->buffer
->data
;
3865 /* Basic Link Local Address type of DUID. */
3866 if (duid_type
== DUID_LLT
) {
3867 putUShort(duid
->buffer
->data
, DUID_LLT
);
3868 putUShort(duid
->buffer
->data
+ 2, ip
->hw_address
.hbuf
[0]);
3869 putULong(duid
->buffer
->data
+ 4, cur_time
- DUID_TIME_EPOCH
);
3870 memcpy(duid
->buffer
->data
+ 8, ip
->hw_address
.hbuf
+ 1,
3871 ip
->hw_address
.hlen
- 1);
3873 putUShort(duid
->buffer
->data
, DUID_LL
);
3874 putUShort(duid
->buffer
->data
+ 2, ip
->hw_address
.hbuf
[0]);
3875 memcpy(duid
->buffer
->data
+ 4, ip
->hw_address
.hbuf
+ 1,
3876 ip
->hw_address
.hlen
- 1);
3879 /* Now format the output based on lease-id-format */
3880 str
= format_lease_id(duid
->data
, duid
->len
,
3881 top_level_config
.lease_id_format
, MDL
);
3883 log_info("form_duid: Couldn't allocate memory to log duid!");
3885 log_info("Created duid %s.", str
);
3890 /* Write the default DUID to the lease store. */
3892 write_duid(struct data_string
*duid
)
3897 if ((duid
== NULL
) || (duid
->len
<= 2))
3898 return DHCP_R_INVALIDARG
;
3900 if (leaseFile
== NULL
) { /* XXX? */
3901 leaseFile
= fopen(path_dhclient_db
, "w");
3902 if (leaseFile
== NULL
) {
3903 log_error("can't create %s: %m", path_dhclient_db
);
3904 return ISC_R_IOERROR
;
3908 /* Generate a formatted duid string per lease-id-format */
3909 str
= format_lease_id(duid
->data
, duid
->len
,
3910 top_level_config
.lease_id_format
, MDL
);
3912 return ISC_R_NOMEMORY
;
3914 stat
= fprintf(leaseFile
, "default-duid %s;\n", str
);
3917 return ISC_R_IOERROR
;
3919 if (fflush(leaseFile
) != 0)
3920 return ISC_R_IOERROR
;
3922 return ISC_R_SUCCESS
;
3925 /* Write a DHCPv6 lease to the store. */
3927 write_client6_lease(struct client_state
*client
, struct dhc6_lease
*lease
,
3928 int rewrite
, int sync
)
3931 struct dhc6_addr
*addr
;
3935 /* This should include the current lease. */
3936 if (!rewrite
&& (leases_written
++ > 20)) {
3937 rewrite_client_leases();
3939 return ISC_R_SUCCESS
;
3942 if (client
== NULL
|| lease
== NULL
)
3943 return DHCP_R_INVALIDARG
;
3945 if (leaseFile
== NULL
) { /* XXX? */
3946 leaseFile
= fopen(path_dhclient_db
, "w");
3947 if (leaseFile
== NULL
) {
3948 log_error("can't create %s: %m", path_dhclient_db
);
3949 return ISC_R_IOERROR
;
3953 stat
= fprintf(leaseFile
, "lease6 {\n");
3955 return ISC_R_IOERROR
;
3957 stat
= fprintf(leaseFile
, " interface \"%s\";\n",
3958 client
->interface
->name
);
3960 return ISC_R_IOERROR
;
3962 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
3963 switch (ia
->ia_type
) {
3976 /* For some reason IAID was never octal or hex, but string or
3977 * hex. Go figure. So for compatibilty's sake we will either
3978 * do hex or "legacy" i.e string rather than octal. What a
3980 switch(top_level_config
.lease_id_format
) {
3982 char* iaid_str
= format_lease_id(
3983 (const unsigned char *) &ia
->iaid
, 4,
3984 top_level_config
.lease_id_format
, MDL
);
3987 log_error("Can't format iaid");
3988 return ISC_R_IOERROR
;
3991 stat
= fprintf(leaseFile
, " %s %s {\n",
3993 dfree(iaid_str
, MDL
);
3999 stat
= fprintf(leaseFile
, " %s %s {\n", ianame
,
4000 print_hex_1(4, ia
->iaid
, 12));
4005 return ISC_R_IOERROR
;
4007 if (ia
->ia_type
!= D6O_IA_TA
)
4008 stat
= fprintf(leaseFile
, " starts %d;\n"
4011 (int)ia
->starts
, ia
->renew
, ia
->rebind
);
4013 stat
= fprintf(leaseFile
, " starts %d;\n",
4016 return ISC_R_IOERROR
;
4018 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
4019 if (ia
->ia_type
!= D6O_IA_PD
)
4020 stat
= fprintf(leaseFile
,
4022 piaddr(addr
->address
));
4024 stat
= fprintf(leaseFile
,
4025 " iaprefix %s/%d {\n",
4026 piaddr(addr
->address
),
4029 return ISC_R_IOERROR
;
4031 stat
= fprintf(leaseFile
, " starts %d;\n"
4032 " preferred-life %u;\n"
4034 (int)addr
->starts
, addr
->preferred_life
,
4037 return ISC_R_IOERROR
;
4039 if (addr
->options
!= NULL
)
4040 write_options(client
, addr
->options
, " ");
4042 stat
= fprintf(leaseFile
, " }\n");
4044 return ISC_R_IOERROR
;
4047 if (ia
->options
!= NULL
)
4048 write_options(client
, ia
->options
, " ");
4050 stat
= fprintf(leaseFile
, " }\n");
4052 return ISC_R_IOERROR
;
4055 if (lease
->released
) {
4056 stat
= fprintf(leaseFile
, " released;\n");
4058 return ISC_R_IOERROR
;
4061 if (lease
->options
!= NULL
)
4062 write_options(client
, lease
->options
, " ");
4064 stat
= fprintf(leaseFile
, "}\n");
4066 return ISC_R_IOERROR
;
4068 if (fflush(leaseFile
) != 0)
4069 return ISC_R_IOERROR
;
4072 if (fsync(fileno(leaseFile
)) < 0) {
4073 log_error("write_client_lease: fsync(): %m");
4074 return ISC_R_IOERROR
;
4078 return ISC_R_SUCCESS
;
4081 int write_client_lease (client
, lease
, rewrite
, makesure
)
4082 struct client_state
*client
;
4083 struct client_lease
*lease
;
4087 struct data_string ds
;
4093 if (leases_written
++ > 20) {
4094 rewrite_client_leases ();
4099 /* If the lease came from the config file, we don't need to stash
4100 a copy in the lease database. */
4101 if (lease
-> is_static
)
4104 if (leaseFile
== NULL
) { /* XXX */
4105 leaseFile
= fopen (path_dhclient_db
, "w");
4106 if (leaseFile
== NULL
) {
4107 log_error ("can't create %s: %m", path_dhclient_db
);
4113 fprintf (leaseFile
, "lease {\n");
4114 if (lease
-> is_bootp
) {
4115 fprintf (leaseFile
, " bootp;\n");
4121 fprintf (leaseFile
, " interface \"%s\";\n",
4122 client
-> interface
-> name
);
4127 if (client
-> name
) {
4128 fprintf (leaseFile
, " name \"%s\";\n", client
-> name
);
4134 fprintf (leaseFile
, " fixed-address %s;\n",
4135 piaddr (lease
-> address
));
4140 if (lease
-> filename
) {
4141 s
= quotify_string (lease
-> filename
, MDL
);
4143 fprintf (leaseFile
, " filename \"%s\";\n", s
);
4153 if (lease
->server_name
!= NULL
) {
4154 s
= quotify_string(lease
->server_name
, MDL
);
4156 fprintf(leaseFile
, " server-name \"%s\";\n", s
);
4165 if (lease
-> medium
) {
4166 s
= quotify_string (lease
-> medium
-> string
, MDL
);
4168 fprintf (leaseFile
, " medium \"%s\";\n", s
);
4182 memset (&ds
, 0, sizeof ds
);
4184 write_options(client
, lease
->options
, " ");
4186 tval
= print_time(lease
->renewal
);
4188 fprintf(leaseFile
, " renew %s\n", tval
) < 0)
4191 tval
= print_time(lease
->rebind
);
4193 fprintf(leaseFile
, " rebind %s\n", tval
) < 0)
4196 tval
= print_time(lease
->expiry
);
4198 fprintf(leaseFile
, " expire %s\n", tval
) < 0)
4201 if (fprintf(leaseFile
, "}\n") < 0)
4204 if (fflush(leaseFile
) != 0)
4207 client
->last_write
= cur_time
;
4209 if (!errors
&& makesure
) {
4210 if (fsync (fileno (leaseFile
)) < 0) {
4211 log_info ("write_client_lease: %m");
4216 return errors
? 0 : 1;
4219 /* Variables holding name of script and file pointer for writing to
4220 script. Needless to say, this is not reentrant - only one script
4221 can be invoked at a time. */
4222 char scriptName
[256];
4226 * @brief Initializes basic variables for a script
4228 * This function is called as an initial preparation for calling a script.
4229 * It sets up a number of common env. variables that will be passed to
4230 * the script. For actual script calling, see @ref script_go .
4232 * @param client variables will be stored here (if null, the whole function
4234 * @param reason specified the reason for calling a script (must be non-null)
4235 * @param medium if specified, defines medium type (may be null)
4237 void script_init(struct client_state
*client
, const char *reason
,
4238 struct string_list
*medium
)
4240 struct string_list
*sl
, *next
;
4243 for (sl
= client
-> env
; sl
; sl
= next
) {
4247 client
-> env
= (struct string_list
*)0;
4250 if (client
-> interface
) {
4251 client_envadd (client
, "", "interface", "%s",
4252 client
-> interface
-> name
);
4255 client_envadd (client
,
4256 "", "client", "%s", client
-> name
);
4258 client_envadd (client
,
4259 "", "medium", "%s", medium
-> string
);
4261 client_envadd (client
, "", "reason", "%s", reason
);
4262 client_envadd (client
, "", "pid", "%ld", (long int)getpid ());
4264 client_envadd (client
, "", "dad_wait_time", "%ld",
4265 (long int)dad_wait_time
);
4270 void client_option_envadd (struct option_cache
*oc
,
4271 struct packet
*packet
, struct lease
*lease
,
4272 struct client_state
*client_state
,
4273 struct option_state
*in_options
,
4274 struct option_state
*cfg_options
,
4275 struct binding_scope
**scope
,
4276 struct universe
*u
, void *stuff
)
4278 struct envadd_state
*es
= stuff
;
4279 struct data_string data
;
4280 memset (&data
, 0, sizeof data
);
4282 if (evaluate_option_cache (&data
, packet
, lease
, client_state
,
4283 in_options
, cfg_options
, scope
, oc
, MDL
)) {
4286 if (dhcp_option_ev_name (name
, sizeof name
,
4290 value
= pretty_print_option(oc
->option
,
4293 length
= strlen(value
);
4295 if (check_option_values(oc
->option
->universe
,
4297 value
, length
) == 0) {
4298 client_envadd(es
->client
, es
->prefix
,
4301 log_error("suspect value in %s "
4302 "option - discarded",
4308 data_string_forget (&data
, MDL
);
4313 * @brief Adds parameters to environment variables for a script
4315 * This function add details of specified lease to a list of env. variables
4316 * to be passed to a script. The lease details will be prepended with
4317 * specified prefix (e.g. "old_") and added to the list stored in client.
4318 * Following variables may be set:
4322 * - broadcast_address
4327 * @param client env. variables will be stored here
4328 * @param prefix textual prefix to be added to each variable (e.g. "old_")
4329 * @param lease lease details will be extracted from here
4331 void script_write_params(struct client_state
*client
, const char *prefix
,
4332 struct client_lease
*lease
)
4335 struct data_string data
;
4336 struct option_cache
*oc
;
4337 struct envadd_state es
;
4342 client_envadd (client
,
4343 prefix
, "ip_address", "%s", piaddr (lease
-> address
));
4345 /* If we've set the next server address in the lease structure
4346 put it into an environment variable for the script */
4347 if (lease
->next_srv_addr
.len
!= 0) {
4348 client_envadd(client
, prefix
, "next_server", "%s",
4349 piaddr(lease
->next_srv_addr
));
4352 /* For the benefit of Linux (and operating systems which may
4353 have similar needs), compute the network address based on
4354 the supplied ip address and netmask, if provided. Also
4355 compute the broadcast address (the host address all ones
4356 broadcast address, not the host address all zeroes
4357 broadcast address). */
4359 memset (&data
, 0, sizeof data
);
4360 oc
= lookup_option (&dhcp_universe
, lease
-> options
, DHO_SUBNET_MASK
);
4361 if (oc
&& evaluate_option_cache (&data
, (struct packet
*)0,
4362 (struct lease
*)0, client
,
4363 (struct option_state
*)0,
4365 &global_scope
, oc
, MDL
)) {
4367 struct iaddr netmask
, subnet
, broadcast
;
4370 * No matter the length of the subnet-mask option,
4371 * use only the first four octets. Note that
4372 * subnet-mask options longer than 4 octets are not
4373 * in conformance with RFC 2132, but servers with this
4376 memcpy(netmask
.iabuf
, data
.data
, 4);
4378 data_string_forget (&data
, MDL
);
4380 subnet
= subnet_number (lease
-> address
, netmask
);
4382 client_envadd (client
, prefix
, "network_number",
4383 "%s", piaddr (subnet
));
4385 oc
= lookup_option (&dhcp_universe
,
4387 DHO_BROADCAST_ADDRESS
);
4389 !(evaluate_option_cache
4390 (&data
, (struct packet
*)0,
4391 (struct lease
*)0, client
,
4392 (struct option_state
*)0,
4394 &global_scope
, oc
, MDL
))) {
4395 broadcast
= broadcast_addr (subnet
, netmask
);
4396 if (broadcast
.len
) {
4397 client_envadd (client
,
4398 prefix
, "broadcast_address",
4399 "%s", piaddr (broadcast
));
4404 data_string_forget (&data
, MDL
);
4407 if (lease
->filename
) {
4408 if (check_option_values(NULL
, DHO_ROOT_PATH
,
4410 strlen(lease
->filename
)) == 0) {
4411 client_envadd(client
, prefix
, "filename",
4412 "%s", lease
->filename
);
4414 log_error("suspect value in %s "
4415 "option - discarded",
4420 if (lease
->server_name
) {
4421 if (check_option_values(NULL
, DHO_HOST_NAME
,
4423 strlen(lease
->server_name
)) == 0 ) {
4424 client_envadd (client
, prefix
, "server_name",
4425 "%s", lease
->server_name
);
4427 log_error("suspect value in %s "
4428 "option - discarded",
4429 lease
->server_name
);
4433 for (i
= 0; i
< lease
-> options
-> universe_count
; i
++) {
4434 option_space_foreach ((struct packet
*)0, (struct lease
*)0,
4435 client
, (struct option_state
*)0,
4436 lease
-> options
, &global_scope
,
4438 &es
, client_option_envadd
);
4441 client_envadd (client
, prefix
, "expiry", "%lu",
4442 (unsigned long)(lease
-> expiry
));
4446 * @brief Write out the environent variable the client requested.
4447 * Write out the environment variables for the objects that the
4448 * client requested. If the object was requested the variable will be:
4449 * requested_<option_name>=1
4450 * If it wasn't requested there won't be a variable.
4452 * @param client client structure
4454 void script_write_requested(struct client_state
*client
)
4457 struct option
**req
;
4459 req
= client
->config
->requested_options
;
4464 for (i
= 0 ; req
[i
] != NULL
; i
++) {
4465 if ((req
[i
]->universe
== &dhcp_universe
) &&
4466 dhcp_option_ev_name(name
, sizeof(name
), req
[i
])) {
4467 client_envadd(client
, "requested_", name
, "%d", 1);
4473 * @brief Calls external script.
4475 * External script is specified either using -sf command line or
4476 * script parameter in the configuration file.
4478 * @param client specifies client information (environment variables,
4479 * and other parameters will be extracted and passed to the script.
4480 * @return If positive, it contains exit code of the process running script.
4481 * If negative, returns the signal number that cause the script process
4484 int script_go(struct client_state
*client
)
4489 char reason
[] = "REASON=NBI";
4490 static char client_path
[] = CLIENT_PATH
;
4492 struct string_list
*sp
, *next
;
4493 int pid
, wpid
, wstatus
;
4496 scriptName
= client
-> config
-> script_name
;
4498 scriptName
= top_level_config
.script_name
;
4500 envp
= dmalloc (((client
? client
-> envc
: 2) +
4501 client_env_count
+ 2) * sizeof (char *), MDL
);
4503 log_error ("No memory for client script environment.");
4507 /* Copy out the environment specified on the command line,
4509 for (sp
= client_env
; sp
; sp
= sp
-> next
) {
4510 envp
[i
++] = sp
-> string
;
4512 /* Copy out the environment specified by dhclient. */
4514 for (sp
= client
-> env
; sp
; sp
= sp
-> next
) {
4515 envp
[i
++] = sp
-> string
;
4518 envp
[i
++] = reason
;
4521 envp
[i
++] = client_path
;
4522 envp
[i
] = (char *)0;
4524 argv
[0] = scriptName
;
4525 argv
[1] = (char *)0;
4529 log_error ("fork: %m");
4533 wpid
= wait (&wstatus
);
4534 } while (wpid
!= pid
&& wpid
> 0);
4536 log_error ("wait: %m");
4540 /* We don't want to pass an open file descriptor for
4541 * dhclient.leases when executing dhclient-script.
4543 if (leaseFile
!= NULL
)
4545 execve (scriptName
, argv
, envp
);
4546 log_error ("execve (%s, ...): %m", scriptName
);
4551 for (sp
= client
-> env
; sp
; sp
= next
) {
4555 client
-> env
= (struct string_list
*)0;
4559 gettimeofday(&cur_tv
, NULL
);
4560 return (WIFEXITED (wstatus
) ?
4561 WEXITSTATUS (wstatus
) : -WTERMSIG (wstatus
));
4564 void client_envadd (struct client_state
*client
,
4565 const char *prefix
, const char *name
, const char *fmt
, ...)
4570 struct string_list
*val
;
4573 va_start (list
, fmt
);
4574 len
= vsnprintf (spbuf
, sizeof spbuf
, fmt
, list
);
4577 val
= dmalloc (strlen (prefix
) + strlen (name
) + 1 /* = */ +
4578 len
+ sizeof *val
, MDL
);
4580 log_error ("client_envadd: cannot allocate space for variable");
4589 if (len
>= sizeof spbuf
) {
4590 va_start (list
, fmt
);
4591 vsnprintf (s
, len
+ 1, fmt
, list
);
4597 val
-> next
= client
-> env
;
4598 client
-> env
= val
;
4602 int dhcp_option_ev_name (buf
, buflen
, option
)
4605 struct option
*option
;
4611 if (option
-> universe
!= &dhcp_universe
) {
4612 s
= option
-> universe
-> name
;
4621 if (j
+ 1 == buflen
)
4631 if (j
+ 1 == buflen
)
4642 void finish (char ret
)
4644 if (no_daemon
|| dfd
[0] == -1 || dfd
[1] == -1)
4646 if (write(dfd
[1], &ret
, 1) != 1)
4647 log_fatal("write to parent: %m");
4648 (void) close(dfd
[1]);
4649 dfd
[0] = dfd
[1] = -1;
4657 /* Don't become a daemon if the user requested otherwise. */
4659 write_client_pid_file ();
4663 /* Only do it once. */
4664 if (dfd
[0] == -1 || dfd
[1] == -1)
4667 /* Signal parent we started successfully. */
4668 if (write(dfd
[1], &buf
, 1) != 1)
4669 log_fatal("write to parent: %m");
4670 (void) close(dfd
[1]);
4671 dfd
[0] = dfd
[1] = -1;
4673 /* Stop logging to stderr... */
4676 /* Become session leader and get pid... */
4679 /* Close standard I/O descriptors. */
4684 /* Reopen them on /dev/null. */
4685 (void) open("/dev/null", O_RDWR
);
4686 (void) open("/dev/null", O_RDWR
);
4687 (void) open("/dev/null", O_RDWR
);
4689 write_client_pid_file ();
4691 IGNORE_RET (chdir("/"));
4695 void write_client_pid_file ()
4700 /* nothing to do if the user doesn't want a pid file */
4701 if (no_pid_file
== ISC_TRUE
) {
4705 pfdesc
= open (path_dhclient_pid
, O_CREAT
| O_TRUNC
| O_WRONLY
, 0644);
4708 log_error ("Can't create %s: %m", path_dhclient_pid
);
4712 pf
= fdopen (pfdesc
, "w");
4715 log_error ("Can't fdopen %s: %m", path_dhclient_pid
);
4717 fprintf (pf
, "%ld\n", (long)getpid ());
4722 void client_location_changed ()
4724 struct interface_info
*ip
;
4725 struct client_state
*client
;
4727 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4728 for (client
= ip
-> client
; client
; client
= client
-> next
) {
4729 switch (client
-> state
) {
4731 cancel_timeout (send_discover
, client
);
4735 cancel_timeout (state_bound
, client
);
4741 cancel_timeout (send_request
, client
);
4751 client
-> state
= S_INIT
;
4752 state_reboot (client
);
4757 void do_release(client
)
4758 struct client_state
*client
;
4760 struct data_string ds
;
4761 struct option_cache
*oc
;
4763 #if defined(DHCPv6) && defined(DHCP4o6)
4764 if (dhcpv4_over_dhcpv6
&& (dhcp4o6_state
<= 0)) {
4765 if (dhcp4o6_state
< 0)
4767 client
->pending
= P_RELEASE
;
4772 /* Pick a random xid. */
4773 client
-> xid
= random ();
4775 /* is there even a lease to release? */
4776 if (client
-> active
) {
4777 /* Make a DHCPRELEASE packet, and set appropriate per-interface
4779 make_release (client
, client
-> active
);
4781 memset (&ds
, 0, sizeof ds
);
4782 oc
= lookup_option (&dhcp_universe
,
4783 client
-> active
-> options
,
4784 DHO_DHCP_SERVER_IDENTIFIER
);
4786 evaluate_option_cache (&ds
, (struct packet
*)0,
4787 (struct lease
*)0, client
,
4788 (struct option_state
*)0,
4789 client
-> active
-> options
,
4790 &global_scope
, oc
, MDL
)) {
4792 memcpy (client
-> destination
.iabuf
,
4794 client
-> destination
.len
= 4;
4796 client
-> destination
= iaddr_broadcast
;
4798 data_string_forget (&ds
, MDL
);
4800 client
-> destination
= iaddr_broadcast
;
4801 client
-> first_sending
= cur_time
;
4802 client
-> interval
= client
-> config
-> initial_interval
;
4804 /* Zap the medium list... */
4805 client
-> medium
= (struct string_list
*)0;
4807 /* Send out the first and only DHCPRELEASE packet. */
4808 send_release (client
);
4810 /* Do the client script RELEASE operation. */
4811 script_init (client
,
4812 "RELEASE", (struct string_list
*)0);
4813 if (client
-> alias
)
4814 script_write_params(client
, "alias_",
4816 script_write_params(client
, "old_", client
-> active
);
4817 script_write_requested(client
);
4821 /* Cancel any timeouts. */
4822 cancel_timeout (state_bound
, client
);
4823 cancel_timeout (send_discover
, client
);
4824 cancel_timeout (state_init
, client
);
4825 cancel_timeout (send_request
, client
);
4826 cancel_timeout (state_reboot
, client
);
4827 cancel_timeout (finish_v6only
, client
);
4828 client
-> state
= S_STOPPED
;
4830 #if defined(DHCPv6) && defined(DHCP4o6)
4831 if (dhcpv4_over_dhcpv6
)
4836 int dhclient_interface_shutdown_hook (struct interface_info
*interface
)
4838 do_release (interface
-> client
);
4843 int dhclient_interface_discovery_hook (struct interface_info
*tmp
)
4845 struct interface_info
*last
, *ip
;
4846 /* See if we can find the client from dummy_interfaces */
4848 for (ip
= dummy_interfaces
; ip
; ip
= ip
-> next
) {
4849 if (!strcmp (ip
-> name
, tmp
-> name
)) {
4850 /* Remove from dummy_interfaces */
4852 ip
= (struct interface_info
*)0;
4853 interface_reference (&ip
, last
-> next
, MDL
);
4854 interface_dereference (&last
-> next
, MDL
);
4856 interface_reference (&last
-> next
,
4858 interface_dereference (&ip
-> next
,
4862 ip
= (struct interface_info
*)0;
4863 interface_reference (&ip
,
4864 dummy_interfaces
, MDL
);
4865 interface_dereference (&dummy_interfaces
, MDL
);
4867 interface_reference (&dummy_interfaces
,
4869 interface_dereference (&ip
-> next
,
4873 /* Copy "client" to tmp */
4875 tmp
-> client
= ip
-> client
;
4876 tmp
-> client
-> interface
= tmp
;
4878 interface_dereference (&ip
, MDL
);
4886 isc_result_t
dhclient_interface_startup_hook (struct interface_info
*interface
)
4888 struct interface_info
*ip
;
4889 struct client_state
*client
;
4891 /* This code needs some rethinking. It doesn't test against
4892 a signal name, and it just kind of bulls into doing something
4893 that may or may not be appropriate. */
4896 interface_reference (&interface
-> next
, interfaces
, MDL
);
4897 interface_dereference (&interfaces
, MDL
);
4899 interface_reference (&interfaces
, interface
, MDL
);
4901 discover_interfaces (DISCOVER_UNCONFIGURED
);
4903 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4904 /* If interfaces were specified, don't configure
4905 interfaces that weren't specified! */
4906 if (ip
-> flags
& INTERFACE_RUNNING
||
4907 (ip
-> flags
& (INTERFACE_REQUESTED
|
4908 INTERFACE_AUTOMATIC
)) !=
4909 INTERFACE_REQUESTED
)
4911 script_init (ip
-> client
,
4912 "PREINIT", (struct string_list
*)0);
4913 if (ip
-> client
-> alias
)
4914 script_write_params(ip
-> client
, "alias_",
4915 ip
-> client
-> alias
);
4916 script_go(ip
-> client
);
4919 discover_interfaces (interfaces_requested
!= 0
4920 ? DISCOVER_REQUESTED
4921 : DISCOVER_RUNNING
);
4923 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4924 if (ip
-> flags
& INTERFACE_RUNNING
)
4926 ip
-> flags
|= INTERFACE_RUNNING
;
4927 for (client
= ip
->client
; client
; client
= client
->next
) {
4928 client
->state
= S_INIT
;
4929 state_reboot(client
);
4932 return ISC_R_SUCCESS
;
4935 /* The client should never receive a relay agent information option,
4936 so if it does, log it and discard it. */
4938 int parse_agent_information_option (packet
, len
, data
)
4939 struct packet
*packet
;
4946 /* The client never sends relay agent information options. */
4948 unsigned cons_agent_information_options (cfg_options
, outpacket
,
4950 struct option_state
*cfg_options
;
4951 struct dhcp_packet
*outpacket
;
4958 static void shutdown_exit (void *foo
)
4960 /* get rid of the pid if we can */
4961 if (no_pid_file
== ISC_FALSE
)
4962 (void) unlink(path_dhclient_pid
);
4966 #if defined (NSUPDATE)
4968 * If the first query fails, the updater MUST NOT delete the DNS name. It
4969 * may be that the host whose lease on the server has expired has moved
4970 * to another network and obtained a lease from a different server,
4971 * which has caused the client's A RR to be replaced. It may also be
4972 * that some other client has been configured with a name that matches
4973 * the name of the DHCP client, and the policy was that the last client
4974 * to specify the name would get the name. In this case, the DHCID RR
4975 * will no longer match the updater's notion of the client-identity of
4976 * the host pointed to by the DNS name.
4977 * -- "Interaction between DHCP and DNS"
4980 /* The first and second stages are pretty similar so we combine them */
4982 client_dns_remove_action(dhcp_ddns_cb_t
*ddns_cb
,
4983 isc_result_t eresult
)
4986 isc_result_t result
;
4988 if ((eresult
== ISC_R_SUCCESS
) &&
4989 (ddns_cb
->state
== DDNS_STATE_REM_FW_YXDHCID
)) {
4990 /* Do the second stage of the FWD removal */
4991 ddns_cb
->state
= DDNS_STATE_REM_FW_NXRR
;
4993 result
= ddns_modify_fwd(ddns_cb
, MDL
);
4994 if (result
== ISC_R_SUCCESS
) {
4999 /* If we are done or have an error clean up */
5000 dhclient_ddns_cb_free(ddns_cb
, MDL
);
5005 client_dns_remove(struct client_state
*client
,
5008 dhcp_ddns_cb_t
*ddns_cb
;
5009 isc_result_t result
;
5011 /* if we have an old ddns request for this client, cancel it */
5012 if (client
->ddns_cb
!= NULL
) {
5013 ddns_cancel(client
->ddns_cb
, MDL
);
5014 client
->ddns_cb
= NULL
;
5017 ddns_cb
= ddns_cb_alloc(MDL
);
5018 if (ddns_cb
!= NULL
) {
5019 ddns_cb
->address
= *addr
;
5020 ddns_cb
->timeout
= 0;
5022 ddns_cb
->state
= DDNS_STATE_REM_FW_YXDHCID
;
5023 ddns_cb
->flags
= DDNS_UPDATE_ADDR
;
5024 ddns_cb
->cur_func
= client_dns_remove_action
;
5026 result
= client_dns_update(client
, ddns_cb
);
5028 if (result
!= ISC_R_TIMEDOUT
) {
5029 dhclient_ddns_cb_free(ddns_cb
, MDL
);
5033 #endif /* defined NSUPDATE */
5036 isc_result_t
dhcp_set_control_state (control_object_state_t oldstate
,
5037 control_object_state_t newstate
)
5039 struct interface_info
*ip
;
5040 struct client_state
*client
;
5043 if (newstate
== server_shutdown
) {
5045 if (shutdown_signal
== SIGUSR1
)
5046 return ISC_R_SUCCESS
;
5047 /* Log shutdown on signal. */
5048 if ((shutdown_signal
== SIGINT
) ||
5049 (shutdown_signal
== SIGTERM
)) {
5050 log_info("Received signal %d, initiating shutdown.",
5053 /* Mark it was called. */
5054 shutdown_signal
= SIGUSR1
;
5057 /* Do the right thing for each interface. */
5058 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
5059 for (client
= ip
-> client
; client
; client
= client
-> next
) {
5061 case server_startup
:
5062 return ISC_R_SUCCESS
;
5064 case server_running
:
5065 return ISC_R_SUCCESS
;
5067 case server_shutdown
:
5068 if (client
-> active
&&
5069 client
-> active
-> expiry
> cur_time
) {
5070 #if defined (NSUPDATE)
5071 if (client
->config
->do_forward_update
) {
5072 client_dns_remove(client
,
5073 &client
->active
->address
);
5075 #endif /* defined NSUPDATE */
5077 do_release (client
);
5081 case server_hibernate
:
5082 state_stop (client
);
5086 state_reboot (client
);
5092 if (newstate
== server_shutdown
) {
5093 tv
.tv_sec
= cur_tv
.tv_sec
;
5094 tv
.tv_usec
= cur_tv
.tv_usec
+ 1;
5095 add_timeout(&tv
, shutdown_exit
, 0, 0, 0);
5097 return ISC_R_SUCCESS
;
5100 #if defined (NSUPDATE)
5102 * Called after a timeout if the DNS update failed on the previous try.
5103 * Starts the retry process. If the retry times out it will schedule
5104 * this routine to run again after a 10x wait.
5107 client_dns_update_timeout (void *cp
)
5109 dhcp_ddns_cb_t
*ddns_cb
= (dhcp_ddns_cb_t
*)cp
;
5110 struct client_state
*client
= (struct client_state
*)ddns_cb
->lease
;
5111 isc_result_t status
= ISC_R_FAILURE
;
5113 if ((client
!= NULL
) &&
5114 ((client
->active
!= NULL
) ||
5115 (client
->active_lease
!= NULL
)))
5116 status
= client_dns_update(client
, ddns_cb
);
5119 * A status of timedout indicates that we started the update and
5120 * have released control of the control block. Any other status
5121 * indicates that we should clean up the control block. We either
5122 * got a success which indicates that we didn't really need to
5123 * send an update or some other error in which case we weren't able
5124 * to start the update process. In both cases we still own
5125 * the control block and should free it.
5127 if (status
!= ISC_R_TIMEDOUT
) {
5128 dhclient_ddns_cb_free(ddns_cb
, MDL
);
5133 * If the first query succeeds, the updater can conclude that it
5134 * has added a new name whose only RRs are the A and DHCID RR records.
5135 * The A RR update is now complete (and a client updater is finished,
5136 * while a server might proceed to perform a PTR RR update).
5137 * -- "Interaction between DHCP and DNS"
5139 * If the second query succeeds, the updater can conclude that the current
5140 * client was the last client associated with the domain name, and that
5141 * the name now contains the updated A RR. The A RR update is now
5142 * complete (and a client updater is finished, while a server would
5143 * then proceed to perform a PTR RR update).
5144 * -- "Interaction between DHCP and DNS"
5146 * If the second query fails with NXRRSET, the updater must conclude
5147 * that the client's desired name is in use by another host. At this
5148 * juncture, the updater can decide (based on some administrative
5149 * configuration outside of the scope of this document) whether to let
5150 * the existing owner of the name keep that name, and to (possibly)
5151 * perform some name disambiguation operation on behalf of the current
5152 * client, or to replace the RRs on the name with RRs that represent
5153 * the current client. If the configured policy allows replacement of
5154 * existing records, the updater submits a query that deletes the
5155 * existing A RR and the existing DHCID RR, adding A and DHCID RRs that
5156 * represent the IP address and client-identity of the new client.
5157 * -- "Interaction between DHCP and DNS"
5160 /* The first and second stages are pretty similar so we combine them */
5162 client_dns_update_action(dhcp_ddns_cb_t
*ddns_cb
,
5163 isc_result_t eresult
)
5165 isc_result_t result
;
5171 /* Either we succeeded or broke in a bad way, clean up */
5176 * This is the only difference between the two stages,
5177 * check to see if it is the first stage, in which case
5178 * start the second stage
5180 if (ddns_cb
->state
== DDNS_STATE_ADD_FW_NXDOMAIN
) {
5181 ddns_cb
->state
= DDNS_STATE_ADD_FW_YXDHCID
;
5182 ddns_cb
->cur_func
= client_dns_update_action
;
5184 result
= ddns_modify_fwd(ddns_cb
, MDL
);
5185 if (result
== ISC_R_SUCCESS
) {
5191 case ISC_R_TIMEDOUT
:
5193 * We got a timeout response from the DNS module. Schedule
5194 * another attempt for later. We forget the name, dhcid and
5195 * zone so if it gets changed we will get the new information.
5197 data_string_forget(&ddns_cb
->fwd_name
, MDL
);
5198 data_string_forget(&ddns_cb
->dhcid
, MDL
);
5199 if (ddns_cb
->zone
!= NULL
) {
5200 forget_zone((struct dns_zone
**)&ddns_cb
->zone
);
5203 /* Reset to doing the first stage */
5204 ddns_cb
->state
= DDNS_STATE_ADD_FW_NXDOMAIN
;
5205 ddns_cb
->cur_func
= client_dns_update_action
;
5207 /* and update our timer */
5208 if (ddns_cb
->timeout
< 3600)
5209 ddns_cb
->timeout
*= 10;
5210 tv
.tv_sec
= cur_tv
.tv_sec
+ ddns_cb
->timeout
;
5211 tv
.tv_usec
= cur_tv
.tv_usec
;
5212 add_timeout(&tv
, client_dns_update_timeout
,
5213 ddns_cb
, NULL
, NULL
);
5217 dhclient_ddns_cb_free(ddns_cb
, MDL
);
5221 /* See if we should do a DNS update, and if so, do it. */
5224 client_dns_update(struct client_state
*client
, dhcp_ddns_cb_t
*ddns_cb
)
5226 struct data_string client_identifier
;
5227 struct option_cache
*oc
;
5233 /* If we didn't send an FQDN option, we certainly aren't going to
5234 be doing an update. */
5235 if (!client
-> sent_options
)
5236 return ISC_R_SUCCESS
;
5238 /* If we don't have a lease, we can't do an update. */
5239 if ((client
->active
== NULL
) && (client
->active_lease
== NULL
))
5240 return ISC_R_SUCCESS
;
5242 /* If we set the no client update flag, don't do the update. */
5243 if ((oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5244 FQDN_NO_CLIENT_UPDATE
)) &&
5245 evaluate_boolean_option_cache (&ignorep
, (struct packet
*)0,
5246 (struct lease
*)0, client
,
5247 client
-> sent_options
,
5248 (struct option_state
*)0,
5249 &global_scope
, oc
, MDL
))
5250 return ISC_R_SUCCESS
;
5252 /* If we set the "server, please update" flag, or didn't set it
5253 to false, don't do the update. */
5254 if (!(oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5255 FQDN_SERVER_UPDATE
)) ||
5256 evaluate_boolean_option_cache (&ignorep
, (struct packet
*)0,
5257 (struct lease
*)0, client
,
5258 client
-> sent_options
,
5259 (struct option_state
*)0,
5260 &global_scope
, oc
, MDL
))
5261 return ISC_R_SUCCESS
;
5263 /* If no FQDN option was supplied, don't do the update. */
5264 if (!(oc
= lookup_option (&fqdn_universe
, client
-> sent_options
,
5266 !evaluate_option_cache (&ddns_cb
->fwd_name
, (struct packet
*)0,
5267 (struct lease
*)0, client
,
5268 client
-> sent_options
,
5269 (struct option_state
*)0,
5270 &global_scope
, oc
, MDL
))
5271 return ISC_R_SUCCESS
;
5274 * Construct the DHCID value for use in the DDNS update process
5275 * We have the newer standard version and the older interim version
5276 * chosen by the '-I' option. The interim version is left as is
5277 * for backwards compatibility. The standard version is based on
5278 * RFC 4701 section 3.3
5283 memset(&client_identifier
, 0, sizeof(client_identifier
));
5285 if (std_dhcid
== 1) {
5286 /* standard style */
5287 ddns_cb
->dhcid_class
= dns_rdatatype_dhcid
;
5291 ddns_cb
->dhcid_class
= dns_rdatatype_txt
;
5292 /* for backwards compatibility */
5293 ddns_v4_type
= DHO_DHCP_CLIENT_IDENTIFIER
;
5295 if (client
->active_lease
!= NULL
) {
5296 /* V6 request, get the client identifier, then
5297 * construct the dhcid for either standard
5299 if (((oc
= lookup_option(&dhcpv6_universe
,
5300 client
->sent_options
,
5301 D6O_CLIENTID
)) != NULL
) &&
5302 evaluate_option_cache(&client_identifier
, NULL
,
5304 client
->sent_options
, NULL
,
5305 &global_scope
, oc
, MDL
)) {
5306 result
= get_dhcid(ddns_cb
, 2,
5307 client_identifier
.data
,
5308 client_identifier
.len
);
5309 data_string_forget(&client_identifier
, MDL
);
5311 log_fatal("Impossible condition at %s:%d.", MDL
);
5314 * V4 request, use the client id if there is one or the
5315 * mac address if there isn't. If we have a client id
5316 * we check to see if it is an embedded DUID.
5318 if (((oc
= lookup_option(&dhcp_universe
,
5319 client
->sent_options
,
5320 DHO_DHCP_CLIENT_IDENTIFIER
)) != NULL
) &&
5321 evaluate_option_cache(&client_identifier
, NULL
,
5323 client
->sent_options
, NULL
,
5324 &global_scope
, oc
, MDL
)) {
5325 if ((std_dhcid
== 1) && (duid_v4
== 1) &&
5326 (client_identifier
.data
[0] == 255)) {
5328 * This appears to be an embedded DUID,
5329 * extract it and treat it as such
5331 if (client_identifier
.len
<= 5)
5332 log_fatal("Impossible condition at %s:%d.",
5334 result
= get_dhcid(ddns_cb
, 2,
5335 client_identifier
.data
+ 5,
5336 client_identifier
.len
- 5);
5338 result
= get_dhcid(ddns_cb
, ddns_v4_type
,
5339 client_identifier
.data
,
5340 client_identifier
.len
);
5342 data_string_forget(&client_identifier
, MDL
);
5344 result
= get_dhcid(ddns_cb
, 0,
5345 client
->interface
->hw_address
.hbuf
,
5346 client
->interface
->hw_address
.hlen
);
5350 return ISC_R_SUCCESS
;
5356 if (ddns_cb
->fwd_name
.len
&& ddns_cb
->dhcid
.len
) {
5357 rcode
= ddns_modify_fwd(ddns_cb
, MDL
);
5359 rcode
= ISC_R_FAILURE
;
5362 * A success from the modify routine means we are performing
5363 * async processing, for which we use the timedout error message.
5365 if (rcode
== ISC_R_SUCCESS
) {
5366 rcode
= ISC_R_TIMEDOUT
;
5374 * Schedule the first update. They will continue to retry occasionally
5375 * until they no longer time out (or fail).
5378 dhclient_schedule_updates(struct client_state
*client
,
5382 dhcp_ddns_cb_t
*ddns_cb
;
5385 if (!client
->config
->do_forward_update
)
5388 /* cancel any outstanding ddns requests */
5389 if (client
->ddns_cb
!= NULL
) {
5390 ddns_cancel(client
->ddns_cb
, MDL
);
5391 client
->ddns_cb
= NULL
;
5394 ddns_cb
= ddns_cb_alloc(MDL
);
5396 if (ddns_cb
!= NULL
) {
5397 ddns_cb
->lease
= (void *)client
;
5398 ddns_cb
->address
= *addr
;
5399 ddns_cb
->timeout
= 1;
5402 * XXX: DNS TTL is a problem we need to solve properly.
5403 * Until that time, 300 is a placeholder default for
5404 * something that is less insane than a value scaled
5409 ddns_cb
->state
= DDNS_STATE_ADD_FW_NXDOMAIN
;
5410 ddns_cb
->cur_func
= client_dns_update_action
;
5411 ddns_cb
->flags
= DDNS_UPDATE_ADDR
| DDNS_INCLUDE_RRSET
;
5413 client
->ddns_cb
= ddns_cb
;
5414 tv
.tv_sec
= cur_tv
.tv_sec
+ offset
;
5415 tv
.tv_usec
= cur_tv
.tv_usec
;
5416 add_timeout(&tv
, client_dns_update_timeout
,
5417 ddns_cb
, NULL
, NULL
);
5419 log_error("Unable to allocate dns update state for %s",
5423 #endif /* defined NSUPDATE */
5426 dhcpv4_client_assignments(void)
5428 struct servent
*ent
;
5430 if (path_dhclient_pid
== NULL
)
5431 path_dhclient_pid
= _PATH_DHCLIENT_PID
;
5432 if (path_dhclient_db
== NULL
)
5433 path_dhclient_db
= _PATH_DHCLIENT_DB
;
5435 /* Default to the DHCP/BOOTP port. */
5437 /* If we're faking a relay agent, and we're not using loopback,
5438 use the server port, not the client port. */
5439 if (mockup_relay
&& giaddr
.s_addr
!= htonl(INADDR_LOOPBACK
)) {
5440 local_port
= htons(67);
5442 ent
= getservbyname("dhcpc", "udp");
5444 ent
= getservbyname("bootpc", "udp");
5446 local_port
= htons(68);
5448 local_port
= ent
->s_port
;
5449 #ifndef __CYGWIN32__
5455 /* If we're faking a relay agent, and we're not using loopback,
5456 we're using the server port, not the client port. */
5457 if (mockup_relay
&& giaddr
.s_addr
!= htonl(INADDR_LOOPBACK
)) {
5458 remote_port
= local_port
;
5460 remote_port
= htons(ntohs(local_port
) - 1); /* XXX */
5464 * The following routines are used to check that certain
5465 * strings are reasonable before we pass them to the scripts.
5466 * This avoids some problems with scripts treating the strings
5467 * as commands - see ticket 23722
5468 * The domain checking code should be done as part of assembling
5469 * the string but we are doing it here for now due to time
5473 static int check_domain_name(const char *ptr
, size_t len
, int dots
)
5477 /* not empty or complete length not over 255 characters */
5478 if ((len
== 0) || (len
> 256))
5481 /* consists of [[:alnum:]-]+ labels separated by [.] */
5482 /* a [_] is against RFC but seems to be "widely used"... */
5483 for (p
=ptr
; (*p
!= 0) && (len
-- > 0); p
++) {
5484 if ((*p
== '-') || (*p
== '_')) {
5485 /* not allowed at begin or end of a label */
5486 if (((p
- ptr
) == 0) || (len
== 0) || (p
[1] == '.'))
5488 } else if (*p
== '.') {
5489 /* each label has to be 1-63 characters;
5490 we allow [.] at the end ('foo.bar.') */
5492 if ((d
<= 0) || (d
>= 64))
5494 ptr
= p
+ 1; /* jump to the next label */
5495 if ((dots
> 0) && (len
> 0))
5497 } else if (isalnum((unsigned char)*p
) == 0) {
5498 /* also numbers at the begin are fine */
5502 return(dots
? -1 : 0);
5505 static int check_domain_name_list(const char *ptr
, size_t len
, int dots
)
5508 int ret
= -1; /* at least one needed */
5510 if ((ptr
== NULL
) || (len
== 0))
5513 for (p
=ptr
; (*p
!= 0) && (len
> 0); p
++, len
--) {
5517 if (check_domain_name(ptr
, p
- ptr
, dots
) != 0)
5524 return(check_domain_name(ptr
, p
- ptr
, dots
));
5529 static int check_option_values(struct universe
*universe
,
5537 /* just reject options we want to protect, will be escaped anyway */
5538 if ((universe
== NULL
) || (universe
== &dhcp_universe
)) {
5540 case DHO_DOMAIN_NAME
:
5541 #ifdef ACCEPT_LIST_IN_DOMAIN_NAME
5542 return check_domain_name_list(ptr
, len
, 0);
5544 return check_domain_name(ptr
, len
, 0);
5547 case DHO_NIS_DOMAIN
:
5548 case DHO_NETBIOS_SCOPE
:
5549 return check_domain_name(ptr
, len
, 0);
5551 case DHO_DOMAIN_SEARCH
:
5552 return check_domain_name_list(ptr
, len
, 0);
5557 for (; (*ptr
!= 0) && (len
-- > 0); ptr
++) {
5558 if(!(isalnum((unsigned char)*ptr
) ||
5559 *ptr
== '#' || *ptr
== '%' ||
5560 *ptr
== '+' || *ptr
== '-' ||
5561 *ptr
== '_' || *ptr
== ':' ||
5562 *ptr
== '.' || *ptr
== ',' ||
5563 *ptr
== '@' || *ptr
== '~' ||
5564 *ptr
== '\\' || *ptr
== '/' ||
5565 *ptr
== '[' || *ptr
== ']' ||
5566 *ptr
== '=' || *ptr
== ' '))
5575 if (universe
== &dhcpv6_universe
) {
5577 case D6O_SIP_SERVERS_DNS
:
5578 case D6O_DOMAIN_SEARCH
:
5579 case D6O_NIS_DOMAIN_NAME
:
5580 case D6O_NISP_DOMAIN_NAME
:
5581 return check_domain_name_list(ptr
, len
, 0);
5591 add_reject(struct packet
*packet
) {
5592 struct iaddrmatchlist
*list
;
5594 list
= dmalloc(sizeof(struct iaddrmatchlist
), MDL
);
5596 log_fatal ("no memory for reject list!");
5599 * client_addr is misleading - it is set to source address in common
5602 list
->match
.addr
= packet
->client_addr
;
5603 /* Set mask to indicate host address. */
5604 list
->match
.mask
.len
= list
->match
.addr
.len
;
5605 memset(list
->match
.mask
.iabuf
, 0xff, sizeof(list
->match
.mask
.iabuf
));
5607 /* Append to reject list for the source interface. */
5608 list
->next
= packet
->interface
->client
->config
->reject_list
;
5609 packet
->interface
->client
->config
->reject_list
= list
;
5612 * We should inform user that we won't be accepting this server
5615 log_info("Server added to list of rejected servers.");
5618 #if defined(NSUPDATE)
5619 /* Wrapper function around common ddns_cb_free function that ensures
5620 * we set the client_state pointer to the control block to NULL. */
5622 dhclient_ddns_cb_free(dhcp_ddns_cb_t
*ddns_cb
, char* file
, int line
) {
5624 struct client_state
*client
= (struct client_state
*)ddns_cb
->lease
;
5625 if (client
!= NULL
) {
5626 client
->ddns_cb
= NULL
;
5629 ddns_cb_free(ddns_cb
, file
, line
);
5632 #endif /* defined NSUPDATE */
5634 #if defined(DHCPv6) && defined(DHCP4o6)
5636 * \brief Omapi I/O handler
5638 * The inter-process communication receive handler.
5640 * On the DHCPv6 side, the message is either a POLL (which is answered
5641 * by a START or a STOP) or a DHCPv4-QUERY (which is forwarded to
5642 * DHCPv4 over DHCPv6 servers by forw_dhcpv4_query()).
5644 * On the DHCPv4 side, the message is either a START, a STOP
5645 * (both for the DHCP4 over DHCPv6 state machine) or a DHCPv4-RESPONSE
5646 * (which is processed by recv_dhcpv4_response()).
5648 * \param h the OMAPI object
5649 * \return a result for I/O success or error (used by the I/O subsystem)
5651 isc_result_t
dhcpv4o6_handler(omapi_object_t
*h
) {
5653 char start_msg
[5] = { 'S', 'T', 'A', 'R', 'T' };
5654 char stop_msg
[4] = { 'S', 'T', 'O', 'P' };
5655 char poll_msg
[4] = { 'P', 'O', 'L', 'L' };
5656 struct data_string raw
;
5659 if (h
->type
!= dhcp4o6_type
)
5660 return DHCP_R_INVALIDARG
;
5662 cc
= recv(dhcp4o6_fd
, buf
, sizeof(buf
), 0);
5664 return ISC_R_UNEXPECTED
;
5666 if (local_family
== AF_INET6
) {
5668 (memcmp(buf
, poll_msg
, sizeof(poll_msg
)) == 0)) {
5669 log_info("RCV: POLL");
5670 if (dhcp4o6_state
< 0)
5671 cc
= send(dhcp4o6_fd
, stop_msg
,
5672 sizeof(stop_msg
), 0);
5674 cc
= send(dhcp4o6_fd
, start_msg
,
5675 sizeof(start_msg
), 0);
5677 log_error("dhcpv4o6_handler: send(): %m");
5678 return ISC_R_IOERROR
;
5681 if (cc
< DHCP_FIXED_NON_UDP
+ 8)
5682 return ISC_R_UNEXPECTED
;
5683 memset(&raw
, 0, sizeof(raw
));
5684 if (!buffer_allocate(&raw
.buffer
, cc
, MDL
)) {
5685 log_error("dhcpv4o6_handler: "
5686 "no memory buffer.");
5687 return ISC_R_NOMEMORY
;
5689 raw
.data
= raw
.buffer
->data
;
5691 memcpy(raw
.buffer
->data
, buf
, cc
);
5693 forw_dhcpv4_query(&raw
);
5695 data_string_forget(&raw
, MDL
);
5699 (memcmp(buf
, stop_msg
, sizeof(stop_msg
)) == 0)) {
5700 log_info("RCV: STOP");
5701 if (dhcp4o6_state
> 0) {
5705 } else if ((cc
== 5) &&
5706 (memcmp(buf
, start_msg
, sizeof(start_msg
)) == 0)) {
5707 log_info("RCV: START");
5708 if (dhcp4o6_state
== 0)
5709 cancel_timeout(dhcp4o6_poll
, NULL
);
5713 if (cc
< DHCP_FIXED_NON_UDP
+ 16)
5714 return ISC_R_UNEXPECTED
;
5715 memset(&raw
, 0, sizeof(raw
));
5716 if (!buffer_allocate(&raw
.buffer
, cc
, MDL
)) {
5717 log_error("dhcpv4o6_handler: "
5718 "no memory buffer.");
5719 return ISC_R_NOMEMORY
;
5721 raw
.data
= raw
.buffer
->data
;
5723 memcpy(raw
.buffer
->data
, buf
, cc
);
5725 recv_dhcpv4_response(&raw
);
5727 data_string_forget(&raw
, MDL
);
5731 return ISC_R_SUCCESS
;
5735 * \brief Poll the DHCPv6 client
5736 * (DHCPv4 client function)
5738 * A POLL message is sent to the DHCPv6 client periodically to check
5739 * if the DHCPv6 is ready (i.e., has a valid DHCPv4-over-DHCPv6 server
5742 static void dhcp4o6_poll(void *dummy
) {
5743 char msg
[4] = { 'P', 'O', 'L', 'L' };
5747 IGNORE_UNUSED(dummy
);
5749 if (dhcp4o6_state
< 0)
5754 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5756 log_error("dhcp4o6_poll: send(): %m");
5758 tv
.tv_sec
= cur_time
+ 60;
5759 tv
.tv_usec
= random() % 1000000;
5761 add_timeout(&tv
, dhcp4o6_poll
, NULL
, 0, 0);
5765 * \brief Resume pending operations
5766 * (DHCPv4 client function)
5768 * A START message was received from the DHCPv6 client so pending
5769 * operations (RELEASE or REBOOT) must be resumed.
5771 static void dhcp4o6_resume() {
5772 struct interface_info
*ip
;
5773 struct client_state
*client
;
5775 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
5776 for (client
= ip
->client
; client
!= NULL
;
5777 client
= client
->next
) {
5778 if (client
->pending
== P_RELEASE
)
5780 else if (client
->pending
== P_REBOOT
)
5781 state_reboot(client
);
5787 * \brief Send a START to the DHCPv4 client
5788 * (DHCPv6 client function)
5790 * First check if there is a valid DHCPv4-over-DHCPv6 server address option,
5791 * and when found go UP and on a transition from another state send
5792 * a START message to the DHCPv4 client.
5794 void dhcp4o6_start() {
5795 struct interface_info
*ip
;
5796 struct client_state
*client
;
5797 struct dhc6_lease
*lease
;
5798 struct option_cache
*oc
;
5799 struct data_string addrs
;
5800 char msg
[5] = { 'S', 'T', 'A', 'R', 'T' };
5803 memset(&addrs
, 0, sizeof(addrs
));
5804 for (ip
= interfaces
; ip
!= NULL
; ip
= ip
->next
) {
5805 for (client
= ip
->client
; client
!= NULL
;
5806 client
= client
->next
) {
5807 if ((client
->state
!= S_BOUND
) &&
5808 (client
->state
!= S_RENEWING
) &&
5809 (client
->state
!= S_REBINDING
))
5811 lease
= client
->active_lease
;
5812 if ((lease
== NULL
) || lease
->released
)
5814 oc
= lookup_option(&dhcpv6_universe
,
5816 D6O_DHCP4_O_DHCP6_SERVER
);
5818 !evaluate_option_cache(&addrs
, NULL
, NULL
, NULL
,
5819 lease
->options
, NULL
,
5820 &global_scope
, oc
, MDL
))
5822 if ((addrs
.len
% 16) != 0) {
5823 data_string_forget(&addrs
, MDL
);
5826 data_string_forget(&addrs
, MDL
);
5830 log_info("dhcp4o6_start: failed");
5835 if (dhcp4o6_state
== 1)
5837 log_info("dhcp4o6_start: go to UP");
5840 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5842 log_info("dhcp4o6_start: send(): %m");
5846 * Send a STOP to the DHCPv4 client
5847 * (DHCPv6 client function)
5849 * Go DOWN and on a transition from another state send a STOP message
5850 * to the DHCPv4 client.
5852 static void dhcp4o6_stop() {
5853 char msg
[4] = { 'S', 'T', 'O', 'P' };
5856 if (dhcp4o6_state
== -1)
5859 log_info("dhcp4o6_stop: go to DOWN");
5862 cc
= send(dhcp4o6_fd
, msg
, sizeof(msg
), 0);
5864 log_error("dhcp4o6_stop: send(): %m");
5866 #endif /* DHCPv6 && DHCP4o6 */