Bug Summary

File:src/sbin/dhclient/dhclient.c
Warning:line 2060, column 2
2nd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dhclient.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/dhclient/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/dhclient/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/dhclient/dhclient.c
1/* $OpenBSD: dhclient.c,v 1.726 2021/10/24 21:24:21 deraadt 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(*__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
98char *path_dhclient_conf;
99char *path_lease_db;
100char *log_procname;
101
102int nullfd = -1;
103int cmd_opts;
104int quit;
105
106const struct in_addr inaddr_any = { INADDR_ANY((u_int32_t)(0x00000000)) };
107const struct in_addr inaddr_broadcast = { INADDR_BROADCAST((u_int32_t)(0xffffffff)) };
108
109struct client_config *config;
110struct imsgbuf *unpriv_ibuf;
111
112void usage(void);
113int res_hnok_list(const char *);
114int addressinuse(char *, struct in_addr, char *);
115
116void fork_privchld(struct interface_info *, int, int);
117void get_name(struct interface_info *, int, char *);
118void get_ssid(struct interface_info *, int);
119void get_sockets(struct interface_info *);
120int get_routefd(int);
121void set_iff_up(struct interface_info *, int);
122void set_user(char *);
123int get_ifa_family(char *, int);
124struct ifaddrs *get_link_ifa(const char *, struct ifaddrs *);
125void interface_state(struct interface_info *);
126struct interface_info *initialize_interface(char *, int);
127void tick_msg(const char *, int);
128void rtm_dispatch(struct interface_info *, struct rt_msghdr *);
129
130struct client_lease *apply_defaults(struct client_lease *);
131struct client_lease *clone_lease(struct client_lease *);
132
133void state_reboot(struct interface_info *);
134void state_init(struct interface_info *);
135void state_selecting(struct interface_info *);
136void state_bound(struct interface_info *);
137void state_panic(struct interface_info *);
138
139void set_interval(struct interface_info *, struct timespec *);
140void set_resend_timeout(struct interface_info *, struct timespec *,
141 void (*where)(struct interface_info *));
142void set_secs(struct interface_info *, struct timespec *);
143
144void send_discover(struct interface_info *);
145void send_request(struct interface_info *);
146void send_decline(struct interface_info *);
147void send_release(struct interface_info *);
148
149void process_offer(struct interface_info *, struct option_data *,
150 const char *);
151void bind_lease(struct interface_info *);
152
153void make_discover(struct interface_info *, struct client_lease *);
154void make_request(struct interface_info *, struct client_lease *);
155void make_decline(struct interface_info *, struct client_lease *);
156void make_release(struct interface_info *, struct client_lease *);
157
158void release_lease(struct interface_info *);
159void propose_release(struct interface_info *);
160
161void write_lease_db(struct interface_info *);
162char *lease_as_string(char *, struct client_lease *);
163struct proposal *lease_as_proposal(struct client_lease *);
164struct unwind_info *lease_as_unwind_info(struct client_lease *);
165void append_statement(char *, size_t, char *, char *);
166time_t lease_expiry(struct client_lease *);
167time_t lease_renewal(struct client_lease *);
168time_t lease_rebind(struct client_lease *);
169void get_lease_timeouts(struct interface_info *, struct client_lease *);
170
171struct client_lease *packet_to_lease(struct interface_info *,
172 struct option_data *);
173void go_daemon(void);
174int rdaemon(int);
175int take_charge(struct interface_info *, int, char *);
176int autoconf(struct interface_info *);
177struct client_lease *get_recorded_lease(struct interface_info *);
178
179#define ROUNDUP(a)((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof
(long))
\
180 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
181#define ADVANCE(x, n)(x += (((n)->sa_len) > 0 ? (1 + ((((n)->sa_len) - 1)
| (sizeof(long) - 1))) : sizeof(long)))
(x += ROUNDUP((n)->sa_len)(((n)->sa_len) > 0 ? (1 + ((((n)->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
)
182
183#define TICK_WAIT0 0
184#define TICK_SUCCESS1 1
185#define TICK_DAEMON2 2
186
187static FILE *leaseFile;
188
189int
190get_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_IFA0x20)
199 return sa->sa_family;
200 ADVANCE(cp, sa)(cp += (((sa)->sa_len) > 0 ? (1 + ((((sa)->sa_len) -
1) | (sizeof(long) - 1))) : sizeof(long)))
;
201 }
202 }
203
204 return AF_UNSPEC0;
205}
206
207struct ifaddrs *
208get_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((void *)0); ifa = ifa->ifa_next) {
214 if (strcmp(name, ifa->ifa_name) == 0 &&
215 (ifa->ifa_flags & IFF_LOOPBACK0x8) == 0 &&
216 (ifa->ifa_flags & IFF_POINTOPOINT0x10) == 0 &&
217 ifa->ifa_data != NULL((void *)0) && /* NULL shouldn't be possible. */
218 ifa->ifa_addr != NULL((void *)0) &&
219 ifa->ifa_addr->sa_family == AF_LINK18) {
220 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
221 if (sdl->sdl_alen == ETHER_ADDR_LEN6 &&
222 (sdl->sdl_type == IFT_ETHER0x06 ||
223 sdl->sdl_type == IFT_CARP0xf7))
224 break;
225 }
226 }
227
228 if (ifa == NULL((void *)0))
229 fatal("get_link_ifa()");
230
231 return ifa;
232}
233
234void
235interface_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)((ifi->link_state) >= 4 || (ifi->link_state) == 0);
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_UP0x1) == 0 ||
253 (ifa->ifa_flags & IFF_RUNNING0x40) == 0) {
254 ifi->link_state = LINK_STATE_DOWN2;
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)((ifi->link_state) >= 4 || (ifi->link_state) == 0);
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_SUCCESS1 : TICK_WAIT0);
266 }
267
268 if (memcmp(&ifi->hw_address, LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen)), ETHER_ADDR_LEN6) != 0) {
269 if (log_getverbose()) {
270 oldlladdr = strdup(ether_ntoa(&ifi->hw_address));
271 if (oldlladdr == NULL((void *)0))
272 fatal("oldlladdr");
273 log_debug("%s: LLADDR %s -> %s", log_procname,
274 oldlladdr,
275 ether_ntoa((struct ether_addr *)LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen))));
276 free(oldlladdr);
277 }
278 memcpy(&ifi->hw_address, LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen)), ETHER_ADDR_LEN6);
279 quit = RESTART2; /* Even if MTU has changed. */
280 }
281
282 freeifaddrs(ifap);
283}
284
285struct interface_info *
286initialize_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((void *)0))
296 fatal("ifi");
297
298 ifi->rbuf_max = RT_BUF_SIZE2048;
299 ifi->rbuf = malloc(ifi->rbuf_max);
300 if (ifi->rbuf == NULL((void *)0))
301 fatal("rbuf");
302
303 if ((ioctlfd = socket(AF_INET2, SOCK_DGRAM2, 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_UP0x1) == 0 ||
319 (ifa->ifa_flags & IFF_RUNNING0x40) == 0)
320 ifi->link_state = LINK_STATE_DOWN2;
321 else
322 ifi->link_state = ifd->ifi_link_state;
323
324 memcpy(ifi->hw_address.ether_addr_octet, LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen)), ETHER_ADDR_LEN6);
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)((ifi->link_state) >= 4 || (ifi->link_state) == 0))
331 set_iff_up(ifi, ioctlfd);
332
333 close(ioctlfd);
334 freeifaddrs(ifap);
335
336 return ifi;
337}
338
339void
340get_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(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((138)))
, (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_groupsifgr_ifgru.ifgru_groups = calloc(1, ifgr.ifgr_len)) == NULL((void *)0))
353 fatalx("ifgr_groups");
354 if (ioctl(ioctlfd, SIOCGIFGMEMB(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((138)))
, (caddr_t)&ifgr) == -1)
355 fatal("SIOCGIFGMEMB");
356 len = strlcpy(ifi->name, ifgr.ifgr_groupsifgr_ifgru.ifgru_groups->ifgrq_memberifgrq_ifgrqu.ifgrqu_member,
357 IFNAMSIZ16);
358 free(ifgr.ifgr_groupsifgr_ifgru.ifgru_groups);
359 } else
360 len = strlcpy(ifi->name, arg, IFNAMSIZ16);
361
362 if (len >= IFNAMSIZ16)
363 fatalx("interface name too long");
364}
365
366void
367get_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_dataifr_ifru.ifru_data = (caddr_t)&nwid;
376 strlcpy(ifr.ifr_name, ifi->name, sizeof(ifr.ifr_name));
377
378 if (ioctl(ioctlfd, SIOCG80211NWID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((231)))
, (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
385void
386set_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(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((17)))
, (caddr_t)&ifr) == -1)
394 fatal("%s: SIOCGIFFLAGS", ifi->name);
395
396 if ((ifr.ifr_flagsifr_ifru.ifru_flags & IFF_UP0x1) == 0) {
397 ifi->link_state = LINK_STATE_DOWN2;
398 ifr.ifr_flagsifr_ifru.ifru_flags |= IFF_UP0x1;
399 if (ioctl(ioctlfd, SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
, (caddr_t)&ifr) == -1)
400 fatal("%s: SIOCSIFFLAGS", ifi->name);
401 }
402}
403
404void
405set_user(char *user)
406{
407 struct passwd *pw;
408
409 pw = getpwnam(user);
410 if (pw == NULL((void *)0))
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
427void
428get_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((void *)0))
439 fatal("rbuf");
440 ifi->rbuf = newp;
441 ifi->rbuf_max = newsize;
442 }
443}
444
445int
446get_routefd(int rdomain)
447{
448 int routefd, rtfilter;
449
450 if ((routefd = socket(AF_ROUTE17, SOCK_RAW3, AF_INET2)) == -1)
451 fatal("socket(AF_ROUTE, SOCK_RAW)");
452
453 rtfilter = ROUTE_FILTER(RTM_PROPOSAL)(1 << (0x13)) | ROUTE_FILTER(RTM_IFINFO)(1 << (0xe)) |
454 ROUTE_FILTER(RTM_NEWADDR)(1 << (0xc)) | ROUTE_FILTER(RTM_DELADDR)(1 << (0xd)) |
455 ROUTE_FILTER(RTM_IFANNOUNCE)(1 << (0xf)) | ROUTE_FILTER(RTM_80211INFO)(1 << (0x15));
456
457 if (setsockopt(routefd, AF_ROUTE17, ROUTE_MSGFILTER1,
458 &rtfilter, sizeof(rtfilter)) == -1)
459 fatal("setsockopt(ROUTE_MSGFILTER)");
460 if (setsockopt(routefd, AF_ROUTE17, ROUTE_TABLEFILTER2, &rdomain,
461 sizeof(rdomain)) == -1)
462 fatal("setsockopt(ROUTE_TABLEFILTER)");
463
464 return routefd;
465}
466
467void
468routefd_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_SIZE2048);
477 } while (n == -1 && errno(*__errno()) == EINTR4);
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_VERSION5)
493 continue;
494
495 rtm_dispatch(ifi, rtm);
496 }
497}
498
499void
500rtm_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_PROPOSAL0x13:
511 if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT62) {
512 if (quit == 0 && ifi->active != NULL((void *)0))
513 tell_unwind(ifi->unwind_info, ifi->flags);
514 return;
515 }
516 if (rtm->rtm_index != ifi->index ||
517 rtm->rtm_priority != RTP_PROPOSAL_DHCLIENT58)
518 return;
519 if ((rtm->rtm_flags & RTF_PROTO30x2000) != 0) {
520 if (rtm->rtm_seq == (int32_t)ifi->xid) {
521 ifi->flags |= IFI_IN_CHARGE0x01;
522 return;
523 } else if ((ifi->flags & IFI_IN_CHARGE0x01) != 0) {
524 log_debug("%s: yielding responsibility",
525 log_procname);
526 quit = TERMINATE1;
527 }
528 } else if ((rtm->rtm_flags & RTF_PROTO20x4000) != 0) {
529 release_lease(ifi); /* OK even if we sent it. */
530 quit = TERMINATE1;
531 } else
532 return; /* Ignore tell_unwind() proposals. */
533 break;
534
535 case RTM_DESYNC0x10:
536 log_warnx("%s: RTM_DESYNC", log_procname);
537 break;
538
539 case RTM_IFINFO0xe:
540 ifm = (struct if_msghdr *)rtm;
541 if (ifm->ifm_index != ifi->index)
542 break;
543 if ((rtm->rtm_flags & RTF_UP0x1) == 0)
544 fatalx("down");
545
546 oldmtu = ifi->mtu;
547 interface_state(ifi);
548 if (oldmtu == ifi->mtu)
549 quit = RESTART2;
550 else
551 log_debug("%s: MTU %u -> %u",
552 log_procname, oldmtu, ifi->mtu);
553 break;
554
555 case RTM_80211INFO0x15:
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((void *)0))
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 = RESTART2;
572 }
573 break;
574
575 case RTM_IFANNOUNCE0xf:
576 ifan = (struct if_announcemsghdr *)rtm;
577 if (ifan->ifan_what == IFAN_DEPARTURE1 && ifan->ifan_index ==
578 ifi->index)
579 fatalx("departed");
580 break;
581
582 case RTM_NEWADDR0xc:
583 case RTM_DELADDR0xd:
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_INET2)
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((void *)0) &&
599 (ifi->flags & IFI_IN_CHARGE0x01) != 0 &&
600 ifi->state == S_BOUND)
601 write_resolv_conf();
602}
603
604int
605main(int argc, char *argv[])
606{
607 uint8_t actions[DHO_END255];
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_FILENO2) != 0)
616 log_init(1, LOG_DEBUG7); /* log to stderr until daemonized */
617 else
618 log_init(0, LOG_DEBUG7); /* can't log to stderr */
619
620 log_setverbose(0); /* Don't show log_debug() messages. */
621
622 if (lstat(_PATH_DHCLIENT_CONF"/etc/dhclient.conf", &sb) == 0)
623 path_dhclient_conf = _PATH_DHCLIENT_CONF"/etc/dhclient.conf";
624 memset(actions, ACTION_USELEASE, sizeof(actions));
625
626 while ((ch = getopt(argc, argv, "c:di:nrv")) != -1)
627 switch (ch) {
628 case 'c':
629 if (strlen(optarg) == 0)
630 path_dhclient_conf = NULL((void *)0);
631 else if (lstat(optarg, &sb) == 0)
632 path_dhclient_conf = optarg;
633 else
634 fatal("lstat(%s)", optarg);
635 break;
636 case 'd':
637 cmd_opts |= OPT_FOREGROUND0x04;
638 break;
639 case 'i':
640 if (strlen(optarg) == 0)
641 break;
642 ignore_list = strdup(optarg);
643 if (ignore_list == NULL((void *)0))
644 fatal("ignore_list");
645 for (p = strsep(&ignore_list, ", "); p != NULL((void *)0);
646 p = strsep(&ignore_list, ", ")) {
647 if (*p == '\0')
648 continue;
649 i = name_to_code(p);
650 if (i == DHO_END255)
651 fatalx("invalid option name: '%s'", p);
652 actions[i] = ACTION_IGNORE;
653 }
654 free(ignore_list);
655 break;
656 case 'n':
657 cmd_opts |= OPT_NOACTION0x01;
658 break;
659 case 'r':
660 cmd_opts |= OPT_RELEASE0x08;
661 break;
662 case 'v':
663 cmd_opts |= OPT_VERBOSE0x02;
664 break;
665 default:
666 usage();
667 }
668
669 argc -= optind;
670 argv += optind;
671
672 if (argc != 1)
673 usage();
674
675 if ((cmd_opts & (OPT_FOREGROUND0x04 | OPT_NOACTION0x01)) != 0)
676 cmd_opts |= OPT_VERBOSE0x02;
677
678 if ((cmd_opts & OPT_VERBOSE0x02) != 0)
679 log_setverbose(1); /* Show log_debug() messages. */
680
681 ifi = initialize_interface(argv[0], cmd_opts & OPT_NOACTION0x01);
682
683 log_procname = strdup(ifi->name);
684 if (log_procname == NULL((void *)0))
685 fatal("log_procname");
686 setproctitle("%s", log_procname);
687 log_procinit(log_procname);
688
689 tzset();
690
691 if (setrtable(ifi->rdomain) == -1)
692 fatal("setrtable(%u)", ifi->rdomain);
693
694 if ((cmd_opts & OPT_RELEASE0x08) != 0) {
695 if ((cmd_opts & OPT_NOACTION0x01) == 0)
696 propose_release(ifi);
697 exit(0);
698 }
699
700 signal(SIGPIPE13, SIG_IGN(void (*)(int))1); /* Don't wait for go_daemon()! */
701
702 if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_NONBLOCK0x4000 | SOCK_CLOEXEC0x8000, 0,
703 socket_fd) == -1)
704 fatal("socketpair");
705
706 if ((nullfd = open(_PATH_DEVNULL"/dev/null", O_RDWR0x0002)) == -1)
707 fatal("open(%s)", _PATH_DEVNULL"/dev/null");
708
709 fork_privchld(ifi, socket_fd[0], socket_fd[1]);
710
711 close(socket_fd[0]);
712 if ((unpriv_ibuf = malloc(sizeof(*unpriv_ibuf))) == NULL((void *)0))
713 fatal("unpriv_ibuf");
714 imsg_init(unpriv_ibuf, socket_fd[1]);
715
716 read_conf(ifi->name, actions, &ifi->hw_address);
717 if ((cmd_opts & OPT_NOACTION0x01) != 0)
718 return 0;
719
720 if (asprintf(&path_lease_db, "%s.%s", _PATH_LEASE_DB"/var/db/dhclient.leases", ifi->name) == -1)
721 fatal("path_lease_db");
722
723 routefd = get_routefd(ifi->rdomain);
724 fd = take_charge(ifi, routefd, path_lease_db); /* Kill other dhclients. */
725 if (autoconf(ifi)) {
726 /* dhcpleased has been notified to request a new lease. */
727 return 0;
728 }
729 if (fd != -1)
730 read_lease_db(&ifi->lease_db);
731
732 if ((leaseFile = fopen(path_lease_db, "w")) == NULL((void *)0))
733 log_warn("%s: fopen(%s)", log_procname, path_lease_db);
734 write_lease_db(ifi);
735
736 set_user("_dhcp");
737
738 if ((cmd_opts & OPT_FOREGROUND0x04) == 0) {
739 if (pledge("stdio inet dns route proc", NULL((void *)0)) == -1)
740 fatal("pledge");
741 } else {
742 if (pledge("stdio inet dns route", NULL((void *)0)) == -1)
743 fatal("pledge");
744 }
745
746 tick_msg("link", LINK_STATE_IS_UP(ifi->link_state)((ifi->link_state) >= 4 || (ifi->link_state) == 0) ? TICK_SUCCESS1 :
747 TICK_WAIT0);
748 quit = RESTART2;
749 dispatch(ifi, routefd);
750
751 return 0;
752}
753
754void
755usage(void)
756{
757 extern char *__progname;
758
759 fprintf(stderr(&__sF[2]),
760 "usage: %s [-dnrv] [-c file] [-i options] "
761 "interface\n", __progname);
762 exit(1);
763}
764
765void
766state_preboot(struct interface_info *ifi)
767{
768 interface_state(ifi);
769 if (quit != 0)
770 return;
771
772 if (LINK_STATE_IS_UP(ifi->link_state)((ifi->link_state) >= 4 || (ifi->link_state) == 0)) {
773 tick_msg("link", TICK_SUCCESS1);
774 ifi->state = S_REBOOTING;
775 state_reboot(ifi);
776 } else {
777 tick_msg("link", TICK_WAIT0);
778 set_timeout(ifi, 1, state_preboot);
779 }
780}
781
782/*
783 * Called when the interface link becomes active.
784 */
785void
786state_reboot(struct interface_info *ifi)
787{
788 const struct timespec reboot_intvl = {config->reboot_interval, 0};
789 struct client_lease *lease;
790
791 cancel_timeout(ifi);
792
793 /*
794 * If there is no recorded lease or the lease is BOOTP then
795 * go straight to INIT and try to DISCOVER a new lease.
796 */
797 ifi->active = get_recorded_lease(ifi);
798 if (ifi->active == NULL((void *)0) || BOOTP_LEASE(ifi->active)((ifi->active)->options[53].len == 0)) {
799 ifi->state = S_INIT;
800 state_init(ifi);
801 return;
802 }
803 lease = apply_defaults(ifi->active);
804 get_lease_timeouts(ifi, lease);
805 free_client_lease(lease);
806
807 ifi->xid = arc4random();
808 make_request(ifi, ifi->active);
809
810 ifi->destination.s_addr = INADDR_BROADCAST((u_int32_t)(0xffffffff));
811 clock_gettime(CLOCK_MONOTONIC3, &ifi->first_sending);
812 timespecadd(&ifi->first_sending, &reboot_intvl, &ifi->reboot_timeout)do { (&ifi->reboot_timeout)->tv_sec = (&ifi->
first_sending)->tv_sec + (&reboot_intvl)->tv_sec; (
&ifi->reboot_timeout)->tv_nsec = (&ifi->first_sending
)->tv_nsec + (&reboot_intvl)->tv_nsec; if ((&ifi
->reboot_timeout)->tv_nsec >= 1000000000L) { (&ifi
->reboot_timeout)->tv_sec++; (&ifi->reboot_timeout
)->tv_nsec -= 1000000000L; } } while (0)
;
813 ifi->interval = 0;
814
815 send_request(ifi);
816}
817
818/*
819 * Called when a lease has completely expired and we've been unable to
820 * renew it.
821 */
822void
823state_init(struct interface_info *ifi)
824{
825 const struct timespec offer_intvl = {config->offer_interval, 0};
826
827 ifi->xid = arc4random();
828 make_discover(ifi, ifi->active);
829
830 ifi->destination.s_addr = INADDR_BROADCAST((u_int32_t)(0xffffffff));
831 ifi->state = S_SELECTING;
832 clock_gettime(CLOCK_MONOTONIC3, &ifi->first_sending);
833 timespecadd(&ifi->first_sending, &offer_intvl, &ifi->offer_timeout)do { (&ifi->offer_timeout)->tv_sec = (&ifi->
first_sending)->tv_sec + (&offer_intvl)->tv_sec; (&
ifi->offer_timeout)->tv_nsec = (&ifi->first_sending
)->tv_nsec + (&offer_intvl)->tv_nsec; if ((&ifi
->offer_timeout)->tv_nsec >= 1000000000L) { (&ifi
->offer_timeout)->tv_sec++; (&ifi->offer_timeout
)->tv_nsec -= 1000000000L; } } while (0)
;
834 ifi->select_timeout = ifi->offer_timeout;
835 ifi->interval = 0;
836
837 send_discover(ifi);
838}
839
840/*
841 * Called when one or more DHCPOFFER packets have been received and a
842 * configurable period of time has passed.
843 */
844void
845state_selecting(struct interface_info *ifi)
846{
847 cancel_timeout(ifi);
848
849 if (ifi->offer == NULL((void *)0)) {
850 state_panic(ifi);
851 return;
852 }
853
854 ifi->state = S_REQUESTING;
855
856 /* If it was a BOOTREPLY, we can just take the lease right now. */
857 if (BOOTP_LEASE(ifi->offer)((ifi->offer)->options[53].len == 0)) {
858 bind_lease(ifi);
859 return;
860 }
861
862 ifi->destination.s_addr = INADDR_BROADCAST((u_int32_t)(0xffffffff));
863 clock_gettime(CLOCK_MONOTONIC3, &ifi->first_sending);
864 ifi->interval = 0;
865
866 /*
867 * Make a DHCPREQUEST packet from the lease we picked. Keep
868 * the current xid, as all offers should have had the same
869 * one.
870 */
871 make_request(ifi, ifi->offer);
872
873 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
874 free_client_lease(ifi->offer);
875 ifi->offer = NULL((void *)0);
876 free(ifi->offer_src);
877 ifi->offer_src = NULL((void *)0);
878
879 send_request(ifi);
880}
881
882void
883dhcpoffer(struct interface_info *ifi, struct option_data *options,
884 const char *src)
885{
886 if (ifi->state != S_SELECTING) {
887 log_debug("%s: unexpected DHCPOFFER from %s - state #%d",
888 log_procname, src, ifi->state);
889 return;
890 }
891
892 log_debug("%s: DHCPOFFER from %s", log_procname, src);
893 process_offer(ifi, options, src);
894}
895
896void
897bootreply(struct interface_info *ifi, struct option_data *options,
898 const char *src)
899{
900 if (ifi->state != S_SELECTING) {
901 log_debug("%s: unexpected BOOTREPLY from %s - state #%d",
902 log_procname, src, ifi->state);
903 return;
904 }
905
906 log_debug("%s: BOOTREPLY from %s", log_procname, src);
907 process_offer(ifi, options, src);
908}
909
910void
911process_offer(struct interface_info *ifi, struct option_data *options,
912 const char *src)
913{
914 const struct timespec select_intvl = {config->select_interval, 0};
915 struct timespec now;
916 struct client_lease *lease;
917
918 clock_gettime(CLOCK_MONOTONIC3, &now);
919
920 lease = packet_to_lease(ifi, options);
921 if (lease != NULL((void *)0)) {
922 if (ifi->offer == NULL((void *)0)) {
923 ifi->offer = lease;
924 free(ifi->offer_src);
925 ifi->offer_src = strdup(src); /* NULL is OK */
926 timespecadd(&now, &select_intvl, &ifi->select_timeout)do { (&ifi->select_timeout)->tv_sec = (&now)->
tv_sec + (&select_intvl)->tv_sec; (&ifi->select_timeout
)->tv_nsec = (&now)->tv_nsec + (&select_intvl)->
tv_nsec; if ((&ifi->select_timeout)->tv_nsec >= 1000000000L
) { (&ifi->select_timeout)->tv_sec++; (&ifi->
select_timeout)->tv_nsec -= 1000000000L; } } while (0)
;
927 if (timespeccmp(&ifi->select_timeout,(((&ifi->select_timeout)->tv_sec == (&ifi->offer_timeout
)->tv_sec) ? ((&ifi->select_timeout)->tv_nsec >
(&ifi->offer_timeout)->tv_nsec) : ((&ifi->select_timeout
)->tv_sec > (&ifi->offer_timeout)->tv_sec))
928 &ifi->offer_timeout, >)(((&ifi->select_timeout)->tv_sec == (&ifi->offer_timeout
)->tv_sec) ? ((&ifi->select_timeout)->tv_nsec >
(&ifi->offer_timeout)->tv_nsec) : ((&ifi->select_timeout
)->tv_sec > (&ifi->offer_timeout)->tv_sec))
)
929 ifi->select_timeout = ifi->offer_timeout;
930 } else if (lease->address.s_addr ==
931 ifi->offer->address.s_addr) {
932 /* Decline duplicate offers. */
933 } else if (lease->address.s_addr ==
934 ifi->requested_address.s_addr) {
935 free_client_lease(ifi->offer);
936 ifi->offer = lease;
937 free(ifi->offer_src);
938 ifi->offer_src = strdup(src); /* NULL is OK */
939 }
940
941 if (ifi->offer != lease) {
942 make_decline(ifi, lease);
943 send_decline(ifi);
944 free_client_lease(lease);
945 } else if (ifi->offer->address.s_addr ==
946 ifi->requested_address.s_addr) {
947 ifi->select_timeout = now;
948 }
949 }
950
951 if (timespeccmp(&now, &ifi->select_timeout, >=)(((&now)->tv_sec == (&ifi->select_timeout)->
tv_sec) ? ((&now)->tv_nsec >= (&ifi->select_timeout
)->tv_nsec) : ((&now)->tv_sec >= (&ifi->select_timeout
)->tv_sec))
)
952 state_selecting(ifi);
953 else {
954 ifi->timeout = ifi->select_timeout;
955 ifi->timeout_func = state_selecting;
956 }
957}
958
959void
960dhcpack(struct interface_info *ifi, struct option_data *options,
961 const char *src)
962{
963 struct client_lease *lease;
964
965 if (ifi->state != S_REBOOTING &&
966 ifi->state != S_REQUESTING &&
967 ifi->state != S_RENEWING) {
968 log_debug("%s: unexpected DHCPACK from %s - state #%d",
969 log_procname, src, ifi->state);
970 return;
971 }
972
973 log_debug("%s: DHCPACK", log_procname);
974
975 lease = packet_to_lease(ifi, options);
976 if (lease == NULL((void *)0)) {
977 ifi->state = S_INIT;
978 state_init(ifi);
979 return;
980 }
981
982 ifi->offer = lease;
983 ifi->offer_src = strdup(src); /* NULL is OK */
984 memcpy(ifi->offer->ssid, ifi->ssid, sizeof(ifi->offer->ssid));
985 ifi->offer->ssid_len = ifi->ssid_len;
986
987 /* Stop resending DHCPREQUEST. */
988 cancel_timeout(ifi);
989
990 bind_lease(ifi);
991}
992
993void
994dhcpnak(struct interface_info *ifi, const char *src)
995{
996 struct client_lease *ll, *pl;
997
998 if (ifi->state != S_REBOOTING &&
999 ifi->state != S_REQUESTING &&
1000 ifi->state != S_RENEWING) {
1001 log_debug("%s: unexpected DHCPNAK from %s - state #%d",
1002 log_procname, src, ifi->state);
1003 return;
1004 }
1005
1006 log_debug("%s: DHCPNAK", log_procname);
1007
1008 /* Remove the NAK'd address from the database. */
1009 TAILQ_FOREACH_SAFE(ll, &ifi->lease_db, next, pl)for ((ll) = ((&ifi->lease_db)->tqh_first); (ll) != (
(void *)0) && ((pl) = ((ll)->next.tqe_next), 1); (
ll) = (pl))
{
1010 if (ifi->ssid_len == ll->ssid_len &&
1011 memcmp(ifi->ssid, ll->ssid, ll->ssid_len) == 0 &&
1012 ll->address.s_addr == ifi->requested_address.s_addr) {
1013 if (ll == ifi->active) {
1014 tell_unwind(NULL((void *)0), ifi->flags);
1015 free(ifi->unwind_info);
1016 ifi->unwind_info = NULL((void *)0);
1017 revoke_proposal(ifi->configured);
1018 free(ifi->configured);
1019 ifi->configured = NULL((void *)0);
1020 ifi->active = NULL((void *)0);
1021 }
1022 TAILQ_REMOVE(&ifi->lease_db, ll, next)do { if (((ll)->next.tqe_next) != ((void *)0)) (ll)->next
.tqe_next->next.tqe_prev = (ll)->next.tqe_prev; else (&
ifi->lease_db)->tqh_last = (ll)->next.tqe_prev; *(ll
)->next.tqe_prev = (ll)->next.tqe_next; ; ; } while (0)
;
1023 free_client_lease(ll);
1024 write_lease_db(ifi);
1025 }
1026 }
1027
1028 /* Stop sending DHCPREQUEST packets. */
1029 cancel_timeout(ifi);
1030
1031 ifi->state = S_INIT;
1032 state_init(ifi);
1033}
1034
1035void
1036bind_lease(struct interface_info *ifi)
1037{
1038 struct timespec now;
1039 struct client_lease *lease, *pl, *ll;
1040 struct proposal *effective_proposal = NULL((void *)0);
1041 struct unwind_info *unwind_info;
1042 char *msg = NULL((void *)0);
1043 int rslt, seen;
1044
1045 tick_msg("lease", TICK_SUCCESS1);
1046 clock_gettime(CLOCK_MONOTONIC3, &now);
1047
1048 lease = apply_defaults(ifi->offer);
1049 get_lease_timeouts(ifi, lease);
1050
1051 /* Replace the old active lease with the accepted offer. */
1052 ifi->active = ifi->offer;
1053 ifi->offer = NULL((void *)0);
1054
1055 /*
1056 * Supply unwind with updated info.
1057 */
1058 unwind_info = lease_as_unwind_info(ifi->active);
1059 if (ifi->unwind_info == NULL((void *)0) && unwind_info != NULL((void *)0)) {
1060 ifi->unwind_info = unwind_info;
1061 tell_unwind(ifi->unwind_info, ifi->flags);
1062 } else if (ifi->unwind_info != NULL((void *)0) && unwind_info == NULL((void *)0)) {
1063 tell_unwind(NULL((void *)0), ifi->flags);
1064 free(ifi->unwind_info);
1065 ifi->unwind_info = NULL((void *)0);
1066 } else if (ifi->unwind_info != NULL((void *)0) && unwind_info != NULL((void *)0)) {
1067 if (memcmp(ifi->unwind_info, unwind_info,
1068 sizeof(*ifi->unwind_info)) != 0) {
1069 tell_unwind(NULL((void *)0), ifi->flags);
1070 free(ifi->unwind_info);
1071 ifi->unwind_info = unwind_info;
1072 tell_unwind(ifi->unwind_info, ifi->flags);
1073 }
1074 }
1075
1076 effective_proposal = lease_as_proposal(lease);
1077 if (ifi->configured != NULL((void *)0)) {
1078 if (memcmp(ifi->configured, effective_proposal,
1079 sizeof(*ifi->configured)) == 0)
1080 goto newlease;
1081 }
1082 free(ifi->configured);
1083 ifi->configured = effective_proposal;
1084 effective_proposal = NULL((void *)0);
1085
1086 propose(ifi->configured);
1087 rslt = asprintf(&msg, "%s lease accepted from %s",
1088 inet_ntoa(ifi->active->address),
1089 (ifi->offer_src == NULL((void *)0)) ? "<unknown>" : ifi->offer_src);
1090 if (rslt == -1)
1091 fatal("bind msg");
1092
1093newlease:
1094 seen = 0;
1095 TAILQ_FOREACH_SAFE(ll, &ifi->lease_db, next, pl)for ((ll) = ((&ifi->lease_db)->tqh_first); (ll) != (
(void *)0) && ((pl) = ((ll)->next.tqe_next), 1); (
ll) = (pl))
{
1096 if (ifi->ssid_len != ll->ssid_len ||
1097 memcmp(ifi->ssid, ll->ssid, ll->ssid_len) != 0)
1098 continue;
1099 if (ifi->active == ll)
1100 seen = 1;
1101 else if (ll->address.s_addr == ifi->active->address.s_addr) {
1102 TAILQ_REMOVE(&ifi->lease_db, ll, next)do { if (((ll)->next.tqe_next) != ((void *)0)) (ll)->next
.tqe_next->next.tqe_prev = (ll)->next.tqe_prev; else (&
ifi->lease_db)->tqh_last = (ll)->next.tqe_prev; *(ll
)->next.tqe_prev = (ll)->next.tqe_next; ; ; } while (0)
;
1103 free_client_lease(ll);
1104 }
1105 }
1106 if (seen == 0) {
1107 if (ifi->active->epoch == 0)
1108 time(&ifi->active->epoch);
1109 TAILQ_INSERT_HEAD(&ifi->lease_db, ifi->active, next)do { if (((ifi->active)->next.tqe_next = (&ifi->
lease_db)->tqh_first) != ((void *)0)) (&ifi->lease_db
)->tqh_first->next.tqe_prev = &(ifi->active)->
next.tqe_next; else (&ifi->lease_db)->tqh_last = &
(ifi->active)->next.tqe_next; (&ifi->lease_db)->
tqh_first = (ifi->active); (ifi->active)->next.tqe_prev
= &(&ifi->lease_db)->tqh_first; } while (0)
;
1110 }
1111
1112 /*
1113 * Write out updated information before going daemon.
1114 *
1115 * Some scripts (e.g. the installer in autoinstall mode) assume that
1116 * the bind process is complete and all related information is in
1117 * place when dhclient(8) goes daemon.
1118 */
1119 write_lease_db(ifi);
1120
1121 free_client_lease(lease);
1122 free(effective_proposal);
1123 free(ifi->offer_src);
1124 ifi->offer_src = NULL((void *)0);
1125
1126 if (msg != NULL((void *)0)) {
1127 if ((cmd_opts & OPT_FOREGROUND0x04) != 0) {
1128 /* log msg on console only. */
1129 ;
1130 } else if (isatty(STDERR_FILENO2) != 0) {
1131 /*
1132 * log msg to console and then go_daemon() so it is
1133 * logged again, this time to /var/log/daemon.
1134 */
1135 log_info("%s: %s", log_procname, msg);
1136 go_daemon();
1137 }
1138 log_info("%s: %s", log_procname, msg);
1139 free(msg);
1140 }
1141
1142 ifi->state = S_BOUND;
1143 go_daemon();
1144
1145 /*
1146 * Set timeout to start the renewal process.
1147 *
1148 * If the renewal time is in the past, the lease is from the
1149 * leaseDB. Rather than immediately trying to contact a server,
1150 * pause the configured time between attempts.
1151 */
1152 if (timespeccmp(&now, &ifi->renew, >=)(((&now)->tv_sec == (&ifi->renew)->tv_sec) ?
((&now)->tv_nsec >= (&ifi->renew)->tv_nsec
) : ((&now)->tv_sec >= (&ifi->renew)->tv_sec
))
)
1153 set_timeout(ifi, config->retry_interval, state_bound);
1154 else {
1155 ifi->timeout = ifi->renew;
1156 ifi->timeout_func = state_bound;
1157 }
1158}
1159
1160/*
1161 * Called when we've successfully bound to a particular lease, but the renewal
1162 * time on that lease has expired. We are expected to unicast a DHCPREQUEST to
1163 * the server that gave us our original lease.
1164 */
1165void
1166state_bound(struct interface_info *ifi)
1167{
1168 struct option_data *opt;
1169 struct in_addr *dest;
1170
1171 ifi->xid = arc4random();
1172 make_request(ifi, ifi->active);
1173
1174 dest = &ifi->destination;
1175 opt = &ifi->active->options[DHO_DHCP_SERVER_IDENTIFIER54];
1176
1177 if (opt->len == sizeof(*dest))
1178 dest->s_addr = ((struct in_addr *)opt->data)->s_addr;
1179 else
1180 dest->s_addr = INADDR_BROADCAST((u_int32_t)(0xffffffff));
1181
1182 clock_gettime(CLOCK_MONOTONIC3, &ifi->first_sending);
1183 ifi->interval = 0;
1184 ifi->state = S_RENEWING;
1185
1186 send_request(ifi);
1187}
1188
1189int
1190addressinuse(char *name, struct in_addr address, char *ifname)
1191{
1192 struct ifaddrs *ifap, *ifa;
1193 struct sockaddr_in *sin;
1194 int used = 0;
1195
1196 if (getifaddrs(&ifap) != 0) {
1197 log_warn("%s: getifaddrs", log_procname);
1198 return 0;
1199 }
1200
1201 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1202 if (ifa->ifa_addr == NULL((void *)0) ||
1203 ifa->ifa_addr->sa_family != AF_INET2)
1204 continue;
1205
1206 sin = (struct sockaddr_in *)ifa->ifa_addr;
1207 if (memcmp(&address, &sin->sin_addr, sizeof(address)) == 0) {
1208 strlcpy(ifname, ifa->ifa_name, IF_NAMESIZE16);
1209 used = 1;
1210 if (strncmp(ifname, name, IF_NAMESIZE16) != 0)
1211 break;
1212 }
1213 }
1214
1215 freeifaddrs(ifap);
1216 return used;
1217}
1218
1219/*
1220 * Allocate a client_lease structure and initialize it from the
1221 * parameters in the received packet.
1222 *
1223 * Return NULL and decline the lease if a valid lease cannot be
1224 * constructed.
1225 */
1226struct client_lease *
1227packet_to_lease(struct interface_info *ifi, struct option_data *options)
1228{
1229 char ifname[IF_NAMESIZE16];
1230 struct dhcp_packet *packet = &ifi->recv_packet;
1231 struct client_lease *lease;
1232 char *pretty, *name;
1233 int i;
1234
1235 lease = calloc(1, sizeof(*lease));
1236 if (lease == NULL((void *)0)) {
1237 log_warn("%s: lease", log_procname);
1238 return NULL((void *)0); /* Can't even DECLINE. */
1239 }
1240
1241 /* Copy the lease addresses. */
1242 lease->address.s_addr = packet->yiaddr.s_addr;
1243 lease->next_server.s_addr = packet->siaddr.s_addr;
1244
1245 /* Copy the lease options. */
1246 for (i = 0; i < DHO_COUNT256; i++) {
1247 if (options[i].len == 0)
1248 continue;
1249 name = code_to_name(i);
1250 if (i == DHO_DOMAIN_SEARCH119) {
1251 /* Replace RFC 1035 data with a string. */
1252 pretty = rfc1035_as_string(options[i].data,
1253 options[i].len);
1254 free(options[i].data);
1255 options[i].data = strdup(pretty);
1256 if (options[i].data == NULL((void *)0))
1257 fatal("RFC1035 string");
1258 options[i].len = strlen(options[i].data);
1259 } else
1260 pretty = pretty_print_option(i, &options[i], 0);
1261 if (strlen(pretty) == 0)
1262 continue;
1263 switch (i) {
1264 case DHO_DOMAIN_SEARCH119:
1265 case DHO_DOMAIN_NAME15:
1266 /*
1267 * Allow deviant but historically blessed
1268 * practice of supplying multiple domain names
1269 * with DHO_DOMAIN_NAME. Thus allowing multiple
1270 * entries in the resolv.conf 'search' statement.
1271 */
1272 if (res_hnok_list(pretty) == 0) {
1273 log_debug("%s: invalid host name in %s",
1274 log_procname, name);
1275 continue;
1276 }
1277 break;
1278 case DHO_HOST_NAME12:
1279 case DHO_NIS_DOMAIN40:
1280 if (res_hnok__res_hnok(pretty) == 0) {
1281 log_debug("%s: invalid host name in %s",
1282 log_procname, name);
1283 continue;
1284 }
1285 break;
1286 default:
1287 break;
1288 }
1289 lease->options[i] = options[i];
1290 options[i].data = NULL((void *)0);
1291 options[i].len = 0;
1292 }
1293
1294 /*
1295 * If this lease doesn't supply a required parameter, decline it.
1296 */
1297 for (i = 0; i < config->required_option_count; i++) {
1298 if (lease->options[config->required_options[i]].len == 0) {
1299 name = code_to_name(config->required_options[i]);
1300 log_warnx("%s: %s required but missing", log_procname,
1301 name);
1302 goto decline;
1303 }
1304 }
1305
1306 /*
1307 * If this lease is trying to sell us an address we are already
1308 * using, decline it.
1309 */
1310 memset(ifname, 0, sizeof(ifname));
1311 if (addressinuse(ifi->name, lease->address, ifname) != 0 &&
1312 strncmp(ifname, ifi->name, IF_NAMESIZE16) != 0) {
1313 log_warnx("%s: %s already configured on %s", log_procname,
1314 inet_ntoa(lease->address), ifname);
1315 goto decline;
1316 }
1317
1318 /* If the server name was filled out, copy it. */
1319 if ((lease->options[DHO_DHCP_OPTION_OVERLOAD52].len == 0 ||
1320 (lease->options[DHO_DHCP_OPTION_OVERLOAD52].data[0] & 2) == 0) &&
1321 packet->sname[0]) {
1322 lease->server_name = calloc(1, DHCP_SNAME_LEN64 + 1);
1323 if (lease->server_name == NULL((void *)0)) {
1324 log_warn("%s: SNAME", log_procname);
1325 goto decline;
1326 }
1327 memcpy(lease->server_name, packet->sname, DHCP_SNAME_LEN64);
1328 if (res_hnok__res_hnok(lease->server_name) == 0) {
1329 log_debug("%s: invalid host name in SNAME ignored",
1330 log_procname);
1331 free(lease->server_name);
1332 lease->server_name = NULL((void *)0);
1333 }
1334 }
1335
1336 /* If the file name was filled out, copy it. */
1337 if ((lease->options[DHO_DHCP_OPTION_OVERLOAD52].len == 0 ||
1338 (lease->options[DHO_DHCP_OPTION_OVERLOAD52].data[0] & 1) == 0) &&
1339 packet->file[0]) {
1340 /* Don't count on the NUL terminator. */
1341 lease->filename = malloc(DHCP_FILE_LEN128 + 1);
1342 if (lease->filename == NULL((void *)0)) {
1343 log_warn("%s: filename", log_procname);
1344 goto decline;
1345 }
1346 memcpy(lease->filename, packet->file, DHCP_FILE_LEN128);
1347 lease->filename[DHCP_FILE_LEN128] = '\0';
1348 }
1349
1350 /*
1351 * Record the client identifier used to obtain the lease. We already
1352 * checked that the packet client identifier is absent (RFC 2131) or
1353 * matches what we sent (RFC 6842),
1354 */
1355 i = DHO_DHCP_CLIENT_IDENTIFIER61;
1356 if (lease->options[i].len == 0 && config->send_options[i].len != 0) {
1357 lease->options[i].len = config->send_options[i].len;
1358 lease->options[i].data = malloc(lease->options[i].len);
1359 if (lease->options[i].data == NULL((void *)0))
1360 fatal("lease client-identifier");
1361 memcpy(lease->options[i].data, config->send_options[i].data,
1362 lease->options[i].len);
1363 }
1364
1365 time(&lease->epoch);
1366 return lease;
1367
1368decline:
1369 make_decline(ifi, lease);
1370 send_decline(ifi);
1371 free_client_lease(lease);
1372 return NULL((void *)0);
1373}
1374
1375void
1376set_interval(struct interface_info *ifi, struct timespec *now)
1377{
1378 struct timespec interval;
1379
1380 if (timespeccmp(now, &ifi->timeout, >)(((now)->tv_sec == (&ifi->timeout)->tv_sec) ? ((
now)->tv_nsec > (&ifi->timeout)->tv_nsec) : (
(now)->tv_sec > (&ifi->timeout)->tv_sec))
)
1381 ifi->interval = 1;
1382 else {
1383 timespecsub(&ifi->timeout, now, &interval)do { (&interval)->tv_sec = (&ifi->timeout)->
tv_sec - (now)->tv_sec; (&interval)->tv_nsec = (&
ifi->timeout)->tv_nsec - (now)->tv_nsec; if ((&interval
)->tv_nsec < 0) { (&interval)->tv_sec--; (&interval
)->tv_nsec += 1000000000L; } } while (0)
;
1384 if (interval.tv_sec == 0 || interval.tv_nsec > 500000000LL)
1385 interval.tv_sec++;
1386 ifi->interval = interval.tv_sec;
1387 }
1388}
1389
1390void
1391set_resend_timeout(struct interface_info *ifi, struct timespec *now,
1392 void (*where)(struct interface_info *))
1393{
1394 const struct timespec reboot_intvl = {config->reboot_interval, 0};
1395 const struct timespec initial_intvl = {config->initial_interval, 0};
1396 const struct timespec cutoff_intvl = {config->backoff_cutoff, 0};
1397 const struct timespec onesecond = {1, 0};
1398 struct timespec interval, when;
1399
1400 if (timespeccmp(now, &ifi->link_timeout, <)(((now)->tv_sec == (&ifi->link_timeout)->tv_sec)
? ((now)->tv_nsec < (&ifi->link_timeout)->tv_nsec
) : ((now)->tv_sec < (&ifi->link_timeout)->tv_sec
))
)
1401 interval = onesecond;
1402 else if (ifi->interval == 0) {
1403 if (ifi->state == S_REBOOTING)
1404 interval = reboot_intvl;
1405 else
1406 interval = initial_intvl;
1407 } else {
1408 timespecclear(&interval)(&interval)->tv_sec = (&interval)->tv_nsec = 0;
1409 interval.tv_sec = ifi->interval + arc4random_uniform(2 *
1410 ifi->interval);
1411 }
1412 if (timespeccmp(&interval, &onesecond, <)(((&interval)->tv_sec == (&onesecond)->tv_sec) ?
((&interval)->tv_nsec < (&onesecond)->tv_nsec
) : ((&interval)->tv_sec < (&onesecond)->tv_sec
))
)
1413 interval = onesecond;
1414 else if (timespeccmp(&interval, &cutoff_intvl, >)(((&interval)->tv_sec == (&cutoff_intvl)->tv_sec
) ? ((&interval)->tv_nsec > (&cutoff_intvl)->
tv_nsec) : ((&interval)->tv_sec > (&cutoff_intvl
)->tv_sec))
)
1415 interval = cutoff_intvl;
1416
1417 timespecadd(now, &interval, &when)do { (&when)->tv_sec = (now)->tv_sec + (&interval
)->tv_sec; (&when)->tv_nsec = (now)->tv_nsec + (
&interval)->tv_nsec; if ((&when)->tv_nsec >=
1000000000L) { (&when)->tv_sec++; (&when)->tv_nsec
-= 1000000000L; } } while (0)
;
1418 switch (ifi->state) {
1419 case S_REBOOTING:
1420 case S_RENEWING:
1421 if (timespeccmp(&when, &ifi->expiry, >)(((&when)->tv_sec == (&ifi->expiry)->tv_sec)
? ((&when)->tv_nsec > (&ifi->expiry)->tv_nsec
) : ((&when)->tv_sec > (&ifi->expiry)->tv_sec
))
)
1422 when = ifi->expiry;
1423 break;
1424 case S_SELECTING:
1425 if (timespeccmp(&when, &ifi->select_timeout, >)(((&when)->tv_sec == (&ifi->select_timeout)->
tv_sec) ? ((&when)->tv_nsec > (&ifi->select_timeout
)->tv_nsec) : ((&when)->tv_sec > (&ifi->select_timeout
)->tv_sec))
)
1426 when = ifi->select_timeout;
1427 break;
1428 case S_REQUESTING:
1429 if (timespeccmp(&when, &ifi->offer_timeout, >)(((&when)->tv_sec == (&ifi->offer_timeout)->
tv_sec) ? ((&when)->tv_nsec > (&ifi->offer_timeout
)->tv_nsec) : ((&when)->tv_sec > (&ifi->offer_timeout
)->tv_sec))
)
1430 when = ifi->offer_timeout;
1431 break;
1432 default:
1433 break;
1434 }
1435
1436 ifi->timeout = when;
1437 ifi->timeout_func = where;
1438}
1439
1440void
1441set_secs(struct interface_info *ifi, struct timespec *now)
1442{
1443 struct timespec interval;
1444
1445 if (ifi->state != S_REQUESTING) {
1446 /* Update the number of seconds since we started sending. */
1447 timespecsub(now, &ifi->first_sending, &interval)do { (&interval)->tv_sec = (now)->tv_sec - (&ifi
->first_sending)->tv_sec; (&interval)->tv_nsec =
(now)->tv_nsec - (&ifi->first_sending)->tv_nsec
; if ((&interval)->tv_nsec < 0) { (&interval)->
tv_sec--; (&interval)->tv_nsec += 1000000000L; } } while
(0)
;
1448 if (interval.tv_nsec > 500000000LL)
1449 interval.tv_sec++;
1450 if (interval.tv_sec > UINT16_MAX0xffff)
1451 ifi->secs = UINT16_MAX0xffff;
1452 else
1453 ifi->secs = interval.tv_sec;
1454 }
1455
1456 ifi->sent_packet.secs = htons(ifi->secs)(__uint16_t)(__builtin_constant_p(ifi->secs) ? (__uint16_t
)(((__uint16_t)(ifi->secs) & 0xffU) << 8 | ((__uint16_t
)(ifi->secs) & 0xff00U) >> 8) : __swap16md(ifi->
secs))
;
1457}
1458
1459/*
1460 * Send out a DHCPDISCOVER packet, and set a timeout to send out another
1461 * one after the right interval has expired. If we don't get an offer by
1462 * the time we reach the panic interval, call the panic function.
1463 */
1464void
1465send_discover(struct interface_info *ifi)
1466{
1467 struct timespec now;
1468 ssize_t rslt;
1469
1470 clock_gettime(CLOCK_MONOTONIC3, &now);
1471 if (timespeccmp(&now, &ifi->offer_timeout, >=)(((&now)->tv_sec == (&ifi->offer_timeout)->tv_sec
) ? ((&now)->tv_nsec >= (&ifi->offer_timeout
)->tv_nsec) : ((&now)->tv_sec >= (&ifi->offer_timeout
)->tv_sec))
) {
1472 state_panic(ifi);
1473 return;
1474 }
1475
1476 set_resend_timeout(ifi, &now, send_discover);
1477 set_interval(ifi, &now);
1478 set_secs(ifi, &now);
1479
1480 rslt = send_packet(ifi, inaddr_any, inaddr_broadcast, "DHCPDISCOVER");
1481 if (rslt != -1)
1482 log_debug("%s: DHCPDISCOVER %s", log_procname,
1483 (ifi->requested_address.s_addr == INADDR_ANY((u_int32_t)(0x00000000))) ? "" :
1484 inet_ntoa(ifi->requested_address));
1485
1486 tick_msg("lease", TICK_WAIT0);
1487}
1488
1489/*
1490 * Called if we haven't received any offers in a preset amount of time. When
1491 * this happens, we try to use existing leases that haven't yet expired.
1492 *
1493 * If LINK_STATE_UNKNOWN, do NOT use recorded leases.
1494 */
1495void
1496state_panic(struct interface_info *ifi)
1497{
1498 log_debug("%s: no acceptable DHCPOFFERS received", log_procname);
1499
1500 if (ifi->link_state >= LINK_STATE_UP4) {
1501 ifi->offer = get_recorded_lease(ifi);
1502 if (ifi->offer != NULL((void *)0)) {
1503 ifi->state = S_REQUESTING;
1504 ifi->offer_src = strdup(path_lease_db); /* NULL is OK. */
1505 bind_lease(ifi);
1506 return;
1507 }
1508 }
1509
1510 /*
1511 * No leases were available, or what was available didn't work
1512 */
1513 log_debug("%s: no working leases in persistent database - sleeping",
1514 log_procname);
1515 ifi->state = S_INIT;
1516 set_timeout(ifi, config->retry_interval, state_init);
1517 tick_msg("lease", TICK_DAEMON2);
1518}
1519
1520void
1521send_request(struct interface_info *ifi)
1522{
1523 struct sockaddr_in destination;
1524 struct in_addr from;
1525 struct timespec now;
1526 ssize_t rslt;
1527 char *addr;
1528
1529 cancel_timeout(ifi);
1530 clock_gettime(CLOCK_MONOTONIC3, &now);
1531
1532 switch (ifi->state) {
1533 case S_REBOOTING:
1534 if (timespeccmp(&now, &ifi->reboot_timeout, >=)(((&now)->tv_sec == (&ifi->reboot_timeout)->
tv_sec) ? ((&now)->tv_nsec >= (&ifi->reboot_timeout
)->tv_nsec) : ((&now)->tv_sec >= (&ifi->reboot_timeout
)->tv_sec))
)
1535 ifi->state = S_INIT;
1536 else {
1537 destination.sin_addr.s_addr = INADDR_BROADCAST((u_int32_t)(0xffffffff));
1538 if (ifi->active == NULL((void *)0))
1539 from.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1540 else
1541 from.s_addr = ifi->active->address.s_addr;
1542 }
1543 break;
1544 case S_RENEWING:
1545 if (timespeccmp(&now, &ifi->expiry, >=)(((&now)->tv_sec == (&ifi->expiry)->tv_sec) ?
((&now)->tv_nsec >= (&ifi->expiry)->tv_nsec
) : ((&now)->tv_sec >= (&ifi->expiry)->tv_sec
))
)
1546 ifi->state = S_INIT;
1547 else {
1548 if (timespeccmp(&now, &ifi->rebind, >=)(((&now)->tv_sec == (&ifi->rebind)->tv_sec) ?
((&now)->tv_nsec >= (&ifi->rebind)->tv_nsec
) : ((&now)->tv_sec >= (&ifi->rebind)->tv_sec
))
)
1549 destination.sin_addr.s_addr = INADDR_BROADCAST((u_int32_t)(0xffffffff));
1550 else
1551 destination.sin_addr.s_addr = ifi->destination.s_addr;
1552 if (ifi->active == NULL((void *)0))
1553 from.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1554 else
1555 from.s_addr = ifi->active->address.s_addr;
1556 }
1557 break;
1558 case S_REQUESTING:
1559 if (timespeccmp(&now, &ifi->offer_timeout, >=)(((&now)->tv_sec == (&ifi->offer_timeout)->tv_sec
) ? ((&now)->tv_nsec >= (&ifi->offer_timeout
)->tv_nsec) : ((&now)->tv_sec >= (&ifi->offer_timeout
)->tv_sec))
)
1560 ifi->state = S_INIT;
1561 else {
1562 destination.sin_addr.s_addr = INADDR_BROADCAST((u_int32_t)(0xffffffff));
1563 from.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1564 }
1565 break;
1566 default:
1567 ifi->state = S_INIT;
1568 break;
1569 }
1570
1571 if (ifi->state == S_INIT) {
1572 /* Something has gone wrong. Start over. */
1573 state_init(ifi);
1574 return;
1575 }
1576
1577 set_resend_timeout(ifi, &now, send_request);
1578 set_interval(ifi, &now);
1579 set_secs(ifi, &now);
1580
1581 rslt = send_packet(ifi, from, destination.sin_addr, "DHCPREQUEST");
1582 if (rslt != -1 && log_getverbose()) {
1583 addr = strdup(inet_ntoa(ifi->requested_address));
1584 if (addr == NULL((void *)0))
1585 fatal("strdup(ifi->requested_address)");
1586 if (destination.sin_addr.s_addr == INADDR_BROADCAST((u_int32_t)(0xffffffff)))
1587 log_debug("%s: DHCPREQUEST %s", log_procname, addr);
1588 else
1589 log_debug("%s: DHCPREQUEST %s from %s", log_procname,
1590 addr, inet_ntoa(destination.sin_addr));
1591 free(addr);
1592 }
1593
1594 tick_msg("lease", TICK_WAIT0);
1595}
1596
1597void
1598send_decline(struct interface_info *ifi)
1599{
1600 ssize_t rslt;
1601
1602 rslt = send_packet(ifi, inaddr_any, inaddr_broadcast, "DHCPDECLINE");
1603 if (rslt != -1)
1604 log_debug("%s: DHCPDECLINE", log_procname);
1605}
1606
1607void
1608send_release(struct interface_info *ifi)
1609{
1610 ssize_t rslt;
1611
1612 rslt = send_packet(ifi, ifi->configured->address, ifi->destination,
1613 "DHCPRELEASE");
1614 if (rslt != -1)
1615 log_debug("%s: DHCPRELEASE", log_procname);
1616}
1617
1618void
1619make_discover(struct interface_info *ifi, struct client_lease *lease)
1620{
1621 struct option_data options[DHO_COUNT256];
1622 struct dhcp_packet *packet = &ifi->sent_packet;
1623 unsigned char discover = DHCPDISCOVER1;
1624 int i;
1625
1626 memset(options, 0, sizeof(options));
1627 memset(packet, 0, sizeof(*packet));
1628
1629 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1630 i = DHO_DHCP_MESSAGE_TYPE53;
1631 options[i].data = &discover;
1632 options[i].len = sizeof(discover);
1633
1634 /* Request the options we want */
1635 i = DHO_DHCP_PARAMETER_REQUEST_LIST55;
1636 options[i].data = config->requested_options;
1637 options[i].len = config->requested_option_count;
1638
1639 /* If we had an address, try to get it again. */
1640 if (lease != NULL((void *)0)) {
1641 ifi->requested_address = lease->address;
1642 i = DHO_DHCP_REQUESTED_ADDRESS50;
1643 options[i].data = (char *)&lease->address;
1644 options[i].len = sizeof(lease->address);
1645 } else
1646 ifi->requested_address.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1647
1648 /* Send any options requested in the config file. */
1649 for (i = 0; i < DHO_COUNT256; i++)
1650 if (options[i].data == NULL((void *)0) &&
1651 config->send_options[i].data != NULL((void *)0)) {
1652 options[i].data = config->send_options[i].data;
1653 options[i].len = config->send_options[i].len;
1654 }
1655
1656 /*
1657 * Set up the option buffer to fit in a 576-byte UDP packet, which
1658 * RFC 791 says is the largest packet that *MUST* be accepted
1659 * by any host.
1660 */
1661 i = pack_options(ifi->sent_packet.options, 576 - DHCP_FIXED_LEN(236 + (20 + 8)),
1662 options);
1663 if (i == -1 || packet->options[i] != DHO_END255)
1664 fatalx("options do not fit in DHCPDISCOVER packet");
1665 ifi->sent_packet_length = DHCP_FIXED_NON_UDP236+i+1;
1666 if (ifi->sent_packet_length < BOOTP_MIN_LEN300)
1667 ifi->sent_packet_length = BOOTP_MIN_LEN300;
1668
1669 packet->op = BOOTREQUEST1;
1670 packet->htype = HTYPE_ETHER1;
1671 packet->hlen = ETHER_ADDR_LEN6;
1672 packet->hops = 0;
1673 packet->xid = ifi->xid;
1674 packet->secs = 0; /* filled in by send_discover. */
1675 packet->flags = 0;
1676
1677 packet->ciaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1678 packet->yiaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1679 packet->siaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1680 packet->giaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1681
1682 memcpy(&packet->chaddr, ifi->hw_address.ether_addr_octet,
1683 ETHER_ADDR_LEN6);
1684}
1685
1686void
1687make_request(struct interface_info *ifi, struct client_lease *lease)
1688{
1689 struct option_data options[DHO_COUNT256];
1690 struct dhcp_packet *packet = &ifi->sent_packet;
1691 unsigned char request = DHCPREQUEST3;
1692 int i;
1693
1694 memset(options, 0, sizeof(options));
1695 memset(packet, 0, sizeof(*packet));
1696
1697 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1698 i = DHO_DHCP_MESSAGE_TYPE53;
1699 options[i].data = &request;
1700 options[i].len = sizeof(request);
1701
1702 /* Request the options we want */
1703 i = DHO_DHCP_PARAMETER_REQUEST_LIST55;
1704 options[i].data = config->requested_options;
1705 options[i].len = config->requested_option_count;
1706
1707 /*
1708 * If we are requesting an address that hasn't yet been assigned
1709 * to us, use the DHCP Requested Address option.
1710 */
1711 if (ifi->state == S_REQUESTING) {
1712 /* Send back the server identifier. */
1713 i = DHO_DHCP_SERVER_IDENTIFIER54;
1714 options[i].data = lease->options[i].data;
1715 options[i].len = lease->options[i].len;
1716 }
1717 if (ifi->state == S_REQUESTING ||
1718 ifi->state == S_REBOOTING) {
1719 i = DHO_DHCP_REQUESTED_ADDRESS50;
1720 options[i].data = (char *)&lease->address.s_addr;
1721 options[i].len = sizeof(lease->address.s_addr);
1722 }
1723
1724 /* Send any options requested in the config file. */
1725 for (i = 0; i < DHO_COUNT256; i++)
1726 if (options[i].data == NULL((void *)0) &&
1727 config->send_options[i].data != NULL((void *)0)) {
1728 options[i].data = config->send_options[i].data;
1729 options[i].len = config->send_options[i].len;
1730 }
1731
1732 /*
1733 * Set up the option buffer to fit in a 576-byte UDP packet, which
1734 * RFC 791 says is the largest packet that *MUST* be accepted
1735 * by any host.
1736 */
1737 i = pack_options(ifi->sent_packet.options, 576 - DHCP_FIXED_LEN(236 + (20 + 8)),
1738 options);
1739 if (i == -1 || packet->options[i] != DHO_END255)
1740 fatalx("options do not fit in DHCPREQUEST packet");
1741 ifi->sent_packet_length = DHCP_FIXED_NON_UDP236+i+1;
1742 if (ifi->sent_packet_length < BOOTP_MIN_LEN300)
1743 ifi->sent_packet_length = BOOTP_MIN_LEN300;
1744
1745 packet->op = BOOTREQUEST1;
1746 packet->htype = HTYPE_ETHER1;
1747 packet->hlen = ETHER_ADDR_LEN6;
1748 packet->hops = 0;
1749 packet->xid = ifi->xid;
1750 packet->secs = 0; /* Filled in by send_request. */
1751 packet->flags = 0;
1752
1753 /*
1754 * If we own the address we're requesting, put it in ciaddr. Otherwise
1755 * set ciaddr to zero.
1756 */
1757 ifi->requested_address = lease->address;
1758 if (ifi->state == S_BOUND ||
1759 ifi->state == S_RENEWING)
1760 packet->ciaddr.s_addr = lease->address.s_addr;
1761 else
1762 packet->ciaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1763
1764 packet->yiaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1765 packet->siaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1766 packet->giaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1767
1768 memcpy(&packet->chaddr, ifi->hw_address.ether_addr_octet,
1769 ETHER_ADDR_LEN6);
1770}
1771
1772void
1773make_decline(struct interface_info *ifi, struct client_lease *lease)
1774{
1775 struct option_data options[DHO_COUNT256];
1776 struct dhcp_packet *packet = &ifi->sent_packet;
1777 unsigned char decline = DHCPDECLINE4;
1778 int i;
1779
1780 memset(options, 0, sizeof(options));
1781 memset(packet, 0, sizeof(*packet));
1782
1783 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1784 i = DHO_DHCP_MESSAGE_TYPE53;
1785 options[i].data = &decline;
1786 options[i].len = sizeof(decline);
1787
1788 /* Send back the server identifier. */
1789 i = DHO_DHCP_SERVER_IDENTIFIER54;
1790 options[i].data = lease->options[i].data;
1791 options[i].len = lease->options[i].len;
1792
1793 /* Send back the address we're declining. */
1794 i = DHO_DHCP_REQUESTED_ADDRESS50;
1795 options[i].data = (char *)&lease->address.s_addr;
1796 options[i].len = sizeof(lease->address.s_addr);
1797
1798 /* Send the uid if the user supplied one. */
1799 i = DHO_DHCP_CLIENT_IDENTIFIER61;
1800 if (config->send_options[i].len != 0) {
1801 options[i].data = config->send_options[i].data;
1802 options[i].len = config->send_options[i].len;
1803 }
1804
1805 /*
1806 * Set up the option buffer to fit in a 576-byte UDP packet, which
1807 * RFC 791 says is the largest packet that *MUST* be accepted
1808 * by any host.
1809 */
1810 i = pack_options(ifi->sent_packet.options, 576 - DHCP_FIXED_LEN(236 + (20 + 8)),
1811 options);
1812 if (i == -1 || packet->options[i] != DHO_END255)
1813 fatalx("options do not fit in DHCPDECLINE packet");
1814 ifi->sent_packet_length = DHCP_FIXED_NON_UDP236+i+1;
1815 if (ifi->sent_packet_length < BOOTP_MIN_LEN300)
1816 ifi->sent_packet_length = BOOTP_MIN_LEN300;
1817
1818 packet->op = BOOTREQUEST1;
1819 packet->htype = HTYPE_ETHER1;
1820 packet->hlen = ETHER_ADDR_LEN6;
1821 packet->hops = 0;
1822 packet->xid = ifi->xid;
1823 packet->secs = 0;
1824 packet->flags = 0;
1825
1826 /* ciaddr must always be zero. */
1827 packet->ciaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1828 packet->yiaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1829 packet->siaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1830 packet->giaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1831
1832 memcpy(&packet->chaddr, ifi->hw_address.ether_addr_octet,
1833 ETHER_ADDR_LEN6);
1834}
1835
1836void
1837make_release(struct interface_info *ifi, struct client_lease *lease)
1838{
1839 struct option_data options[DHO_COUNT256];
1840 struct dhcp_packet *packet = &ifi->sent_packet;
1841 unsigned char release = DHCPRELEASE7;
1842 int i;
1843
1844 memset(options, 0, sizeof(options));
1845 memset(packet, 0, sizeof(*packet));
1846
1847 /* Set DHCP_MESSAGE_TYPE to DHCPRELEASE */
1848 i = DHO_DHCP_MESSAGE_TYPE53;
1849 options[i].data = &release;
1850 options[i].len = sizeof(release);
1851
1852 /* Send back the server identifier. */
1853 i = DHO_DHCP_SERVER_IDENTIFIER54;
1854 options[i].data = lease->options[i].data;
1855 options[i].len = lease->options[i].len;
1856
1857 i = pack_options(ifi->sent_packet.options, 576 - DHCP_FIXED_LEN(236 + (20 + 8)),
1858 options);
1859 if (i == -1 || packet->options[i] != DHO_END255)
1860 fatalx("options do not fit in DHCPRELEASE packet");
1861 ifi->sent_packet_length = DHCP_FIXED_NON_UDP236+i+1;
1862 if (ifi->sent_packet_length < BOOTP_MIN_LEN300)
1863 ifi->sent_packet_length = BOOTP_MIN_LEN300;
1864
1865 packet->op = BOOTREQUEST1;
1866 packet->htype = HTYPE_ETHER1;
1867 packet->hlen = ETHER_ADDR_LEN6;
1868 packet->hops = 0;
1869 packet->xid = ifi->xid;
1870 packet->secs = 0;
1871 packet->flags = 0;
1872
1873 /*
1874 * Note we return the *offered* address. NOT the configured address
1875 * which could have been changed via dhclient.conf. But the packet
1876 * is sent from the *configured* address.
1877 *
1878 * This might easily confuse a server, but if you play with fire
1879 * by modifying the address you are on your own!
1880 */
1881 packet->ciaddr.s_addr = ifi->active->address.s_addr;
1882 packet->yiaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1883 packet->siaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1884 packet->giaddr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
1885
1886 memcpy(&packet->chaddr, ifi->hw_address.ether_addr_octet,
1887 ETHER_ADDR_LEN6);
1888}
1889
1890void
1891free_client_lease(struct client_lease *lease)
1892{
1893 int i;
1894
1895 if (lease == NULL((void *)0))
1896 return;
1897
1898 free(lease->server_name);
1899 free(lease->filename);
1900 for (i = 0; i < DHO_COUNT256; i++)
1901 free(lease->options[i].data);
1902
1903 free(lease);
1904}
1905
1906void
1907write_lease_db(struct interface_info *ifi)
1908{
1909 struct client_lease_tq *lease_db = &ifi->lease_db;
1910 struct client_lease *lp, *pl;
1911 char *leasestr;
1912
1913 TAILQ_FOREACH_SAFE(lp, lease_db, next, pl)for ((lp) = ((lease_db)->tqh_first); (lp) != ((void *)0) &&
((pl) = ((lp)->next.tqe_next), 1); (lp) = (pl))
{
1914 if (lp != ifi->active && lease_expiry(lp) == 0) {
1915 TAILQ_REMOVE(lease_db, lp, next)do { if (((lp)->next.tqe_next) != ((void *)0)) (lp)->next
.tqe_next->next.tqe_prev = (lp)->next.tqe_prev; else (lease_db
)->tqh_last = (lp)->next.tqe_prev; *(lp)->next.tqe_prev
= (lp)->next.tqe_next; ; ; } while (0)
;
1916 free_client_lease(lp);
1917 }
1918 }
1919
1920 if (leaseFile == NULL((void *)0))
1921 return;
1922
1923 rewind(leaseFile);
1924
1925 /*
1926 * The leases file is kept in chronological order, with the
1927 * most recently bound lease last. When the file was read
1928 * leases that were not expired were added to the head of the
1929 * TAILQ ifi->leases as they were read. Therefore write out
1930 * the leases in ifi->leases in reverse order to recreate
1931 * the chonological order required.
1932 */
1933 TAILQ_FOREACH_REVERSE(lp, lease_db, client_lease_tq, next)for((lp) = (*(((struct client_lease_tq *)((lease_db)->tqh_last
))->tqh_last)); (lp) != ((void *)0); (lp) = (*(((struct client_lease_tq
*)((lp)->next.tqe_prev))->tqh_last)))
{
1934 leasestr = lease_as_string("lease", lp);
1935 if (leasestr != NULL((void *)0))
1936 fprintf(leaseFile, "%s", leasestr);
1937 else
1938 log_warnx("%s: cannot make lease into string",
1939 log_procname);
1940 }
1941
1942 fflush(leaseFile);
1943 ftruncate(fileno(leaseFile)(!__isthreaded ? ((leaseFile)->_file) : (fileno)(leaseFile
))
, ftello(leaseFile));
1944 fsync(fileno(leaseFile)(!__isthreaded ? ((leaseFile)->_file) : (fileno)(leaseFile
))
);
1945}
1946
1947void
1948append_statement(char *string, size_t sz, char *s1, char *s2)
1949{
1950 strlcat(string, s1, sz);
1951 strlcat(string, s2, sz);
1952 strlcat(string, ";\n", sz);
1953}
1954
1955struct unwind_info *
1956lease_as_unwind_info(struct client_lease *lease)
1957{
1958 struct unwind_info *unwind_info;
1959 struct option_data *opt;
1960 unsigned int servers;
1961
1962 unwind_info = calloc(1, sizeof(*unwind_info));
1963 if (unwind_info == NULL((void *)0))
1964 fatal("unwind_info");
1965
1966 opt = &lease->options[DHO_DOMAIN_NAME_SERVERS6];
1967 if (opt->len != 0) {
1968 servers = opt->len / sizeof(in_addr_t);
1969 if (servers > MAXNS3)
1970 servers = MAXNS3;
1971 if (servers > 0) {
1972 unwind_info->count = servers;
1973 memcpy(unwind_info->ns, opt->data, servers *
1974 sizeof(in_addr_t));
1975 }
1976 }
1977
1978 if (unwind_info->count == 0) {
1979 free(unwind_info);
1980 unwind_info = NULL((void *)0);
1981 }
1982
1983 return unwind_info;
1984}
1985
1986struct proposal *
1987lease_as_proposal(struct client_lease *lease)
1988{
1989 uint8_t defroute[5]; /* 1 + sizeof(in_addr_t) */
1990 struct option_data fake;
1991 struct option_data *opt;
1992 struct proposal *proposal;
1993 uint8_t *ns, *p, *routes, *domains;
1
'ns' declared without an initial value
1994 unsigned int routes_len = 0, domains_len = 0, ns_len = 0;
1995 uint16_t mtu;
1996
1997 /* Determine sizes of variable length data. */
1998 opt = NULL((void *)0);
1999 if (lease->options[DHO_CLASSLESS_STATIC_ROUTES121].len != 0) {
2
Assuming field 'len' is not equal to 0
3
Taking true branch
2000 opt = &lease->options[DHO_CLASSLESS_STATIC_ROUTES121];
2001 } else if (lease->options[DHO_CLASSLESS_MS_STATIC_ROUTES249].len != 0) {
2002 opt = &lease->options[DHO_CLASSLESS_MS_STATIC_ROUTES249];
2003 } else if (lease->options[DHO_ROUTERS3].len != 0) {
2004 /* Fake a classless static default route. */
2005 opt = &lease->options[DHO_ROUTERS3];
2006 fake.len = sizeof(defroute);
2007 fake.data = defroute;
2008 fake.data[0] = 0;
2009 memcpy(&fake.data[1], opt->data, sizeof(defroute) - 1);
2010 opt = &fake;
2011 }
2012 if (opt
3.1
'opt' is not equal to NULL
!= NULL((void *)0)) {
4
Taking true branch
2013 routes_len = opt->len;
2014 routes = opt->data;
2015 }
2016
2017 opt = NULL((void *)0);
2018 if (lease->options[DHO_DOMAIN_SEARCH119].len != 0)
5
Assuming field 'len' is not equal to 0
6
Taking true branch
2019 opt = &lease->options[DHO_DOMAIN_SEARCH119];
2020 else if (lease->options[DHO_DOMAIN_NAME15].len != 0)
2021 opt = &lease->options[DHO_DOMAIN_NAME15];
2022 if (opt
6.1
'opt' is not equal to NULL
!= NULL((void *)0)) {
7
Taking true branch
2023 domains_len = opt->len;
2024 domains = opt->data;
2025 }
2026
2027 if (lease->options[DHO_DOMAIN_NAME_SERVERS6].len != 0) {
8
Assuming field 'len' is equal to 0
9
Taking false branch
2028 opt = &lease->options[DHO_DOMAIN_NAME_SERVERS6];
2029 ns_len = opt->len;
2030 ns = opt->data;
2031 }
2032
2033 /* Allocate proposal. */
2034 proposal = calloc(1, sizeof(*proposal) + routes_len + domains_len +
2035 ns_len);
2036 if (proposal == NULL((void *)0))
10
Assuming 'proposal' is not equal to NULL
11
Taking false branch
2037 fatal("proposal");
2038
2039 /* Fill in proposal. */
2040 proposal->address = lease->address;
2041
2042 opt = &lease->options[DHO_INTERFACE_MTU26];
2043 if (opt->len == sizeof(mtu)) {
12
Assuming the condition is false
13
Taking false branch
2044 memcpy(&mtu, opt->data, sizeof(mtu));
2045 proposal->mtu = ntohs(mtu)(__uint16_t)(__builtin_constant_p(mtu) ? (__uint16_t)(((__uint16_t
)(mtu) & 0xffU) << 8 | ((__uint16_t)(mtu) & 0xff00U
) >> 8) : __swap16md(mtu))
;
2046 }
2047
2048 opt = &lease->options[DHO_SUBNET_MASK1];
2049 if (opt->len == sizeof(proposal->netmask))
14
Assuming the condition is false
15
Taking false branch
2050 memcpy(&proposal->netmask, opt->data, opt->len);
2051
2052 /* Append variable length uint8_t data. */
2053 p = (uint8_t *)proposal + sizeof(struct proposal);
2054 memcpy(p, routes, routes_len);
2055 p += routes_len;
2056 proposal->routes_len = routes_len;
2057 memcpy(p, domains, domains_len);
2058 p += domains_len;
2059 proposal->domains_len = domains_len;
2060 memcpy(p, ns, ns_len);
16
2nd function call argument is an uninitialized value
2061 proposal->ns_len = ns_len;
2062
2063 return proposal;
2064}
2065
2066char *
2067lease_as_string(char *type, struct client_lease *lease)
2068{
2069 static char string[8192];
2070 char timebuf[27]; /* 6 2017/04/08 05:47:50 UTC; */
2071 struct option_data *opt;
2072 char *buf, *name;
2073 time_t t;
2074 size_t rslt;
2075 int i;
2076
2077 memset(string, 0, sizeof(string));
2078
2079 strlcat(string, type, sizeof(string));
2080 strlcat(string, " {\n", sizeof(string));
2081 strlcat(string, BOOTP_LEASE(lease)((lease)->options[53].len == 0) ? " bootp;\n" : "", sizeof(string));
2082
2083 append_statement(string, sizeof(string), " fixed-address ",
2084 inet_ntoa(lease->address));
2085 append_statement(string, sizeof(string), " next-server ",
2086 inet_ntoa(lease->next_server));
2087
2088 if (lease->filename != NULL((void *)0)) {
2089 buf = pretty_print_string(lease->filename,
2090 strlen(lease->filename), 1);
2091 if (buf == NULL((void *)0))
2092 return NULL((void *)0);
2093 append_statement(string, sizeof(string), " filename ", buf);
2094 }
2095 if (lease->server_name != NULL((void *)0)) {
2096 buf = pretty_print_string(lease->server_name,
2097 strlen(lease->server_name), 1);
2098 if (buf == NULL((void *)0))
2099 return NULL((void *)0);
2100 append_statement(string, sizeof(string), " server-name ",
2101 buf);
2102 }
2103 if (lease->ssid_len != 0) {
2104 buf = pretty_print_string(lease->ssid, lease->ssid_len, 1);
2105 if (buf == NULL((void *)0))
2106 return NULL((void *)0);
2107 append_statement(string, sizeof(string), " ssid ", buf);
2108 }
2109
2110 for (i = 0; i < DHO_COUNT256; i++) {
2111 opt = &lease->options[i];
2112 if (opt->len == 0)
2113 continue;
2114 name = code_to_name(i);
2115
2116 buf = pretty_print_option(i, opt, 1);
2117 if (strlen(buf) == 0)
2118 continue;
2119 strlcat(string, " option ", sizeof(string));
2120 strlcat(string, name, sizeof(string));
2121 append_statement(string, sizeof(string), " ", buf);
2122 }
2123
2124 i = asprintf(&buf, "%lld", (long long)lease->epoch);
2125 if (i == -1)
2126 return NULL((void *)0);
2127 append_statement(string, sizeof(string), " epoch ", buf);
2128 free(buf);
2129
2130 t = lease->epoch + lease_renewal(lease);
2131 rslt = strftime(timebuf, sizeof(timebuf), DB_TIMEFMT"%w %Y/%m/%d %T UTC", gmtime(&t));
2132 if (rslt == 0)
2133 return NULL((void *)0);
2134 append_statement(string, sizeof(string), " renew ", timebuf);
2135
2136 t = lease->epoch + lease_rebind(lease);
2137 rslt = strftime(timebuf, sizeof(timebuf), DB_TIMEFMT"%w %Y/%m/%d %T UTC", gmtime(&t));
2138 if (rslt == 0)
2139 return NULL((void *)0);
2140 append_statement(string, sizeof(string), " rebind ", timebuf);
2141
2142 t = lease->epoch + lease_expiry(lease);
2143 rslt = strftime(timebuf, sizeof(timebuf), DB_TIMEFMT"%w %Y/%m/%d %T UTC", gmtime(&t));
2144 if (rslt == 0)
2145 return NULL((void *)0);
2146 append_statement(string, sizeof(string), " expire ", timebuf);
2147
2148 rslt = strlcat(string, "}\n", sizeof(string));
2149 if (rslt >= sizeof(string))
2150 return NULL((void *)0);
2151
2152 return string;
2153}
2154
2155void
2156go_daemon(void)
2157{
2158 static int daemonized = 0;
2159
2160 if ((cmd_opts & OPT_FOREGROUND0x04) != 0 || daemonized != 0)
2161 return;
2162
2163 daemonized = 1;
2164
2165 if (rdaemon(nullfd) == -1)
2166 fatal("daemonize");
2167
2168 /* Stop logging to stderr. */
2169 log_init(0, LOG_DAEMON(3<<3));
2170 if ((cmd_opts & OPT_VERBOSE0x02) != 0)
2171 log_setverbose(1); /* Show log_debug() messages. */
2172 log_procinit(log_procname);
2173
2174 setproctitle("%s", log_procname);
2175 signal(SIGHUP1, SIG_IGN(void (*)(int))1);
2176 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
2177}
2178
2179int
2180rdaemon(int devnull)
2181{
2182 if (devnull == -1) {
2183 errno(*__errno()) = EBADF9;
2184 return -1;
2185 }
2186 if (fcntl(devnull, F_GETFL3) == -1)
2187 return -1;
2188
2189 switch (fork()) {
2190 case -1:
2191 return -1;
2192 case 0:
2193 break;
2194 default:
2195 _exit(0);
2196 }
2197
2198 if (setsid() == -1)
2199 return -1;
2200
2201 (void)dup2(devnull, STDIN_FILENO0);
2202 (void)dup2(devnull, STDOUT_FILENO1);
2203 (void)dup2(devnull, STDERR_FILENO2);
2204 if (devnull > 2)
2205 (void)close(devnull);
2206
2207 return 0;
2208}
2209
2210/*
2211 * resolv_conf(5) says a max of DHCP_DOMAIN_SEARCH_CNT domains and total
2212 * length of DHCP_DOMAIN_SEARCH_LEN bytes are acceptable for the 'search'
2213 * statement.
2214 */
2215int
2216res_hnok_list(const char *names)
2217{
2218 char *dupnames, *hn, *inputstring;
2219 int count;
2220
2221 if (strlen(names) >= DHCP_DOMAIN_SEARCH_LEN1024)
2222 return 0;
2223
2224 dupnames = inputstring = strdup(names);
2225 if (inputstring == NULL((void *)0))
2226 fatal("domain name list");
2227
2228 count = 0;
2229 while ((hn = strsep(&inputstring, " \t")) != NULL((void *)0)) {
2230 if (strlen(hn) == 0)
2231 continue;
2232 if (res_hnok__res_hnok(hn) == 0)
2233 break;
2234 count++;
2235 if (count > DHCP_DOMAIN_SEARCH_CNT6)
2236 break;
2237 }
2238
2239 free(dupnames);
2240
2241 return count > 0 && count < 7 && hn == NULL((void *)0);
2242}
2243
2244/*
2245 * Decode a byte string encoding a list of domain names as specified in RFC1035
2246 * section 4.1.4.
2247 *
2248 * The result is a string consisting of a blank separated list of domain names.
2249 *
2250 * e.g.
2251 *
2252 * 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
2253 *
2254 * which represents
2255 *
2256 * 3 |'e'|'n'|'g'| 5 |'a'|'p'|'p'|'l'|
2257 * 'e'| 3 |'c'|'o'|'m'| 0 | 9 |'m'|'a'|
2258 * 'r'|'k'|'e'|'t'|'i'|'n'|'g'|xC0|x04|
2259 *
2260 * will be translated to
2261 *
2262 * "eng.apple.com. marketing.apple.com."
2263 */
2264char *
2265rfc1035_as_string(unsigned char *src, size_t srclen)
2266{
2267 static char search[DHCP_DOMAIN_SEARCH_LEN1024];
2268 unsigned char name[DHCP_DOMAIN_SEARCH_LEN1024];
2269 unsigned char *endsrc, *cp;
2270 int len, domains;
2271
2272 memset(search, 0, sizeof(search));
2273
2274 /* Compute expanded length. */
2275 domains = 0;
2276 cp = src;
2277 endsrc = src + srclen;
2278
2279 while (cp < endsrc && domains < DHCP_DOMAIN_SEARCH_CNT6) {
2280 len = dn_expand(src, endsrc, cp, name, sizeof(name));
2281 if (len == -1)
2282 goto bad;
2283 cp += len;
2284 if (domains > 0)
2285 strlcat(search, " ", sizeof(search));
2286 strlcat(search, name, sizeof(search));
2287 if (strlcat(search, ".", sizeof(search)) >= sizeof(search))
2288 goto bad;
2289 domains++;
2290 }
2291
2292 return search;
2293
2294bad:
2295 memset(search, 0, sizeof(search));
2296 return search;
2297}
2298
2299void
2300fork_privchld(struct interface_info *ifi, int fd, int fd2)
2301{
2302 struct pollfd pfd[1];
2303 struct imsgbuf *priv_ibuf;
2304 ssize_t n;
2305 int ioctlfd, routefd, nfds, rslt;
2306
2307 switch (fork()) {
2308 case -1:
2309 fatal("fork");
2310 break;
2311 case 0:
2312 break;
2313 default:
2314 return;
2315 }
2316
2317 if (chdir("/") == -1)
2318 fatal("chdir(\"/\")");
2319
2320 go_daemon();
2321
2322 free(log_procname);
2323 rslt = asprintf(&log_procname, "%s [priv]", ifi->name);
2324 if (rslt == -1)
2325 fatal("log_procname");
2326 setproctitle("%s", log_procname);
2327 log_procinit(log_procname);
2328
2329 close(fd2);
2330
2331 if ((priv_ibuf = malloc(sizeof(*priv_ibuf))) == NULL((void *)0))
2332 fatal("priv_ibuf");
2333
2334 imsg_init(priv_ibuf, fd);
2335
2336 if ((ioctlfd = socket(AF_INET2, SOCK_DGRAM2, 0)) == -1)
2337 fatal("socket(AF_INET, SOCK_DGRAM)");
2338 if ((routefd = socket(AF_ROUTE17, SOCK_RAW3, 0)) == -1)
2339 fatal("socket(AF_ROUTE, SOCK_RAW)");
2340
2341 if (unveil(_PATH_RESCONF"/etc/resolv.conf", "wc") == -1)
2342 fatal("unveil %s", _PATH_RESCONF"/etc/resolv.conf");
2343 if (unveil("/etc/resolv.conf.tail", "r") == -1)
2344 fatal("unveil /etc/resolve.conf.tail");
2345 if (unveil(NULL((void *)0), NULL((void *)0)) == -1)
2346 fatal("unveil");
2347
2348 while (quit == 0) {
2349 pfd[0].fd = priv_ibuf->fd;
2350 pfd[0].events = POLLIN0x0001;
2351
2352 nfds = ppoll(pfd, 1, NULL((void *)0), NULL((void *)0));
2353 if (nfds == -1) {
2354 if (errno(*__errno()) == EINTR4)
2355 continue;
2356 log_warn("%s: ppoll(priv_ibuf)", log_procname);
2357 break;
2358 }
2359 if ((pfd[0].revents & (POLLERR0x0008 | POLLHUP0x0010 | POLLNVAL0x0020)) != 0)
2360 break;
2361 if (nfds == 0 || (pfd[0].revents & POLLIN0x0001) == 0)
2362 continue;
2363
2364 if ((n = imsg_read(priv_ibuf)) == -1 && errno(*__errno()) != EAGAIN35) {
2365 log_warn("%s: imsg_read(priv_ibuf)", log_procname);
2366 break;
2367 }
2368 if (n == 0) {
2369 /* Connection closed - other end should log message. */
2370 break;
2371 }
2372
2373 dispatch_imsg(ifi->name, ifi->rdomain, ioctlfd, routefd,
2374 priv_ibuf);
2375 }
2376 close(routefd);
2377 close(ioctlfd);
2378
2379 imsg_clear(priv_ibuf);
2380 close(fd);
2381
2382 exit(1);
2383}
2384
2385struct client_lease *
2386apply_defaults(struct client_lease *lease)
2387{
2388 struct option_data emptyopt = {0, NULL((void *)0)};
2389 struct client_lease *newlease;
2390 char *fmt;
2391 int i;
2392
2393 newlease = clone_lease(lease);
2394 if (newlease == NULL((void *)0))
2395 fatalx("unable to clone lease");
2396
2397 if (config->filename != NULL((void *)0)) {
2398 free(newlease->filename);
2399 newlease->filename = strdup(config->filename);
2400 if (newlease->filename == NULL((void *)0))
2401 fatal("strdup(config->filename)");
2402 }
2403 if (config->server_name != NULL((void *)0)) {
2404 free(newlease->server_name);
2405 newlease->server_name = strdup(config->server_name);
2406 if (newlease->server_name == NULL((void *)0))
2407 fatal("strdup(config->server_name)");
2408 }
2409 if (config->address.s_addr != INADDR_ANY((u_int32_t)(0x00000000)))
2410 newlease->address.s_addr = config->address.s_addr;
2411 if (config->next_server.s_addr != INADDR_ANY((u_int32_t)(0x00000000)))
2412 newlease->next_server.s_addr = config->next_server.s_addr;
2413
2414 for (i = 0; i < DHO_COUNT256; i++) {
2415 fmt = code_to_format(i);
2416 switch (config->default_actions[i]) {
2417 case ACTION_IGNORE:
2418 merge_option_data(fmt, &emptyopt, &emptyopt,
2419 &newlease->options[i]);
2420 break;
2421
2422 case ACTION_SUPERSEDE:
2423 merge_option_data(fmt, &config->defaults[i], &emptyopt,
2424 &newlease->options[i]);
2425 break;
2426
2427 case ACTION_PREPEND:
2428 merge_option_data(fmt, &config->defaults[i],
2429 &lease->options[i], &newlease->options[i]);
2430 break;
2431
2432 case ACTION_APPEND:
2433 merge_option_data(fmt, &lease->options[i],
2434 &config->defaults[i], &newlease->options[i]);
2435 break;
2436
2437 case ACTION_DEFAULT:
2438 if (newlease->options[i].len == 0)
2439 merge_option_data(fmt, &config->defaults[i],
2440 &emptyopt, &newlease->options[i]);
2441 break;
2442
2443 default:
2444 break;
2445 }
2446 }
2447
2448 if (newlease->options[DHO_STATIC_ROUTES33].len != 0) {
2449 log_debug("%s: DHO_STATIC_ROUTES (option 33) not supported",
2450 log_procname);
2451 free(newlease->options[DHO_STATIC_ROUTES33].data);
2452 newlease->options[DHO_STATIC_ROUTES33].data = NULL((void *)0);
2453 newlease->options[DHO_STATIC_ROUTES33].len = 0;
2454 }
2455
2456 /*
2457 * RFC 3442 says client *MUST* ignore DHO_ROUTERS
2458 * when DHO_CLASSLESS_[MS_]_ROUTES present.
2459 */
2460 if ((newlease->options[DHO_CLASSLESS_MS_STATIC_ROUTES249].len != 0) ||
2461 (newlease->options[DHO_CLASSLESS_STATIC_ROUTES121].len != 0)) {
2462 free(newlease->options[DHO_ROUTERS3].data);
2463 newlease->options[DHO_ROUTERS3].data = NULL((void *)0);
2464 newlease->options[DHO_ROUTERS3].len = 0;
2465 }
2466
2467 return newlease;
2468}
2469
2470struct client_lease *
2471clone_lease(struct client_lease *oldlease)
2472{
2473 struct client_lease *newlease;
2474 int i;
2475
2476 newlease = calloc(1, sizeof(*newlease));
2477 if (newlease == NULL((void *)0))
2478 goto cleanup;
2479
2480 newlease->epoch = oldlease->epoch;
2481 newlease->address = oldlease->address;
2482 newlease->next_server = oldlease->next_server;
2483 memcpy(newlease->ssid, oldlease->ssid, sizeof(newlease->ssid));
2484 newlease->ssid_len = oldlease->ssid_len;
2485
2486 if (oldlease->server_name != NULL((void *)0)) {
2487 newlease->server_name = strdup(oldlease->server_name);
2488 if (newlease->server_name == NULL((void *)0))
2489 goto cleanup;
2490 }
2491 if (oldlease->filename != NULL((void *)0)) {
2492 newlease->filename = strdup(oldlease->filename);
2493 if (newlease->filename == NULL((void *)0))
2494 goto cleanup;
2495 }
2496
2497 for (i = 0; i < DHO_COUNT256; i++) {
2498 if (oldlease->options[i].len == 0)
2499 continue;
2500 newlease->options[i].len = oldlease->options[i].len;
2501 newlease->options[i].data = calloc(1,
2502 newlease->options[i].len);
2503 if (newlease->options[i].data == NULL((void *)0))
2504 goto cleanup;
2505 memcpy(newlease->options[i].data, oldlease->options[i].data,
2506 newlease->options[i].len);
2507 }
2508
2509 return newlease;
2510
2511cleanup:
2512 free_client_lease(newlease);
2513
2514 return NULL((void *)0);
2515}
2516
2517int
2518autoconf(struct interface_info *ifi)
2519{
2520 struct ifreq ifr;
2521 int ioctlfd;
2522
2523 if ((ioctlfd = socket(AF_INET2, SOCK_DGRAM2, 0)) == -1)
2524 fatal("socket(AF_INET, SOCK_DGRAM)");
2525
2526 memset(&ifr, 0, sizeof(ifr));
2527 strlcpy(ifr.ifr_name, ifi->name, sizeof(ifr.ifr_name));
2528
2529 if (ioctl(ioctlfd, SIOCGIFXFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((158)))
, (caddr_t)&ifr) < 0)
2530 fatal("SIOGIFXFLAGS");
2531
2532 close(ioctlfd);
2533
2534 return ifr.ifr_flagsifr_ifru.ifru_flags & IFXF_AUTOCONF40x80;
2535}
2536
2537int
2538take_charge(struct interface_info *ifi, int routefd, char *leasespath)
2539{
2540 const struct timespec max_timeout = { 9, 0 };
2541 const struct timespec resend_intvl = { 3, 0 };
2542 const struct timespec leasefile_intvl = { 0, 3000000 };
2543 struct timespec now, resend, stop, timeout;
2544 struct pollfd fds[1];
2545 struct rt_msghdr rtm;
2546 int fd, nfds;
2547
2548 clock_gettime(CLOCK_MONOTONIC3, &now);
2549 resend = now;
2550 timespecadd(&now, &max_timeout, &stop)do { (&stop)->tv_sec = (&now)->tv_sec + (&max_timeout
)->tv_sec; (&stop)->tv_nsec = (&now)->tv_nsec
+ (&max_timeout)->tv_nsec; if ((&stop)->tv_nsec
>= 1000000000L) { (&stop)->tv_sec++; (&stop)->
tv_nsec -= 1000000000L; } } while (0)
;
2551
2552 /*
2553 * Send RTM_PROPOSAL with RTF_PROTO3 set.
2554 *
2555 * When it comes back, we're in charge and other dhclients are
2556 * dead processes walking.
2557 */
2558 memset(&rtm, 0, sizeof(rtm));
2559
2560 rtm.rtm_version = RTM_VERSION5;
2561 rtm.rtm_type = RTM_PROPOSAL0x13;
2562 rtm.rtm_msglen = sizeof(rtm);
2563 rtm.rtm_tableid = ifi->rdomain;
2564 rtm.rtm_index = ifi->index;
2565 rtm.rtm_priority = RTP_PROPOSAL_DHCLIENT58;
2566 rtm.rtm_addrs = 0;
2567 rtm.rtm_flags = RTF_UP0x1 | RTF_PROTO30x2000;
2568
2569 for (fd = -1; fd == -1 && quit != TERMINATE1;) {
2570 clock_gettime(CLOCK_MONOTONIC3, &now);
2571 if (timespeccmp(&now, &stop, >=)(((&now)->tv_sec == (&stop)->tv_sec) ? ((&now
)->tv_nsec >= (&stop)->tv_nsec) : ((&now)->
tv_sec >= (&stop)->tv_sec))
)
2572 fatalx("failed to take charge");
2573
2574 if ((ifi->flags & IFI_IN_CHARGE0x01) == 0) {
2575 if (timespeccmp(&now, &resend, >=)(((&now)->tv_sec == (&resend)->tv_sec) ? ((&
now)->tv_nsec >= (&resend)->tv_nsec) : ((&now
)->tv_sec >= (&resend)->tv_sec))
) {
2576 timespecadd(&resend, &resend_intvl, &resend)do { (&resend)->tv_sec = (&resend)->tv_sec + (&
resend_intvl)->tv_sec; (&resend)->tv_nsec = (&resend
)->tv_nsec + (&resend_intvl)->tv_nsec; if ((&resend
)->tv_nsec >= 1000000000L) { (&resend)->tv_sec++
; (&resend)->tv_nsec -= 1000000000L; } } while (0)
;
2577 rtm.rtm_seq = ifi->xid = arc4random();
2578 if (write(routefd, &rtm, sizeof(rtm)) == -1)
2579 fatal("write(routefd)");
2580 }
2581 timespecsub(&resend, &now, &timeout)do { (&timeout)->tv_sec = (&resend)->tv_sec - (
&now)->tv_sec; (&timeout)->tv_nsec = (&resend
)->tv_nsec - (&now)->tv_nsec; if ((&timeout)->
tv_nsec < 0) { (&timeout)->tv_sec--; (&timeout)
->tv_nsec += 1000000000L; } } while (0)
;
2582 } else {
2583 /*
2584 * Keep trying to open leasefile in 3ms intervals
2585 * while continuing to process any RTM_* messages
2586 * that come in.
2587 */
2588 timeout = leasefile_intvl;
2589 }
2590
2591 fds[0].fd = routefd;
2592 fds[0].events = POLLIN0x0001;
2593 nfds = ppoll(fds, 1, &timeout, NULL((void *)0));
2594 if (nfds == -1) {
2595 if (errno(*__errno()) == EINTR4)
2596 continue;
2597 fatal("ppoll(routefd)");
2598 }
2599
2600 if ((fds[0].revents & (POLLERR0x0008 | POLLHUP0x0010 | POLLNVAL0x0020)) != 0)
2601 fatalx("routefd: ERR|HUP|NVAL");
2602 if (nfds == 1 && (fds[0].revents & POLLIN0x0001) == POLLIN0x0001)
2603 routefd_handler(ifi, routefd);
2604
2605 if (quit != TERMINATE1 && (ifi->flags & IFI_IN_CHARGE0x01) == IFI_IN_CHARGE0x01) {
2606 fd = open(leasespath, O_NONBLOCK0x0004 |
2607 O_RDONLY0x0000|O_EXLOCK0x0020|O_CREAT0x0200|O_NOFOLLOW0x0100, 0640);
2608 if (fd == -1 && errno(*__errno()) != EWOULDBLOCK35)
2609 break;
2610 }
2611 }
2612
2613 return fd;
2614}
2615
2616struct client_lease *
2617get_recorded_lease(struct interface_info *ifi)
2618{
2619 char ifname[IF_NAMESIZE16];
2620 struct client_lease *lp;
2621 int i;
2622
2623 /* Update on-disk db, which clears out expired leases. */
2624 ifi->active = NULL((void *)0);
2625 write_lease_db(ifi);
2626
2627 /* Run through the list of leases and see if one can be used. */
2628 i = DHO_DHCP_CLIENT_IDENTIFIER61;
2629 TAILQ_FOREACH(lp, &ifi->lease_db, next)for((lp) = ((&ifi->lease_db)->tqh_first); (lp) != (
(void *)0); (lp) = ((lp)->next.tqe_next))
{
2630 if (lp->ssid_len != ifi->ssid_len)
2631 continue;
2632 if (memcmp(lp->ssid, ifi->ssid, lp->ssid_len) != 0)
2633 continue;
2634 if ((lp->options[i].len != 0) && ((lp->options[i].len !=
2635 config->send_options[i].len) ||
2636 memcmp(lp->options[i].data, config->send_options[i].data,
2637 lp->options[i].len) != 0))
2638 continue;
2639 if (addressinuse(ifi->name, lp->address, ifname) != 0 &&
2640 strncmp(ifname, ifi->name, IF_NAMESIZE16) != 0)
2641 continue;
2642 break;
2643 }
2644
2645 return lp;
2646}
2647
2648time_t
2649lease_expiry(struct client_lease *lease)
2650{
2651 time_t cur_time;
2652 uint32_t expiry;
2653
2654 time(&cur_time);
2655 expiry = 0;
2656 if (lease->options[DHO_DHCP_LEASE_TIME51].len == sizeof(expiry)) {
2657 memcpy(&expiry, lease->options[DHO_DHCP_LEASE_TIME51].data,
2658 sizeof(expiry));
2659 expiry = ntohl(expiry)(__uint32_t)(__builtin_constant_p(expiry) ? (__uint32_t)(((__uint32_t
)(expiry) & 0xff) << 24 | ((__uint32_t)(expiry) &
0xff00) << 8 | ((__uint32_t)(expiry) & 0xff0000) >>
8 | ((__uint32_t)(expiry) & 0xff000000) >> 24) : __swap32md
(expiry))
;
2660 if (expiry < 60)
2661 expiry = 60;
2662 }
2663 expiry = lease->epoch + expiry - cur_time;
2664
2665 return (expiry > 0) ? expiry : 0;
2666}
2667
2668time_t
2669lease_renewal(struct client_lease *lease)
2670{
2671 time_t cur_time, expiry;
2672 uint32_t renewal;
2673
2674 time(&cur_time);
2675 expiry = lease_expiry(lease);
2676
2677 renewal = expiry / 2;
2678 if (lease->options[DHO_DHCP_RENEWAL_TIME58].len == sizeof(renewal)) {
2679 memcpy(&renewal, lease->options[DHO_DHCP_RENEWAL_TIME58].data,
2680 sizeof(renewal));
2681 renewal = ntohl(renewal)(__uint32_t)(__builtin_constant_p(renewal) ? (__uint32_t)(((__uint32_t
)(renewal) & 0xff) << 24 | ((__uint32_t)(renewal) &
0xff00) << 8 | ((__uint32_t)(renewal) & 0xff0000) >>
8 | ((__uint32_t)(renewal) & 0xff000000) >> 24) : __swap32md
(renewal))
;
2682 }
2683 renewal = lease->epoch + renewal - cur_time;
2684
2685 return (renewal > 0) ? renewal : 0;
2686}
2687
2688time_t
2689lease_rebind(struct client_lease *lease)
2690{
2691 time_t cur_time, expiry;
2692 uint32_t rebind;
2693
2694 time(&cur_time);
2695 expiry = lease_expiry(lease);
2696
2697 rebind = (expiry / 8) * 7;
2698 if (lease->options[DHO_DHCP_REBINDING_TIME59].len == sizeof(rebind)) {
2699 memcpy(&rebind, lease->options[DHO_DHCP_REBINDING_TIME59].data,
2700 sizeof(rebind));
2701 rebind = ntohl(rebind)(__uint32_t)(__builtin_constant_p(rebind) ? (__uint32_t)(((__uint32_t
)(rebind) & 0xff) << 24 | ((__uint32_t)(rebind) &
0xff00) << 8 | ((__uint32_t)(rebind) & 0xff0000) >>
8 | ((__uint32_t)(rebind) & 0xff000000) >> 24) : __swap32md
(rebind))
;
2702 }
2703 rebind = lease->epoch + rebind - cur_time;
2704
2705 return (rebind > 0) ? rebind : 0;
2706}
2707
2708void
2709get_lease_timeouts(struct interface_info *ifi, struct client_lease *lease)
2710{
2711 struct timespec now, interval;
2712
2713 clock_gettime(CLOCK_MONOTONIC3, &now);
2714 timespecclear(&interval)(&interval)->tv_sec = (&interval)->tv_nsec = 0;
2715
2716 interval.tv_sec = lease_expiry(lease);
2717 timespecadd(&now, &interval, &ifi->expiry)do { (&ifi->expiry)->tv_sec = (&now)->tv_sec
+ (&interval)->tv_sec; (&ifi->expiry)->tv_nsec
= (&now)->tv_nsec + (&interval)->tv_nsec; if (
(&ifi->expiry)->tv_nsec >= 1000000000L) { (&
ifi->expiry)->tv_sec++; (&ifi->expiry)->tv_nsec
-= 1000000000L; } } while (0)
;
2718
2719 interval.tv_sec = lease_rebind(lease);
2720 timespecadd(&now, &interval, &ifi->rebind)do { (&ifi->rebind)->tv_sec = (&now)->tv_sec
+ (&interval)->tv_sec; (&ifi->rebind)->tv_nsec
= (&now)->tv_nsec + (&interval)->tv_nsec; if (
(&ifi->rebind)->tv_nsec >= 1000000000L) { (&
ifi->rebind)->tv_sec++; (&ifi->rebind)->tv_nsec
-= 1000000000L; } } while (0)
;
2721
2722 interval.tv_sec = lease_renewal(lease);
2723 timespecadd(&now, &interval, &ifi->renew)do { (&ifi->renew)->tv_sec = (&now)->tv_sec +
(&interval)->tv_sec; (&ifi->renew)->tv_nsec
= (&now)->tv_nsec + (&interval)->tv_nsec; if (
(&ifi->renew)->tv_nsec >= 1000000000L) { (&ifi
->renew)->tv_sec++; (&ifi->renew)->tv_nsec -=
1000000000L; } } while (0)
;
2724
2725 if (timespeccmp(&ifi->rebind, &ifi->expiry, >)(((&ifi->rebind)->tv_sec == (&ifi->expiry)->
tv_sec) ? ((&ifi->rebind)->tv_nsec > (&ifi->
expiry)->tv_nsec) : ((&ifi->rebind)->tv_sec >
(&ifi->expiry)->tv_sec))
)
2726 ifi->rebind = ifi->expiry;
2727 if (timespeccmp(&ifi->renew, &ifi->rebind, >)(((&ifi->renew)->tv_sec == (&ifi->rebind)->
tv_sec) ? ((&ifi->renew)->tv_nsec > (&ifi->
rebind)->tv_nsec) : ((&ifi->renew)->tv_sec > (
&ifi->rebind)->tv_sec))
)
2728 ifi->renew = ifi->rebind;
2729}
2730
2731void
2732tick_msg(const char *preamble, int action)
2733{
2734 const struct timespec grace_intvl = {3, 0};
2735 const struct timespec link_intvl = {config->link_interval, 0};
2736 static struct timespec grace, stop;
2737 struct timespec now;
2738 static int linkup, preamble_sent, sleeping;
2739 int printmsg;
2740
2741 clock_gettime(CLOCK_MONOTONIC3, &now);
2742
2743 if (!timespecisset(&stop)((&stop)->tv_sec || (&stop)->tv_nsec)) {
2744 preamble_sent = 0;
2745 timespecadd(&now, &link_intvl, &stop)do { (&stop)->tv_sec = (&now)->tv_sec + (&link_intvl
)->tv_sec; (&stop)->tv_nsec = (&now)->tv_nsec
+ (&link_intvl)->tv_nsec; if ((&stop)->tv_nsec
>= 1000000000L) { (&stop)->tv_sec++; (&stop)->
tv_nsec -= 1000000000L; } } while (0)
;
2746 timespecadd(&now, &grace_intvl, &grace)do { (&grace)->tv_sec = (&now)->tv_sec + (&
grace_intvl)->tv_sec; (&grace)->tv_nsec = (&now
)->tv_nsec + (&grace_intvl)->tv_nsec; if ((&grace
)->tv_nsec >= 1000000000L) { (&grace)->tv_sec++;
(&grace)->tv_nsec -= 1000000000L; } } while (0)
;
2747 return;
2748 }
2749
2750 if (isatty(STDERR_FILENO2) == 0 || sleeping == 1)
2751 printmsg = 0; /* Already in the background. */
2752 else if (timespeccmp(&now, &grace, <)(((&now)->tv_sec == (&grace)->tv_sec) ? ((&
now)->tv_nsec < (&grace)->tv_nsec) : ((&now)
->tv_sec < (&grace)->tv_sec))
)
2753 printmsg = 0; /* Wait a bit before speaking. */
2754 else if (linkup && strcmp("link", preamble) == 0)
2755 printmsg = 0; /* One 'got link' is enough for anyone. */
2756 else if (log_getverbose())
2757 printmsg = 0; /* Verbose has sufficent verbiage. */
2758 else
2759 printmsg = 1;
2760
2761 if (timespeccmp(&now, &stop, >=)(((&now)->tv_sec == (&stop)->tv_sec) ? ((&now
)->tv_nsec >= (&stop)->tv_nsec) : ((&now)->
tv_sec >= (&stop)->tv_sec))
) {
2762 if (action == TICK_WAIT0)
2763 action = TICK_DAEMON2;
2764 if (linkup == 0) {
2765 log_debug("%s: link timeout (%lld seconds) expired",
2766 log_procname, (long long)link_intvl.tv_sec);
2767 linkup = 1;
2768 }
2769 }
2770
2771 if (printmsg && preamble_sent == 0) {
2772 fprintf(stderr(&__sF[2]), "%s: no %s...", log_procname, preamble);
2773 preamble_sent = 1;
2774 }
2775
2776 switch (action) {
2777 case TICK_SUCCESS1:
2778 if (printmsg)
2779 fprintf(stderr(&__sF[2]), "got %s\n", preamble);
2780 preamble_sent = 0;
2781 if (strcmp("link", preamble) == 0) {
2782 linkup = 1;
2783 /* New silent period for "no lease ... got lease". */
2784 timespecadd(&now, &grace_intvl, &grace)do { (&grace)->tv_sec = (&now)->tv_sec + (&
grace_intvl)->tv_sec; (&grace)->tv_nsec = (&now
)->tv_nsec + (&grace_intvl)->tv_nsec; if ((&grace
)->tv_nsec >= 1000000000L) { (&grace)->tv_sec++;
(&grace)->tv_nsec -= 1000000000L; } } while (0)
;
2785 }
2786 break;
2787 case TICK_WAIT0:
2788 if (printmsg)
2789 fprintf(stderr(&__sF[2]), ".");
2790 break;
2791 case TICK_DAEMON2:
2792 if (printmsg)
2793 fprintf(stderr(&__sF[2]), "sleeping\n");
2794 go_daemon();
2795 sleeping = 1; /* OPT_FOREGROUND means isatty() == 1! */
2796 break;
2797 default:
2798 break;
2799 }
2800
2801 if (printmsg)
2802 fflush(stderr(&__sF[2]));
2803}
2804
2805/*
2806 * Release the lease used to configure the interface.
2807 *
2808 * 1) Send DHCPRELEASE.
2809 * 2) Unconfigure address/routes/etc.
2810 * 3) Remove lease from database & write updated DB.
2811 */
2812void
2813release_lease(struct interface_info *ifi)
2814{
2815 char buf[INET_ADDRSTRLEN16];
2816 struct option_data *opt;
2817
2818 if (ifi->configured == NULL((void *)0) || ifi->active == NULL((void *)0))
2819 return; /* Nothing to release. */
2820 strlcpy(buf, inet_ntoa(ifi->configured->address), sizeof(buf));
2821
2822 opt = &ifi->active->options[DHO_DHCP_SERVER_IDENTIFIER54];
2823 if (opt->len == sizeof(in_addr_t))
2824 ifi->destination.s_addr = *(in_addr_t *)opt->data;
2825 else
2826 ifi->destination.s_addr = INADDR_BROADCAST((u_int32_t)(0xffffffff));
2827
2828 ifi->xid = arc4random();
2829 make_release(ifi, ifi->active);
2830 send_release(ifi);
2831
2832 tell_unwind(NULL((void *)0), ifi->flags);
2833
2834 revoke_proposal(ifi->configured);
2835 imsg_flush(unpriv_ibuf);
2836
2837 TAILQ_REMOVE(&ifi->lease_db, ifi->active, next)do { if (((ifi->active)->next.tqe_next) != ((void *)0))
(ifi->active)->next.tqe_next->next.tqe_prev = (ifi->
active)->next.tqe_prev; else (&ifi->lease_db)->tqh_last
= (ifi->active)->next.tqe_prev; *(ifi->active)->
next.tqe_prev = (ifi->active)->next.tqe_next; ; ; } while
(0)
;
2838 free_client_lease(ifi->active);
2839 ifi->active = NULL((void *)0);
2840 write_lease_db(ifi);
2841
2842 free(ifi->configured);
2843 ifi->configured = NULL((void *)0);
2844 free(ifi->unwind_info);
2845 ifi->unwind_info = NULL((void *)0);
2846
2847 log_warnx("%s: %s RELEASED to %s", log_procname, buf,
2848 inet_ntoa(ifi->destination));
2849}
2850
2851void
2852propose_release(struct interface_info *ifi)
2853{
2854 const struct timespec max_timeout = { 3, 0 };
2855 struct timespec now, stop, timeout;
2856 struct pollfd fds[1];
2857 struct rt_msghdr rtm;
2858 int nfds, routefd, rtfilter;
2859
2860 clock_gettime(CLOCK_MONOTONIC3, &now);
2861 timespecadd(&now, &max_timeout, &stop)do { (&stop)->tv_sec = (&now)->tv_sec + (&max_timeout
)->tv_sec; (&stop)->tv_nsec = (&now)->tv_nsec
+ (&max_timeout)->tv_nsec; if ((&stop)->tv_nsec
>= 1000000000L) { (&stop)->tv_sec++; (&stop)->
tv_nsec -= 1000000000L; } } while (0)
;
2862
2863 if ((routefd = socket(AF_ROUTE17, SOCK_RAW3, AF_INET2)) == -1)
2864 fatal("socket(AF_ROUTE, SOCK_RAW)");
2865
2866 rtfilter = ROUTE_FILTER(RTM_PROPOSAL)(1 << (0x13));
2867
2868 if (setsockopt(routefd, AF_ROUTE17, ROUTE_MSGFILTER1,
2869 &rtfilter, sizeof(rtfilter)) == -1)
2870 fatal("setsockopt(ROUTE_MSGFILTER)");
2871 if (setsockopt(routefd, AF_ROUTE17, ROUTE_TABLEFILTER2, &ifi->rdomain,
2872 sizeof(ifi->rdomain)) == -1)
2873 fatal("setsockopt(ROUTE_TABLEFILTER)");
2874
2875 memset(&rtm, 0, sizeof(rtm));
2876 rtm.rtm_version = RTM_VERSION5;
2877 rtm.rtm_type = RTM_PROPOSAL0x13;
2878 rtm.rtm_msglen = sizeof(rtm);
2879 rtm.rtm_tableid = ifi->rdomain;
2880 rtm.rtm_index = ifi->index;
2881 rtm.rtm_priority = RTP_PROPOSAL_DHCLIENT58;
2882 rtm.rtm_addrs = 0;
2883 rtm.rtm_flags = RTF_UP0x1;
2884 rtm.rtm_flags |= RTF_PROTO20x4000;
2885 rtm.rtm_seq = ifi->xid = arc4random();
2886
2887 if (write(routefd, &rtm, sizeof(rtm)) == -1)
2888 fatal("write(routefd)");
2889 log_debug("%s: sent RTM_PROPOSAL to release lease", log_procname);
2890
2891 while (quit == 0) {
2892 clock_gettime(CLOCK_MONOTONIC3, &now);
2893 if (timespeccmp(&now, &stop, >=)(((&now)->tv_sec == (&stop)->tv_sec) ? ((&now
)->tv_nsec >= (&stop)->tv_nsec) : ((&now)->
tv_sec >= (&stop)->tv_sec))
)
2894 break;
2895 timespecsub(&stop, &now, &timeout)do { (&timeout)->tv_sec = (&stop)->tv_sec - (&
now)->tv_sec; (&timeout)->tv_nsec = (&stop)->
tv_nsec - (&now)->tv_nsec; if ((&timeout)->tv_nsec
< 0) { (&timeout)->tv_sec--; (&timeout)->tv_nsec
+= 1000000000L; } } while (0)
;
2896 fds[0].fd = routefd;
2897 fds[0].events = POLLIN0x0001;
2898 nfds = ppoll(fds, 1, &timeout, NULL((void *)0));
2899 if (nfds == -1) {
2900 if (errno(*__errno()) == EINTR4)
2901 continue;
2902 fatal("ppoll(routefd)");
2903 }
2904 if ((fds[0].revents & (POLLERR0x0008 | POLLHUP0x0010 | POLLNVAL0x0020)) != 0)
2905 fatalx("routefd: ERR|HUP|NVAL");
2906 if (nfds == 0 || (fds[0].revents & POLLIN0x0001) == 0)
2907 continue;
2908 routefd_handler(ifi, routefd);
2909 }
2910}