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