1 /* $OpenBSD: dhclient.c,v 1.63 2005/02/06 17:10:13 krw Exp $ */
2
3 /*-
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Copyright 2004 Henning Brauer <[email protected]>
7 * Copyright (c) 1995, 1996, 1997, 1998, 1999
8 * The Internet Software Consortium. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of The Internet Software Consortium nor the names
20 * of its contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
24 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
31 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * This software has been written for the Internet Software Consortium
38 * by Ted Lemon <[email protected]> in cooperation with Vixie
39 * Enterprises. To learn more about the Internet Software Consortium,
40 * see ``http://www.vix.com/isc''. To learn more about Vixie
41 * Enterprises, see ``http://www.vix.com''.
42 *
43 * This client was substantially modified and enhanced by Elliot Poger
44 * for use on Linux while he was working on the MosquitoNet project at
45 * Stanford.
46 *
47 * The current version owes much to Elliot's Linux enhancements, but
48 * was substantially reorganized and partially rewritten by Ted Lemon
49 * so as to use the same networking framework that the Internet Software
50 * Consortium DHCP server uses. Much system-specific configuration code
51 * was moved into a shell script so that as support for more operating
52 * systems is added, it will not be necessary to port and maintain
53 * system-specific configuration code to these operating systems - instead,
54 * the shell script can invoke the native tools to accomplish the same
55 * purpose.
56 */
57
58 #include <sys/cdefs.h>
59 __FBSDID("$FreeBSD$");
60
61 #include "dhcpd.h"
62 #include "privsep.h"
63
64 #include <sys/capsicum.h>
65 #include <sys/endian.h>
66
67 #include <capsicum_helpers.h>
68 #include <libgen.h>
69
70 #include <net80211/ieee80211_freebsd.h>
71
72
73 #ifndef _PATH_VAREMPTY
74 #define _PATH_VAREMPTY "/var/empty"
75 #endif
76
77 #define PERIOD 0x2e
78 #define hyphenchar(c) ((c) == 0x2d)
79 #define bslashchar(c) ((c) == 0x5c)
80 #define periodchar(c) ((c) == PERIOD)
81 #define asterchar(c) ((c) == 0x2a)
82 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
83 ((c) >= 0x61 && (c) <= 0x7a))
84 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
85 #define whitechar(c) ((c) == ' ' || (c) == '\t')
86
87 #define borderchar(c) (alphachar(c) || digitchar(c))
88 #define middlechar(c) (borderchar(c) || hyphenchar(c))
89 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
90
91 #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
92
93 cap_channel_t *capsyslog;
94
95 time_t cur_time;
96 static time_t default_lease_time = 43200; /* 12 hours... */
97
98 const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
99 char *path_dhclient_db = NULL;
100
101 int log_perror = 1;
102 static int privfd;
103 static int nullfd = -1;
104
105 static char hostname[_POSIX_HOST_NAME_MAX + 1];
106
107 static struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
108 static struct in_addr inaddr_any, inaddr_broadcast;
109
110 static char *path_dhclient_pidfile;
111 struct pidfh *pidfile;
112
113 /*
114 * ASSERT_STATE() does nothing now; it used to be
115 * assert (state_is == state_shouldbe).
116 */
117 #define ASSERT_STATE(state_is, state_shouldbe) {}
118
119 /*
120 * We need to check that the expiry, renewal and rebind times are not beyond
121 * the end of time (~2038 when a 32-bit time_t is being used).
122 */
123 #define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
124
125 int log_priority;
126 static int no_daemon;
127 static int unknown_ok = 1;
128 static int routefd;
129
130 struct interface_info *ifi;
131
132 int findproto(char *, int);
133 struct sockaddr *get_ifa(char *, int);
134 void routehandler(struct protocol *);
135 void usage(void);
136 int check_option(struct client_lease *l, int option);
137 int check_classless_option(unsigned char *data, int len);
138 int ipv4addrs(const char * buf);
139 int res_hnok(const char *dn);
140 int check_search(const char *srch);
141 const char *option_as_string(unsigned int code, unsigned char *data, int len);
142 int fork_privchld(int, int);
143
144 #define ROUNDUP(a) \
145 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
146 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
147
148 /* Minimum MTU is 68 as per RFC791, p. 24 */
149 #define MIN_MTU 68
150
151 static time_t scripttime;
152
153 int
findproto(char * cp,int n)154 findproto(char *cp, int n)
155 {
156 struct sockaddr *sa;
157 unsigned i;
158
159 if (n == 0)
160 return -1;
161 for (i = 1; i; i <<= 1) {
162 if (i & n) {
163 sa = (struct sockaddr *)cp;
164 switch (i) {
165 case RTA_IFA:
166 case RTA_DST:
167 case RTA_GATEWAY:
168 case RTA_NETMASK:
169 if (sa->sa_family == AF_INET)
170 return AF_INET;
171 if (sa->sa_family == AF_INET6)
172 return AF_INET6;
173 break;
174 case RTA_IFP:
175 break;
176 }
177 ADVANCE(cp, sa);
178 }
179 }
180 return (-1);
181 }
182
183 struct sockaddr *
get_ifa(char * cp,int n)184 get_ifa(char *cp, int n)
185 {
186 struct sockaddr *sa;
187 unsigned i;
188
189 if (n == 0)
190 return (NULL);
191 for (i = 1; i; i <<= 1)
192 if (i & n) {
193 sa = (struct sockaddr *)cp;
194 if (i == RTA_IFA)
195 return (sa);
196 ADVANCE(cp, sa);
197 }
198
199 return (NULL);
200 }
201
202 static struct iaddr defaddr = { .len = 4 };
203 static uint8_t curbssid[6];
204
205 static void
disassoc(void * arg)206 disassoc(void *arg)
207 {
208 struct interface_info *_ifi = arg;
209
210 /*
211 * Clear existing state.
212 */
213 if (_ifi->client->active != NULL) {
214 script_init("EXPIRE", NULL);
215 script_write_params("old_",
216 _ifi->client->active);
217 if (_ifi->client->alias)
218 script_write_params("alias_",
219 _ifi->client->alias);
220 script_go();
221 }
222 _ifi->client->state = S_INIT;
223 }
224
225 void
routehandler(struct protocol * p __unused)226 routehandler(struct protocol *p __unused)
227 {
228 char msg[2048], *addr;
229 struct rt_msghdr *rtm;
230 struct if_msghdr *ifm;
231 struct ifa_msghdr *ifam;
232 struct if_announcemsghdr *ifan;
233 struct ieee80211_join_event *jev;
234 struct client_lease *l;
235 time_t t = time(NULL);
236 struct sockaddr_in *sa;
237 struct iaddr a;
238 ssize_t n;
239 int linkstat;
240
241 n = read(routefd, &msg, sizeof(msg));
242 rtm = (struct rt_msghdr *)msg;
243 if (n < (ssize_t)sizeof(rtm->rtm_msglen) ||
244 n < (ssize_t)rtm->rtm_msglen ||
245 rtm->rtm_version != RTM_VERSION)
246 return;
247
248 switch (rtm->rtm_type) {
249 case RTM_NEWADDR:
250 case RTM_DELADDR:
251 ifam = (struct ifa_msghdr *)rtm;
252
253 if (ifam->ifam_index != ifi->index)
254 break;
255 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
256 break;
257 if (scripttime == 0 || t < scripttime + 10)
258 break;
259
260 sa = (struct sockaddr_in*)get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
261 if (sa == NULL)
262 break;
263
264 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
265 error("king bula sez: len mismatch");
266 memcpy(a.iabuf, &sa->sin_addr, a.len);
267 if (addr_eq(a, defaddr))
268 break;
269
270 for (l = ifi->client->active; l != NULL; l = l->next)
271 if (addr_eq(a, l->address))
272 break;
273
274 if (l == NULL) /* added/deleted addr is not the one we set */
275 break;
276
277 addr = inet_ntoa(sa->sin_addr);
278 if (rtm->rtm_type == RTM_NEWADDR) {
279 /*
280 * XXX: If someone other than us adds our address,
281 * should we assume they are taking over from us,
282 * delete the lease record, and exit without modifying
283 * the interface?
284 */
285 warning("My address (%s) was re-added", addr);
286 } else {
287 warning("My address (%s) was deleted, dhclient exiting",
288 addr);
289 goto die;
290 }
291 break;
292 case RTM_IFINFO:
293 ifm = (struct if_msghdr *)rtm;
294 if (ifm->ifm_index != ifi->index)
295 break;
296 if ((rtm->rtm_flags & RTF_UP) == 0) {
297 warning("Interface %s is down, dhclient exiting",
298 ifi->name);
299 goto die;
300 }
301 linkstat = interface_link_status(ifi->name);
302 if (linkstat != ifi->linkstat) {
303 debug("%s link state %s -> %s", ifi->name,
304 ifi->linkstat ? "up" : "down",
305 linkstat ? "up" : "down");
306 ifi->linkstat = linkstat;
307 if (linkstat)
308 state_reboot(ifi);
309 }
310 break;
311 case RTM_IFANNOUNCE:
312 ifan = (struct if_announcemsghdr *)rtm;
313 if (ifan->ifan_what == IFAN_DEPARTURE &&
314 ifan->ifan_index == ifi->index) {
315 warning("Interface %s is gone, dhclient exiting",
316 ifi->name);
317 goto die;
318 }
319 break;
320 case RTM_IEEE80211:
321 ifan = (struct if_announcemsghdr *)rtm;
322 if (ifan->ifan_index != ifi->index)
323 break;
324 switch (ifan->ifan_what) {
325 case RTM_IEEE80211_ASSOC:
326 case RTM_IEEE80211_REASSOC:
327 /*
328 * Use assoc/reassoc event to kick state machine
329 * in case we roam. Otherwise fall back to the
330 * normal state machine just like a wired network.
331 */
332 jev = (struct ieee80211_join_event *) &ifan[1];
333 if (memcmp(curbssid, jev->iev_addr, 6)) {
334 disassoc(ifi);
335 state_reboot(ifi);
336 }
337 memcpy(curbssid, jev->iev_addr, 6);
338 break;
339 }
340 break;
341 default:
342 break;
343 }
344 return;
345
346 die:
347 script_init("FAIL", NULL);
348 if (ifi->client->alias)
349 script_write_params("alias_", ifi->client->alias);
350 script_go();
351 if (pidfile != NULL)
352 pidfile_remove(pidfile);
353 exit(1);
354 }
355
356 static void
init_casper(void)357 init_casper(void)
358 {
359 cap_channel_t *casper;
360
361 casper = cap_init();
362 if (casper == NULL)
363 error("unable to start casper");
364
365 capsyslog = cap_service_open(casper, "system.syslog");
366 cap_close(casper);
367 if (capsyslog == NULL)
368 error("unable to open system.syslog service");
369 }
370
371 int
main(int argc,char * argv[])372 main(int argc, char *argv[])
373 {
374 u_int capmode;
375 int ch, fd, quiet = 0, i = 0;
376 int pipe_fd[2];
377 int immediate_daemon = 0;
378 struct passwd *pw;
379 pid_t otherpid;
380 cap_rights_t rights;
381
382 init_casper();
383
384 /* Initially, log errors to stderr as well as to syslogd. */
385 cap_openlog(capsyslog, getprogname(), LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
386 cap_setlogmask(capsyslog, LOG_UPTO(LOG_DEBUG));
387
388 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
389 switch (ch) {
390 case 'b':
391 immediate_daemon = 1;
392 break;
393 case 'c':
394 path_dhclient_conf = optarg;
395 break;
396 case 'd':
397 no_daemon = 1;
398 break;
399 case 'l':
400 path_dhclient_db = optarg;
401 break;
402 case 'p':
403 path_dhclient_pidfile = optarg;
404 break;
405 case 'q':
406 quiet = 1;
407 break;
408 case 'u':
409 unknown_ok = 0;
410 break;
411 default:
412 usage();
413 }
414
415 argc -= optind;
416 argv += optind;
417
418 if (argc != 1)
419 usage();
420
421 if (path_dhclient_pidfile == NULL) {
422 asprintf(&path_dhclient_pidfile,
423 "%s/dhclient/dhclient.%s.pid", _PATH_VARRUN, *argv);
424 if (path_dhclient_pidfile == NULL)
425 error("asprintf");
426 }
427 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
428 if (pidfile == NULL) {
429 if (errno == EEXIST)
430 error("dhclient already running, pid: %d.", otherpid);
431 if (errno == EAGAIN)
432 error("dhclient already running.");
433 warning("Cannot open or create pidfile: %m");
434 }
435
436 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
437 error("calloc");
438 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
439 error("Interface name too long");
440 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
441 _PATH_DHCLIENT_DB, ifi->name) == -1)
442 error("asprintf");
443
444 if (quiet)
445 log_perror = 0;
446
447 tzset();
448 time(&cur_time);
449
450 inaddr_broadcast.s_addr = INADDR_BROADCAST;
451 inaddr_any.s_addr = INADDR_ANY;
452
453 read_client_conf();
454
455 /* The next bit is potentially very time-consuming, so write out
456 the pidfile right away. We will write it out again with the
457 correct pid after daemonizing. */
458 if (pidfile != NULL)
459 pidfile_write(pidfile);
460
461 if (!interface_link_status(ifi->name)) {
462 fprintf(stderr, "%s: no link ...", ifi->name);
463 fflush(stderr);
464 sleep(1);
465 while (!interface_link_status(ifi->name)) {
466 fprintf(stderr, ".");
467 fflush(stderr);
468 if (++i > 10) {
469 fprintf(stderr, " giving up\n");
470 exit(1);
471 }
472 sleep(1);
473 }
474 fprintf(stderr, " got link\n");
475 }
476 ifi->linkstat = 1;
477
478 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
479 error("cannot open %s: %m", _PATH_DEVNULL);
480
481 if ((pw = getpwnam("_dhcp")) == NULL) {
482 warning("no such user: _dhcp, falling back to \"nobody\"");
483 if ((pw = getpwnam("nobody")) == NULL)
484 error("no such user: nobody");
485 }
486
487 /*
488 * Obtain hostname before entering capability mode - it won't be
489 * possible then, as reading kern.hostname is not permitted.
490 */
491 if (gethostname(hostname, sizeof(hostname)) < 0)
492 hostname[0] = '\0';
493
494 priv_script_init("PREINIT", NULL);
495 if (ifi->client->alias)
496 priv_script_write_params("alias_", ifi->client->alias);
497 priv_script_go();
498
499 /* set up the interface */
500 discover_interfaces(ifi);
501
502 if (pipe(pipe_fd) == -1)
503 error("pipe");
504
505 fork_privchld(pipe_fd[0], pipe_fd[1]);
506
507 close(ifi->ufdesc);
508 ifi->ufdesc = -1;
509 close(ifi->wfdesc);
510 ifi->wfdesc = -1;
511
512 close(pipe_fd[0]);
513 privfd = pipe_fd[1];
514 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
515 if (caph_rights_limit(privfd, &rights) < 0)
516 error("can't limit private descriptor: %m");
517
518 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
519 error("can't open and lock %s: %m", path_dhclient_db);
520 read_client_leases();
521 rewrite_client_leases();
522 close(fd);
523
524 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
525 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
526 if (shutdown(routefd, SHUT_WR) < 0)
527 error("can't shutdown route socket: %m");
528 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
529 if (caph_rights_limit(routefd, &rights) < 0)
530 error("can't limit route socket: %m");
531
532 endpwent();
533
534 setproctitle("%s", ifi->name);
535
536 /* setgroups(2) is not permitted in capability mode. */
537 if (setgroups(1, &pw->pw_gid) != 0)
538 error("can't restrict groups: %m");
539
540 if (caph_enter_casper() < 0)
541 error("can't enter capability mode: %m");
542
543 /*
544 * If we are not in capability mode (i.e., Capsicum or libcasper is
545 * disabled), try to restrict filesystem access. This will fail if
546 * kern.chroot_allow_open_directories is 0 or the process is jailed.
547 */
548 if (cap_getmode(&capmode) < 0 || capmode == 0) {
549 if (chroot(_PATH_VAREMPTY) == -1)
550 error("chroot");
551 if (chdir("/") == -1)
552 error("chdir(\"/\")");
553 }
554
555 if (setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
556 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
557 error("can't drop privileges: %m");
558
559 if (immediate_daemon)
560 go_daemon();
561
562 ifi->client->state = S_INIT;
563 state_reboot(ifi);
564
565 bootp_packet_handler = do_packet;
566
567 dispatch();
568
569 /* not reached */
570 return (0);
571 }
572
573 void
usage(void)574 usage(void)
575 {
576
577 fprintf(stderr, "usage: %s [-bdqu] ", getprogname());
578 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
579 exit(1);
580 }
581
582 /*
583 * Individual States:
584 *
585 * Each routine is called from the dhclient_state_machine() in one of
586 * these conditions:
587 * -> entering INIT state
588 * -> recvpacket_flag == 0: timeout in this state
589 * -> otherwise: received a packet in this state
590 *
591 * Return conditions as handled by dhclient_state_machine():
592 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
593 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
594 * Returns 0: finish the nap which was interrupted for no good reason.
595 *
596 * Several per-interface variables are used to keep track of the process:
597 * active_lease: the lease that is being used on the interface
598 * (null pointer if not configured yet).
599 * offered_leases: leases corresponding to DHCPOFFER messages that have
600 * been sent to us by DHCP servers.
601 * acked_leases: leases corresponding to DHCPACK messages that have been
602 * sent to us by DHCP servers.
603 * sendpacket: DHCP packet we're trying to send.
604 * destination: IP address to send sendpacket to
605 * In addition, there are several relevant per-lease variables.
606 * T1_expiry, T2_expiry, lease_expiry: lease milestones
607 * In the active lease, these control the process of renewing the lease;
608 * In leases on the acked_leases list, this simply determines when we
609 * can no longer legitimately use the lease.
610 */
611
612 void
state_reboot(void * ipp)613 state_reboot(void *ipp)
614 {
615 struct interface_info *ip = ipp;
616
617 /* If we don't remember an active lease, go straight to INIT. */
618 if (!ip->client->active || ip->client->active->is_bootp) {
619 state_init(ip);
620 return;
621 }
622
623 /* We are in the rebooting state. */
624 ip->client->state = S_REBOOTING;
625
626 /* make_request doesn't initialize xid because it normally comes
627 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
628 so pick an xid now. */
629 ip->client->xid = arc4random();
630
631 /* Make a DHCPREQUEST packet, and set appropriate per-interface
632 flags. */
633 make_request(ip, ip->client->active);
634 ip->client->destination = iaddr_broadcast;
635 ip->client->first_sending = cur_time;
636 ip->client->interval = ip->client->config->initial_interval;
637
638 /* Zap the medium list... */
639 ip->client->medium = NULL;
640
641 /* Send out the first DHCPREQUEST packet. */
642 send_request(ip);
643 }
644
645 /*
646 * Called when a lease has completely expired and we've
647 * been unable to renew it.
648 */
649 void
state_init(void * ipp)650 state_init(void *ipp)
651 {
652 struct interface_info *ip = ipp;
653
654 ASSERT_STATE(state, S_INIT);
655
656 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
657 flags. */
658 make_discover(ip, ip->client->active);
659 ip->client->xid = ip->client->packet.xid;
660 ip->client->destination = iaddr_broadcast;
661 ip->client->state = S_SELECTING;
662 ip->client->first_sending = cur_time;
663 ip->client->interval = ip->client->config->initial_interval;
664
665 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
666 to go out. */
667 send_discover(ip);
668 }
669
670 /*
671 * state_selecting is called when one or more DHCPOFFER packets
672 * have been received and a configurable period of time has passed.
673 */
674 void
state_selecting(void * ipp)675 state_selecting(void *ipp)
676 {
677 struct interface_info *ip = ipp;
678 struct client_lease *lp, *next, *picked;
679
680 ASSERT_STATE(state, S_SELECTING);
681
682 /* Cancel state_selecting and send_discover timeouts, since either
683 one could have got us here. */
684 cancel_timeout(state_selecting, ip);
685 cancel_timeout(send_discover, ip);
686
687 /* We have received one or more DHCPOFFER packets. Currently,
688 the only criterion by which we judge leases is whether or
689 not we get a response when we arp for them. */
690 picked = NULL;
691 for (lp = ip->client->offered_leases; lp; lp = next) {
692 next = lp->next;
693
694 /* Check to see if we got an ARPREPLY for the address
695 in this particular lease. */
696 if (!picked) {
697 script_init("ARPCHECK", lp->medium);
698 script_write_params("check_", lp);
699
700 /* If the ARPCHECK code detects another
701 machine using the offered address, it exits
702 nonzero. We need to send a DHCPDECLINE and
703 toss the lease. */
704 if (script_go()) {
705 make_decline(ip, lp);
706 send_decline(ip);
707 goto freeit;
708 }
709 picked = lp;
710 picked->next = NULL;
711 } else {
712 freeit:
713 free_client_lease(lp);
714 }
715 }
716 ip->client->offered_leases = NULL;
717
718 /* If we just tossed all the leases we were offered, go back
719 to square one. */
720 if (!picked) {
721 ip->client->state = S_INIT;
722 state_init(ip);
723 return;
724 }
725
726 /* If it was a BOOTREPLY, we can just take the address right now. */
727 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
728 ip->client->new = picked;
729
730 /* Make up some lease expiry times
731 XXX these should be configurable. */
732 ip->client->new->expiry = cur_time + 12000;
733 ip->client->new->renewal += cur_time + 8000;
734 ip->client->new->rebind += cur_time + 10000;
735
736 ip->client->state = S_REQUESTING;
737
738 /* Bind to the address we received. */
739 bind_lease(ip);
740 return;
741 }
742
743 /* Go to the REQUESTING state. */
744 ip->client->destination = iaddr_broadcast;
745 ip->client->state = S_REQUESTING;
746 ip->client->first_sending = cur_time;
747 ip->client->interval = ip->client->config->initial_interval;
748
749 /* Make a DHCPREQUEST packet from the lease we picked. */
750 make_request(ip, picked);
751 ip->client->xid = ip->client->packet.xid;
752
753 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
754 free_client_lease(picked);
755
756 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
757 send_request(ip);
758 }
759
760 /* state_requesting is called when we receive a DHCPACK message after
761 having sent out one or more DHCPREQUEST packets. */
762
763 void
dhcpack(struct packet * packet)764 dhcpack(struct packet *packet)
765 {
766 struct interface_info *ip = packet->interface;
767 struct client_lease *lease;
768
769 /* If we're not receptive to an offer right now, or if the offer
770 has an unrecognizable transaction id, then just drop it. */
771 if (packet->interface->client->xid != packet->raw->xid ||
772 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
773 (memcmp(packet->interface->hw_address.haddr,
774 packet->raw->chaddr, packet->raw->hlen)))
775 return;
776
777 if (ip->client->state != S_REBOOTING &&
778 ip->client->state != S_REQUESTING &&
779 ip->client->state != S_RENEWING &&
780 ip->client->state != S_REBINDING)
781 return;
782
783 note("DHCPACK from %s", piaddr(packet->client_addr));
784
785 lease = packet_to_lease(packet);
786 if (!lease) {
787 note("packet_to_lease failed.");
788 return;
789 }
790
791 ip->client->new = lease;
792
793 /* Stop resending DHCPREQUEST. */
794 cancel_timeout(send_request, ip);
795
796 /* Figure out the lease time. */
797 if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
798 ACTION_SUPERSEDE)
799 ip->client->new->expiry = getULong(
800 ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
801 else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
802 ip->client->new->expiry = getULong(
803 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
804 else
805 ip->client->new->expiry = default_lease_time;
806 /* A number that looks negative here is really just very large,
807 because the lease expiry offset is unsigned. Also make sure that
808 the addition of cur_time below does not overflow (a 32 bit) time_t. */
809 if (ip->client->new->expiry < 0 ||
810 ip->client->new->expiry > TIME_MAX - cur_time)
811 ip->client->new->expiry = TIME_MAX - cur_time;
812 /* XXX should be fixed by resetting the client state */
813 if (ip->client->new->expiry < 60)
814 ip->client->new->expiry = 60;
815
816 /* Unless overridden in the config, take the server-provided renewal
817 * time if there is one. Otherwise figure it out according to the spec.
818 * Also make sure the renewal time does not exceed the expiry time.
819 */
820 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
821 ACTION_SUPERSEDE)
822 ip->client->new->renewal = getULong(
823 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
824 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
825 ip->client->new->renewal = getULong(
826 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
827 else
828 ip->client->new->renewal = ip->client->new->expiry / 2;
829 if (ip->client->new->renewal < 0 ||
830 ip->client->new->renewal > ip->client->new->expiry / 2)
831 ip->client->new->renewal = ip->client->new->expiry / 2;
832
833 /* Same deal with the rebind time. */
834 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
835 ACTION_SUPERSEDE)
836 ip->client->new->rebind = getULong(
837 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
838 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
839 ip->client->new->rebind = getULong(
840 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
841 else
842 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
843 if (ip->client->new->rebind < 0 ||
844 ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
845 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
846
847 /* Convert the time offsets into seconds-since-the-epoch */
848 ip->client->new->expiry += cur_time;
849 ip->client->new->renewal += cur_time;
850 ip->client->new->rebind += cur_time;
851
852 bind_lease(ip);
853 }
854
855 void
bind_lease(struct interface_info * ip)856 bind_lease(struct interface_info *ip)
857 {
858 struct option_data *opt;
859
860 /* Remember the medium. */
861 ip->client->new->medium = ip->client->medium;
862
863 opt = &ip->client->new->options[DHO_INTERFACE_MTU];
864 if (opt->len == sizeof(u_int16_t)) {
865 u_int16_t mtu = 0;
866 u_int16_t old_mtu = 0;
867 bool supersede = (ip->client->config->default_actions[DHO_INTERFACE_MTU] ==
868 ACTION_SUPERSEDE);
869
870 if (supersede)
871 mtu = getUShort(ip->client->config->defaults[DHO_INTERFACE_MTU].data);
872 else
873 mtu = be16dec(opt->data);
874
875 if (ip->client->active) {
876 opt = &ip->client->active->options[DHO_INTERFACE_MTU];
877 if (opt->len == sizeof(u_int16_t)) {
878 old_mtu = be16dec(opt->data);
879 }
880 }
881
882 if (mtu < MIN_MTU) {
883 /* Treat 0 like a user intentionally doesn't want to change MTU and,
884 * therefore, warning is not needed */
885 if (!supersede || mtu != 0)
886 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
887 } else if (ip->client->state != S_RENEWING || mtu != old_mtu) {
888 interface_set_mtu_unpriv(privfd, mtu);
889 }
890 }
891
892 /* Write out the new lease. */
893 write_client_lease(ip, ip->client->new, 0);
894
895 /* Run the client script with the new parameters. */
896 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
897 (ip->client->state == S_RENEWING ? "RENEW" :
898 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
899 ip->client->new->medium);
900 if (ip->client->active && ip->client->state != S_REBOOTING)
901 script_write_params("old_", ip->client->active);
902 script_write_params("new_", ip->client->new);
903 if (ip->client->alias)
904 script_write_params("alias_", ip->client->alias);
905 script_go();
906
907 /* Replace the old active lease with the new one. */
908 if (ip->client->active)
909 free_client_lease(ip->client->active);
910 ip->client->active = ip->client->new;
911 ip->client->new = NULL;
912
913 /* Set up a timeout to start the renewal process. */
914 add_timeout(ip->client->active->renewal, state_bound, ip);
915
916 note("bound to %s -- renewal in %d seconds.",
917 piaddr(ip->client->active->address),
918 (int)(ip->client->active->renewal - cur_time));
919 ip->client->state = S_BOUND;
920 reinitialize_interfaces();
921 go_daemon();
922 }
923
924 /*
925 * state_bound is called when we've successfully bound to a particular
926 * lease, but the renewal time on that lease has expired. We are
927 * expected to unicast a DHCPREQUEST to the server that gave us our
928 * original lease.
929 */
930 void
state_bound(void * ipp)931 state_bound(void *ipp)
932 {
933 struct interface_info *ip = ipp;
934 u_int8_t *dp = NULL;
935 int len;
936
937 ASSERT_STATE(state, S_BOUND);
938
939 /* T1 has expired. */
940 make_request(ip, ip->client->active);
941 ip->client->xid = ip->client->packet.xid;
942
943 if (ip->client->config->default_actions[DHO_DHCP_SERVER_IDENTIFIER] ==
944 ACTION_SUPERSEDE) {
945 dp = ip->client->config->defaults[DHO_DHCP_SERVER_IDENTIFIER].data;
946 len = ip->client->config->defaults[DHO_DHCP_SERVER_IDENTIFIER].len;
947 } else {
948 dp = ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].data;
949 len = ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len;
950 }
951 if (len == 4) {
952 memcpy(ip->client->destination.iabuf, dp, len);
953 ip->client->destination.len = len;
954 } else
955 ip->client->destination = iaddr_broadcast;
956
957 ip->client->first_sending = cur_time;
958 ip->client->interval = ip->client->config->initial_interval;
959 ip->client->state = S_RENEWING;
960
961 /* Send the first packet immediately. */
962 send_request(ip);
963 }
964
965 void
bootp(struct packet * packet)966 bootp(struct packet *packet)
967 {
968 struct iaddrlist *ap;
969
970 if (packet->raw->op != BOOTREPLY)
971 return;
972
973 /* If there's a reject list, make sure this packet's sender isn't
974 on it. */
975 for (ap = packet->interface->client->config->reject_list;
976 ap; ap = ap->next) {
977 if (addr_eq(packet->client_addr, ap->addr)) {
978 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
979 return;
980 }
981 }
982 dhcpoffer(packet);
983 }
984
985 void
dhcp(struct packet * packet)986 dhcp(struct packet *packet)
987 {
988 struct iaddrlist *ap;
989 void (*handler)(struct packet *);
990 const char *type;
991
992 switch (packet->packet_type) {
993 case DHCPOFFER:
994 handler = dhcpoffer;
995 type = "DHCPOFFER";
996 break;
997 case DHCPNAK:
998 handler = dhcpnak;
999 type = "DHCPNACK";
1000 break;
1001 case DHCPACK:
1002 handler = dhcpack;
1003 type = "DHCPACK";
1004 break;
1005 default:
1006 return;
1007 }
1008
1009 /* If there's a reject list, make sure this packet's sender isn't
1010 on it. */
1011 for (ap = packet->interface->client->config->reject_list;
1012 ap; ap = ap->next) {
1013 if (addr_eq(packet->client_addr, ap->addr)) {
1014 note("%s from %s rejected.", type, piaddr(ap->addr));
1015 return;
1016 }
1017 }
1018 (*handler)(packet);
1019 }
1020
1021 void
dhcpoffer(struct packet * packet)1022 dhcpoffer(struct packet *packet)
1023 {
1024 struct interface_info *ip = packet->interface;
1025 struct client_lease *lease, *lp;
1026 int i;
1027 int arp_timeout_needed, stop_selecting;
1028 const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
1029 "DHCPOFFER" : "BOOTREPLY";
1030
1031 /* If we're not receptive to an offer right now, or if the offer
1032 has an unrecognizable transaction id, then just drop it. */
1033 if (ip->client->state != S_SELECTING ||
1034 packet->interface->client->xid != packet->raw->xid ||
1035 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1036 (memcmp(packet->interface->hw_address.haddr,
1037 packet->raw->chaddr, packet->raw->hlen)))
1038 return;
1039
1040 note("%s from %s", name, piaddr(packet->client_addr));
1041
1042
1043 /* If this lease doesn't supply the minimum required parameters,
1044 blow it off. */
1045 for (i = 0; ip->client->config->required_options[i]; i++) {
1046 if (!packet->options[ip->client->config->
1047 required_options[i]].len) {
1048 note("%s isn't satisfactory.", name);
1049 return;
1050 }
1051 }
1052
1053 /* If we've already seen this lease, don't record it again. */
1054 for (lease = ip->client->offered_leases;
1055 lease; lease = lease->next) {
1056 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
1057 !memcmp(lease->address.iabuf,
1058 &packet->raw->yiaddr, lease->address.len)) {
1059 debug("%s already seen.", name);
1060 return;
1061 }
1062 }
1063
1064 lease = packet_to_lease(packet);
1065 if (!lease) {
1066 note("packet_to_lease failed.");
1067 return;
1068 }
1069
1070 /* If this lease was acquired through a BOOTREPLY, record that
1071 fact. */
1072 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1073 lease->is_bootp = 1;
1074
1075 /* Record the medium under which this lease was offered. */
1076 lease->medium = ip->client->medium;
1077
1078 /* Send out an ARP Request for the offered IP address. */
1079 script_init("ARPSEND", lease->medium);
1080 script_write_params("check_", lease);
1081 /* If the script can't send an ARP request without waiting,
1082 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1083 if (script_go())
1084 arp_timeout_needed = 0;
1085 else
1086 arp_timeout_needed = 2;
1087
1088 /* Figure out when we're supposed to stop selecting. */
1089 stop_selecting =
1090 ip->client->first_sending + ip->client->config->select_interval;
1091
1092 /* If this is the lease we asked for, put it at the head of the
1093 list, and don't mess with the arp request timeout. */
1094 if (lease->address.len == ip->client->requested_address.len &&
1095 !memcmp(lease->address.iabuf,
1096 ip->client->requested_address.iabuf,
1097 ip->client->requested_address.len)) {
1098 lease->next = ip->client->offered_leases;
1099 ip->client->offered_leases = lease;
1100 } else {
1101 /* If we already have an offer, and arping for this
1102 offer would take us past the selection timeout,
1103 then don't extend the timeout - just hope for the
1104 best. */
1105 if (ip->client->offered_leases &&
1106 (cur_time + arp_timeout_needed) > stop_selecting)
1107 arp_timeout_needed = 0;
1108
1109 /* Put the lease at the end of the list. */
1110 lease->next = NULL;
1111 if (!ip->client->offered_leases)
1112 ip->client->offered_leases = lease;
1113 else {
1114 for (lp = ip->client->offered_leases; lp->next;
1115 lp = lp->next)
1116 ; /* nothing */
1117 lp->next = lease;
1118 }
1119 }
1120
1121 /* If we're supposed to stop selecting before we've had time
1122 to wait for the ARPREPLY, add some delay to wait for
1123 the ARPREPLY. */
1124 if (stop_selecting - cur_time < arp_timeout_needed)
1125 stop_selecting = cur_time + arp_timeout_needed;
1126
1127 /* If the selecting interval has expired, go immediately to
1128 state_selecting(). Otherwise, time out into
1129 state_selecting at the select interval. */
1130 if (stop_selecting <= 0)
1131 state_selecting(ip);
1132 else {
1133 add_timeout(stop_selecting, state_selecting, ip);
1134 cancel_timeout(send_discover, ip);
1135 }
1136 }
1137
1138 /* Allocate a client_lease structure and initialize it from the parameters
1139 in the specified packet. */
1140
1141 struct client_lease *
packet_to_lease(struct packet * packet)1142 packet_to_lease(struct packet *packet)
1143 {
1144 struct client_lease *lease;
1145 int i;
1146
1147 lease = malloc(sizeof(struct client_lease));
1148
1149 if (!lease) {
1150 warning("dhcpoffer: no memory to record lease.");
1151 return (NULL);
1152 }
1153
1154 memset(lease, 0, sizeof(*lease));
1155
1156 /* Copy the lease options. */
1157 for (i = 0; i < 256; i++) {
1158 if (packet->options[i].len) {
1159 lease->options[i].data =
1160 malloc(packet->options[i].len + 1);
1161 if (!lease->options[i].data) {
1162 warning("dhcpoffer: no memory for option %d", i);
1163 free_client_lease(lease);
1164 return (NULL);
1165 } else {
1166 memcpy(lease->options[i].data,
1167 packet->options[i].data,
1168 packet->options[i].len);
1169 lease->options[i].len =
1170 packet->options[i].len;
1171 lease->options[i].data[lease->options[i].len] =
1172 0;
1173 }
1174 if (!check_option(lease,i)) {
1175 /* ignore a bogus lease offer */
1176 warning("Invalid lease option - ignoring offer");
1177 free_client_lease(lease);
1178 return (NULL);
1179 }
1180 }
1181 }
1182
1183 lease->address.len = sizeof(packet->raw->yiaddr);
1184 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1185
1186 lease->nextserver.len = sizeof(packet->raw->siaddr);
1187 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1188
1189 /* If the server name was filled out, copy it.
1190 Do not attempt to validate the server name as a host name.
1191 RFC 2131 merely states that sname is NUL-terminated (which do
1192 do not assume) and that it is the server's host name. Since
1193 the ISC client and server allow arbitrary characters, we do
1194 as well. */
1195 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1196 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1197 packet->raw->sname[0]) {
1198 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1199 if (!lease->server_name) {
1200 warning("dhcpoffer: no memory for server name.");
1201 free_client_lease(lease);
1202 return (NULL);
1203 }
1204 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1205 lease->server_name[DHCP_SNAME_LEN]='\0';
1206 }
1207
1208 /* Ditto for the filename. */
1209 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1210 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1211 packet->raw->file[0]) {
1212 /* Don't count on the NUL terminator. */
1213 lease->filename = malloc(DHCP_FILE_LEN + 1);
1214 if (!lease->filename) {
1215 warning("dhcpoffer: no memory for filename.");
1216 free_client_lease(lease);
1217 return (NULL);
1218 }
1219 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1220 lease->filename[DHCP_FILE_LEN]='\0';
1221 }
1222 return lease;
1223 }
1224
1225 void
dhcpnak(struct packet * packet)1226 dhcpnak(struct packet *packet)
1227 {
1228 struct interface_info *ip = packet->interface;
1229
1230 /* If we're not receptive to an offer right now, or if the offer
1231 has an unrecognizable transaction id, then just drop it. */
1232 if (packet->interface->client->xid != packet->raw->xid ||
1233 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1234 (memcmp(packet->interface->hw_address.haddr,
1235 packet->raw->chaddr, packet->raw->hlen)))
1236 return;
1237
1238 if (ip->client->state != S_REBOOTING &&
1239 ip->client->state != S_REQUESTING &&
1240 ip->client->state != S_RENEWING &&
1241 ip->client->state != S_REBINDING)
1242 return;
1243
1244 note("DHCPNAK from %s", piaddr(packet->client_addr));
1245
1246 if (!ip->client->active) {
1247 note("DHCPNAK with no active lease.\n");
1248 return;
1249 }
1250
1251 free_client_lease(ip->client->active);
1252 ip->client->active = NULL;
1253
1254 /* Stop sending DHCPREQUEST packets... */
1255 cancel_timeout(send_request, ip);
1256
1257 ip->client->state = S_INIT;
1258 state_init(ip);
1259 }
1260
1261 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1262 one after the right interval has expired. If we don't get an offer by
1263 the time we reach the panic interval, call the panic function. */
1264
1265 void
send_discover(void * ipp)1266 send_discover(void *ipp)
1267 {
1268 struct interface_info *ip = ipp;
1269 int interval, increase = 1;
1270
1271 /* Figure out how long it's been since we started transmitting. */
1272 interval = cur_time - ip->client->first_sending;
1273
1274 /* If we're past the panic timeout, call the script and tell it
1275 we haven't found anything for this interface yet. */
1276 if (interval > ip->client->config->timeout) {
1277 state_panic(ip);
1278 return;
1279 }
1280
1281 /* If we're selecting media, try the whole list before doing
1282 the exponential backoff, but if we've already received an
1283 offer, stop looping, because we obviously have it right. */
1284 if (!ip->client->offered_leases &&
1285 ip->client->config->media) {
1286 int fail = 0;
1287 again:
1288 if (ip->client->medium) {
1289 ip->client->medium = ip->client->medium->next;
1290 increase = 0;
1291 }
1292 if (!ip->client->medium) {
1293 if (fail)
1294 error("No valid media types for %s!", ip->name);
1295 ip->client->medium = ip->client->config->media;
1296 increase = 1;
1297 }
1298
1299 note("Trying medium \"%s\" %d", ip->client->medium->string,
1300 increase);
1301 script_init("MEDIUM", ip->client->medium);
1302 if (script_go())
1303 goto again;
1304 }
1305
1306 /*
1307 * If we're supposed to increase the interval, do so. If it's
1308 * currently zero (i.e., we haven't sent any packets yet), set
1309 * it to one; otherwise, add to it a random number between zero
1310 * and two times itself. On average, this means that it will
1311 * double with every transmission.
1312 */
1313 if (increase) {
1314 if (!ip->client->interval)
1315 ip->client->interval =
1316 ip->client->config->initial_interval;
1317 else {
1318 ip->client->interval += (arc4random() >> 2) %
1319 (2 * ip->client->interval);
1320 }
1321
1322 /* Don't backoff past cutoff. */
1323 if (ip->client->interval >
1324 ip->client->config->backoff_cutoff)
1325 ip->client->interval =
1326 ((ip->client->config->backoff_cutoff / 2)
1327 + ((arc4random() >> 2) %
1328 ip->client->config->backoff_cutoff));
1329 } else if (!ip->client->interval)
1330 ip->client->interval =
1331 ip->client->config->initial_interval;
1332
1333 /* If the backoff would take us to the panic timeout, just use that
1334 as the interval. */
1335 if (cur_time + ip->client->interval >
1336 ip->client->first_sending + ip->client->config->timeout)
1337 ip->client->interval =
1338 (ip->client->first_sending +
1339 ip->client->config->timeout) - cur_time + 1;
1340
1341 /* Record the number of seconds since we started sending. */
1342 if (interval < 65536)
1343 ip->client->packet.secs = htons(interval);
1344 else
1345 ip->client->packet.secs = htons(65535);
1346 ip->client->secs = ip->client->packet.secs;
1347
1348 note("DHCPDISCOVER on %s to %s port %d interval %d",
1349 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1350 (int)ip->client->interval);
1351
1352 /* Send out a packet. */
1353 send_packet_unpriv(privfd, &ip->client->packet,
1354 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1355
1356 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1357 }
1358
1359 /*
1360 * state_panic gets called if we haven't received any offers in a preset
1361 * amount of time. When this happens, we try to use existing leases
1362 * that haven't yet expired, and failing that, we call the client script
1363 * and hope it can do something.
1364 */
1365 void
state_panic(void * ipp)1366 state_panic(void *ipp)
1367 {
1368 struct interface_info *ip = ipp;
1369 struct client_lease *loop = ip->client->active;
1370 struct client_lease *lp;
1371
1372 note("No DHCPOFFERS received.");
1373
1374 /* We may not have an active lease, but we may have some
1375 predefined leases that we can try. */
1376 if (!ip->client->active && ip->client->leases)
1377 goto activate_next;
1378
1379 /* Run through the list of leases and see if one can be used. */
1380 while (ip->client->active) {
1381 if (ip->client->active->expiry > cur_time) {
1382 note("Trying recorded lease %s",
1383 piaddr(ip->client->active->address));
1384 /* Run the client script with the existing
1385 parameters. */
1386 script_init("TIMEOUT",
1387 ip->client->active->medium);
1388 script_write_params("new_", ip->client->active);
1389 if (ip->client->alias)
1390 script_write_params("alias_",
1391 ip->client->alias);
1392
1393 /* If the old lease is still good and doesn't
1394 yet need renewal, go into BOUND state and
1395 timeout at the renewal time. */
1396 if (!script_go()) {
1397 if (cur_time <
1398 ip->client->active->renewal) {
1399 ip->client->state = S_BOUND;
1400 note("bound: renewal in %d seconds.",
1401 (int)(ip->client->active->renewal -
1402 cur_time));
1403 add_timeout(
1404 ip->client->active->renewal,
1405 state_bound, ip);
1406 } else {
1407 ip->client->state = S_BOUND;
1408 note("bound: immediate renewal.");
1409 state_bound(ip);
1410 }
1411 reinitialize_interfaces();
1412 go_daemon();
1413 return;
1414 }
1415 }
1416
1417 /* If there are no other leases, give up. */
1418 if (!ip->client->leases) {
1419 ip->client->leases = ip->client->active;
1420 ip->client->active = NULL;
1421 break;
1422 }
1423
1424 activate_next:
1425 /* Otherwise, put the active lease at the end of the
1426 lease list, and try another lease.. */
1427 for (lp = ip->client->leases; lp->next; lp = lp->next)
1428 ;
1429 lp->next = ip->client->active;
1430 if (lp->next)
1431 lp->next->next = NULL;
1432 ip->client->active = ip->client->leases;
1433 ip->client->leases = ip->client->leases->next;
1434
1435 /* If we already tried this lease, we've exhausted the
1436 set of leases, so we might as well give up for
1437 now. */
1438 if (ip->client->active == loop)
1439 break;
1440 else if (!loop)
1441 loop = ip->client->active;
1442 }
1443
1444 /* No leases were available, or what was available didn't work, so
1445 tell the shell script that we failed to allocate an address,
1446 and try again later. */
1447 note("No working leases in persistent database - sleeping.\n");
1448 script_init("FAIL", NULL);
1449 if (ip->client->alias)
1450 script_write_params("alias_", ip->client->alias);
1451 script_go();
1452 ip->client->state = S_INIT;
1453 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1454 ip);
1455 go_daemon();
1456 }
1457
1458 void
send_request(void * ipp)1459 send_request(void *ipp)
1460 {
1461 struct interface_info *ip = ipp;
1462 struct in_addr from, to;
1463 int interval;
1464
1465 /* Figure out how long it's been since we started transmitting. */
1466 interval = cur_time - ip->client->first_sending;
1467
1468 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1469 past the reboot timeout, go to INIT and see if we can
1470 DISCOVER an address... */
1471 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1472 means either that we're on a network with no DHCP server,
1473 or that our server is down. In the latter case, assuming
1474 that there is a backup DHCP server, DHCPDISCOVER will get
1475 us a new address, but we could also have successfully
1476 reused our old address. In the former case, we're hosed
1477 anyway. This is not a win-prone situation. */
1478 if ((ip->client->state == S_REBOOTING ||
1479 ip->client->state == S_REQUESTING) &&
1480 interval > ip->client->config->reboot_timeout) {
1481 cancel:
1482 ip->client->state = S_INIT;
1483 cancel_timeout(send_request, ip);
1484 state_init(ip);
1485 return;
1486 }
1487
1488 /* If we're in the reboot state, make sure the media is set up
1489 correctly. */
1490 if (ip->client->state == S_REBOOTING &&
1491 !ip->client->medium &&
1492 ip->client->active->medium ) {
1493 script_init("MEDIUM", ip->client->active->medium);
1494
1495 /* If the medium we chose won't fly, go to INIT state. */
1496 if (script_go())
1497 goto cancel;
1498
1499 /* Record the medium. */
1500 ip->client->medium = ip->client->active->medium;
1501 }
1502
1503 /* If the lease has expired, relinquish the address and go back
1504 to the INIT state. */
1505 if (ip->client->state != S_REQUESTING &&
1506 cur_time > ip->client->active->expiry) {
1507 /* Run the client script with the new parameters. */
1508 script_init("EXPIRE", NULL);
1509 script_write_params("old_", ip->client->active);
1510 if (ip->client->alias)
1511 script_write_params("alias_", ip->client->alias);
1512 script_go();
1513
1514 /* Now do a preinit on the interface so that we can
1515 discover a new address. */
1516 script_init("PREINIT", NULL);
1517 if (ip->client->alias)
1518 script_write_params("alias_", ip->client->alias);
1519 script_go();
1520
1521 ip->client->state = S_INIT;
1522 state_init(ip);
1523 return;
1524 }
1525
1526 /* Do the exponential backoff... */
1527 if (!ip->client->interval)
1528 ip->client->interval = ip->client->config->initial_interval;
1529 else
1530 ip->client->interval += ((arc4random() >> 2) %
1531 (2 * ip->client->interval));
1532
1533 /* Don't backoff past cutoff. */
1534 if (ip->client->interval >
1535 ip->client->config->backoff_cutoff)
1536 ip->client->interval =
1537 ((ip->client->config->backoff_cutoff / 2) +
1538 ((arc4random() >> 2) % ip->client->interval));
1539
1540 /* If the backoff would take us to the expiry time, just set the
1541 timeout to the expiry time. */
1542 if (ip->client->state != S_REQUESTING &&
1543 cur_time + ip->client->interval >
1544 ip->client->active->expiry)
1545 ip->client->interval =
1546 ip->client->active->expiry - cur_time + 1;
1547
1548 /* If the lease T2 time has elapsed, or if we're not yet bound,
1549 broadcast the DHCPREQUEST rather than unicasting. */
1550 if (ip->client->state == S_REQUESTING ||
1551 ip->client->state == S_REBOOTING ||
1552 cur_time > ip->client->active->rebind)
1553 to.s_addr = INADDR_BROADCAST;
1554 else
1555 memcpy(&to.s_addr, ip->client->destination.iabuf,
1556 sizeof(to.s_addr));
1557
1558 if (ip->client->state != S_REQUESTING &&
1559 ip->client->state != S_REBOOTING)
1560 memcpy(&from, ip->client->active->address.iabuf,
1561 sizeof(from));
1562 else
1563 from.s_addr = INADDR_ANY;
1564
1565 /* Record the number of seconds since we started sending. */
1566 if (ip->client->state == S_REQUESTING)
1567 ip->client->packet.secs = ip->client->secs;
1568 else {
1569 if (interval < 65536)
1570 ip->client->packet.secs = htons(interval);
1571 else
1572 ip->client->packet.secs = htons(65535);
1573 }
1574
1575 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1576 REMOTE_PORT);
1577
1578 /* Send out a packet. */
1579 send_packet_unpriv(privfd, &ip->client->packet,
1580 ip->client->packet_length, from, to);
1581
1582 add_timeout(cur_time + ip->client->interval, send_request, ip);
1583 }
1584
1585 void
send_decline(void * ipp)1586 send_decline(void *ipp)
1587 {
1588 struct interface_info *ip = ipp;
1589
1590 note("DHCPDECLINE on %s to %s port %d", ip->name,
1591 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1592
1593 /* Send out a packet. */
1594 send_packet_unpriv(privfd, &ip->client->packet,
1595 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1596 }
1597
1598 void
make_discover(struct interface_info * ip,struct client_lease * lease)1599 make_discover(struct interface_info *ip, struct client_lease *lease)
1600 {
1601 unsigned char discover = DHCPDISCOVER;
1602 struct tree_cache *options[256];
1603 struct tree_cache option_elements[256];
1604 int i;
1605
1606 memset(option_elements, 0, sizeof(option_elements));
1607 memset(options, 0, sizeof(options));
1608 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1609
1610 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1611 i = DHO_DHCP_MESSAGE_TYPE;
1612 options[i] = &option_elements[i];
1613 options[i]->value = &discover;
1614 options[i]->len = sizeof(discover);
1615 options[i]->buf_size = sizeof(discover);
1616 options[i]->timeout = 0xFFFFFFFF;
1617
1618 /* Request the options we want */
1619 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1620 options[i] = &option_elements[i];
1621 options[i]->value = ip->client->config->requested_options;
1622 options[i]->len = ip->client->config->requested_option_count;
1623 options[i]->buf_size =
1624 ip->client->config->requested_option_count;
1625 options[i]->timeout = 0xFFFFFFFF;
1626
1627 /* If we had an address, try to get it again. */
1628 if (lease) {
1629 ip->client->requested_address = lease->address;
1630 i = DHO_DHCP_REQUESTED_ADDRESS;
1631 options[i] = &option_elements[i];
1632 options[i]->value = lease->address.iabuf;
1633 options[i]->len = lease->address.len;
1634 options[i]->buf_size = lease->address.len;
1635 options[i]->timeout = 0xFFFFFFFF;
1636 } else
1637 ip->client->requested_address.len = 0;
1638
1639 /* Send any options requested in the config file. */
1640 for (i = 0; i < 256; i++)
1641 if (!options[i] &&
1642 ip->client->config->send_options[i].data) {
1643 options[i] = &option_elements[i];
1644 options[i]->value =
1645 ip->client->config->send_options[i].data;
1646 options[i]->len =
1647 ip->client->config->send_options[i].len;
1648 options[i]->buf_size =
1649 ip->client->config->send_options[i].len;
1650 options[i]->timeout = 0xFFFFFFFF;
1651 }
1652
1653 /* send host name if not set via config file. */
1654 if (!options[DHO_HOST_NAME]) {
1655 if (hostname[0] != '\0') {
1656 size_t len;
1657 char* posDot = strchr(hostname, '.');
1658 if (posDot != NULL)
1659 len = posDot - hostname;
1660 else
1661 len = strlen(hostname);
1662 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1663 options[DHO_HOST_NAME]->value = hostname;
1664 options[DHO_HOST_NAME]->len = len;
1665 options[DHO_HOST_NAME]->buf_size = len;
1666 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1667 }
1668 }
1669
1670 /* set unique client identifier */
1671 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1672 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1673 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1674 ip->hw_address.hlen : sizeof(client_ident)-1;
1675 client_ident[0] = ip->hw_address.htype;
1676 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1677 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1678 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1679 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1680 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1681 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1682 }
1683
1684 /* Set up the option buffer... */
1685 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1686 options, 0, 0, 0, NULL, 0);
1687 if (ip->client->packet_length < BOOTP_MIN_LEN)
1688 ip->client->packet_length = BOOTP_MIN_LEN;
1689
1690 ip->client->packet.op = BOOTREQUEST;
1691 ip->client->packet.htype = ip->hw_address.htype;
1692 ip->client->packet.hlen = ip->hw_address.hlen;
1693 ip->client->packet.hops = 0;
1694 ip->client->packet.xid = arc4random();
1695 ip->client->packet.secs = 0; /* filled in by send_discover. */
1696 ip->client->packet.flags = 0;
1697
1698 memset(&(ip->client->packet.ciaddr),
1699 0, sizeof(ip->client->packet.ciaddr));
1700 memset(&(ip->client->packet.yiaddr),
1701 0, sizeof(ip->client->packet.yiaddr));
1702 memset(&(ip->client->packet.siaddr),
1703 0, sizeof(ip->client->packet.siaddr));
1704 memset(&(ip->client->packet.giaddr),
1705 0, sizeof(ip->client->packet.giaddr));
1706 memcpy(ip->client->packet.chaddr,
1707 ip->hw_address.haddr, ip->hw_address.hlen);
1708 }
1709
1710
1711 void
make_request(struct interface_info * ip,struct client_lease * lease)1712 make_request(struct interface_info *ip, struct client_lease * lease)
1713 {
1714 unsigned char request = DHCPREQUEST;
1715 struct tree_cache *options[256];
1716 struct tree_cache option_elements[256];
1717 int i;
1718
1719 memset(options, 0, sizeof(options));
1720 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1721
1722 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1723 i = DHO_DHCP_MESSAGE_TYPE;
1724 options[i] = &option_elements[i];
1725 options[i]->value = &request;
1726 options[i]->len = sizeof(request);
1727 options[i]->buf_size = sizeof(request);
1728 options[i]->timeout = 0xFFFFFFFF;
1729
1730 /* Request the options we want */
1731 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1732 options[i] = &option_elements[i];
1733 options[i]->value = ip->client->config->requested_options;
1734 options[i]->len = ip->client->config->requested_option_count;
1735 options[i]->buf_size =
1736 ip->client->config->requested_option_count;
1737 options[i]->timeout = 0xFFFFFFFF;
1738
1739 /* If we are requesting an address that hasn't yet been assigned
1740 to us, use the DHCP Requested Address option. */
1741 if (ip->client->state == S_REQUESTING) {
1742 /* Send back the server identifier... */
1743 i = DHO_DHCP_SERVER_IDENTIFIER;
1744 options[i] = &option_elements[i];
1745 options[i]->value = lease->options[i].data;
1746 options[i]->len = lease->options[i].len;
1747 options[i]->buf_size = lease->options[i].len;
1748 options[i]->timeout = 0xFFFFFFFF;
1749 }
1750 if (ip->client->state == S_REQUESTING ||
1751 ip->client->state == S_REBOOTING) {
1752 ip->client->requested_address = lease->address;
1753 i = DHO_DHCP_REQUESTED_ADDRESS;
1754 options[i] = &option_elements[i];
1755 options[i]->value = lease->address.iabuf;
1756 options[i]->len = lease->address.len;
1757 options[i]->buf_size = lease->address.len;
1758 options[i]->timeout = 0xFFFFFFFF;
1759 } else
1760 ip->client->requested_address.len = 0;
1761
1762 /* Send any options requested in the config file. */
1763 for (i = 0; i < 256; i++)
1764 if (!options[i] &&
1765 ip->client->config->send_options[i].data) {
1766 options[i] = &option_elements[i];
1767 options[i]->value =
1768 ip->client->config->send_options[i].data;
1769 options[i]->len =
1770 ip->client->config->send_options[i].len;
1771 options[i]->buf_size =
1772 ip->client->config->send_options[i].len;
1773 options[i]->timeout = 0xFFFFFFFF;
1774 }
1775
1776 /* send host name if not set via config file. */
1777 if (!options[DHO_HOST_NAME]) {
1778 if (hostname[0] != '\0') {
1779 size_t len;
1780 char* posDot = strchr(hostname, '.');
1781 if (posDot != NULL)
1782 len = posDot - hostname;
1783 else
1784 len = strlen(hostname);
1785 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1786 options[DHO_HOST_NAME]->value = hostname;
1787 options[DHO_HOST_NAME]->len = len;
1788 options[DHO_HOST_NAME]->buf_size = len;
1789 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1790 }
1791 }
1792
1793 /* set unique client identifier */
1794 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1795 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1796 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1797 ip->hw_address.hlen : sizeof(client_ident)-1;
1798 client_ident[0] = ip->hw_address.htype;
1799 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1800 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1801 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1802 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1803 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1804 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1805 }
1806
1807 /* Set up the option buffer... */
1808 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1809 options, 0, 0, 0, NULL, 0);
1810 if (ip->client->packet_length < BOOTP_MIN_LEN)
1811 ip->client->packet_length = BOOTP_MIN_LEN;
1812
1813 ip->client->packet.op = BOOTREQUEST;
1814 ip->client->packet.htype = ip->hw_address.htype;
1815 ip->client->packet.hlen = ip->hw_address.hlen;
1816 ip->client->packet.hops = 0;
1817 ip->client->packet.xid = ip->client->xid;
1818 ip->client->packet.secs = 0; /* Filled in by send_request. */
1819
1820 /* If we own the address we're requesting, put it in ciaddr;
1821 otherwise set ciaddr to zero. */
1822 if (ip->client->state == S_BOUND ||
1823 ip->client->state == S_RENEWING ||
1824 ip->client->state == S_REBINDING) {
1825 memcpy(&ip->client->packet.ciaddr,
1826 lease->address.iabuf, lease->address.len);
1827 ip->client->packet.flags = 0;
1828 } else {
1829 memset(&ip->client->packet.ciaddr, 0,
1830 sizeof(ip->client->packet.ciaddr));
1831 ip->client->packet.flags = 0;
1832 }
1833
1834 memset(&ip->client->packet.yiaddr, 0,
1835 sizeof(ip->client->packet.yiaddr));
1836 memset(&ip->client->packet.siaddr, 0,
1837 sizeof(ip->client->packet.siaddr));
1838 memset(&ip->client->packet.giaddr, 0,
1839 sizeof(ip->client->packet.giaddr));
1840 memcpy(ip->client->packet.chaddr,
1841 ip->hw_address.haddr, ip->hw_address.hlen);
1842 }
1843
1844 void
make_decline(struct interface_info * ip,struct client_lease * lease)1845 make_decline(struct interface_info *ip, struct client_lease *lease)
1846 {
1847 struct tree_cache *options[256], message_type_tree;
1848 struct tree_cache requested_address_tree;
1849 struct tree_cache server_id_tree, client_id_tree;
1850 unsigned char decline = DHCPDECLINE;
1851 int i;
1852
1853 memset(options, 0, sizeof(options));
1854 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1855
1856 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1857 i = DHO_DHCP_MESSAGE_TYPE;
1858 options[i] = &message_type_tree;
1859 options[i]->value = &decline;
1860 options[i]->len = sizeof(decline);
1861 options[i]->buf_size = sizeof(decline);
1862 options[i]->timeout = 0xFFFFFFFF;
1863
1864 /* Send back the server identifier... */
1865 i = DHO_DHCP_SERVER_IDENTIFIER;
1866 options[i] = &server_id_tree;
1867 options[i]->value = lease->options[i].data;
1868 options[i]->len = lease->options[i].len;
1869 options[i]->buf_size = lease->options[i].len;
1870 options[i]->timeout = 0xFFFFFFFF;
1871
1872 /* Send back the address we're declining. */
1873 i = DHO_DHCP_REQUESTED_ADDRESS;
1874 options[i] = &requested_address_tree;
1875 options[i]->value = lease->address.iabuf;
1876 options[i]->len = lease->address.len;
1877 options[i]->buf_size = lease->address.len;
1878 options[i]->timeout = 0xFFFFFFFF;
1879
1880 /* Send the uid if the user supplied one. */
1881 i = DHO_DHCP_CLIENT_IDENTIFIER;
1882 if (ip->client->config->send_options[i].len) {
1883 options[i] = &client_id_tree;
1884 options[i]->value = ip->client->config->send_options[i].data;
1885 options[i]->len = ip->client->config->send_options[i].len;
1886 options[i]->buf_size = ip->client->config->send_options[i].len;
1887 options[i]->timeout = 0xFFFFFFFF;
1888 }
1889
1890
1891 /* Set up the option buffer... */
1892 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1893 options, 0, 0, 0, NULL, 0);
1894 if (ip->client->packet_length < BOOTP_MIN_LEN)
1895 ip->client->packet_length = BOOTP_MIN_LEN;
1896
1897 ip->client->packet.op = BOOTREQUEST;
1898 ip->client->packet.htype = ip->hw_address.htype;
1899 ip->client->packet.hlen = ip->hw_address.hlen;
1900 ip->client->packet.hops = 0;
1901 ip->client->packet.xid = ip->client->xid;
1902 ip->client->packet.secs = 0; /* Filled in by send_request. */
1903 ip->client->packet.flags = 0;
1904
1905 /* ciaddr must always be zero. */
1906 memset(&ip->client->packet.ciaddr, 0,
1907 sizeof(ip->client->packet.ciaddr));
1908 memset(&ip->client->packet.yiaddr, 0,
1909 sizeof(ip->client->packet.yiaddr));
1910 memset(&ip->client->packet.siaddr, 0,
1911 sizeof(ip->client->packet.siaddr));
1912 memset(&ip->client->packet.giaddr, 0,
1913 sizeof(ip->client->packet.giaddr));
1914 memcpy(ip->client->packet.chaddr,
1915 ip->hw_address.haddr, ip->hw_address.hlen);
1916 }
1917
1918 void
free_client_lease(struct client_lease * lease)1919 free_client_lease(struct client_lease *lease)
1920 {
1921 int i;
1922
1923 if (lease->server_name)
1924 free(lease->server_name);
1925 if (lease->filename)
1926 free(lease->filename);
1927 for (i = 0; i < 256; i++) {
1928 if (lease->options[i].len)
1929 free(lease->options[i].data);
1930 }
1931 free(lease);
1932 }
1933
1934 static FILE *leaseFile;
1935
1936 void
rewrite_client_leases(void)1937 rewrite_client_leases(void)
1938 {
1939 struct client_lease *lp;
1940 cap_rights_t rights;
1941
1942 if (!leaseFile) {
1943 leaseFile = fopen(path_dhclient_db, "w");
1944 if (!leaseFile)
1945 error("can't create %s: %m", path_dhclient_db);
1946 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1947 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1948 if (caph_rights_limit(fileno(leaseFile), &rights) < 0) {
1949 error("can't limit lease descriptor: %m");
1950 }
1951 if (caph_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0) {
1952 error("can't limit lease descriptor fcntls: %m");
1953 }
1954 } else {
1955 fflush(leaseFile);
1956 rewind(leaseFile);
1957 }
1958
1959 for (lp = ifi->client->leases; lp; lp = lp->next)
1960 write_client_lease(ifi, lp, 1);
1961 if (ifi->client->active)
1962 write_client_lease(ifi, ifi->client->active, 1);
1963
1964 fflush(leaseFile);
1965 ftruncate(fileno(leaseFile), ftello(leaseFile));
1966 fsync(fileno(leaseFile));
1967 }
1968
1969 void
write_client_lease(struct interface_info * ip,struct client_lease * lease,int rewrite)1970 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1971 int rewrite)
1972 {
1973 static int leases_written;
1974 struct tm *t;
1975 int i;
1976
1977 if (!rewrite) {
1978 if (leases_written++ > 20) {
1979 rewrite_client_leases();
1980 leases_written = 0;
1981 }
1982 }
1983
1984 /* If the lease came from the config file, we don't need to stash
1985 a copy in the lease database. */
1986 if (lease->is_static)
1987 return;
1988
1989 if (!leaseFile) { /* XXX */
1990 leaseFile = fopen(path_dhclient_db, "w");
1991 if (!leaseFile)
1992 error("can't create %s: %m", path_dhclient_db);
1993 }
1994
1995 fprintf(leaseFile, "lease {\n");
1996 if (lease->is_bootp)
1997 fprintf(leaseFile, " bootp;\n");
1998 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1999 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
2000 if (lease->nextserver.len == sizeof(inaddr_any) &&
2001 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
2002 sizeof(inaddr_any)))
2003 fprintf(leaseFile, " next-server %s;\n",
2004 piaddr(lease->nextserver));
2005 if (lease->filename)
2006 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
2007 if (lease->server_name)
2008 fprintf(leaseFile, " server-name \"%s\";\n",
2009 lease->server_name);
2010 if (lease->medium)
2011 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
2012 for (i = 0; i < 256; i++)
2013 if (lease->options[i].len)
2014 fprintf(leaseFile, " option %s %s;\n",
2015 dhcp_options[i].name,
2016 pretty_print_option(i, lease->options[i].data,
2017 lease->options[i].len, 1, 1));
2018
2019 t = gmtime(&lease->renewal);
2020 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
2021 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2022 t->tm_hour, t->tm_min, t->tm_sec);
2023 t = gmtime(&lease->rebind);
2024 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
2025 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2026 t->tm_hour, t->tm_min, t->tm_sec);
2027 t = gmtime(&lease->expiry);
2028 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
2029 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2030 t->tm_hour, t->tm_min, t->tm_sec);
2031 fprintf(leaseFile, "}\n");
2032 fflush(leaseFile);
2033 }
2034
2035 void
script_init(const char * reason,struct string_list * medium)2036 script_init(const char *reason, struct string_list *medium)
2037 {
2038 size_t len, mediumlen = 0;
2039 struct imsg_hdr hdr;
2040 struct buf *buf;
2041 int errs;
2042
2043 if (medium != NULL && medium->string != NULL)
2044 mediumlen = strlen(medium->string);
2045
2046 hdr.code = IMSG_SCRIPT_INIT;
2047 hdr.len = sizeof(struct imsg_hdr) +
2048 sizeof(size_t) + mediumlen +
2049 sizeof(size_t) + strlen(reason);
2050
2051 if ((buf = buf_open(hdr.len)) == NULL)
2052 error("buf_open: %m");
2053
2054 errs = 0;
2055 errs += buf_add(buf, &hdr, sizeof(hdr));
2056 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2057 if (mediumlen > 0)
2058 errs += buf_add(buf, medium->string, mediumlen);
2059 len = strlen(reason);
2060 errs += buf_add(buf, &len, sizeof(len));
2061 errs += buf_add(buf, reason, len);
2062
2063 if (errs)
2064 error("buf_add: %m");
2065
2066 if (buf_close(privfd, buf) == -1)
2067 error("buf_close: %m");
2068 }
2069
2070 void
priv_script_init(const char * reason,char * medium)2071 priv_script_init(const char *reason, char *medium)
2072 {
2073 struct interface_info *ip = ifi;
2074
2075 if (ip) {
2076 ip->client->scriptEnvsize = 100;
2077 if (ip->client->scriptEnv == NULL)
2078 ip->client->scriptEnv =
2079 malloc(ip->client->scriptEnvsize * sizeof(char *));
2080 if (ip->client->scriptEnv == NULL)
2081 error("script_init: no memory for environment");
2082
2083 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2084 if (ip->client->scriptEnv[0] == NULL)
2085 error("script_init: no memory for environment");
2086
2087 ip->client->scriptEnv[1] = NULL;
2088
2089 script_set_env(ip->client, "", "interface", ip->name);
2090
2091 if (medium)
2092 script_set_env(ip->client, "", "medium", medium);
2093
2094 script_set_env(ip->client, "", "reason", reason);
2095 }
2096 }
2097
2098 void
priv_script_write_params(const char * prefix,struct client_lease * lease)2099 priv_script_write_params(const char *prefix, struct client_lease *lease)
2100 {
2101 struct interface_info *ip = ifi;
2102 u_int8_t dbuf[1500], *dp = NULL;
2103 int i;
2104 size_t len;
2105 char tbuf[128];
2106
2107 script_set_env(ip->client, prefix, "ip_address",
2108 piaddr(lease->address));
2109
2110 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2111 ACTION_SUPERSEDE) {
2112 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2113 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2114 } else {
2115 dp = lease->options[DHO_SUBNET_MASK].data;
2116 len = lease->options[DHO_SUBNET_MASK].len;
2117 }
2118 if (len && (len < sizeof(lease->address.iabuf))) {
2119 struct iaddr netmask, subnet, broadcast;
2120
2121 memcpy(netmask.iabuf, dp, len);
2122 netmask.len = len;
2123 subnet = subnet_number(lease->address, netmask);
2124 if (subnet.len) {
2125 script_set_env(ip->client, prefix, "network_number",
2126 piaddr(subnet));
2127 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2128 broadcast = broadcast_addr(subnet, netmask);
2129 if (broadcast.len)
2130 script_set_env(ip->client, prefix,
2131 "broadcast_address",
2132 piaddr(broadcast));
2133 }
2134 }
2135 }
2136
2137 if (lease->filename)
2138 script_set_env(ip->client, prefix, "filename", lease->filename);
2139 if (lease->server_name)
2140 script_set_env(ip->client, prefix, "server_name",
2141 lease->server_name);
2142 for (i = 0; i < 256; i++) {
2143 len = 0;
2144
2145 if (ip->client->config->defaults[i].len) {
2146 if (lease->options[i].len) {
2147 switch (
2148 ip->client->config->default_actions[i]) {
2149 case ACTION_DEFAULT:
2150 dp = lease->options[i].data;
2151 len = lease->options[i].len;
2152 break;
2153 case ACTION_SUPERSEDE:
2154 supersede:
2155 dp = ip->client->
2156 config->defaults[i].data;
2157 len = ip->client->
2158 config->defaults[i].len;
2159 break;
2160 case ACTION_PREPEND:
2161 len = ip->client->
2162 config->defaults[i].len +
2163 lease->options[i].len;
2164 if (len >= sizeof(dbuf)) {
2165 warning("no space to %s %s",
2166 "prepend option",
2167 dhcp_options[i].name);
2168 goto supersede;
2169 }
2170 dp = dbuf;
2171 memcpy(dp,
2172 ip->client->
2173 config->defaults[i].data,
2174 ip->client->
2175 config->defaults[i].len);
2176 memcpy(dp + ip->client->
2177 config->defaults[i].len,
2178 lease->options[i].data,
2179 lease->options[i].len);
2180 dp[len] = '\0';
2181 break;
2182 case ACTION_APPEND:
2183 /*
2184 * When we append, we assume that we're
2185 * appending to text. Some MS servers
2186 * include a NUL byte at the end of
2187 * the search string provided.
2188 */
2189 len = ip->client->
2190 config->defaults[i].len +
2191 lease->options[i].len;
2192 if (len >= sizeof(dbuf)) {
2193 warning("no space to %s %s",
2194 "append option",
2195 dhcp_options[i].name);
2196 goto supersede;
2197 }
2198 memcpy(dbuf,
2199 lease->options[i].data,
2200 lease->options[i].len);
2201 for (dp = dbuf + lease->options[i].len;
2202 dp > dbuf; dp--, len--)
2203 if (dp[-1] != '\0')
2204 break;
2205 memcpy(dp,
2206 ip->client->
2207 config->defaults[i].data,
2208 ip->client->
2209 config->defaults[i].len);
2210 dp = dbuf;
2211 dp[len] = '\0';
2212 }
2213 } else {
2214 dp = ip->client->
2215 config->defaults[i].data;
2216 len = ip->client->
2217 config->defaults[i].len;
2218 }
2219 } else if (lease->options[i].len) {
2220 len = lease->options[i].len;
2221 dp = lease->options[i].data;
2222 } else {
2223 len = 0;
2224 }
2225 if (len) {
2226 char name[256];
2227
2228 if (dhcp_option_ev_name(name, sizeof(name),
2229 &dhcp_options[i]))
2230 script_set_env(ip->client, prefix, name,
2231 pretty_print_option(i, dp, len, 0, 0));
2232 }
2233 }
2234 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2235 script_set_env(ip->client, prefix, "expiry", tbuf);
2236 }
2237
2238 void
script_write_params(const char * prefix,struct client_lease * lease)2239 script_write_params(const char *prefix, struct client_lease *lease)
2240 {
2241 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2242 struct imsg_hdr hdr;
2243 struct buf *buf;
2244 int errs, i;
2245
2246 if (lease->filename != NULL)
2247 fn_len = strlen(lease->filename);
2248 if (lease->server_name != NULL)
2249 sn_len = strlen(lease->server_name);
2250 if (prefix != NULL)
2251 pr_len = strlen(prefix);
2252
2253 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2254 hdr.len = sizeof(hdr) + sizeof(*lease) +
2255 sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2256 sizeof(pr_len) + pr_len;
2257
2258 for (i = 0; i < 256; i++) {
2259 hdr.len += sizeof(lease->options[i].len);
2260 hdr.len += lease->options[i].len;
2261 }
2262
2263 scripttime = time(NULL);
2264
2265 if ((buf = buf_open(hdr.len)) == NULL)
2266 error("buf_open: %m");
2267
2268 errs = 0;
2269 errs += buf_add(buf, &hdr, sizeof(hdr));
2270 errs += buf_add(buf, lease, sizeof(*lease));
2271 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2272 errs += buf_add(buf, lease->filename, fn_len);
2273 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2274 errs += buf_add(buf, lease->server_name, sn_len);
2275 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2276 errs += buf_add(buf, prefix, pr_len);
2277
2278 for (i = 0; i < 256; i++) {
2279 errs += buf_add(buf, &lease->options[i].len,
2280 sizeof(lease->options[i].len));
2281 errs += buf_add(buf, lease->options[i].data,
2282 lease->options[i].len);
2283 }
2284
2285 if (errs)
2286 error("buf_add: %m");
2287
2288 if (buf_close(privfd, buf) == -1)
2289 error("buf_close: %m");
2290 }
2291
2292 int
script_go(void)2293 script_go(void)
2294 {
2295 struct imsg_hdr hdr;
2296 struct buf *buf;
2297 int ret;
2298
2299 hdr.code = IMSG_SCRIPT_GO;
2300 hdr.len = sizeof(struct imsg_hdr);
2301
2302 if ((buf = buf_open(hdr.len)) == NULL)
2303 error("buf_open: %m");
2304
2305 if (buf_add(buf, &hdr, sizeof(hdr)))
2306 error("buf_add: %m");
2307
2308 if (buf_close(privfd, buf) == -1)
2309 error("buf_close: %m");
2310
2311 bzero(&hdr, sizeof(hdr));
2312 buf_read(privfd, &hdr, sizeof(hdr));
2313 if (hdr.code != IMSG_SCRIPT_GO_RET)
2314 error("unexpected msg type %u", hdr.code);
2315 if (hdr.len != sizeof(hdr) + sizeof(int))
2316 error("received corrupted message");
2317 buf_read(privfd, &ret, sizeof(ret));
2318
2319 scripttime = time(NULL);
2320
2321 return (ret);
2322 }
2323
2324 int
priv_script_go(void)2325 priv_script_go(void)
2326 {
2327 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2328 static char client_path[] = CLIENT_PATH;
2329 struct interface_info *ip = ifi;
2330 int pid, wpid, wstatus;
2331
2332 scripttime = time(NULL);
2333
2334 if (ip) {
2335 scriptName = ip->client->config->script_name;
2336 envp = ip->client->scriptEnv;
2337 } else {
2338 scriptName = top_level_config.script_name;
2339 epp[0] = reason;
2340 epp[1] = client_path;
2341 epp[2] = NULL;
2342 envp = epp;
2343 }
2344
2345 argv[0] = scriptName;
2346 argv[1] = NULL;
2347
2348 pid = fork();
2349 if (pid < 0) {
2350 error("fork: %m");
2351 wstatus = 0;
2352 } else if (pid) {
2353 do {
2354 wpid = wait(&wstatus);
2355 } while (wpid != pid && wpid > 0);
2356 if (wpid < 0) {
2357 error("wait: %m");
2358 wstatus = 0;
2359 }
2360 } else {
2361 execve(scriptName, argv, envp);
2362 error("execve (%s, ...): %m", scriptName);
2363 }
2364
2365 if (ip)
2366 script_flush_env(ip->client);
2367
2368 return (WIFEXITED(wstatus) ?
2369 WEXITSTATUS(wstatus) : 128 + WTERMSIG(wstatus));
2370 }
2371
2372 void
script_set_env(struct client_state * client,const char * prefix,const char * name,const char * value)2373 script_set_env(struct client_state *client, const char *prefix,
2374 const char *name, const char *value)
2375 {
2376 int i, namelen;
2377 size_t j;
2378
2379 /* No `` or $() command substitution allowed in environment values! */
2380 for (j=0; j < strlen(value); j++)
2381 switch (value[j]) {
2382 case '`':
2383 case '$':
2384 warning("illegal character (%c) in value '%s'",
2385 value[j], value);
2386 /* Ignore this option */
2387 return;
2388 }
2389
2390 namelen = strlen(name);
2391
2392 for (i = 0; client->scriptEnv[i]; i++)
2393 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2394 client->scriptEnv[i][namelen] == '=')
2395 break;
2396
2397 if (client->scriptEnv[i])
2398 /* Reuse the slot. */
2399 free(client->scriptEnv[i]);
2400 else {
2401 /* New variable. Expand if necessary. */
2402 if (i >= client->scriptEnvsize - 1) {
2403 char **newscriptEnv;
2404 int newscriptEnvsize = client->scriptEnvsize + 50;
2405
2406 newscriptEnv = realloc(client->scriptEnv,
2407 newscriptEnvsize);
2408 if (newscriptEnv == NULL) {
2409 free(client->scriptEnv);
2410 client->scriptEnv = NULL;
2411 client->scriptEnvsize = 0;
2412 error("script_set_env: no memory for variable");
2413 }
2414 client->scriptEnv = newscriptEnv;
2415 client->scriptEnvsize = newscriptEnvsize;
2416 }
2417 /* need to set the NULL pointer at end of array beyond
2418 the new slot. */
2419 client->scriptEnv[i + 1] = NULL;
2420 }
2421 /* Allocate space and format the variable in the appropriate slot. */
2422 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2423 strlen(value) + 1);
2424 if (client->scriptEnv[i] == NULL)
2425 error("script_set_env: no memory for variable assignment");
2426 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2427 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2428 }
2429
2430 void
script_flush_env(struct client_state * client)2431 script_flush_env(struct client_state *client)
2432 {
2433 int i;
2434
2435 for (i = 0; client->scriptEnv[i]; i++) {
2436 free(client->scriptEnv[i]);
2437 client->scriptEnv[i] = NULL;
2438 }
2439 client->scriptEnvsize = 0;
2440 }
2441
2442 int
dhcp_option_ev_name(char * buf,size_t buflen,struct option * option)2443 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2444 {
2445 size_t i;
2446
2447 for (i = 0; option->name[i]; i++) {
2448 if (i + 1 == buflen)
2449 return 0;
2450 if (option->name[i] == '-')
2451 buf[i] = '_';
2452 else
2453 buf[i] = option->name[i];
2454 }
2455
2456 buf[i] = 0;
2457 return 1;
2458 }
2459
2460 void
go_daemon(void)2461 go_daemon(void)
2462 {
2463 static int state = 0;
2464 cap_rights_t rights;
2465
2466 if (no_daemon || state)
2467 return;
2468
2469 state = 1;
2470
2471 /* Stop logging to stderr... */
2472 log_perror = 0;
2473
2474 if (daemonfd(-1, nullfd) == -1)
2475 error("daemon");
2476
2477 cap_rights_init(&rights);
2478
2479 if (pidfile != NULL) {
2480 pidfile_write(pidfile);
2481
2482 if (caph_rights_limit(pidfile_fileno(pidfile), &rights) < 0)
2483 error("can't limit pidfile descriptor: %m");
2484 }
2485
2486 if (nullfd != -1) {
2487 close(nullfd);
2488 nullfd = -1;
2489 }
2490
2491 if (caph_rights_limit(STDIN_FILENO, &rights) < 0)
2492 error("can't limit stdin: %m");
2493 cap_rights_init(&rights, CAP_WRITE);
2494 if (caph_rights_limit(STDOUT_FILENO, &rights) < 0)
2495 error("can't limit stdout: %m");
2496 if (caph_rights_limit(STDERR_FILENO, &rights) < 0)
2497 error("can't limit stderr: %m");
2498 }
2499
2500 int
check_option(struct client_lease * l,int option)2501 check_option(struct client_lease *l, int option)
2502 {
2503 const char *opbuf;
2504 const char *sbuf;
2505
2506 /* we use this, since this is what gets passed to dhclient-script */
2507
2508 opbuf = pretty_print_option(option, l->options[option].data,
2509 l->options[option].len, 0, 0);
2510
2511 sbuf = option_as_string(option, l->options[option].data,
2512 l->options[option].len);
2513
2514 switch (option) {
2515 case DHO_SUBNET_MASK:
2516 case DHO_TIME_SERVERS:
2517 case DHO_NAME_SERVERS:
2518 case DHO_ROUTERS:
2519 case DHO_DOMAIN_NAME_SERVERS:
2520 case DHO_LOG_SERVERS:
2521 case DHO_COOKIE_SERVERS:
2522 case DHO_LPR_SERVERS:
2523 case DHO_IMPRESS_SERVERS:
2524 case DHO_RESOURCE_LOCATION_SERVERS:
2525 case DHO_SWAP_SERVER:
2526 case DHO_BROADCAST_ADDRESS:
2527 case DHO_NIS_SERVERS:
2528 case DHO_NTP_SERVERS:
2529 case DHO_NETBIOS_NAME_SERVERS:
2530 case DHO_NETBIOS_DD_SERVER:
2531 case DHO_FONT_SERVERS:
2532 case DHO_DHCP_SERVER_IDENTIFIER:
2533 case DHO_NISPLUS_SERVERS:
2534 case DHO_MOBILE_IP_HOME_AGENT:
2535 case DHO_SMTP_SERVER:
2536 case DHO_POP_SERVER:
2537 case DHO_NNTP_SERVER:
2538 case DHO_WWW_SERVER:
2539 case DHO_FINGER_SERVER:
2540 case DHO_IRC_SERVER:
2541 case DHO_STREETTALK_SERVER:
2542 case DHO_STREETTALK_DA_SERVER:
2543 if (!ipv4addrs(opbuf)) {
2544 warning("Invalid IP address in option: %s", opbuf);
2545 return (0);
2546 }
2547 return (1) ;
2548 case DHO_HOST_NAME:
2549 case DHO_NIS_DOMAIN:
2550 case DHO_NISPLUS_DOMAIN:
2551 case DHO_TFTP_SERVER_NAME:
2552 if (!res_hnok(sbuf)) {
2553 warning("Bogus Host Name option %d: %s (%s)", option,
2554 sbuf, opbuf);
2555 l->options[option].len = 0;
2556 free(l->options[option].data);
2557 }
2558 return (1);
2559 case DHO_DOMAIN_NAME:
2560 case DHO_DOMAIN_SEARCH:
2561 if (!res_hnok(sbuf)) {
2562 if (!check_search(sbuf)) {
2563 warning("Bogus domain search list %d: %s (%s)",
2564 option, sbuf, opbuf);
2565 l->options[option].len = 0;
2566 free(l->options[option].data);
2567 }
2568 }
2569 return (1);
2570 case DHO_PAD:
2571 case DHO_TIME_OFFSET:
2572 case DHO_BOOT_SIZE:
2573 case DHO_MERIT_DUMP:
2574 case DHO_ROOT_PATH:
2575 case DHO_EXTENSIONS_PATH:
2576 case DHO_IP_FORWARDING:
2577 case DHO_NON_LOCAL_SOURCE_ROUTING:
2578 case DHO_POLICY_FILTER:
2579 case DHO_MAX_DGRAM_REASSEMBLY:
2580 case DHO_DEFAULT_IP_TTL:
2581 case DHO_PATH_MTU_AGING_TIMEOUT:
2582 case DHO_PATH_MTU_PLATEAU_TABLE:
2583 case DHO_INTERFACE_MTU:
2584 case DHO_ALL_SUBNETS_LOCAL:
2585 case DHO_PERFORM_MASK_DISCOVERY:
2586 case DHO_MASK_SUPPLIER:
2587 case DHO_ROUTER_DISCOVERY:
2588 case DHO_ROUTER_SOLICITATION_ADDRESS:
2589 case DHO_STATIC_ROUTES:
2590 case DHO_TRAILER_ENCAPSULATION:
2591 case DHO_ARP_CACHE_TIMEOUT:
2592 case DHO_IEEE802_3_ENCAPSULATION:
2593 case DHO_DEFAULT_TCP_TTL:
2594 case DHO_TCP_KEEPALIVE_INTERVAL:
2595 case DHO_TCP_KEEPALIVE_GARBAGE:
2596 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2597 case DHO_NETBIOS_NODE_TYPE:
2598 case DHO_NETBIOS_SCOPE:
2599 case DHO_X_DISPLAY_MANAGER:
2600 case DHO_DHCP_REQUESTED_ADDRESS:
2601 case DHO_DHCP_LEASE_TIME:
2602 case DHO_DHCP_OPTION_OVERLOAD:
2603 case DHO_DHCP_MESSAGE_TYPE:
2604 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2605 case DHO_DHCP_MESSAGE:
2606 case DHO_DHCP_MAX_MESSAGE_SIZE:
2607 case DHO_DHCP_RENEWAL_TIME:
2608 case DHO_DHCP_REBINDING_TIME:
2609 case DHO_DHCP_CLASS_IDENTIFIER:
2610 case DHO_DHCP_CLIENT_IDENTIFIER:
2611 case DHO_BOOTFILE_NAME:
2612 case DHO_DHCP_USER_CLASS_ID:
2613 case DHO_URL:
2614 case DHO_END:
2615 return (1);
2616 case DHO_CLASSLESS_ROUTES:
2617 return (check_classless_option(l->options[option].data,
2618 l->options[option].len));
2619 default:
2620 warning("unknown dhcp option value 0x%x", option);
2621 return (unknown_ok);
2622 }
2623 }
2624
2625 /* RFC 3442 The Classless Static Routes option checks */
2626 int
check_classless_option(unsigned char * data,int len)2627 check_classless_option(unsigned char *data, int len)
2628 {
2629 int i = 0;
2630 unsigned char width;
2631 in_addr_t addr, mask;
2632
2633 if (len < 5) {
2634 warning("Too small length: %d", len);
2635 return (0);
2636 }
2637 while(i < len) {
2638 width = data[i++];
2639 if (width == 0) {
2640 i += 4;
2641 continue;
2642 } else if (width < 9) {
2643 addr = (in_addr_t)(data[i] << 24);
2644 i += 1;
2645 } else if (width < 17) {
2646 addr = (in_addr_t)(data[i] << 24) +
2647 (in_addr_t)(data[i + 1] << 16);
2648 i += 2;
2649 } else if (width < 25) {
2650 addr = (in_addr_t)(data[i] << 24) +
2651 (in_addr_t)(data[i + 1] << 16) +
2652 (in_addr_t)(data[i + 2] << 8);
2653 i += 3;
2654 } else if (width < 33) {
2655 addr = (in_addr_t)(data[i] << 24) +
2656 (in_addr_t)(data[i + 1] << 16) +
2657 (in_addr_t)(data[i + 2] << 8) +
2658 data[i + 3];
2659 i += 4;
2660 } else {
2661 warning("Incorrect subnet width: %d", width);
2662 return (0);
2663 }
2664 mask = (in_addr_t)(~0) << (32 - width);
2665 addr = ntohl(addr);
2666 mask = ntohl(mask);
2667
2668 /*
2669 * From RFC 3442:
2670 * ... After deriving a subnet number and subnet mask
2671 * from each destination descriptor, the DHCP client
2672 * MUST zero any bits in the subnet number where the
2673 * corresponding bit in the mask is zero...
2674 */
2675 if ((addr & mask) != addr) {
2676 addr &= mask;
2677 data[i - 1] = (unsigned char)(
2678 (addr >> (((32 - width)/8)*8)) & 0xFF);
2679 }
2680 i += 4;
2681 }
2682 if (i > len) {
2683 warning("Incorrect data length: %d (must be %d)", len, i);
2684 return (0);
2685 }
2686 return (1);
2687 }
2688
2689 int
res_hnok(const char * dn)2690 res_hnok(const char *dn)
2691 {
2692 int pch = PERIOD, ch = *dn++;
2693
2694 while (ch != '\0') {
2695 int nch = *dn++;
2696
2697 if (periodchar(ch)) {
2698 ;
2699 } else if (periodchar(pch)) {
2700 if (!borderchar(ch))
2701 return (0);
2702 } else if (periodchar(nch) || nch == '\0') {
2703 if (!borderchar(ch))
2704 return (0);
2705 } else {
2706 if (!middlechar(ch))
2707 return (0);
2708 }
2709 pch = ch, ch = nch;
2710 }
2711 return (1);
2712 }
2713
2714 int
check_search(const char * srch)2715 check_search(const char *srch)
2716 {
2717 int pch = PERIOD, ch = *srch++;
2718 int domains = 1;
2719
2720 /* 256 char limit re resolv.conf(5) */
2721 if (strlen(srch) > 256)
2722 return (0);
2723
2724 while (whitechar(ch))
2725 ch = *srch++;
2726
2727 while (ch != '\0') {
2728 int nch = *srch++;
2729
2730 if (periodchar(ch) || whitechar(ch)) {
2731 ;
2732 } else if (periodchar(pch)) {
2733 if (!borderchar(ch))
2734 return (0);
2735 } else if (periodchar(nch) || nch == '\0') {
2736 if (!borderchar(ch))
2737 return (0);
2738 } else {
2739 if (!middlechar(ch))
2740 return (0);
2741 }
2742 if (!whitechar(ch)) {
2743 pch = ch;
2744 } else {
2745 while (whitechar(nch)) {
2746 nch = *srch++;
2747 }
2748 if (nch != '\0')
2749 domains++;
2750 pch = PERIOD;
2751 }
2752 ch = nch;
2753 }
2754 /* 6 domain limit re resolv.conf(5) */
2755 if (domains > 6)
2756 return (0);
2757 return (1);
2758 }
2759
2760 /* Does buf consist only of dotted decimal ipv4 addrs?
2761 * return how many if so,
2762 * otherwise, return 0
2763 */
2764 int
ipv4addrs(const char * buf)2765 ipv4addrs(const char * buf)
2766 {
2767 struct in_addr jnk;
2768 int count = 0;
2769
2770 while (inet_aton(buf, &jnk) == 1){
2771 count++;
2772 while (periodchar(*buf) || digitchar(*buf))
2773 buf++;
2774 if (*buf == '\0')
2775 return (count);
2776 while (*buf == ' ')
2777 buf++;
2778 }
2779 return (0);
2780 }
2781
2782
2783 const char *
option_as_string(unsigned int code,unsigned char * data,int len)2784 option_as_string(unsigned int code, unsigned char *data, int len)
2785 {
2786 static char optbuf[32768]; /* XXX */
2787 char *op = optbuf;
2788 int opleft = sizeof(optbuf);
2789 unsigned char *dp = data;
2790
2791 if (code > 255)
2792 error("option_as_string: bad code %d", code);
2793
2794 for (; dp < data + len; dp++) {
2795 if (!isascii(*dp) || !isprint(*dp)) {
2796 if (dp + 1 != data + len || *dp != 0) {
2797 snprintf(op, opleft, "\\%03o", *dp);
2798 op += 4;
2799 opleft -= 4;
2800 }
2801 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2802 *dp == '`' || *dp == '\\') {
2803 *op++ = '\\';
2804 *op++ = *dp;
2805 opleft -= 2;
2806 } else {
2807 *op++ = *dp;
2808 opleft--;
2809 }
2810 }
2811 if (opleft < 1)
2812 goto toobig;
2813 *op = 0;
2814 return optbuf;
2815 toobig:
2816 warning("dhcp option too large");
2817 return "<error>";
2818 }
2819
2820 int
fork_privchld(int fd,int fd2)2821 fork_privchld(int fd, int fd2)
2822 {
2823 struct pollfd pfd[1];
2824 int nfds;
2825
2826 switch (fork()) {
2827 case -1:
2828 error("cannot fork");
2829 case 0:
2830 break;
2831 default:
2832 return (0);
2833 }
2834
2835 setproctitle("%s [priv]", ifi->name);
2836
2837 setsid();
2838 dup2(nullfd, STDIN_FILENO);
2839 dup2(nullfd, STDOUT_FILENO);
2840 dup2(nullfd, STDERR_FILENO);
2841 close(nullfd);
2842 close(fd2);
2843 close(ifi->rfdesc);
2844 ifi->rfdesc = -1;
2845
2846 for (;;) {
2847 pfd[0].fd = fd;
2848 pfd[0].events = POLLIN;
2849 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2850 if (errno != EINTR)
2851 error("poll error");
2852
2853 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2854 continue;
2855
2856 dispatch_imsg(ifi, fd);
2857 }
2858 }
2859