Bug Summary

File:src/sbin/dhclient/dhclient.c
Warning:line 649, column 41
Potential leak of memory pointed to by 'p'

Annotated Source Code

Press '?' to see keyboard shortcuts

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