1 /* $OpenBSD: dhclient.c,v 1.728 2024/04/28 16:43:42 florian Exp $ */
2
3 /*
4 * Copyright 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 1995, 1996, 1997, 1998, 1999
6 * The Internet Software Consortium. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of The Internet Software Consortium nor the names
18 * of its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
22 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
26 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
29 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * This software has been written for the Internet Software Consortium
36 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
37 * Enterprises. To learn more about the Internet Software Consortium,
38 * see ``http://www.vix.com/isc''. To learn more about Vixie
39 * Enterprises, see ``http://www.vix.com''.
40 *
41 * This client was substantially modified and enhanced by Elliot Poger
42 * for use on Linux while he was working on the MosquitoNet project at
43 * Stanford.
44 *
45 * The current version owes much to Elliot's Linux enhancements, but
46 * was substantially reorganized and partially rewritten by Ted Lemon
47 * so as to use the same networking framework that the Internet Software
48 * Consortium DHCP server uses. Much system-specific configuration code
49 * was moved into a shell script so that as support for more operating
50 * systems is added, it will not be necessary to port and maintain
51 * system-specific configuration code to these operating systems - instead,
52 * the shell script can invoke the native tools to accomplish the same
53 * purpose.
54 */
55
56 #include <sys/types.h>
57 #include <sys/socket.h>
58 #include <sys/stat.h>
59 #include <sys/ioctl.h>
60 #include <sys/uio.h>
61 #include <sys/queue.h>
62
63 #include <net/if.h>
64 #include <net/if_types.h>
65 #include <net/if_dl.h>
66 #include <net/route.h>
67
68 #include <netinet/in.h>
69 #include <netinet/if_ether.h>
70
71 #include <net80211/ieee80211.h>
72 #include <net80211/ieee80211_ioctl.h>
73
74 #include <arpa/inet.h>
75
76 #include <ctype.h>
77 #include <errno.h>
78 #include <fcntl.h>
79 #include <ifaddrs.h>
80 #include <imsg.h>
81 #include <limits.h>
82 #include <paths.h>
83 #include <poll.h>
84 #include <pwd.h>
85 #include <resolv.h>
86 #include <signal.h>
87 #include <stdint.h>
88 #include <stdlib.h>
89 #include <string.h>
90 #include <syslog.h>
91 #include <unistd.h>
92
93 #include "dhcp.h"
94 #include "dhcpd.h"
95 #include "log.h"
96 #include "privsep.h"
97
98 char *path_dhclient_conf;
99 char *path_lease_db;
100 char *log_procname;
101
102 int nullfd = -1;
103 int cmd_opts;
104 int quit;
105
106 const struct in_addr inaddr_any = { INADDR_ANY };
107 const struct in_addr inaddr_broadcast = { INADDR_BROADCAST };
108
109 struct client_config *config;
110 struct imsgbuf *unpriv_ibuf;
111
112 void usage(void);
113 int res_hnok_list(const char *);
114 int addressinuse(char *, struct in_addr, char *);
115
116 void fork_privchld(struct interface_info *, int, int);
117 void get_name(struct interface_info *, int, char *);
118 void get_ssid(struct interface_info *, int);
119 void get_sockets(struct interface_info *);
120 int get_routefd(int);
121 void set_iff_up(struct interface_info *, int);
122 void set_user(char *);
123 int get_ifa_family(char *, int);
124 struct ifaddrs *get_link_ifa(const char *, struct ifaddrs *);
125 void interface_state(struct interface_info *);
126 struct interface_info *initialize_interface(char *, int);
127 void tick_msg(const char *, int);
128 void rtm_dispatch(struct interface_info *, struct rt_msghdr *);
129
130 struct client_lease *apply_defaults(struct client_lease *);
131 struct client_lease *clone_lease(struct client_lease *);
132
133 void state_reboot(struct interface_info *);
134 void state_init(struct interface_info *);
135 void state_selecting(struct interface_info *);
136 void state_bound(struct interface_info *);
137 void state_panic(struct interface_info *);
138
139 void set_interval(struct interface_info *, struct timespec *);
140 void set_resend_timeout(struct interface_info *, struct timespec *,
141 void (*where)(struct interface_info *));
142 void set_secs(struct interface_info *, struct timespec *);
143
144 void send_discover(struct interface_info *);
145 void send_request(struct interface_info *);
146 void send_decline(struct interface_info *);
147 void send_release(struct interface_info *);
148
149 void process_offer(struct interface_info *, struct option_data *,
150 const char *);
151 void bind_lease(struct interface_info *);
152
153 void make_discover(struct interface_info *, struct client_lease *);
154 void make_request(struct interface_info *, struct client_lease *);
155 void make_decline(struct interface_info *, struct client_lease *);
156 void make_release(struct interface_info *, struct client_lease *);
157
158 void release_lease(struct interface_info *);
159 void propose_release(struct interface_info *);
160
161 void write_lease_db(struct interface_info *);
162 char *lease_as_string(char *, struct client_lease *);
163 struct proposal *lease_as_proposal(struct client_lease *);
164 struct unwind_info *lease_as_unwind_info(struct client_lease *);
165 void append_statement(char *, size_t, char *, char *);
166 time_t lease_expiry(struct client_lease *);
167 time_t lease_renewal(struct client_lease *);
168 time_t lease_rebind(struct client_lease *);
169 void get_lease_timeouts(struct interface_info *, struct client_lease *);
170
171 struct client_lease *packet_to_lease(struct interface_info *,
172 struct option_data *);
173 void go_daemon(void);
174 int rdaemon(int);
175 int take_charge(struct interface_info *, int, char *);
176 int autoconf(struct interface_info *);
177 struct client_lease *get_recorded_lease(struct interface_info *);
178
179 #define ROUNDUP(a) \
180 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
181 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
182
183 #define TICK_WAIT 0
184 #define TICK_SUCCESS 1
185 #define TICK_DAEMON 2
186
187 static FILE *leaseFile;
188
189 int
get_ifa_family(char * cp,int n)190 get_ifa_family(char *cp, int n)
191 {
192 struct sockaddr *sa;
193 unsigned int i;
194
195 for (i = 1; i; i <<= 1) {
196 if ((i & n) != 0) {
197 sa = (struct sockaddr *)cp;
198 if (i == RTA_IFA)
199 return sa->sa_family;
200 ADVANCE(cp, sa);
201 }
202 }
203
204 return AF_UNSPEC;
205 }
206
207 struct ifaddrs *
get_link_ifa(const char * name,struct ifaddrs * ifap)208 get_link_ifa(const char *name, struct ifaddrs *ifap)
209 {
210 struct ifaddrs *ifa;
211 struct sockaddr_dl *sdl;
212
213 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
214 if (strcmp(name, ifa->ifa_name) == 0 &&
215 (ifa->ifa_flags & IFF_LOOPBACK) == 0 &&
216 (ifa->ifa_flags & IFF_POINTOPOINT) == 0 &&
217 ifa->ifa_data != NULL && /* NULL shouldn't be possible. */
218 ifa->ifa_addr != NULL &&
219 ifa->ifa_addr->sa_family == AF_LINK) {
220 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
221 if (sdl->sdl_alen == ETHER_ADDR_LEN &&
222 (sdl->sdl_type == IFT_ETHER ||
223 sdl->sdl_type == IFT_CARP))
224 break;
225 }
226 }
227
228 if (ifa == NULL)
229 fatal("get_link_ifa()");
230
231 return ifa;
232 }
233
234 void
interface_state(struct interface_info * ifi)235 interface_state(struct interface_info *ifi)
236 {
237 struct ifaddrs *ifap, *ifa;
238 struct if_data *ifd;
239 struct sockaddr_dl *sdl;
240 char *oldlladdr;
241 int newlinkup, oldlinkup;
242
243 oldlinkup = LINK_STATE_IS_UP(ifi->link_state);
244
245 if (getifaddrs(&ifap) == -1)
246 fatal("getifaddrs");
247
248 ifa = get_link_ifa(ifi->name, ifap);
249 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
250 ifd = (struct if_data *)ifa->ifa_data;
251
252 if ((ifa->ifa_flags & IFF_UP) == 0 ||
253 (ifa->ifa_flags & IFF_RUNNING) == 0) {
254 ifi->link_state = LINK_STATE_DOWN;
255 } else {
256 ifi->link_state = ifd->ifi_link_state;
257 ifi->mtu = ifd->ifi_mtu;
258 }
259
260 newlinkup = LINK_STATE_IS_UP(ifi->link_state);
261 if (newlinkup != oldlinkup) {
262 log_debug("%s: link %s -> %s", log_procname,
263 (oldlinkup != 0) ? "up" : "down",
264 (newlinkup != 0) ? "up" : "down");
265 tick_msg("link", newlinkup ? TICK_SUCCESS : TICK_WAIT);
266 }
267
268 if (memcmp(&ifi->hw_address, LLADDR(sdl), ETHER_ADDR_LEN) != 0) {
269 if (log_getverbose()) {
270 oldlladdr = strdup(ether_ntoa(&ifi->hw_address));
271 if (oldlladdr == NULL)
272 fatal("oldlladdr");
273 log_debug("%s: LLADDR %s -> %s", log_procname,
274 oldlladdr,
275 ether_ntoa((struct ether_addr *)LLADDR(sdl)));
276 free(oldlladdr);
277 }
278 memcpy(&ifi->hw_address, LLADDR(sdl), ETHER_ADDR_LEN);
279 quit = RESTART; /* Even if MTU has changed. */
280 }
281
282 freeifaddrs(ifap);
283 }
284
285 struct interface_info *
initialize_interface(char * name,int noaction)286 initialize_interface(char *name, int noaction)
287 {
288 struct interface_info *ifi;
289 struct ifaddrs *ifap, *ifa;
290 struct if_data *ifd;
291 struct sockaddr_dl *sdl;
292 int ioctlfd;
293
294 ifi = calloc(1, sizeof(*ifi));
295 if (ifi == NULL)
296 fatal("ifi");
297
298 ifi->rbuf_max = RT_BUF_SIZE;
299 ifi->rbuf = malloc(ifi->rbuf_max);
300 if (ifi->rbuf == NULL)
301 fatal("rbuf");
302
303 if ((ioctlfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
304 fatal("socket(AF_INET, SOCK_DGRAM)");
305
306 get_name(ifi, ioctlfd, name);
307 ifi->index = if_nametoindex(ifi->name);
308 if (ifi->index == 0)
309 fatalx("if_nametoindex(%s) == 0", ifi->name);
310
311 if (getifaddrs(&ifap) == -1)
312 fatal("getifaddrs()");
313
314 ifa = get_link_ifa(ifi->name, ifap);
315 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
316 ifd = (struct if_data *)ifa->ifa_data;
317
318 if ((ifa->ifa_flags & IFF_UP) == 0 ||
319 (ifa->ifa_flags & IFF_RUNNING) == 0)
320 ifi->link_state = LINK_STATE_DOWN;
321 else
322 ifi->link_state = ifd->ifi_link_state;
323
324 memcpy(ifi->hw_address.ether_addr_octet, LLADDR(sdl), ETHER_ADDR_LEN);
325 ifi->rdomain = ifd->ifi_rdomain;
326
327 get_sockets(ifi);
328 get_ssid(ifi, ioctlfd);
329
330 if (noaction == 0 && !LINK_STATE_IS_UP(ifi->link_state))
331 set_iff_up(ifi, ioctlfd);
332
333 close(ioctlfd);
334 freeifaddrs(ifap);
335
336 return ifi;
337 }
338
339 void
get_name(struct interface_info * ifi,int ioctlfd,char * arg)340 get_name(struct interface_info *ifi, int ioctlfd, char *arg)
341 {
342 struct ifgroupreq ifgr;
343 size_t len;
344
345 if (strcmp(arg, "egress") == 0) {
346 memset(&ifgr, 0, sizeof(ifgr));
347 strlcpy(ifgr.ifgr_name, "egress", sizeof(ifgr.ifgr_name));
348 if (ioctl(ioctlfd, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
349 fatal("SIOCGIFGMEMB");
350 if (ifgr.ifgr_len > sizeof(struct ifg_req))
351 fatalx("too many interfaces in group egress");
352 if ((ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len)) == NULL)
353 fatalx("ifgr_groups");
354 if (ioctl(ioctlfd, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
355 fatal("SIOCGIFGMEMB");
356 len = strlcpy(ifi->name, ifgr.ifgr_groups->ifgrq_member,
357 IFNAMSIZ);
358 free(ifgr.ifgr_groups);
359 } else
360 len = strlcpy(ifi->name, arg, IFNAMSIZ);
361
362 if (len >= IFNAMSIZ)
363 fatalx("interface name too long");
364 }
365
366 void
get_ssid(struct interface_info * ifi,int ioctlfd)367 get_ssid(struct interface_info *ifi, int ioctlfd)
368 {
369 struct ieee80211_nwid nwid;
370 struct ifreq ifr;
371
372 memset(&ifr, 0, sizeof(ifr));
373 memset(&nwid, 0, sizeof(nwid));
374
375 ifr.ifr_data = (caddr_t)&nwid;
376 strlcpy(ifr.ifr_name, ifi->name, sizeof(ifr.ifr_name));
377
378 if (ioctl(ioctlfd, SIOCG80211NWID, (caddr_t)&ifr) == 0) {
379 memset(ifi->ssid, 0, sizeof(ifi->ssid));
380 memcpy(ifi->ssid, nwid.i_nwid, nwid.i_len);
381 ifi->ssid_len = nwid.i_len;
382 }
383 }
384
385 void
set_iff_up(struct interface_info * ifi,int ioctlfd)386 set_iff_up(struct interface_info *ifi, int ioctlfd)
387 {
388 struct ifreq ifr;
389
390 memset(&ifr, 0, sizeof(ifr));
391 strlcpy(ifr.ifr_name, ifi->name, sizeof(ifr.ifr_name));
392
393 if (ioctl(ioctlfd, SIOCGIFFLAGS, (caddr_t)&ifr) == -1)
394 fatal("%s: SIOCGIFFLAGS", ifi->name);
395
396 if ((ifr.ifr_flags & IFF_UP) == 0) {
397 ifi->link_state = LINK_STATE_DOWN;
398 ifr.ifr_flags |= IFF_UP;
399 if (ioctl(ioctlfd, SIOCSIFFLAGS, (caddr_t)&ifr) == -1)
400 fatal("%s: SIOCSIFFLAGS", ifi->name);
401 }
402 }
403
404 void
set_user(char * user)405 set_user(char *user)
406 {
407 struct passwd *pw;
408
409 pw = getpwnam(user);
410 if (pw == NULL)
411 fatalx("no such user: %s", user);
412
413 if (chroot(pw->pw_dir) == -1)
414 fatal("chroot(%s)", pw->pw_dir);
415 if (chdir("/") == -1)
416 fatal("chdir(\"/\")");
417 if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
418 fatal("setresgid");
419 if (setgroups(1, &pw->pw_gid) == -1)
420 fatal("setgroups");
421 if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
422 fatal("setresuid");
423
424 endpwent();
425 }
426
427 void
get_sockets(struct interface_info * ifi)428 get_sockets(struct interface_info *ifi)
429 {
430 unsigned char *newp;
431 size_t newsize;
432
433 ifi->udpfd = get_udp_sock(ifi->rdomain);
434 ifi->bpffd = get_bpf_sock(ifi->name);
435
436 newsize = configure_bpf_sock(ifi->bpffd);
437 if (newsize > ifi->rbuf_max) {
438 if ((newp = realloc(ifi->rbuf, newsize)) == NULL)
439 fatal("rbuf");
440 ifi->rbuf = newp;
441 ifi->rbuf_max = newsize;
442 }
443 }
444
445 int
get_routefd(int rdomain)446 get_routefd(int rdomain)
447 {
448 int routefd, rtfilter;
449
450 if ((routefd = socket(AF_ROUTE, SOCK_RAW, AF_INET)) == -1)
451 fatal("socket(AF_ROUTE, SOCK_RAW)");
452
453 rtfilter = ROUTE_FILTER(RTM_PROPOSAL) | ROUTE_FILTER(RTM_IFINFO) |
454 ROUTE_FILTER(RTM_NEWADDR) | ROUTE_FILTER(RTM_DELADDR) |
455 ROUTE_FILTER(RTM_IFANNOUNCE) | ROUTE_FILTER(RTM_80211INFO);
456
457 if (setsockopt(routefd, AF_ROUTE, ROUTE_MSGFILTER,
458 &rtfilter, sizeof(rtfilter)) == -1)
459 fatal("setsockopt(ROUTE_MSGFILTER)");
460 if (setsockopt(routefd, AF_ROUTE, ROUTE_TABLEFILTER, &rdomain,
461 sizeof(rdomain)) == -1)
462 fatal("setsockopt(ROUTE_TABLEFILTER)");
463
464 return routefd;
465 }
466
467 void
routefd_handler(struct interface_info * ifi,int routefd)468 routefd_handler(struct interface_info *ifi, int routefd)
469 {
470 struct rt_msghdr *rtm;
471 unsigned char *buf = ifi->rbuf;
472 unsigned char *lim, *next;
473 ssize_t n;
474
475 do {
476 n = read(routefd, buf, RT_BUF_SIZE);
477 } while (n == -1 && errno == EINTR);
478 if (n == -1) {
479 log_warn("%s: routing socket", log_procname);
480 return;
481 }
482 if (n == 0)
483 fatalx("%s: routing socket closed", log_procname);
484
485 lim = buf + n;
486 for (next = buf; next < lim && quit == 0; next += rtm->rtm_msglen) {
487 rtm = (struct rt_msghdr *)next;
488 if (lim < next + sizeof(rtm->rtm_msglen) ||
489 lim < next + rtm->rtm_msglen)
490 fatalx("%s: partial rtm in buffer", log_procname);
491
492 if (rtm->rtm_version != RTM_VERSION)
493 continue;
494
495 rtm_dispatch(ifi, rtm);
496 }
497 }
498
499 void
rtm_dispatch(struct interface_info * ifi,struct rt_msghdr * rtm)500 rtm_dispatch(struct interface_info *ifi, struct rt_msghdr *rtm)
501 {
502 struct if_msghdr *ifm;
503 struct if_announcemsghdr *ifan;
504 struct ifa_msghdr *ifam;
505 struct if_ieee80211_data *ifie;
506 char *oldssid;
507 uint32_t oldmtu;
508
509 switch (rtm->rtm_type) {
510 case RTM_PROPOSAL:
511 if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT) {
512 if (quit == 0 && ifi->active != NULL)
513 tell_unwind(ifi->unwind_info, ifi->flags);
514 return;
515 }
516 if (rtm->rtm_index != ifi->index ||
517 rtm->rtm_priority != RTP_PROPOSAL_DHCLIENT)
518 return;
519 if ((rtm->rtm_flags & RTF_PROTO3) != 0) {
520 if (rtm->rtm_seq == (int32_t)ifi->xid) {
521 ifi->flags |= IFI_IN_CHARGE;
522 return;
523 } else if ((ifi->flags & IFI_IN_CHARGE) != 0) {
524 log_debug("%s: yielding responsibility",
525 log_procname);
526 quit = TERMINATE;
527 }
528 } else if ((rtm->rtm_flags & RTF_PROTO2) != 0) {
529 release_lease(ifi); /* OK even if we sent it. */
530 quit = TERMINATE;
531 } else
532 return; /* Ignore tell_unwind() proposals. */
533 break;
534
535 case RTM_DESYNC:
536 log_warnx("%s: RTM_DESYNC", log_procname);
537 break;
538
539 case RTM_IFINFO:
540 ifm = (struct if_msghdr *)rtm;
541 if (ifm->ifm_index != ifi->index)
542 break;
543 if ((rtm->rtm_flags & RTF_UP) == 0)
544 fatalx("down");
545
546 oldmtu = ifi->mtu;
547 interface_state(ifi);
548 if (oldmtu == ifi->mtu)
549 quit = RESTART;
550 else
551 log_debug("%s: MTU %u -> %u",
552 log_procname, oldmtu, ifi->mtu);
553 break;
554
555 case RTM_80211INFO:
556 if (rtm->rtm_index != ifi->index)
557 break;
558 ifie = &((struct if_ieee80211_msghdr *)rtm)->ifim_ifie;
559 if (ifi->ssid_len != ifie->ifie_nwid_len || memcmp(ifi->ssid,
560 ifie->ifie_nwid, ifie->ifie_nwid_len) != 0) {
561 if (log_getverbose()) {
562 oldssid = strdup(pretty_print_string(ifi->ssid,
563 ifi->ssid_len, 1));
564 if (oldssid == NULL)
565 fatal("oldssid");
566 log_debug("%s: SSID %s -> %s", log_procname,
567 oldssid, pretty_print_string(ifie->ifie_nwid,
568 ifie->ifie_nwid_len, 1));
569 free(oldssid);
570 }
571 quit = RESTART;
572 }
573 break;
574
575 case RTM_IFANNOUNCE:
576 ifan = (struct if_announcemsghdr *)rtm;
577 if (ifan->ifan_what == IFAN_DEPARTURE && ifan->ifan_index ==
578 ifi->index)
579 fatalx("departed");
580 break;
581
582 case RTM_NEWADDR:
583 case RTM_DELADDR:
584 /* Need to check if it is time to write resolv.conf. */
585 ifam = (struct ifa_msghdr *)rtm;
586 if (get_ifa_family((char *)ifam + ifam->ifam_hdrlen,
587 ifam->ifam_addrs) != AF_INET)
588 return;
589 break;
590
591 default:
592 break;
593 }
594
595 /*
596 * Responsibility for resolv.conf may have changed hands.
597 */
598 if (quit == 0 && ifi->active != NULL &&
599 (ifi->flags & IFI_IN_CHARGE) != 0 &&
600 ifi->state == S_BOUND)
601 write_resolv_conf();
602 }
603
604 int
main(int argc,char * argv[])605 main(int argc, char *argv[])
606 {
607 uint8_t actions[DHO_END];
608 struct stat sb;
609 struct interface_info *ifi;
610 char *ignore_list, *p;
611 int fd, socket_fd[2];
612 int routefd;
613 int ch, i;
614
615 if (isatty(STDERR_FILENO) != 0)
616 log_init(1, LOG_DEBUG); /* log to stderr until daemonized */
617 else
618 log_init(0, LOG_DEBUG); /* can't log to stderr */
619
620 log_setverbose(0); /* Don't show log_debug() messages. */
621
622 if (lstat(_PATH_DHCLIENT_CONF, &sb) == 0)
623 path_dhclient_conf = _PATH_DHCLIENT_CONF;
624 memset(actions, ACTION_USELEASE, sizeof(actions));
625
626 while ((ch = getopt(argc, argv, "c:di:nrv")) != -1) {
627 syslog(LOG_ALERT | LOG_CONS,
628 "dhclient will go away, so -%c option will not exist", ch);
629 switch (ch) {
630 case 'c':
631 if (strlen(optarg) == 0)
632 path_dhclient_conf = NULL;
633 else if (lstat(optarg, &sb) == 0)
634 path_dhclient_conf = optarg;
635 else
636 fatal("lstat(%s)", optarg);
637 break;
638 case 'd':
639 cmd_opts |= OPT_FOREGROUND;
640 break;
641 case 'i':
642 syslog(LOG_ALERT | LOG_CONS,
643 "dhclient will go away, for -i learn dhcpleased.conf");
644 if (strlen(optarg) == 0)
645 break;
646 ignore_list = strdup(optarg);
647 if (ignore_list == NULL)
648 fatal("ignore_list");
649 for (p = strsep(&ignore_list, ", "); p != NULL;
650 p = strsep(&ignore_list, ", ")) {
651 if (*p == '\0')
652 continue;
653 i = name_to_code(p);
654 if (i == DHO_END)
655 fatalx("invalid option name: '%s'", p);
656 actions[i] = ACTION_IGNORE;
657 }
658 free(ignore_list);
659 break;
660 case 'n':
661 cmd_opts |= OPT_NOACTION;
662 break;
663 case 'r':
664 cmd_opts |= OPT_RELEASE;
665 break;
666 case 'v':
667 cmd_opts |= OPT_VERBOSE;
668 break;
669 default:
670 usage();
671 }
672 }
673
674 argc -= optind;
675 argv += optind;
676
677 if (argc != 1)
678 usage();
679
680 syslog(LOG_ALERT | LOG_CONS,
681 "dhclient will go away, stop using it");
682
683 execl("/sbin/ifconfig", "ifconfig", argv[0], "inet", "autoconf", NULL);
684
685 if ((cmd_opts & (OPT_FOREGROUND | OPT_NOACTION)) != 0)
686 cmd_opts |= OPT_VERBOSE;
687
688 if ((cmd_opts & OPT_VERBOSE) != 0)
689 log_setverbose(1); /* Show log_debug() messages. */
690
691 ifi = initialize_interface(argv[0], cmd_opts & OPT_NOACTION);
692
693 log_procname = strdup(ifi->name);
694 if (log_procname == NULL)
695 fatal("log_procname");
696 setproctitle("%s", log_procname);
697 log_procinit(log_procname);
698
699 tzset();
700
701 if (setrtable(ifi->rdomain) == -1)
702 fatal("setrtable(%u)", ifi->rdomain);
703
704 if ((cmd_opts & OPT_RELEASE) != 0) {
705 if ((cmd_opts & OPT_NOACTION) == 0)
706 propose_release(ifi);
707 exit(0);
708 }
709
710 signal(SIGPIPE, SIG_IGN); /* Don't wait for go_daemon()! */
711
712 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0,
713 socket_fd) == -1)
714 fatal("socketpair");
715
716 if ((nullfd = open(_PATH_DEVNULL, O_RDWR)) == -1)
717 fatal("open(%s)", _PATH_DEVNULL);
718
719 fork_privchld(ifi, socket_fd[0], socket_fd[1]);
720
721 close(socket_fd[0]);
722 if ((unpriv_ibuf = malloc(sizeof(*unpriv_ibuf))) == NULL)
723 fatal("unpriv_ibuf");
724 imsg_init(unpriv_ibuf, socket_fd[1]);
725
726 read_conf(ifi->name, actions, &ifi->hw_address);
727 if ((cmd_opts & OPT_NOACTION) != 0)
728 return 0;
729
730 if (asprintf(&path_lease_db, "%s.%s", _PATH_LEASE_DB, ifi->name) == -1)
731 fatal("path_lease_db");
732
733 routefd = get_routefd(ifi->rdomain);
734 fd = take_charge(ifi, routefd, path_lease_db); /* Kill other dhclients. */
735 if (autoconf(ifi)) {
736 /* dhcpleased has been notified to request a new lease. */
737 return 0;
738 }
739 if (fd != -1)
740 read_lease_db(&ifi->lease_db);
741
742 if ((leaseFile = fopen(path_lease_db, "w")) == NULL)
743 log_warn("%s: fopen(%s)", log_procname, path_lease_db);
744 write_lease_db(ifi);
745
746 set_user("_dhcp");
747
748 if ((cmd_opts & OPT_FOREGROUND) == 0) {
749 if (pledge("stdio inet dns route proc", NULL) == -1)
750 fatal("pledge");
751 } else {
752 if (pledge("stdio inet dns route", NULL) == -1)
753 fatal("pledge");
754 }
755
756 tick_msg("link", LINK_STATE_IS_UP(ifi->link_state) ? TICK_SUCCESS :
757 TICK_WAIT);
758 quit = RESTART;
759 dispatch(ifi, routefd);
760
761 return 0;
762 }
763
764 void
usage(void)765 usage(void)
766 {
767 extern char *__progname;
768
769 fprintf(stderr,
770 "usage: %s [-dnrv] [-c file] [-i options] "
771 "interface\n", __progname);
772 exit(1);
773 }
774
775 void
state_preboot(struct interface_info * ifi)776 state_preboot(struct interface_info *ifi)
777 {
778 interface_state(ifi);
779 if (quit != 0)
780 return;
781
782 if (LINK_STATE_IS_UP(ifi->link_state)) {
783 tick_msg("link", TICK_SUCCESS);
784 ifi->state = S_REBOOTING;
785 state_reboot(ifi);
786 } else {
787 tick_msg("link", TICK_WAIT);
788 set_timeout(ifi, 1, state_preboot);
789 }
790 }
791
792 /*
793 * Called when the interface link becomes active.
794 */
795 void
state_reboot(struct interface_info * ifi)796 state_reboot(struct interface_info *ifi)
797 {
798 const struct timespec reboot_intvl = {config->reboot_interval, 0};
799 struct client_lease *lease;
800
801 cancel_timeout(ifi);
802
803 /*
804 * If there is no recorded lease or the lease is BOOTP then
805 * go straight to INIT and try to DISCOVER a new lease.
806 */
807 ifi->active = get_recorded_lease(ifi);
808 if (ifi->active == NULL || BOOTP_LEASE(ifi->active)) {
809 ifi->state = S_INIT;
810 state_init(ifi);
811 return;
812 }
813 lease = apply_defaults(ifi->active);
814 get_lease_timeouts(ifi, lease);
815 free_client_lease(lease);
816
817 ifi->xid = arc4random();
818 make_request(ifi, ifi->active);
819
820 ifi->destination.s_addr = INADDR_BROADCAST;
821 clock_gettime(CLOCK_MONOTONIC, &ifi->first_sending);
822 timespecadd(&ifi->first_sending, &reboot_intvl, &ifi->reboot_timeout);
823 ifi->interval = 0;
824
825 send_request(ifi);
826 }
827
828 /*
829 * Called when a lease has completely expired and we've been unable to
830 * renew it.
831 */
832 void
state_init(struct interface_info * ifi)833 state_init(struct interface_info *ifi)
834 {
835 const struct timespec offer_intvl = {config->offer_interval, 0};
836
837 ifi->xid = arc4random();
838 make_discover(ifi, ifi->active);
839
840 ifi->destination.s_addr = INADDR_BROADCAST;
841 ifi->state = S_SELECTING;
842 clock_gettime(CLOCK_MONOTONIC, &ifi->first_sending);
843 timespecadd(&ifi->first_sending, &offer_intvl, &ifi->offer_timeout);
844 ifi->select_timeout = ifi->offer_timeout;
845 ifi->interval = 0;
846
847 send_discover(ifi);
848 }
849
850 /*
851 * Called when one or more DHCPOFFER packets have been received and a
852 * configurable period of time has passed.
853 */
854 void
state_selecting(struct interface_info * ifi)855 state_selecting(struct interface_info *ifi)
856 {
857 cancel_timeout(ifi);
858
859 if (ifi->offer == NULL) {
860 state_panic(ifi);
861 return;
862 }
863
864 ifi->state = S_REQUESTING;
865
866 /* If it was a BOOTREPLY, we can just take the lease right now. */
867 if (BOOTP_LEASE(ifi->offer)) {
868 bind_lease(ifi);
869 return;
870 }
871
872 ifi->destination.s_addr = INADDR_BROADCAST;
873 clock_gettime(CLOCK_MONOTONIC, &ifi->first_sending);
874 ifi->interval = 0;
875
876 /*
877 * Make a DHCPREQUEST packet from the lease we picked. Keep
878 * the current xid, as all offers should have had the same
879 * one.
880 */
881 make_request(ifi, ifi->offer);
882
883 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
884 free_client_lease(ifi->offer);
885 ifi->offer = NULL;
886 free(ifi->offer_src);
887 ifi->offer_src = NULL;
888
889 send_request(ifi);
890 }
891
892 void
dhcpoffer(struct interface_info * ifi,struct option_data * options,const char * src)893 dhcpoffer(struct interface_info *ifi, struct option_data *options,
894 const char *src)
895 {
896 if (ifi->state != S_SELECTING) {
897 log_debug("%s: unexpected DHCPOFFER from %s - state #%d",
898 log_procname, src, ifi->state);
899 return;
900 }
901
902 log_debug("%s: DHCPOFFER from %s", log_procname, src);
903 process_offer(ifi, options, src);
904 }
905
906 void
bootreply(struct interface_info * ifi,struct option_data * options,const char * src)907 bootreply(struct interface_info *ifi, struct option_data *options,
908 const char *src)
909 {
910 if (ifi->state != S_SELECTING) {
911 log_debug("%s: unexpected BOOTREPLY from %s - state #%d",
912 log_procname, src, ifi->state);
913 return;
914 }
915
916 log_debug("%s: BOOTREPLY from %s", log_procname, src);
917 process_offer(ifi, options, src);
918 }
919
920 void
process_offer(struct interface_info * ifi,struct option_data * options,const char * src)921 process_offer(struct interface_info *ifi, struct option_data *options,
922 const char *src)
923 {
924 const struct timespec select_intvl = {config->select_interval, 0};
925 struct timespec now;
926 struct client_lease *lease;
927
928 clock_gettime(CLOCK_MONOTONIC, &now);
929
930 lease = packet_to_lease(ifi, options);
931 if (lease != NULL) {
932 if (ifi->offer == NULL) {
933 ifi->offer = lease;
934 free(ifi->offer_src);
935 ifi->offer_src = strdup(src); /* NULL is OK */
936 timespecadd(&now, &select_intvl, &ifi->select_timeout);
937 if (timespeccmp(&ifi->select_timeout,
938 &ifi->offer_timeout, >))
939 ifi->select_timeout = ifi->offer_timeout;
940 } else if (lease->address.s_addr ==
941 ifi->offer->address.s_addr) {
942 /* Decline duplicate offers. */
943 } else if (lease->address.s_addr ==
944 ifi->requested_address.s_addr) {
945 free_client_lease(ifi->offer);
946 ifi->offer = lease;
947 free(ifi->offer_src);
948 ifi->offer_src = strdup(src); /* NULL is OK */
949 }
950
951 if (ifi->offer != lease) {
952 make_decline(ifi, lease);
953 send_decline(ifi);
954 free_client_lease(lease);
955 } else if (ifi->offer->address.s_addr ==
956 ifi->requested_address.s_addr) {
957 ifi->select_timeout = now;
958 }
959 }
960
961 if (timespeccmp(&now, &ifi->select_timeout, >=))
962 state_selecting(ifi);
963 else {
964 ifi->timeout = ifi->select_timeout;
965 ifi->timeout_func = state_selecting;
966 }
967 }
968
969 void
dhcpack(struct interface_info * ifi,struct option_data * options,const char * src)970 dhcpack(struct interface_info *ifi, struct option_data *options,
971 const char *src)
972 {
973 struct client_lease *lease;
974
975 if (ifi->state != S_REBOOTING &&
976 ifi->state != S_REQUESTING &&
977 ifi->state != S_RENEWING) {
978 log_debug("%s: unexpected DHCPACK from %s - state #%d",
979 log_procname, src, ifi->state);
980 return;
981 }
982
983 log_debug("%s: DHCPACK", log_procname);
984
985 lease = packet_to_lease(ifi, options);
986 if (lease == NULL) {
987 ifi->state = S_INIT;
988 state_init(ifi);
989 return;
990 }
991
992 ifi->offer = lease;
993 ifi->offer_src = strdup(src); /* NULL is OK */
994 memcpy(ifi->offer->ssid, ifi->ssid, sizeof(ifi->offer->ssid));
995 ifi->offer->ssid_len = ifi->ssid_len;
996
997 /* Stop resending DHCPREQUEST. */
998 cancel_timeout(ifi);
999
1000 bind_lease(ifi);
1001 }
1002
1003 void
dhcpnak(struct interface_info * ifi,const char * src)1004 dhcpnak(struct interface_info *ifi, const char *src)
1005 {
1006 struct client_lease *ll, *pl;
1007
1008 if (ifi->state != S_REBOOTING &&
1009 ifi->state != S_REQUESTING &&
1010 ifi->state != S_RENEWING) {
1011 log_debug("%s: unexpected DHCPNAK from %s - state #%d",
1012 log_procname, src, ifi->state);
1013 return;
1014 }
1015
1016 log_debug("%s: DHCPNAK", log_procname);
1017
1018 /* Remove the NAK'd address from the database. */
1019 TAILQ_FOREACH_SAFE(ll, &ifi->lease_db, next, pl) {
1020 if (ifi->ssid_len == ll->ssid_len &&
1021 memcmp(ifi->ssid, ll->ssid, ll->ssid_len) == 0 &&
1022 ll->address.s_addr == ifi->requested_address.s_addr) {
1023 if (ll == ifi->active) {
1024 tell_unwind(NULL, ifi->flags);
1025 free(ifi->unwind_info);
1026 ifi->unwind_info = NULL;
1027 revoke_proposal(ifi->configured);
1028 free(ifi->configured);
1029 ifi->configured = NULL;
1030 ifi->active = NULL;
1031 }
1032 TAILQ_REMOVE(&ifi->lease_db, ll, next);
1033 free_client_lease(ll);
1034 write_lease_db(ifi);
1035 }
1036 }
1037
1038 /* Stop sending DHCPREQUEST packets. */
1039 cancel_timeout(ifi);
1040
1041 ifi->state = S_INIT;
1042 state_init(ifi);
1043 }
1044
1045 void
bind_lease(struct interface_info * ifi)1046 bind_lease(struct interface_info *ifi)
1047 {
1048 struct timespec now;
1049 struct client_lease *lease, *pl, *ll;
1050 struct proposal *effective_proposal = NULL;
1051 struct unwind_info *unwind_info;
1052 char *msg = NULL;
1053 int rslt, seen;
1054
1055 tick_msg("lease", TICK_SUCCESS);
1056 clock_gettime(CLOCK_MONOTONIC, &now);
1057
1058 lease = apply_defaults(ifi->offer);
1059 get_lease_timeouts(ifi, lease);
1060
1061 /* Replace the old active lease with the accepted offer. */
1062 ifi->active = ifi->offer;
1063 ifi->offer = NULL;
1064
1065 /*
1066 * Supply unwind with updated info.
1067 */
1068 unwind_info = lease_as_unwind_info(ifi->active);
1069 if (ifi->unwind_info == NULL && unwind_info != NULL) {
1070 ifi->unwind_info = unwind_info;
1071 tell_unwind(ifi->unwind_info, ifi->flags);
1072 } else if (ifi->unwind_info != NULL && unwind_info == NULL) {
1073 tell_unwind(NULL, ifi->flags);
1074 free(ifi->unwind_info);
1075 ifi->unwind_info = NULL;
1076 } else if (ifi->unwind_info != NULL && unwind_info != NULL) {
1077 if (memcmp(ifi->unwind_info, unwind_info,
1078 sizeof(*ifi->unwind_info)) != 0) {
1079 tell_unwind(NULL, ifi->flags);
1080 free(ifi->unwind_info);
1081 ifi->unwind_info = unwind_info;
1082 tell_unwind(ifi->unwind_info, ifi->flags);
1083 }
1084 }
1085
1086 effective_proposal = lease_as_proposal(lease);
1087 if (ifi->configured != NULL) {
1088 if (memcmp(ifi->configured, effective_proposal,
1089 sizeof(*ifi->configured)) == 0)
1090 goto newlease;
1091 }
1092 free(ifi->configured);
1093 ifi->configured = effective_proposal;
1094 effective_proposal = NULL;
1095
1096 propose(ifi->configured);
1097 rslt = asprintf(&msg, "%s lease accepted from %s",
1098 inet_ntoa(ifi->active->address),
1099 (ifi->offer_src == NULL) ? "<unknown>" : ifi->offer_src);
1100 if (rslt == -1)
1101 fatal("bind msg");
1102
1103 newlease:
1104 seen = 0;
1105 TAILQ_FOREACH_SAFE(ll, &ifi->lease_db, next, pl) {
1106 if (ifi->ssid_len != ll->ssid_len ||
1107 memcmp(ifi->ssid, ll->ssid, ll->ssid_len) != 0)
1108 continue;
1109 if (ifi->active == ll)
1110 seen = 1;
1111 else if (ll->address.s_addr == ifi->active->address.s_addr) {
1112 TAILQ_REMOVE(&ifi->lease_db, ll, next);
1113 free_client_lease(ll);
1114 }
1115 }
1116 if (seen == 0) {
1117 if (ifi->active->epoch == 0)
1118 time(&ifi->active->epoch);
1119 TAILQ_INSERT_HEAD(&ifi->lease_db, ifi->active, next);
1120 }
1121
1122 /*
1123 * Write out updated information before going daemon.
1124 *
1125 * Some scripts (e.g. the installer in autoinstall mode) assume that
1126 * the bind process is complete and all related information is in
1127 * place when dhclient(8) goes daemon.
1128 */
1129 write_lease_db(ifi);
1130
1131 free_client_lease(lease);
1132 free(effective_proposal);
1133 free(ifi->offer_src);
1134 ifi->offer_src = NULL;
1135
1136 if (msg != NULL) {
1137 if ((cmd_opts & OPT_FOREGROUND) != 0) {
1138 /* log msg on console only. */
1139 ;
1140 } else if (isatty(STDERR_FILENO) != 0) {
1141 /*
1142 * log msg to console and then go_daemon() so it is
1143 * logged again, this time to /var/log/daemon.
1144 */
1145 log_info("%s: %s", log_procname, msg);
1146 go_daemon();
1147 }
1148 log_info("%s: %s", log_procname, msg);
1149 free(msg);
1150 }
1151
1152 ifi->state = S_BOUND;
1153 go_daemon();
1154
1155 /*
1156 * Set timeout to start the renewal process.
1157 *
1158 * If the renewal time is in the past, the lease is from the
1159 * leaseDB. Rather than immediately trying to contact a server,
1160 * pause the configured time between attempts.
1161 */
1162 if (timespeccmp(&now, &ifi->renew, >=))
1163 set_timeout(ifi, config->retry_interval, state_bound);
1164 else {
1165 ifi->timeout = ifi->renew;
1166 ifi->timeout_func = state_bound;
1167 }
1168 }
1169
1170 /*
1171 * Called when we've successfully bound to a particular lease, but the renewal
1172 * time on that lease has expired. We are expected to unicast a DHCPREQUEST to
1173 * the server that gave us our original lease.
1174 */
1175 void
state_bound(struct interface_info * ifi)1176 state_bound(struct interface_info *ifi)
1177 {
1178 struct option_data *opt;
1179 struct in_addr *dest;
1180
1181 ifi->xid = arc4random();
1182 make_request(ifi, ifi->active);
1183
1184 dest = &ifi->destination;
1185 opt = &ifi->active->options[DHO_DHCP_SERVER_IDENTIFIER];
1186
1187 if (opt->len == sizeof(*dest))
1188 dest->s_addr = ((struct in_addr *)opt->data)->s_addr;
1189 else
1190 dest->s_addr = INADDR_BROADCAST;
1191
1192 clock_gettime(CLOCK_MONOTONIC, &ifi->first_sending);
1193 ifi->interval = 0;
1194 ifi->state = S_RENEWING;
1195
1196 send_request(ifi);
1197 }
1198
1199 int
addressinuse(char * name,struct in_addr address,char * ifname)1200 addressinuse(char *name, struct in_addr address, char *ifname)
1201 {
1202 struct ifaddrs *ifap, *ifa;
1203 struct sockaddr_in *sin;
1204 int used = 0;
1205
1206 if (getifaddrs(&ifap) != 0) {
1207 log_warn("%s: getifaddrs", log_procname);
1208 return 0;
1209 }
1210
1211 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1212 if (ifa->ifa_addr == NULL ||
1213 ifa->ifa_addr->sa_family != AF_INET)
1214 continue;
1215
1216 sin = (struct sockaddr_in *)ifa->ifa_addr;
1217 if (memcmp(&address, &sin->sin_addr, sizeof(address)) == 0) {
1218 strlcpy(ifname, ifa->ifa_name, IF_NAMESIZE);
1219 used = 1;
1220 if (strncmp(ifname, name, IF_NAMESIZE) != 0)
1221 break;
1222 }
1223 }
1224
1225 freeifaddrs(ifap);
1226 return used;
1227 }
1228
1229 /*
1230 * Allocate a client_lease structure and initialize it from the
1231 * parameters in the received packet.
1232 *
1233 * Return NULL and decline the lease if a valid lease cannot be
1234 * constructed.
1235 */
1236 struct client_lease *
packet_to_lease(struct interface_info * ifi,struct option_data * options)1237 packet_to_lease(struct interface_info *ifi, struct option_data *options)
1238 {
1239 char ifname[IF_NAMESIZE];
1240 struct dhcp_packet *packet = &ifi->recv_packet;
1241 struct client_lease *lease;
1242 char *pretty, *name;
1243 int i;
1244
1245 lease = calloc(1, sizeof(*lease));
1246 if (lease == NULL) {
1247 log_warn("%s: lease", log_procname);
1248 return NULL; /* Can't even DECLINE. */
1249 }
1250
1251 /* Copy the lease addresses. */
1252 lease->address.s_addr = packet->yiaddr.s_addr;
1253 lease->next_server.s_addr = packet->siaddr.s_addr;
1254
1255 /* Copy the lease options. */
1256 for (i = 0; i < DHO_COUNT; i++) {
1257 if (options[i].len == 0)
1258 continue;
1259 name = code_to_name(i);
1260 if (i == DHO_DOMAIN_SEARCH) {
1261 /* Replace RFC 1035 data with a string. */
1262 pretty = rfc1035_as_string(options[i].data,
1263 options[i].len);
1264 free(options[i].data);
1265 options[i].data = strdup(pretty);
1266 if (options[i].data == NULL)
1267 fatal("RFC1035 string");
1268 options[i].len = strlen(options[i].data);
1269 } else
1270 pretty = pretty_print_option(i, &options[i], 0);
1271 if (strlen(pretty) == 0)
1272 continue;
1273 switch (i) {
1274 case DHO_DOMAIN_SEARCH:
1275 case DHO_DOMAIN_NAME:
1276 /*
1277 * Allow deviant but historically blessed
1278 * practice of supplying multiple domain names
1279 * with DHO_DOMAIN_NAME. Thus allowing multiple
1280 * entries in the resolv.conf 'search' statement.
1281 */
1282 if (res_hnok_list(pretty) == 0) {
1283 log_debug("%s: invalid host name in %s",
1284 log_procname, name);
1285 continue;
1286 }
1287 break;
1288 case DHO_HOST_NAME:
1289 case DHO_NIS_DOMAIN:
1290 if (res_hnok(pretty) == 0) {
1291 log_debug("%s: invalid host name in %s",
1292 log_procname, name);
1293 continue;
1294 }
1295 break;
1296 default:
1297 break;
1298 }
1299 lease->options[i] = options[i];
1300 options[i].data = NULL;
1301 options[i].len = 0;
1302 }
1303
1304 /*
1305 * If this lease doesn't supply a required parameter, decline it.
1306 */
1307 for (i = 0; i < config->required_option_count; i++) {
1308 if (lease->options[config->required_options[i]].len == 0) {
1309 name = code_to_name(config->required_options[i]);
1310 log_warnx("%s: %s required but missing", log_procname,
1311 name);
1312 goto decline;
1313 }
1314 }
1315
1316 /*
1317 * If this lease is trying to sell us an address we are already
1318 * using, decline it.
1319 */
1320 memset(ifname, 0, sizeof(ifname));
1321 if (addressinuse(ifi->name, lease->address, ifname) != 0 &&
1322 strncmp(ifname, ifi->name, IF_NAMESIZE) != 0) {
1323 log_warnx("%s: %s already configured on %s", log_procname,
1324 inet_ntoa(lease->address), ifname);
1325 goto decline;
1326 }
1327
1328 /* If the server name was filled out, copy it. */
1329 if ((lease->options[DHO_DHCP_OPTION_OVERLOAD].len == 0 ||
1330 (lease->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2) == 0) &&
1331 packet->sname[0]) {
1332 lease->server_name = calloc(1, DHCP_SNAME_LEN + 1);
1333 if (lease->server_name == NULL) {
1334 log_warn("%s: SNAME", log_procname);
1335 goto decline;
1336 }
1337 memcpy(lease->server_name, packet->sname, DHCP_SNAME_LEN);
1338 if (res_hnok(lease->server_name) == 0) {
1339 log_debug("%s: invalid host name in SNAME ignored",
1340 log_procname);
1341 free(lease->server_name);
1342 lease->server_name = NULL;
1343 }
1344 }
1345
1346 /* If the file name was filled out, copy it. */
1347 if ((lease->options[DHO_DHCP_OPTION_OVERLOAD].len == 0 ||
1348 (lease->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1) == 0) &&
1349 packet->file[0]) {
1350 /* Don't count on the NUL terminator. */
1351 lease->filename = malloc(DHCP_FILE_LEN + 1);
1352 if (lease->filename == NULL) {
1353 log_warn("%s: filename", log_procname);
1354 goto decline;
1355 }
1356 memcpy(lease->filename, packet->file, DHCP_FILE_LEN);
1357 lease->filename[DHCP_FILE_LEN] = '\0';
1358 }
1359
1360 /*
1361 * Record the client identifier used to obtain the lease. We already
1362 * checked that the packet client identifier is absent (RFC 2131) or
1363 * matches what we sent (RFC 6842),
1364 */
1365 i = DHO_DHCP_CLIENT_IDENTIFIER;
1366 if (lease->options[i].len == 0 && config->send_options[i].len != 0) {
1367 lease->options[i].len = config->send_options[i].len;
1368 lease->options[i].data = malloc(lease->options[i].len);
1369 if (lease->options[i].data == NULL)
1370 fatal("lease client-identifier");
1371 memcpy(lease->options[i].data, config->send_options[i].data,
1372 lease->options[i].len);
1373 }
1374
1375 time(&lease->epoch);
1376 return lease;
1377
1378 decline:
1379 make_decline(ifi, lease);
1380 send_decline(ifi);
1381 free_client_lease(lease);
1382 return NULL;
1383 }
1384
1385 void
set_interval(struct interface_info * ifi,struct timespec * now)1386 set_interval(struct interface_info *ifi, struct timespec *now)
1387 {
1388 struct timespec interval;
1389
1390 if (timespeccmp(now, &ifi->timeout, >))
1391 ifi->interval = 1;
1392 else {
1393 timespecsub(&ifi->timeout, now, &interval);
1394 if (interval.tv_sec == 0 || interval.tv_nsec > 500000000LL)
1395 interval.tv_sec++;
1396 ifi->interval = interval.tv_sec;
1397 }
1398 }
1399
1400 void
set_resend_timeout(struct interface_info * ifi,struct timespec * now,void (* where)(struct interface_info *))1401 set_resend_timeout(struct interface_info *ifi, struct timespec *now,
1402 void (*where)(struct interface_info *))
1403 {
1404 const struct timespec reboot_intvl = {config->reboot_interval, 0};
1405 const struct timespec initial_intvl = {config->initial_interval, 0};
1406 const struct timespec cutoff_intvl = {config->backoff_cutoff, 0};
1407 const struct timespec onesecond = {1, 0};
1408 struct timespec interval, when;
1409
1410 if (timespeccmp(now, &ifi->link_timeout, <))
1411 interval = onesecond;
1412 else if (ifi->interval == 0) {
1413 if (ifi->state == S_REBOOTING)
1414 interval = reboot_intvl;
1415 else
1416 interval = initial_intvl;
1417 } else {
1418 timespecclear(&interval);
1419 interval.tv_sec = ifi->interval + arc4random_uniform(2 *
1420 ifi->interval);
1421 }
1422 if (timespeccmp(&interval, &onesecond, <))
1423 interval = onesecond;
1424 else if (timespeccmp(&interval, &cutoff_intvl, >))
1425 interval = cutoff_intvl;
1426
1427 timespecadd(now, &interval, &when);
1428 switch (ifi->state) {
1429 case S_REBOOTING:
1430 case S_RENEWING:
1431 if (timespeccmp(&when, &ifi->expiry, >))
1432 when = ifi->expiry;
1433 break;
1434 case S_SELECTING:
1435 if (timespeccmp(&when, &ifi->select_timeout, >))
1436 when = ifi->select_timeout;
1437 break;
1438 case S_REQUESTING:
1439 if (timespeccmp(&when, &ifi->offer_timeout, >))
1440 when = ifi->offer_timeout;
1441 break;
1442 default:
1443 break;
1444 }
1445
1446 ifi->timeout = when;
1447 ifi->timeout_func = where;
1448 }
1449
1450 void
set_secs(struct interface_info * ifi,struct timespec * now)1451 set_secs(struct interface_info *ifi, struct timespec *now)
1452 {
1453 struct timespec interval;
1454
1455 if (ifi->state != S_REQUESTING) {
1456 /* Update the number of seconds since we started sending. */
1457 timespecsub(now, &ifi->first_sending, &interval);
1458 if (interval.tv_nsec > 500000000LL)
1459 interval.tv_sec++;
1460 if (interval.tv_sec > UINT16_MAX)
1461 ifi->secs = UINT16_MAX;
1462 else
1463 ifi->secs = interval.tv_sec;
1464 }
1465
1466 ifi->sent_packet.secs = htons(ifi->secs);
1467 }
1468
1469 /*
1470 * Send out a DHCPDISCOVER packet, and set a timeout to send out another
1471 * one after the right interval has expired. If we don't get an offer by
1472 * the time we reach the panic interval, call the panic function.
1473 */
1474 void
send_discover(struct interface_info * ifi)1475 send_discover(struct interface_info *ifi)
1476 {
1477 struct timespec now;
1478 ssize_t rslt;
1479
1480 clock_gettime(CLOCK_MONOTONIC, &now);
1481 if (timespeccmp(&now, &ifi->offer_timeout, >=)) {
1482 state_panic(ifi);
1483 return;
1484 }
1485
1486 set_resend_timeout(ifi, &now, send_discover);
1487 set_interval(ifi, &now);
1488 set_secs(ifi, &now);
1489
1490 rslt = send_packet(ifi, inaddr_any, inaddr_broadcast, "DHCPDISCOVER");
1491 if (rslt != -1)
1492 log_debug("%s: DHCPDISCOVER %s", log_procname,
1493 (ifi->requested_address.s_addr == INADDR_ANY) ? "" :
1494 inet_ntoa(ifi->requested_address));
1495
1496 tick_msg("lease", TICK_WAIT);
1497 }
1498
1499 /*
1500 * Called if we haven't received any offers in a preset amount of time. When
1501 * this happens, we try to use existing leases that haven't yet expired.
1502 *
1503 * If LINK_STATE_UNKNOWN, do NOT use recorded leases.
1504 */
1505 void
state_panic(struct interface_info * ifi)1506 state_panic(struct interface_info *ifi)
1507 {
1508 log_debug("%s: no acceptable DHCPOFFERS received", log_procname);
1509
1510 if (ifi->link_state >= LINK_STATE_UP) {
1511 ifi->offer = get_recorded_lease(ifi);
1512 if (ifi->offer != NULL) {
1513 ifi->state = S_REQUESTING;
1514 ifi->offer_src = strdup(path_lease_db); /* NULL is OK. */
1515 bind_lease(ifi);
1516 return;
1517 }
1518 }
1519
1520 /*
1521 * No leases were available, or what was available didn't work
1522 */
1523 log_debug("%s: no working leases in persistent database - sleeping",
1524 log_procname);
1525 ifi->state = S_INIT;
1526 set_timeout(ifi, config->retry_interval, state_init);
1527 tick_msg("lease", TICK_DAEMON);
1528 }
1529
1530 void
send_request(struct interface_info * ifi)1531 send_request(struct interface_info *ifi)
1532 {
1533 struct sockaddr_in destination;
1534 struct in_addr from;
1535 struct timespec now;
1536 ssize_t rslt;
1537 char *addr;
1538
1539 cancel_timeout(ifi);
1540 clock_gettime(CLOCK_MONOTONIC, &now);
1541
1542 switch (ifi->state) {
1543 case S_REBOOTING:
1544 if (timespeccmp(&now, &ifi->reboot_timeout, >=))
1545 ifi->state = S_INIT;
1546 else {
1547 destination.sin_addr.s_addr = INADDR_BROADCAST;
1548 if (ifi->active == NULL)
1549 from.s_addr = INADDR_ANY;
1550 else
1551 from.s_addr = ifi->active->address.s_addr;
1552 }
1553 break;
1554 case S_RENEWING:
1555 if (timespeccmp(&now, &ifi->expiry, >=))
1556 ifi->state = S_INIT;
1557 else {
1558 if (timespeccmp(&now, &ifi->rebind, >=))
1559 destination.sin_addr.s_addr = INADDR_BROADCAST;
1560 else
1561 destination.sin_addr.s_addr = ifi->destination.s_addr;
1562 if (ifi->active == NULL)
1563 from.s_addr = INADDR_ANY;
1564 else
1565 from.s_addr = ifi->active->address.s_addr;
1566 }
1567 break;
1568 case S_REQUESTING:
1569 if (timespeccmp(&now, &ifi->offer_timeout, >=))
1570 ifi->state = S_INIT;
1571 else {
1572 destination.sin_addr.s_addr = INADDR_BROADCAST;
1573 from.s_addr = INADDR_ANY;
1574 }
1575 break;
1576 default:
1577 ifi->state = S_INIT;
1578 break;
1579 }
1580
1581 if (ifi->state == S_INIT) {
1582 /* Something has gone wrong. Start over. */
1583 state_init(ifi);
1584 return;
1585 }
1586
1587 set_resend_timeout(ifi, &now, send_request);
1588 set_interval(ifi, &now);
1589 set_secs(ifi, &now);
1590
1591 rslt = send_packet(ifi, from, destination.sin_addr, "DHCPREQUEST");
1592 if (rslt != -1 && log_getverbose()) {
1593 addr = strdup(inet_ntoa(ifi->requested_address));
1594 if (addr == NULL)
1595 fatal("strdup(ifi->requested_address)");
1596 if (destination.sin_addr.s_addr == INADDR_BROADCAST)
1597 log_debug("%s: DHCPREQUEST %s", log_procname, addr);
1598 else
1599 log_debug("%s: DHCPREQUEST %s from %s", log_procname,
1600 addr, inet_ntoa(destination.sin_addr));
1601 free(addr);
1602 }
1603
1604 tick_msg("lease", TICK_WAIT);
1605 }
1606
1607 void
send_decline(struct interface_info * ifi)1608 send_decline(struct interface_info *ifi)
1609 {
1610 ssize_t rslt;
1611
1612 rslt = send_packet(ifi, inaddr_any, inaddr_broadcast, "DHCPDECLINE");
1613 if (rslt != -1)
1614 log_debug("%s: DHCPDECLINE", log_procname);
1615 }
1616
1617 void
send_release(struct interface_info * ifi)1618 send_release(struct interface_info *ifi)
1619 {
1620 ssize_t rslt;
1621
1622 rslt = send_packet(ifi, ifi->configured->address, ifi->destination,
1623 "DHCPRELEASE");
1624 if (rslt != -1)
1625 log_debug("%s: DHCPRELEASE", log_procname);
1626 }
1627
1628 void
make_discover(struct interface_info * ifi,struct client_lease * lease)1629 make_discover(struct interface_info *ifi, struct client_lease *lease)
1630 {
1631 struct option_data options[DHO_COUNT];
1632 struct dhcp_packet *packet = &ifi->sent_packet;
1633 unsigned char discover = DHCPDISCOVER;
1634 int i;
1635
1636 memset(options, 0, sizeof(options));
1637 memset(packet, 0, sizeof(*packet));
1638
1639 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1640 i = DHO_DHCP_MESSAGE_TYPE;
1641 options[i].data = &discover;
1642 options[i].len = sizeof(discover);
1643
1644 /* Request the options we want */
1645 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1646 options[i].data = config->requested_options;
1647 options[i].len = config->requested_option_count;
1648
1649 /* If we had an address, try to get it again. */
1650 if (lease != NULL) {
1651 ifi->requested_address = lease->address;
1652 i = DHO_DHCP_REQUESTED_ADDRESS;
1653 options[i].data = (char *)&lease->address;
1654 options[i].len = sizeof(lease->address);
1655 } else
1656 ifi->requested_address.s_addr = INADDR_ANY;
1657
1658 /* Send any options requested in the config file. */
1659 for (i = 0; i < DHO_COUNT; i++)
1660 if (options[i].data == NULL &&
1661 config->send_options[i].data != NULL) {
1662 options[i].data = config->send_options[i].data;
1663 options[i].len = config->send_options[i].len;
1664 }
1665
1666 /*
1667 * Set up the option buffer to fit in a 576-byte UDP packet, which
1668 * RFC 791 says is the largest packet that *MUST* be accepted
1669 * by any host.
1670 */
1671 i = pack_options(ifi->sent_packet.options, 576 - DHCP_FIXED_LEN,
1672 options);
1673 if (i == -1 || packet->options[i] != DHO_END)
1674 fatalx("options do not fit in DHCPDISCOVER packet");
1675 ifi->sent_packet_length = DHCP_FIXED_NON_UDP+i+1;
1676 if (ifi->sent_packet_length < BOOTP_MIN_LEN)
1677 ifi->sent_packet_length = BOOTP_MIN_LEN;
1678
1679 packet->op = BOOTREQUEST;
1680 packet->htype = HTYPE_ETHER;
1681 packet->hlen = ETHER_ADDR_LEN;
1682 packet->hops = 0;
1683 packet->xid = ifi->xid;
1684 packet->secs = 0; /* filled in by send_discover. */
1685 packet->flags = 0;
1686
1687 packet->ciaddr.s_addr = INADDR_ANY;
1688 packet->yiaddr.s_addr = INADDR_ANY;
1689 packet->siaddr.s_addr = INADDR_ANY;
1690 packet->giaddr.s_addr = INADDR_ANY;
1691
1692 memcpy(&packet->chaddr, ifi->hw_address.ether_addr_octet,
1693 ETHER_ADDR_LEN);
1694 }
1695
1696 void
make_request(struct interface_info * ifi,struct client_lease * lease)1697 make_request(struct interface_info *ifi, struct client_lease *lease)
1698 {
1699 struct option_data options[DHO_COUNT];
1700 struct dhcp_packet *packet = &ifi->sent_packet;
1701 unsigned char request = DHCPREQUEST;
1702 int i;
1703
1704 memset(options, 0, sizeof(options));
1705 memset(packet, 0, sizeof(*packet));
1706
1707 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1708 i = DHO_DHCP_MESSAGE_TYPE;
1709 options[i].data = &request;
1710 options[i].len = sizeof(request);
1711
1712 /* Request the options we want */
1713 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1714 options[i].data = config->requested_options;
1715 options[i].len = config->requested_option_count;
1716
1717 /*
1718 * If we are requesting an address that hasn't yet been assigned
1719 * to us, use the DHCP Requested Address option.
1720 */
1721 if (ifi->state == S_REQUESTING) {
1722 /* Send back the server identifier. */
1723 i = DHO_DHCP_SERVER_IDENTIFIER;
1724 options[i].data = lease->options[i].data;
1725 options[i].len = lease->options[i].len;
1726 }
1727 if (ifi->state == S_REQUESTING ||
1728 ifi->state == S_REBOOTING) {
1729 i = DHO_DHCP_REQUESTED_ADDRESS;
1730 options[i].data = (char *)&lease->address.s_addr;
1731 options[i].len = sizeof(lease->address.s_addr);
1732 }
1733
1734 /* Send any options requested in the config file. */
1735 for (i = 0; i < DHO_COUNT; i++)
1736 if (options[i].data == NULL &&
1737 config->send_options[i].data != NULL) {
1738 options[i].data = config->send_options[i].data;
1739 options[i].len = config->send_options[i].len;
1740 }
1741
1742 /*
1743 * Set up the option buffer to fit in a 576-byte UDP packet, which
1744 * RFC 791 says is the largest packet that *MUST* be accepted
1745 * by any host.
1746 */
1747 i = pack_options(ifi->sent_packet.options, 576 - DHCP_FIXED_LEN,
1748 options);
1749 if (i == -1 || packet->options[i] != DHO_END)
1750 fatalx("options do not fit in DHCPREQUEST packet");
1751 ifi->sent_packet_length = DHCP_FIXED_NON_UDP+i+1;
1752 if (ifi->sent_packet_length < BOOTP_MIN_LEN)
1753 ifi->sent_packet_length = BOOTP_MIN_LEN;
1754
1755 packet->op = BOOTREQUEST;
1756 packet->htype = HTYPE_ETHER;
1757 packet->hlen = ETHER_ADDR_LEN;
1758 packet->hops = 0;
1759 packet->xid = ifi->xid;
1760 packet->secs = 0; /* Filled in by send_request. */
1761 packet->flags = 0;
1762
1763 /*
1764 * If we own the address we're requesting, put it in ciaddr. Otherwise
1765 * set ciaddr to zero.
1766 */
1767 ifi->requested_address = lease->address;
1768 if (ifi->state == S_BOUND ||
1769 ifi->state == S_RENEWING)
1770 packet->ciaddr.s_addr = lease->address.s_addr;
1771 else
1772 packet->ciaddr.s_addr = INADDR_ANY;
1773
1774 packet->yiaddr.s_addr = INADDR_ANY;
1775 packet->siaddr.s_addr = INADDR_ANY;
1776 packet->giaddr.s_addr = INADDR_ANY;
1777
1778 memcpy(&packet->chaddr, ifi->hw_address.ether_addr_octet,
1779 ETHER_ADDR_LEN);
1780 }
1781
1782 void
make_decline(struct interface_info * ifi,struct client_lease * lease)1783 make_decline(struct interface_info *ifi, struct client_lease *lease)
1784 {
1785 struct option_data options[DHO_COUNT];
1786 struct dhcp_packet *packet = &ifi->sent_packet;
1787 unsigned char decline = DHCPDECLINE;
1788 int i;
1789
1790 memset(options, 0, sizeof(options));
1791 memset(packet, 0, sizeof(*packet));
1792
1793 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1794 i = DHO_DHCP_MESSAGE_TYPE;
1795 options[i].data = &decline;
1796 options[i].len = sizeof(decline);
1797
1798 /* Send back the server identifier. */
1799 i = DHO_DHCP_SERVER_IDENTIFIER;
1800 options[i].data = lease->options[i].data;
1801 options[i].len = lease->options[i].len;
1802
1803 /* Send back the address we're declining. */
1804 i = DHO_DHCP_REQUESTED_ADDRESS;
1805 options[i].data = (char *)&lease->address.s_addr;
1806 options[i].len = sizeof(lease->address.s_addr);
1807
1808 /* Send the uid if the user supplied one. */
1809 i = DHO_DHCP_CLIENT_IDENTIFIER;
1810 if (config->send_options[i].len != 0) {
1811 options[i].data = config->send_options[i].data;
1812 options[i].len = config->send_options[i].len;
1813 }
1814
1815 /*
1816 * Set up the option buffer to fit in a 576-byte UDP packet, which
1817 * RFC 791 says is the largest packet that *MUST* be accepted
1818 * by any host.
1819 */
1820 i = pack_options(ifi->sent_packet.options, 576 - DHCP_FIXED_LEN,
1821 options);
1822 if (i == -1 || packet->options[i] != DHO_END)
1823 fatalx("options do not fit in DHCPDECLINE packet");
1824 ifi->sent_packet_length = DHCP_FIXED_NON_UDP+i+1;
1825 if (ifi->sent_packet_length < BOOTP_MIN_LEN)
1826 ifi->sent_packet_length = BOOTP_MIN_LEN;
1827
1828 packet->op = BOOTREQUEST;
1829 packet->htype = HTYPE_ETHER;
1830 packet->hlen = ETHER_ADDR_LEN;
1831 packet->hops = 0;
1832 packet->xid = ifi->xid;
1833 packet->secs = 0;
1834 packet->flags = 0;
1835
1836 /* ciaddr must always be zero. */
1837 packet->ciaddr.s_addr = INADDR_ANY;
1838 packet->yiaddr.s_addr = INADDR_ANY;
1839 packet->siaddr.s_addr = INADDR_ANY;
1840 packet->giaddr.s_addr = INADDR_ANY;
1841
1842 memcpy(&packet->chaddr, ifi->hw_address.ether_addr_octet,
1843 ETHER_ADDR_LEN);
1844 }
1845
1846 void
make_release(struct interface_info * ifi,struct client_lease * lease)1847 make_release(struct interface_info *ifi, struct client_lease *lease)
1848 {
1849 struct option_data options[DHO_COUNT];
1850 struct dhcp_packet *packet = &ifi->sent_packet;
1851 unsigned char release = DHCPRELEASE;
1852 int i;
1853
1854 memset(options, 0, sizeof(options));
1855 memset(packet, 0, sizeof(*packet));
1856
1857 /* Set DHCP_MESSAGE_TYPE to DHCPRELEASE */
1858 i = DHO_DHCP_MESSAGE_TYPE;
1859 options[i].data = &release;
1860 options[i].len = sizeof(release);
1861
1862 /* Send back the server identifier. */
1863 i = DHO_DHCP_SERVER_IDENTIFIER;
1864 options[i].data = lease->options[i].data;
1865 options[i].len = lease->options[i].len;
1866
1867 i = pack_options(ifi->sent_packet.options, 576 - DHCP_FIXED_LEN,
1868 options);
1869 if (i == -1 || packet->options[i] != DHO_END)
1870 fatalx("options do not fit in DHCPRELEASE packet");
1871 ifi->sent_packet_length = DHCP_FIXED_NON_UDP+i+1;
1872 if (ifi->sent_packet_length < BOOTP_MIN_LEN)
1873 ifi->sent_packet_length = BOOTP_MIN_LEN;
1874
1875 packet->op = BOOTREQUEST;
1876 packet->htype = HTYPE_ETHER;
1877 packet->hlen = ETHER_ADDR_LEN;
1878 packet->hops = 0;
1879 packet->xid = ifi->xid;
1880 packet->secs = 0;
1881 packet->flags = 0;
1882
1883 /*
1884 * Note we return the *offered* address. NOT the configured address
1885 * which could have been changed via dhclient.conf. But the packet
1886 * is sent from the *configured* address.
1887 *
1888 * This might easily confuse a server, but if you play with fire
1889 * by modifying the address you are on your own!
1890 */
1891 packet->ciaddr.s_addr = ifi->active->address.s_addr;
1892 packet->yiaddr.s_addr = INADDR_ANY;
1893 packet->siaddr.s_addr = INADDR_ANY;
1894 packet->giaddr.s_addr = INADDR_ANY;
1895
1896 memcpy(&packet->chaddr, ifi->hw_address.ether_addr_octet,
1897 ETHER_ADDR_LEN);
1898 }
1899
1900 void
free_client_lease(struct client_lease * lease)1901 free_client_lease(struct client_lease *lease)
1902 {
1903 int i;
1904
1905 if (lease == NULL)
1906 return;
1907
1908 free(lease->server_name);
1909 free(lease->filename);
1910 for (i = 0; i < DHO_COUNT; i++)
1911 free(lease->options[i].data);
1912
1913 free(lease);
1914 }
1915
1916 void
write_lease_db(struct interface_info * ifi)1917 write_lease_db(struct interface_info *ifi)
1918 {
1919 struct client_lease_tq *lease_db = &ifi->lease_db;
1920 struct client_lease *lp, *pl;
1921 char *leasestr;
1922
1923 TAILQ_FOREACH_SAFE(lp, lease_db, next, pl) {
1924 if (lp != ifi->active && lease_expiry(lp) == 0) {
1925 TAILQ_REMOVE(lease_db, lp, next);
1926 free_client_lease(lp);
1927 }
1928 }
1929
1930 if (leaseFile == NULL)
1931 return;
1932
1933 rewind(leaseFile);
1934
1935 /*
1936 * The leases file is kept in chronological order, with the
1937 * most recently bound lease last. When the file was read
1938 * leases that were not expired were added to the head of the
1939 * TAILQ ifi->leases as they were read. Therefore write out
1940 * the leases in ifi->leases in reverse order to recreate
1941 * the chonological order required.
1942 */
1943 TAILQ_FOREACH_REVERSE(lp, lease_db, client_lease_tq, next) {
1944 leasestr = lease_as_string("lease", lp);
1945 if (leasestr != NULL)
1946 fprintf(leaseFile, "%s", leasestr);
1947 else
1948 log_warnx("%s: cannot make lease into string",
1949 log_procname);
1950 }
1951
1952 fflush(leaseFile);
1953 ftruncate(fileno(leaseFile), ftello(leaseFile));
1954 fsync(fileno(leaseFile));
1955 }
1956
1957 void
append_statement(char * string,size_t sz,char * s1,char * s2)1958 append_statement(char *string, size_t sz, char *s1, char *s2)
1959 {
1960 strlcat(string, s1, sz);
1961 strlcat(string, s2, sz);
1962 strlcat(string, ";\n", sz);
1963 }
1964
1965 struct unwind_info *
lease_as_unwind_info(struct client_lease * lease)1966 lease_as_unwind_info(struct client_lease *lease)
1967 {
1968 struct unwind_info *unwind_info;
1969 struct option_data *opt;
1970 unsigned int servers;
1971
1972 unwind_info = calloc(1, sizeof(*unwind_info));
1973 if (unwind_info == NULL)
1974 fatal("unwind_info");
1975
1976 opt = &lease->options[DHO_DOMAIN_NAME_SERVERS];
1977 if (opt->len != 0) {
1978 servers = opt->len / sizeof(in_addr_t);
1979 if (servers > MAXNS)
1980 servers = MAXNS;
1981 if (servers > 0) {
1982 unwind_info->count = servers;
1983 memcpy(unwind_info->ns, opt->data, servers *
1984 sizeof(in_addr_t));
1985 }
1986 }
1987
1988 if (unwind_info->count == 0) {
1989 free(unwind_info);
1990 unwind_info = NULL;
1991 }
1992
1993 return unwind_info;
1994 }
1995
1996 struct proposal *
lease_as_proposal(struct client_lease * lease)1997 lease_as_proposal(struct client_lease *lease)
1998 {
1999 uint8_t defroute[5]; /* 1 + sizeof(in_addr_t) */
2000 struct option_data fake;
2001 struct option_data *opt;
2002 struct proposal *proposal;
2003 uint8_t *ns, *p, *routes, *domains;
2004 unsigned int routes_len = 0, domains_len = 0, ns_len = 0;
2005 uint16_t mtu;
2006
2007 /* Determine sizes of variable length data. */
2008 opt = NULL;
2009 if (lease->options[DHO_CLASSLESS_STATIC_ROUTES].len != 0) {
2010 opt = &lease->options[DHO_CLASSLESS_STATIC_ROUTES];
2011 } else if (lease->options[DHO_CLASSLESS_MS_STATIC_ROUTES].len != 0) {
2012 opt = &lease->options[DHO_CLASSLESS_MS_STATIC_ROUTES];
2013 } else if (lease->options[DHO_ROUTERS].len != 0) {
2014 /* Fake a classless static default route. */
2015 opt = &lease->options[DHO_ROUTERS];
2016 fake.len = sizeof(defroute);
2017 fake.data = defroute;
2018 fake.data[0] = 0;
2019 memcpy(&fake.data[1], opt->data, sizeof(defroute) - 1);
2020 opt = &fake;
2021 }
2022 if (opt != NULL) {
2023 routes_len = opt->len;
2024 routes = opt->data;
2025 }
2026
2027 opt = NULL;
2028 if (lease->options[DHO_DOMAIN_SEARCH].len != 0)
2029 opt = &lease->options[DHO_DOMAIN_SEARCH];
2030 else if (lease->options[DHO_DOMAIN_NAME].len != 0)
2031 opt = &lease->options[DHO_DOMAIN_NAME];
2032 if (opt != NULL) {
2033 domains_len = opt->len;
2034 domains = opt->data;
2035 }
2036
2037 if (lease->options[DHO_DOMAIN_NAME_SERVERS].len != 0) {
2038 opt = &lease->options[DHO_DOMAIN_NAME_SERVERS];
2039 ns_len = opt->len;
2040 ns = opt->data;
2041 }
2042
2043 /* Allocate proposal. */
2044 proposal = calloc(1, sizeof(*proposal) + routes_len + domains_len +
2045 ns_len);
2046 if (proposal == NULL)
2047 fatal("proposal");
2048
2049 /* Fill in proposal. */
2050 proposal->address = lease->address;
2051
2052 opt = &lease->options[DHO_INTERFACE_MTU];
2053 if (opt->len == sizeof(mtu)) {
2054 memcpy(&mtu, opt->data, sizeof(mtu));
2055 proposal->mtu = ntohs(mtu);
2056 }
2057
2058 opt = &lease->options[DHO_SUBNET_MASK];
2059 if (opt->len == sizeof(proposal->netmask))
2060 memcpy(&proposal->netmask, opt->data, opt->len);
2061
2062 /* Append variable length uint8_t data. */
2063 p = (uint8_t *)proposal + sizeof(struct proposal);
2064 memcpy(p, routes, routes_len);
2065 p += routes_len;
2066 proposal->routes_len = routes_len;
2067 memcpy(p, domains, domains_len);
2068 p += domains_len;
2069 proposal->domains_len = domains_len;
2070 memcpy(p, ns, ns_len);
2071 proposal->ns_len = ns_len;
2072
2073 return proposal;
2074 }
2075
2076 char *
lease_as_string(char * type,struct client_lease * lease)2077 lease_as_string(char *type, struct client_lease *lease)
2078 {
2079 static char string[8192];
2080 char timebuf[27]; /* 6 2017/04/08 05:47:50 UTC; */
2081 struct option_data *opt;
2082 struct tm *tm;
2083 char *buf, *name;
2084 time_t t;
2085 size_t rslt;
2086 int i;
2087
2088 memset(string, 0, sizeof(string));
2089
2090 strlcat(string, type, sizeof(string));
2091 strlcat(string, " {\n", sizeof(string));
2092 strlcat(string, BOOTP_LEASE(lease) ? " bootp;\n" : "", sizeof(string));
2093
2094 append_statement(string, sizeof(string), " fixed-address ",
2095 inet_ntoa(lease->address));
2096 append_statement(string, sizeof(string), " next-server ",
2097 inet_ntoa(lease->next_server));
2098
2099 if (lease->filename != NULL) {
2100 buf = pretty_print_string(lease->filename,
2101 strlen(lease->filename), 1);
2102 if (buf == NULL)
2103 return NULL;
2104 append_statement(string, sizeof(string), " filename ", buf);
2105 }
2106 if (lease->server_name != NULL) {
2107 buf = pretty_print_string(lease->server_name,
2108 strlen(lease->server_name), 1);
2109 if (buf == NULL)
2110 return NULL;
2111 append_statement(string, sizeof(string), " server-name ",
2112 buf);
2113 }
2114 if (lease->ssid_len != 0) {
2115 buf = pretty_print_string(lease->ssid, lease->ssid_len, 1);
2116 if (buf == NULL)
2117 return NULL;
2118 append_statement(string, sizeof(string), " ssid ", buf);
2119 }
2120
2121 for (i = 0; i < DHO_COUNT; i++) {
2122 opt = &lease->options[i];
2123 if (opt->len == 0)
2124 continue;
2125 name = code_to_name(i);
2126
2127 buf = pretty_print_option(i, opt, 1);
2128 if (strlen(buf) == 0)
2129 continue;
2130 strlcat(string, " option ", sizeof(string));
2131 strlcat(string, name, sizeof(string));
2132 append_statement(string, sizeof(string), " ", buf);
2133 }
2134
2135 i = asprintf(&buf, "%lld", (long long)lease->epoch);
2136 if (i == -1)
2137 return NULL;
2138 append_statement(string, sizeof(string), " epoch ", buf);
2139 free(buf);
2140
2141 t = lease->epoch + lease_renewal(lease);
2142 if ((tm = gmtime(&t)) == NULL)
2143 return NULL;
2144 rslt = strftime(timebuf, sizeof(timebuf), DB_TIMEFMT, tm);
2145 if (rslt == 0)
2146 return NULL;
2147 append_statement(string, sizeof(string), " renew ", timebuf);
2148
2149 t = lease->epoch + lease_rebind(lease);
2150 if ((tm = gmtime(&t)) == NULL)
2151 return NULL;
2152 rslt = strftime(timebuf, sizeof(timebuf), DB_TIMEFMT, tm);
2153 if (rslt == 0)
2154 return NULL;
2155 append_statement(string, sizeof(string), " rebind ", timebuf);
2156
2157 t = lease->epoch + lease_expiry(lease);
2158 if ((tm = gmtime(&t)) == NULL)
2159 return NULL;
2160 rslt = strftime(timebuf, sizeof(timebuf), DB_TIMEFMT, tm);
2161 if (rslt == 0)
2162 return NULL;
2163 append_statement(string, sizeof(string), " expire ", timebuf);
2164
2165 rslt = strlcat(string, "}\n", sizeof(string));
2166 if (rslt >= sizeof(string))
2167 return NULL;
2168
2169 return string;
2170 }
2171
2172 void
go_daemon(void)2173 go_daemon(void)
2174 {
2175 static int daemonized = 0;
2176
2177 if ((cmd_opts & OPT_FOREGROUND) != 0 || daemonized != 0)
2178 return;
2179
2180 daemonized = 1;
2181
2182 if (rdaemon(nullfd) == -1)
2183 fatal("daemonize");
2184
2185 /* Stop logging to stderr. */
2186 log_init(0, LOG_DAEMON);
2187 if ((cmd_opts & OPT_VERBOSE) != 0)
2188 log_setverbose(1); /* Show log_debug() messages. */
2189 log_procinit(log_procname);
2190
2191 setproctitle("%s", log_procname);
2192 signal(SIGHUP, SIG_IGN);
2193 signal(SIGPIPE, SIG_IGN);
2194 }
2195
2196 int
rdaemon(int devnull)2197 rdaemon(int devnull)
2198 {
2199 if (devnull == -1) {
2200 errno = EBADF;
2201 return -1;
2202 }
2203 if (fcntl(devnull, F_GETFL) == -1)
2204 return -1;
2205
2206 switch (fork()) {
2207 case -1:
2208 return -1;
2209 case 0:
2210 break;
2211 default:
2212 _exit(0);
2213 }
2214
2215 if (setsid() == -1)
2216 return -1;
2217
2218 (void)dup2(devnull, STDIN_FILENO);
2219 (void)dup2(devnull, STDOUT_FILENO);
2220 (void)dup2(devnull, STDERR_FILENO);
2221 if (devnull > 2)
2222 (void)close(devnull);
2223
2224 return 0;
2225 }
2226
2227 /*
2228 * resolv_conf(5) says a max of DHCP_DOMAIN_SEARCH_CNT domains and total
2229 * length of DHCP_DOMAIN_SEARCH_LEN bytes are acceptable for the 'search'
2230 * statement.
2231 */
2232 int
res_hnok_list(const char * names)2233 res_hnok_list(const char *names)
2234 {
2235 char *dupnames, *hn, *inputstring;
2236 int count;
2237
2238 if (strlen(names) >= DHCP_DOMAIN_SEARCH_LEN)
2239 return 0;
2240
2241 dupnames = inputstring = strdup(names);
2242 if (inputstring == NULL)
2243 fatal("domain name list");
2244
2245 count = 0;
2246 while ((hn = strsep(&inputstring, " \t")) != NULL) {
2247 if (strlen(hn) == 0)
2248 continue;
2249 if (res_hnok(hn) == 0)
2250 break;
2251 count++;
2252 if (count > DHCP_DOMAIN_SEARCH_CNT)
2253 break;
2254 }
2255
2256 free(dupnames);
2257
2258 return count > 0 && count < 7 && hn == NULL;
2259 }
2260
2261 /*
2262 * Decode a byte string encoding a list of domain names as specified in RFC1035
2263 * section 4.1.4.
2264 *
2265 * The result is a string consisting of a blank separated list of domain names.
2266 *
2267 * e.g.
2268 *
2269 * 3:65:6e:67:5:61:70:70:6c:65:3:63:6f:6d:0:9:6d:61:72:6b:65:74:69:6e:67:c0:04
2270 *
2271 * which represents
2272 *
2273 * 3 |'e'|'n'|'g'| 5 |'a'|'p'|'p'|'l'|
2274 * 'e'| 3 |'c'|'o'|'m'| 0 | 9 |'m'|'a'|
2275 * 'r'|'k'|'e'|'t'|'i'|'n'|'g'|xC0|x04|
2276 *
2277 * will be translated to
2278 *
2279 * "eng.apple.com. marketing.apple.com."
2280 */
2281 char *
rfc1035_as_string(unsigned char * src,size_t srclen)2282 rfc1035_as_string(unsigned char *src, size_t srclen)
2283 {
2284 static char search[DHCP_DOMAIN_SEARCH_LEN];
2285 unsigned char name[DHCP_DOMAIN_SEARCH_LEN];
2286 unsigned char *endsrc, *cp;
2287 int len, domains;
2288
2289 memset(search, 0, sizeof(search));
2290
2291 /* Compute expanded length. */
2292 domains = 0;
2293 cp = src;
2294 endsrc = src + srclen;
2295
2296 while (cp < endsrc && domains < DHCP_DOMAIN_SEARCH_CNT) {
2297 len = dn_expand(src, endsrc, cp, name, sizeof(name));
2298 if (len == -1)
2299 goto bad;
2300 cp += len;
2301 if (domains > 0)
2302 strlcat(search, " ", sizeof(search));
2303 strlcat(search, name, sizeof(search));
2304 if (strlcat(search, ".", sizeof(search)) >= sizeof(search))
2305 goto bad;
2306 domains++;
2307 }
2308
2309 return search;
2310
2311 bad:
2312 memset(search, 0, sizeof(search));
2313 return search;
2314 }
2315
2316 void
fork_privchld(struct interface_info * ifi,int fd,int fd2)2317 fork_privchld(struct interface_info *ifi, int fd, int fd2)
2318 {
2319 struct pollfd pfd[1];
2320 struct imsgbuf *priv_ibuf;
2321 ssize_t n;
2322 int ioctlfd, routefd, nfds, rslt;
2323
2324 switch (fork()) {
2325 case -1:
2326 fatal("fork");
2327 break;
2328 case 0:
2329 break;
2330 default:
2331 return;
2332 }
2333
2334 if (chdir("/") == -1)
2335 fatal("chdir(\"/\")");
2336
2337 go_daemon();
2338
2339 free(log_procname);
2340 rslt = asprintf(&log_procname, "%s [priv]", ifi->name);
2341 if (rslt == -1)
2342 fatal("log_procname");
2343 setproctitle("%s", log_procname);
2344 log_procinit(log_procname);
2345
2346 close(fd2);
2347
2348 if ((priv_ibuf = malloc(sizeof(*priv_ibuf))) == NULL)
2349 fatal("priv_ibuf");
2350
2351 imsg_init(priv_ibuf, fd);
2352
2353 if ((ioctlfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
2354 fatal("socket(AF_INET, SOCK_DGRAM)");
2355 if ((routefd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1)
2356 fatal("socket(AF_ROUTE, SOCK_RAW)");
2357
2358 if (unveil(_PATH_RESCONF, "wc") == -1)
2359 fatal("unveil %s", _PATH_RESCONF);
2360 if (unveil("/etc/resolv.conf.tail", "r") == -1)
2361 fatal("unveil /etc/resolve.conf.tail");
2362 if (unveil(NULL, NULL) == -1)
2363 fatal("unveil");
2364
2365 while (quit == 0) {
2366 pfd[0].fd = priv_ibuf->fd;
2367 pfd[0].events = POLLIN;
2368
2369 nfds = ppoll(pfd, 1, NULL, NULL);
2370 if (nfds == -1) {
2371 if (errno == EINTR)
2372 continue;
2373 log_warn("%s: ppoll(priv_ibuf)", log_procname);
2374 break;
2375 }
2376 if ((pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) != 0)
2377 break;
2378 if (nfds == 0 || (pfd[0].revents & POLLIN) == 0)
2379 continue;
2380
2381 if ((n = imsg_read(priv_ibuf)) == -1 && errno != EAGAIN) {
2382 log_warn("%s: imsg_read(priv_ibuf)", log_procname);
2383 break;
2384 }
2385 if (n == 0) {
2386 /* Connection closed - other end should log message. */
2387 break;
2388 }
2389
2390 dispatch_imsg(ifi->name, ifi->rdomain, ioctlfd, routefd,
2391 priv_ibuf);
2392 }
2393 close(routefd);
2394 close(ioctlfd);
2395
2396 imsg_clear(priv_ibuf);
2397 close(fd);
2398
2399 exit(1);
2400 }
2401
2402 struct client_lease *
apply_defaults(struct client_lease * lease)2403 apply_defaults(struct client_lease *lease)
2404 {
2405 struct option_data emptyopt = {0, NULL};
2406 struct client_lease *newlease;
2407 char *fmt;
2408 int i;
2409
2410 newlease = clone_lease(lease);
2411 if (newlease == NULL)
2412 fatalx("unable to clone lease");
2413
2414 if (config->filename != NULL) {
2415 free(newlease->filename);
2416 newlease->filename = strdup(config->filename);
2417 if (newlease->filename == NULL)
2418 fatal("strdup(config->filename)");
2419 }
2420 if (config->server_name != NULL) {
2421 free(newlease->server_name);
2422 newlease->server_name = strdup(config->server_name);
2423 if (newlease->server_name == NULL)
2424 fatal("strdup(config->server_name)");
2425 }
2426 if (config->address.s_addr != INADDR_ANY)
2427 newlease->address.s_addr = config->address.s_addr;
2428 if (config->next_server.s_addr != INADDR_ANY)
2429 newlease->next_server.s_addr = config->next_server.s_addr;
2430
2431 for (i = 0; i < DHO_COUNT; i++) {
2432 fmt = code_to_format(i);
2433 switch (config->default_actions[i]) {
2434 case ACTION_IGNORE:
2435 merge_option_data(fmt, &emptyopt, &emptyopt,
2436 &newlease->options[i]);
2437 break;
2438
2439 case ACTION_SUPERSEDE:
2440 merge_option_data(fmt, &config->defaults[i], &emptyopt,
2441 &newlease->options[i]);
2442 break;
2443
2444 case ACTION_PREPEND:
2445 merge_option_data(fmt, &config->defaults[i],
2446 &lease->options[i], &newlease->options[i]);
2447 break;
2448
2449 case ACTION_APPEND:
2450 merge_option_data(fmt, &lease->options[i],
2451 &config->defaults[i], &newlease->options[i]);
2452 break;
2453
2454 case ACTION_DEFAULT:
2455 if (newlease->options[i].len == 0)
2456 merge_option_data(fmt, &config->defaults[i],
2457 &emptyopt, &newlease->options[i]);
2458 break;
2459
2460 default:
2461 break;
2462 }
2463 }
2464
2465 if (newlease->options[DHO_STATIC_ROUTES].len != 0) {
2466 log_debug("%s: DHO_STATIC_ROUTES (option 33) not supported",
2467 log_procname);
2468 free(newlease->options[DHO_STATIC_ROUTES].data);
2469 newlease->options[DHO_STATIC_ROUTES].data = NULL;
2470 newlease->options[DHO_STATIC_ROUTES].len = 0;
2471 }
2472
2473 /*
2474 * RFC 3442 says client *MUST* ignore DHO_ROUTERS
2475 * when DHO_CLASSLESS_[MS_]_ROUTES present.
2476 */
2477 if ((newlease->options[DHO_CLASSLESS_MS_STATIC_ROUTES].len != 0) ||
2478 (newlease->options[DHO_CLASSLESS_STATIC_ROUTES].len != 0)) {
2479 free(newlease->options[DHO_ROUTERS].data);
2480 newlease->options[DHO_ROUTERS].data = NULL;
2481 newlease->options[DHO_ROUTERS].len = 0;
2482 }
2483
2484 return newlease;
2485 }
2486
2487 struct client_lease *
clone_lease(struct client_lease * oldlease)2488 clone_lease(struct client_lease *oldlease)
2489 {
2490 struct client_lease *newlease;
2491 int i;
2492
2493 newlease = calloc(1, sizeof(*newlease));
2494 if (newlease == NULL)
2495 goto cleanup;
2496
2497 newlease->epoch = oldlease->epoch;
2498 newlease->address = oldlease->address;
2499 newlease->next_server = oldlease->next_server;
2500 memcpy(newlease->ssid, oldlease->ssid, sizeof(newlease->ssid));
2501 newlease->ssid_len = oldlease->ssid_len;
2502
2503 if (oldlease->server_name != NULL) {
2504 newlease->server_name = strdup(oldlease->server_name);
2505 if (newlease->server_name == NULL)
2506 goto cleanup;
2507 }
2508 if (oldlease->filename != NULL) {
2509 newlease->filename = strdup(oldlease->filename);
2510 if (newlease->filename == NULL)
2511 goto cleanup;
2512 }
2513
2514 for (i = 0; i < DHO_COUNT; i++) {
2515 if (oldlease->options[i].len == 0)
2516 continue;
2517 newlease->options[i].len = oldlease->options[i].len;
2518 newlease->options[i].data = calloc(1,
2519 newlease->options[i].len);
2520 if (newlease->options[i].data == NULL)
2521 goto cleanup;
2522 memcpy(newlease->options[i].data, oldlease->options[i].data,
2523 newlease->options[i].len);
2524 }
2525
2526 return newlease;
2527
2528 cleanup:
2529 free_client_lease(newlease);
2530
2531 return NULL;
2532 }
2533
2534 int
autoconf(struct interface_info * ifi)2535 autoconf(struct interface_info *ifi)
2536 {
2537 struct ifreq ifr;
2538 int ioctlfd;
2539
2540 if ((ioctlfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
2541 fatal("socket(AF_INET, SOCK_DGRAM)");
2542
2543 memset(&ifr, 0, sizeof(ifr));
2544 strlcpy(ifr.ifr_name, ifi->name, sizeof(ifr.ifr_name));
2545
2546 if (ioctl(ioctlfd, SIOCGIFXFLAGS, (caddr_t)&ifr) < 0)
2547 fatal("SIOGIFXFLAGS");
2548
2549 close(ioctlfd);
2550
2551 return ifr.ifr_flags & IFXF_AUTOCONF4;
2552 }
2553
2554 int
take_charge(struct interface_info * ifi,int routefd,char * leasespath)2555 take_charge(struct interface_info *ifi, int routefd, char *leasespath)
2556 {
2557 const struct timespec max_timeout = { 9, 0 };
2558 const struct timespec resend_intvl = { 3, 0 };
2559 const struct timespec leasefile_intvl = { 0, 3000000 };
2560 struct timespec now, resend, stop, timeout;
2561 struct pollfd fds[1];
2562 struct rt_msghdr rtm;
2563 int fd, nfds;
2564
2565 clock_gettime(CLOCK_MONOTONIC, &now);
2566 resend = now;
2567 timespecadd(&now, &max_timeout, &stop);
2568
2569 /*
2570 * Send RTM_PROPOSAL with RTF_PROTO3 set.
2571 *
2572 * When it comes back, we're in charge and other dhclients are
2573 * dead processes walking.
2574 */
2575 memset(&rtm, 0, sizeof(rtm));
2576
2577 rtm.rtm_version = RTM_VERSION;
2578 rtm.rtm_type = RTM_PROPOSAL;
2579 rtm.rtm_msglen = sizeof(rtm);
2580 rtm.rtm_tableid = ifi->rdomain;
2581 rtm.rtm_index = ifi->index;
2582 rtm.rtm_priority = RTP_PROPOSAL_DHCLIENT;
2583 rtm.rtm_addrs = 0;
2584 rtm.rtm_flags = RTF_UP | RTF_PROTO3;
2585
2586 for (fd = -1; fd == -1 && quit != TERMINATE;) {
2587 clock_gettime(CLOCK_MONOTONIC, &now);
2588 if (timespeccmp(&now, &stop, >=))
2589 fatalx("failed to take charge");
2590
2591 if ((ifi->flags & IFI_IN_CHARGE) == 0) {
2592 if (timespeccmp(&now, &resend, >=)) {
2593 timespecadd(&resend, &resend_intvl, &resend);
2594 rtm.rtm_seq = ifi->xid = arc4random();
2595 if (write(routefd, &rtm, sizeof(rtm)) == -1)
2596 fatal("write(routefd)");
2597 }
2598 timespecsub(&resend, &now, &timeout);
2599 } else {
2600 /*
2601 * Keep trying to open leasefile in 3ms intervals
2602 * while continuing to process any RTM_* messages
2603 * that come in.
2604 */
2605 timeout = leasefile_intvl;
2606 }
2607
2608 fds[0].fd = routefd;
2609 fds[0].events = POLLIN;
2610 nfds = ppoll(fds, 1, &timeout, NULL);
2611 if (nfds == -1) {
2612 if (errno == EINTR)
2613 continue;
2614 fatal("ppoll(routefd)");
2615 }
2616
2617 if ((fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) != 0)
2618 fatalx("routefd: ERR|HUP|NVAL");
2619 if (nfds == 1 && (fds[0].revents & POLLIN) == POLLIN)
2620 routefd_handler(ifi, routefd);
2621
2622 if (quit != TERMINATE && (ifi->flags & IFI_IN_CHARGE) == IFI_IN_CHARGE) {
2623 fd = open(leasespath, O_NONBLOCK |
2624 O_RDONLY|O_EXLOCK|O_CREAT|O_NOFOLLOW, 0640);
2625 if (fd == -1 && errno != EWOULDBLOCK)
2626 break;
2627 }
2628 }
2629
2630 return fd;
2631 }
2632
2633 struct client_lease *
get_recorded_lease(struct interface_info * ifi)2634 get_recorded_lease(struct interface_info *ifi)
2635 {
2636 char ifname[IF_NAMESIZE];
2637 struct client_lease *lp;
2638 int i;
2639
2640 /* Update on-disk db, which clears out expired leases. */
2641 ifi->active = NULL;
2642 write_lease_db(ifi);
2643
2644 /* Run through the list of leases and see if one can be used. */
2645 i = DHO_DHCP_CLIENT_IDENTIFIER;
2646 TAILQ_FOREACH(lp, &ifi->lease_db, next) {
2647 if (lp->ssid_len != ifi->ssid_len)
2648 continue;
2649 if (memcmp(lp->ssid, ifi->ssid, lp->ssid_len) != 0)
2650 continue;
2651 if ((lp->options[i].len != 0) && ((lp->options[i].len !=
2652 config->send_options[i].len) ||
2653 memcmp(lp->options[i].data, config->send_options[i].data,
2654 lp->options[i].len) != 0))
2655 continue;
2656 if (addressinuse(ifi->name, lp->address, ifname) != 0 &&
2657 strncmp(ifname, ifi->name, IF_NAMESIZE) != 0)
2658 continue;
2659 break;
2660 }
2661
2662 return lp;
2663 }
2664
2665 time_t
lease_expiry(struct client_lease * lease)2666 lease_expiry(struct client_lease *lease)
2667 {
2668 time_t cur_time;
2669 uint32_t expiry;
2670
2671 time(&cur_time);
2672 expiry = 0;
2673 if (lease->options[DHO_DHCP_LEASE_TIME].len == sizeof(expiry)) {
2674 memcpy(&expiry, lease->options[DHO_DHCP_LEASE_TIME].data,
2675 sizeof(expiry));
2676 expiry = ntohl(expiry);
2677 if (expiry < 60)
2678 expiry = 60;
2679 }
2680 expiry = lease->epoch + expiry - cur_time;
2681
2682 return (expiry > 0) ? expiry : 0;
2683 }
2684
2685 time_t
lease_renewal(struct client_lease * lease)2686 lease_renewal(struct client_lease *lease)
2687 {
2688 time_t cur_time, expiry;
2689 uint32_t renewal;
2690
2691 time(&cur_time);
2692 expiry = lease_expiry(lease);
2693
2694 renewal = expiry / 2;
2695 if (lease->options[DHO_DHCP_RENEWAL_TIME].len == sizeof(renewal)) {
2696 memcpy(&renewal, lease->options[DHO_DHCP_RENEWAL_TIME].data,
2697 sizeof(renewal));
2698 renewal = ntohl(renewal);
2699 }
2700 renewal = lease->epoch + renewal - cur_time;
2701
2702 return (renewal > 0) ? renewal : 0;
2703 }
2704
2705 time_t
lease_rebind(struct client_lease * lease)2706 lease_rebind(struct client_lease *lease)
2707 {
2708 time_t cur_time, expiry;
2709 uint32_t rebind;
2710
2711 time(&cur_time);
2712 expiry = lease_expiry(lease);
2713
2714 rebind = (expiry / 8) * 7;
2715 if (lease->options[DHO_DHCP_REBINDING_TIME].len == sizeof(rebind)) {
2716 memcpy(&rebind, lease->options[DHO_DHCP_REBINDING_TIME].data,
2717 sizeof(rebind));
2718 rebind = ntohl(rebind);
2719 }
2720 rebind = lease->epoch + rebind - cur_time;
2721
2722 return (rebind > 0) ? rebind : 0;
2723 }
2724
2725 void
get_lease_timeouts(struct interface_info * ifi,struct client_lease * lease)2726 get_lease_timeouts(struct interface_info *ifi, struct client_lease *lease)
2727 {
2728 struct timespec now, interval;
2729
2730 clock_gettime(CLOCK_MONOTONIC, &now);
2731 timespecclear(&interval);
2732
2733 interval.tv_sec = lease_expiry(lease);
2734 timespecadd(&now, &interval, &ifi->expiry);
2735
2736 interval.tv_sec = lease_rebind(lease);
2737 timespecadd(&now, &interval, &ifi->rebind);
2738
2739 interval.tv_sec = lease_renewal(lease);
2740 timespecadd(&now, &interval, &ifi->renew);
2741
2742 if (timespeccmp(&ifi->rebind, &ifi->expiry, >))
2743 ifi->rebind = ifi->expiry;
2744 if (timespeccmp(&ifi->renew, &ifi->rebind, >))
2745 ifi->renew = ifi->rebind;
2746 }
2747
2748 void
tick_msg(const char * preamble,int action)2749 tick_msg(const char *preamble, int action)
2750 {
2751 const struct timespec grace_intvl = {3, 0};
2752 const struct timespec link_intvl = {config->link_interval, 0};
2753 static struct timespec grace, stop;
2754 struct timespec now;
2755 static int linkup, preamble_sent, sleeping;
2756 int printmsg;
2757
2758 clock_gettime(CLOCK_MONOTONIC, &now);
2759
2760 if (!timespecisset(&stop)) {
2761 preamble_sent = 0;
2762 timespecadd(&now, &link_intvl, &stop);
2763 timespecadd(&now, &grace_intvl, &grace);
2764 return;
2765 }
2766
2767 if (isatty(STDERR_FILENO) == 0 || sleeping == 1)
2768 printmsg = 0; /* Already in the background. */
2769 else if (timespeccmp(&now, &grace, <))
2770 printmsg = 0; /* Wait a bit before speaking. */
2771 else if (linkup && strcmp("link", preamble) == 0)
2772 printmsg = 0; /* One 'got link' is enough for anyone. */
2773 else if (log_getverbose())
2774 printmsg = 0; /* Verbose has sufficent verbiage. */
2775 else
2776 printmsg = 1;
2777
2778 if (timespeccmp(&now, &stop, >=)) {
2779 if (action == TICK_WAIT)
2780 action = TICK_DAEMON;
2781 if (linkup == 0) {
2782 log_debug("%s: link timeout (%lld seconds) expired",
2783 log_procname, (long long)link_intvl.tv_sec);
2784 linkup = 1;
2785 }
2786 }
2787
2788 if (printmsg && preamble_sent == 0) {
2789 fprintf(stderr, "%s: no %s...", log_procname, preamble);
2790 preamble_sent = 1;
2791 }
2792
2793 switch (action) {
2794 case TICK_SUCCESS:
2795 if (printmsg)
2796 fprintf(stderr, "got %s\n", preamble);
2797 preamble_sent = 0;
2798 if (strcmp("link", preamble) == 0) {
2799 linkup = 1;
2800 /* New silent period for "no lease ... got lease". */
2801 timespecadd(&now, &grace_intvl, &grace);
2802 }
2803 break;
2804 case TICK_WAIT:
2805 if (printmsg)
2806 fprintf(stderr, ".");
2807 break;
2808 case TICK_DAEMON:
2809 if (printmsg)
2810 fprintf(stderr, "sleeping\n");
2811 go_daemon();
2812 sleeping = 1; /* OPT_FOREGROUND means isatty() == 1! */
2813 break;
2814 default:
2815 break;
2816 }
2817
2818 if (printmsg)
2819 fflush(stderr);
2820 }
2821
2822 /*
2823 * Release the lease used to configure the interface.
2824 *
2825 * 1) Send DHCPRELEASE.
2826 * 2) Unconfigure address/routes/etc.
2827 * 3) Remove lease from database & write updated DB.
2828 */
2829 void
release_lease(struct interface_info * ifi)2830 release_lease(struct interface_info *ifi)
2831 {
2832 char buf[INET_ADDRSTRLEN];
2833 struct option_data *opt;
2834
2835 if (ifi->configured == NULL || ifi->active == NULL)
2836 return; /* Nothing to release. */
2837 strlcpy(buf, inet_ntoa(ifi->configured->address), sizeof(buf));
2838
2839 opt = &ifi->active->options[DHO_DHCP_SERVER_IDENTIFIER];
2840 if (opt->len == sizeof(in_addr_t))
2841 ifi->destination.s_addr = *(in_addr_t *)opt->data;
2842 else
2843 ifi->destination.s_addr = INADDR_BROADCAST;
2844
2845 ifi->xid = arc4random();
2846 make_release(ifi, ifi->active);
2847 send_release(ifi);
2848
2849 tell_unwind(NULL, ifi->flags);
2850
2851 revoke_proposal(ifi->configured);
2852 imsg_flush(unpriv_ibuf);
2853
2854 TAILQ_REMOVE(&ifi->lease_db, ifi->active, next);
2855 free_client_lease(ifi->active);
2856 ifi->active = NULL;
2857 write_lease_db(ifi);
2858
2859 free(ifi->configured);
2860 ifi->configured = NULL;
2861 free(ifi->unwind_info);
2862 ifi->unwind_info = NULL;
2863
2864 log_warnx("%s: %s RELEASED to %s", log_procname, buf,
2865 inet_ntoa(ifi->destination));
2866 }
2867
2868 void
propose_release(struct interface_info * ifi)2869 propose_release(struct interface_info *ifi)
2870 {
2871 const struct timespec max_timeout = { 3, 0 };
2872 struct timespec now, stop, timeout;
2873 struct pollfd fds[1];
2874 struct rt_msghdr rtm;
2875 int nfds, routefd, rtfilter;
2876
2877 clock_gettime(CLOCK_MONOTONIC, &now);
2878 timespecadd(&now, &max_timeout, &stop);
2879
2880 if ((routefd = socket(AF_ROUTE, SOCK_RAW, AF_INET)) == -1)
2881 fatal("socket(AF_ROUTE, SOCK_RAW)");
2882
2883 rtfilter = ROUTE_FILTER(RTM_PROPOSAL);
2884
2885 if (setsockopt(routefd, AF_ROUTE, ROUTE_MSGFILTER,
2886 &rtfilter, sizeof(rtfilter)) == -1)
2887 fatal("setsockopt(ROUTE_MSGFILTER)");
2888 if (setsockopt(routefd, AF_ROUTE, ROUTE_TABLEFILTER, &ifi->rdomain,
2889 sizeof(ifi->rdomain)) == -1)
2890 fatal("setsockopt(ROUTE_TABLEFILTER)");
2891
2892 memset(&rtm, 0, sizeof(rtm));
2893 rtm.rtm_version = RTM_VERSION;
2894 rtm.rtm_type = RTM_PROPOSAL;
2895 rtm.rtm_msglen = sizeof(rtm);
2896 rtm.rtm_tableid = ifi->rdomain;
2897 rtm.rtm_index = ifi->index;
2898 rtm.rtm_priority = RTP_PROPOSAL_DHCLIENT;
2899 rtm.rtm_addrs = 0;
2900 rtm.rtm_flags = RTF_UP;
2901 rtm.rtm_flags |= RTF_PROTO2;
2902 rtm.rtm_seq = ifi->xid = arc4random();
2903
2904 if (write(routefd, &rtm, sizeof(rtm)) == -1)
2905 fatal("write(routefd)");
2906 log_debug("%s: sent RTM_PROPOSAL to release lease", log_procname);
2907
2908 while (quit == 0) {
2909 clock_gettime(CLOCK_MONOTONIC, &now);
2910 if (timespeccmp(&now, &stop, >=))
2911 break;
2912 timespecsub(&stop, &now, &timeout);
2913 fds[0].fd = routefd;
2914 fds[0].events = POLLIN;
2915 nfds = ppoll(fds, 1, &timeout, NULL);
2916 if (nfds == -1) {
2917 if (errno == EINTR)
2918 continue;
2919 fatal("ppoll(routefd)");
2920 }
2921 if ((fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) != 0)
2922 fatalx("routefd: ERR|HUP|NVAL");
2923 if (nfds == 0 || (fds[0].revents & POLLIN) == 0)
2924 continue;
2925 routefd_handler(ifi, routefd);
2926 }
2927 }
2928