Update to dhcpcd-9.2.0 with the following changes:
[dragonfly.git] / contrib / dhcpcd / src / dhcpcd.c
blobba0c905a75839528a8bb0049027699e32d04051e
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3 * dhcpcd - DHCP client daemon
4 * Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
5 * All rights reserved
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 const char dhcpcd_copyright[] = "Copyright (c) 2006-2020 Roy Marples";
31 #include <sys/file.h>
32 #include <sys/ioctl.h>
33 #include <sys/socket.h>
34 #include <sys/stat.h>
35 #include <sys/time.h>
36 #include <sys/types.h>
37 #include <sys/uio.h>
38 #include <sys/wait.h>
40 #include <ctype.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <getopt.h>
44 #include <limits.h>
45 #include <paths.h>
46 #include <signal.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <syslog.h>
51 #include <unistd.h>
52 #include <time.h>
54 #include "config.h"
55 #include "arp.h"
56 #include "common.h"
57 #include "control.h"
58 #include "dev.h"
59 #include "dhcp-common.h"
60 #include "dhcpcd.h"
61 #include "dhcp.h"
62 #include "dhcp6.h"
63 #include "duid.h"
64 #include "eloop.h"
65 #include "if.h"
66 #include "if-options.h"
67 #include "ipv4.h"
68 #include "ipv4ll.h"
69 #include "ipv6.h"
70 #include "ipv6nd.h"
71 #include "logerr.h"
72 #include "privsep.h"
73 #include "script.h"
75 #ifdef HAVE_CAPSICUM
76 #include <sys/capsicum.h>
77 #endif
78 #ifdef HAVE_UTIL_H
79 #include <util.h>
80 #endif
82 #ifdef USE_SIGNALS
83 const int dhcpcd_signals[] = {
84 SIGTERM,
85 SIGINT,
86 SIGALRM,
87 SIGHUP,
88 SIGUSR1,
89 SIGUSR2,
90 SIGCHLD,
92 const size_t dhcpcd_signals_len = __arraycount(dhcpcd_signals);
94 const int dhcpcd_signals_ignore[] = {
95 SIGPIPE,
97 const size_t dhcpcd_signals_ignore_len = __arraycount(dhcpcd_signals_ignore);
98 #endif
100 #define IF_UPANDRUNNING(a) \
101 (((a)->flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
103 const char *dhcpcd_default_script = SCRIPT;
105 static void
106 usage(void)
109 printf("usage: "PACKAGE"\t[-146ABbDdEGgHJKLMNPpqTV]\n"
110 "\t\t[-C, --nohook hook] [-c, --script script]\n"
111 "\t\t[-e, --env value] [-F, --fqdn FQDN] [-f, --config file]\n"
112 "\t\t[-h, --hostname hostname] [-I, --clientid clientid]\n"
113 "\t\t[-i, --vendorclassid vendorclassid] [-j, --logfile logfile]\n"
114 "\t\t[-l, --leasetime seconds] [-m, --metric metric]\n"
115 "\t\t[-O, --nooption option] [-o, --option option]\n"
116 "\t\t[-Q, --require option] [-r, --request address]\n"
117 "\t\t[-S, --static value]\n"
118 "\t\t[-s, --inform address[/cidr[/broadcast_address]]]\n [--inform6]"
119 "\t\t[-t, --timeout seconds] [-u, --userclass class]\n"
120 "\t\t[-v, --vendor code, value] [-W, --whitelist address[/cidr]] [-w]\n"
121 "\t\t[--waitip [4 | 6]] [-y, --reboot seconds]\n"
122 "\t\t[-X, --blacklist address[/cidr]] [-Z, --denyinterfaces pattern]\n"
123 "\t\t[-z, --allowinterfaces pattern] [--inactive] [interface] [...]\n"
124 " "PACKAGE"\t-n, --rebind [interface]\n"
125 " "PACKAGE"\t-k, --release [interface]\n"
126 " "PACKAGE"\t-U, --dumplease interface\n"
127 " "PACKAGE"\t--version\n"
128 " "PACKAGE"\t-x, --exit [interface]\n");
131 static void
132 free_globals(struct dhcpcd_ctx *ctx)
134 struct dhcp_opt *opt;
136 if (ctx->ifac) {
137 for (; ctx->ifac > 0; ctx->ifac--)
138 free(ctx->ifav[ctx->ifac - 1]);
139 free(ctx->ifav);
140 ctx->ifav = NULL;
142 if (ctx->ifdc) {
143 for (; ctx->ifdc > 0; ctx->ifdc--)
144 free(ctx->ifdv[ctx->ifdc - 1]);
145 free(ctx->ifdv);
146 ctx->ifdv = NULL;
148 if (ctx->ifcc) {
149 for (; ctx->ifcc > 0; ctx->ifcc--)
150 free(ctx->ifcv[ctx->ifcc - 1]);
151 free(ctx->ifcv);
152 ctx->ifcv = NULL;
155 #ifdef INET
156 if (ctx->dhcp_opts) {
157 for (opt = ctx->dhcp_opts;
158 ctx->dhcp_opts_len > 0;
159 opt++, ctx->dhcp_opts_len--)
160 free_dhcp_opt_embenc(opt);
161 free(ctx->dhcp_opts);
162 ctx->dhcp_opts = NULL;
164 #endif
165 #ifdef INET6
166 if (ctx->nd_opts) {
167 for (opt = ctx->nd_opts;
168 ctx->nd_opts_len > 0;
169 opt++, ctx->nd_opts_len--)
170 free_dhcp_opt_embenc(opt);
171 free(ctx->nd_opts);
172 ctx->nd_opts = NULL;
174 #ifdef DHCP6
175 if (ctx->dhcp6_opts) {
176 for (opt = ctx->dhcp6_opts;
177 ctx->dhcp6_opts_len > 0;
178 opt++, ctx->dhcp6_opts_len--)
179 free_dhcp_opt_embenc(opt);
180 free(ctx->dhcp6_opts);
181 ctx->dhcp6_opts = NULL;
183 #endif
184 #endif
185 if (ctx->vivso) {
186 for (opt = ctx->vivso;
187 ctx->vivso_len > 0;
188 opt++, ctx->vivso_len--)
189 free_dhcp_opt_embenc(opt);
190 free(ctx->vivso);
191 ctx->vivso = NULL;
195 static void
196 handle_exit_timeout(void *arg)
198 struct dhcpcd_ctx *ctx;
200 ctx = arg;
201 logerrx("timed out");
202 if (!(ctx->options & DHCPCD_MASTER)) {
203 struct interface *ifp;
205 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
206 if (ifp->active == IF_ACTIVE_USER)
207 script_runreason(ifp, "STOPPED");
209 eloop_exit(ctx->eloop, EXIT_FAILURE);
210 return;
212 ctx->options |= DHCPCD_NOWAITIP;
213 dhcpcd_daemonise(ctx);
216 static const char *
217 dhcpcd_af(int af)
220 switch (af) {
221 case AF_UNSPEC:
222 return "IP";
223 case AF_INET:
224 return "IPv4";
225 case AF_INET6:
226 return "IPv6";
227 default:
228 return NULL;
233 dhcpcd_ifafwaiting(const struct interface *ifp)
235 unsigned long long opts;
236 bool foundany = false;
238 if (ifp->active != IF_ACTIVE_USER)
239 return AF_MAX;
241 #define DHCPCD_WAITALL (DHCPCD_WAITIP4 | DHCPCD_WAITIP6)
242 opts = ifp->options->options;
243 #ifdef INET
244 if (opts & DHCPCD_WAITIP4 ||
245 (opts & DHCPCD_WAITIP && !(opts & DHCPCD_WAITALL)))
247 bool foundaddr = ipv4_hasaddr(ifp);
249 if (opts & DHCPCD_WAITIP4 && !foundaddr)
250 return AF_INET;
251 if (foundaddr)
252 foundany = true;
254 #endif
255 #ifdef INET6
256 if (opts & DHCPCD_WAITIP6 ||
257 (opts & DHCPCD_WAITIP && !(opts & DHCPCD_WAITALL)))
259 bool foundaddr = ipv6_hasaddr(ifp);
261 if (opts & DHCPCD_WAITIP6 && !foundaddr)
262 return AF_INET;
263 if (foundaddr)
264 foundany = true;
266 #endif
268 if (opts & DHCPCD_WAITIP && !(opts & DHCPCD_WAITALL) && !foundany)
269 return AF_UNSPEC;
270 return AF_MAX;
274 dhcpcd_afwaiting(const struct dhcpcd_ctx *ctx)
276 unsigned long long opts;
277 const struct interface *ifp;
278 int af;
280 if (!(ctx->options & DHCPCD_WAITOPTS))
281 return AF_MAX;
283 opts = ctx->options;
284 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
285 #ifdef INET
286 if (opts & (DHCPCD_WAITIP | DHCPCD_WAITIP4) &&
287 ipv4_hasaddr(ifp))
288 opts &= ~(DHCPCD_WAITIP | DHCPCD_WAITIP4);
289 #endif
290 #ifdef INET6
291 if (opts & (DHCPCD_WAITIP | DHCPCD_WAITIP6) &&
292 ipv6_hasaddr(ifp))
293 opts &= ~(DHCPCD_WAITIP | DHCPCD_WAITIP6);
294 #endif
295 if (!(opts & DHCPCD_WAITOPTS))
296 break;
298 if (opts & DHCPCD_WAITIP)
299 af = AF_UNSPEC;
300 else if (opts & DHCPCD_WAITIP4)
301 af = AF_INET;
302 else if (opts & DHCPCD_WAITIP6)
303 af = AF_INET6;
304 else
305 return AF_MAX;
306 return af;
309 static int
310 dhcpcd_ipwaited(struct dhcpcd_ctx *ctx)
312 struct interface *ifp;
313 int af;
315 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
316 if ((af = dhcpcd_ifafwaiting(ifp)) != AF_MAX) {
317 logdebugx("%s: waiting for an %s address",
318 ifp->name, dhcpcd_af(af));
319 return 0;
323 if ((af = dhcpcd_afwaiting(ctx)) != AF_MAX) {
324 logdebugx("waiting for an %s address",
325 dhcpcd_af(af));
326 return 0;
329 return 1;
332 /* Returns the pid of the child, otherwise 0. */
333 void
334 dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
336 #ifdef THERE_IS_NO_FORK
337 eloop_timeout_delete(ctx->eloop, handle_exit_timeout, ctx);
338 errno = ENOSYS;
339 return;
340 #else
341 int i;
342 unsigned int logopts = loggetopts();
344 if (ctx->options & DHCPCD_DAEMONISE &&
345 !(ctx->options & (DHCPCD_DAEMONISED | DHCPCD_NOWAITIP)))
347 if (!dhcpcd_ipwaited(ctx))
348 return;
351 if (ctx->options & DHCPCD_ONESHOT) {
352 loginfox("exiting due to oneshot");
353 eloop_exit(ctx->eloop, EXIT_SUCCESS);
354 return;
357 eloop_timeout_delete(ctx->eloop, handle_exit_timeout, ctx);
358 if (ctx->options & DHCPCD_DAEMONISED ||
359 !(ctx->options & DHCPCD_DAEMONISE))
360 return;
362 /* Don't use loginfo because this makes no sense in a log. */
363 if (!(logopts & LOGERR_QUIET))
364 (void)fprintf(stderr,
365 "forked to background, child pid %d\n", getpid());
366 i = EXIT_SUCCESS;
367 if (write(ctx->fork_fd, &i, sizeof(i)) == -1)
368 logerr("write");
369 ctx->options |= DHCPCD_DAEMONISED;
370 eloop_event_delete(ctx->eloop, ctx->fork_fd);
371 close(ctx->fork_fd);
372 ctx->fork_fd = -1;
375 * Stop writing to stderr.
376 * On the happy path, only the master process writes to stderr,
377 * so this just stops wasting fprintf calls to nowhere.
378 * All other calls - ie errors in privsep processes or script output,
379 * will error when printing.
380 * If we *really* want to fix that, then we need to suck
381 * stderr/stdout in the master process and either disacrd it or pass
382 * it to the launcher process and then to stderr.
384 logopts &= ~LOGERR_ERR;
385 logsetopts(logopts);
386 #endif
389 static void
390 dhcpcd_drop(struct interface *ifp, int stop)
393 #ifdef DHCP6
394 dhcp6_drop(ifp, stop ? NULL : "EXPIRE6");
395 #endif
396 #ifdef INET6
397 ipv6nd_drop(ifp);
398 ipv6_drop(ifp);
399 #endif
400 #ifdef IPV4LL
401 ipv4ll_drop(ifp);
402 #endif
403 #ifdef INET
404 dhcp_drop(ifp, stop ? "STOP" : "EXPIRE");
405 #endif
406 #ifdef ARP
407 arp_drop(ifp);
408 #endif
409 #if !defined(DHCP6) && !defined(DHCP)
410 UNUSED(stop);
411 #endif
414 static void
415 stop_interface(struct interface *ifp)
417 struct dhcpcd_ctx *ctx;
419 ctx = ifp->ctx;
420 loginfox("%s: removing interface", ifp->name);
421 ifp->options->options |= DHCPCD_STOPPING;
423 dhcpcd_drop(ifp, 1);
424 if (ifp->options->options & DHCPCD_DEPARTED)
425 script_runreason(ifp, "DEPARTED");
426 else
427 script_runreason(ifp, "STOPPED");
429 /* Delete all timeouts for the interfaces */
430 eloop_q_timeout_delete(ctx->eloop, ELOOP_QUEUE_ALL, NULL, ifp);
432 /* De-activate the interface */
433 ifp->active = IF_INACTIVE;
434 ifp->options->options &= ~DHCPCD_STOPPING;
435 /* Set the link state to unknown as we're no longer tracking it. */
436 ifp->carrier = LINK_UNKNOWN;
438 if (!(ctx->options & (DHCPCD_MASTER | DHCPCD_TEST)))
439 eloop_exit(ctx->eloop, EXIT_FAILURE);
442 static void
443 configure_interface1(struct interface *ifp)
445 struct if_options *ifo = ifp->options;
447 /* Do any platform specific configuration */
448 if_conf(ifp);
450 /* If we want to release a lease, we can't really persist the
451 * address either. */
452 if (ifo->options & DHCPCD_RELEASE)
453 ifo->options &= ~DHCPCD_PERSISTENT;
455 if (ifp->flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) {
456 ifo->options &= ~DHCPCD_ARP;
457 if (!(ifp->flags & IFF_MULTICAST))
458 ifo->options &= ~DHCPCD_IPV6RS;
459 if (!(ifo->options & (DHCPCD_INFORM | DHCPCD_WANTDHCP)))
460 ifo->options |= DHCPCD_STATIC;
463 if (ifo->metric != -1)
464 ifp->metric = (unsigned int)ifo->metric;
466 #ifdef INET6
467 /* We want to setup INET6 on the interface as soon as possible. */
468 if (ifp->active == IF_ACTIVE_USER &&
469 ifo->options & DHCPCD_IPV6 &&
470 !(ifp->ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST)))
472 /* If not doing any DHCP, disable the RDNSS requirement. */
473 if (!(ifo->options & (DHCPCD_DHCP | DHCPCD_DHCP6)))
474 ifo->options &= ~DHCPCD_IPV6RA_REQRDNSS;
475 if_setup_inet6(ifp);
477 #endif
479 if (!(ifo->options & DHCPCD_IAID)) {
481 * An IAID is for identifying a unqiue interface within
482 * the client. It is 4 bytes long. Working out a default
483 * value is problematic.
485 * Interface name and number are not stable
486 * between different OS's. Some OS's also cannot make
487 * up their mind what the interface should be called
488 * (yes, udev, I'm looking at you).
489 * Also, the name could be longer than 4 bytes.
490 * Also, with pluggable interfaces the name and index
491 * could easily get swapped per actual interface.
493 * The MAC address is 6 bytes long, the final 3
494 * being unique to the manufacturer and the initial 3
495 * being unique to the organisation which makes it.
496 * We could use the last 4 bytes of the MAC address
497 * as the IAID as it's the most stable part given the
498 * above, but equally it's not guaranteed to be
499 * unique.
501 * Given the above, and our need to reliably work
502 * between reboots without persitent storage,
503 * generating the IAID from the MAC address is the only
504 * logical default.
505 * Saying that, if a VLANID has been specified then we
506 * can use that. It's possible that different interfaces
507 * can have the same VLANID, but this is no worse than
508 * generating the IAID from the duplicate MAC address.
510 * dhclient uses the last 4 bytes of the MAC address.
511 * dibbler uses an increamenting counter.
512 * wide-dhcpv6 uses 0 or a configured value.
513 * odhcp6c uses 1.
514 * Windows 7 uses the first 3 bytes of the MAC address
515 * and an unknown byte.
516 * dhcpcd-6.1.0 and earlier used the interface name,
517 * falling back to interface index if name > 4.
519 if (ifp->vlanid != 0) {
520 uint32_t vlanid;
522 /* Maximal VLANID is 4095, so prefix with 0xff
523 * so we don't conflict with an interface index. */
524 vlanid = htonl(ifp->vlanid | 0xff000000);
525 memcpy(ifo->iaid, &vlanid, sizeof(vlanid));
526 } else if (ifo->options & DHCPCD_ANONYMOUS)
527 memset(ifo->iaid, 0, sizeof(ifo->iaid));
528 else if (ifp->hwlen >= sizeof(ifo->iaid)) {
529 memcpy(ifo->iaid,
530 ifp->hwaddr + ifp->hwlen - sizeof(ifo->iaid),
531 sizeof(ifo->iaid));
532 } else {
533 uint32_t len;
535 len = (uint32_t)strlen(ifp->name);
536 if (len <= sizeof(ifo->iaid)) {
537 memcpy(ifo->iaid, ifp->name, len);
538 if (len < sizeof(ifo->iaid))
539 memset(ifo->iaid + len, 0,
540 sizeof(ifo->iaid) - len);
541 } else {
542 /* IAID is the same size as a uint32_t */
543 len = htonl(ifp->index);
544 memcpy(ifo->iaid, &len, sizeof(ifo->iaid));
547 ifo->options |= DHCPCD_IAID;
550 #ifdef DHCP6
551 if (ifo->ia_len == 0 && ifo->options & DHCPCD_IPV6 &&
552 ifp->name[0] != '\0')
554 ifo->ia = malloc(sizeof(*ifo->ia));
555 if (ifo->ia == NULL)
556 logerr(__func__);
557 else {
558 ifo->ia_len = 1;
559 ifo->ia->ia_type = D6_OPTION_IA_NA;
560 memcpy(ifo->ia->iaid, ifo->iaid, sizeof(ifo->iaid));
561 memset(&ifo->ia->addr, 0, sizeof(ifo->ia->addr));
562 #ifndef SMALL
563 ifo->ia->sla = NULL;
564 ifo->ia->sla_len = 0;
565 #endif
567 } else {
568 size_t i;
570 for (i = 0; i < ifo->ia_len; i++) {
571 if (!ifo->ia[i].iaid_set) {
572 memcpy(&ifo->ia[i].iaid, ifo->iaid,
573 sizeof(ifo->ia[i].iaid));
574 ifo->ia[i].iaid_set = 1;
578 #endif
580 /* If root is network mounted, we don't want to kill the connection
581 * if the DHCP server goes the way of the dodo OR dhcpcd is rebooting
582 * and the lease file has expired. */
583 if (is_root_local() == 0)
584 ifo->options |= DHCPCD_LASTLEASE_EXTEND;
588 dhcpcd_selectprofile(struct interface *ifp, const char *profile)
590 struct if_options *ifo;
591 char pssid[PROFILE_LEN];
593 if (ifp->ssid_len) {
594 ssize_t r;
596 r = print_string(pssid, sizeof(pssid), OT_ESCSTRING,
597 ifp->ssid, ifp->ssid_len);
598 if (r == -1) {
599 logerr(__func__);
600 pssid[0] = '\0';
602 } else
603 pssid[0] = '\0';
604 ifo = read_config(ifp->ctx, ifp->name, pssid, profile);
605 if (ifo == NULL) {
606 logdebugx("%s: no profile %s", ifp->name, profile);
607 return -1;
609 if (profile != NULL) {
610 strlcpy(ifp->profile, profile, sizeof(ifp->profile));
611 loginfox("%s: selected profile %s", ifp->name, profile);
612 } else
613 *ifp->profile = '\0';
615 free_options(ifp->ctx, ifp->options);
616 ifp->options = ifo;
617 if (profile) {
618 add_options(ifp->ctx, ifp->name, ifp->options,
619 ifp->ctx->argc, ifp->ctx->argv);
620 configure_interface1(ifp);
622 return 1;
625 static void
626 configure_interface(struct interface *ifp, int argc, char **argv,
627 unsigned long long options)
629 time_t old;
631 old = ifp->options ? ifp->options->mtime : 0;
632 dhcpcd_selectprofile(ifp, NULL);
633 if (ifp->options == NULL) {
634 /* dhcpcd cannot continue with this interface. */
635 ifp->active = IF_INACTIVE;
636 return;
638 add_options(ifp->ctx, ifp->name, ifp->options, argc, argv);
639 ifp->options->options |= options;
640 configure_interface1(ifp);
642 /* If the mtime has changed drop any old lease */
643 if (old != 0 && ifp->options->mtime != old) {
644 logwarnx("%s: config file changed, expiring leases",
645 ifp->name);
646 dhcpcd_drop(ifp, 0);
650 static void
651 dhcpcd_initstate2(struct interface *ifp, unsigned long long options)
653 struct if_options *ifo;
655 if (options) {
656 if ((ifo = default_config(ifp->ctx)) == NULL) {
657 logerr(__func__);
658 return;
660 ifo->options |= options;
661 free(ifp->options);
662 ifp->options = ifo;
663 } else
664 ifo = ifp->options;
666 #ifdef INET6
667 if (ifo->options & DHCPCD_IPV6 && ipv6_init(ifp->ctx) == -1) {
668 logerr(__func__);
669 ifo->options &= ~DHCPCD_IPV6;
671 #endif
674 static void
675 dhcpcd_initstate1(struct interface *ifp, int argc, char **argv,
676 unsigned long long options)
679 configure_interface(ifp, argc, argv, options);
680 if (ifp->active)
681 dhcpcd_initstate2(ifp, 0);
684 static void
685 dhcpcd_initstate(struct interface *ifp, unsigned long long options)
688 dhcpcd_initstate1(ifp, ifp->ctx->argc, ifp->ctx->argv, options);
691 static void
692 dhcpcd_reportssid(struct interface *ifp)
694 char pssid[IF_SSIDLEN * 4];
696 if (print_string(pssid, sizeof(pssid), OT_ESCSTRING,
697 ifp->ssid, ifp->ssid_len) == -1)
699 logerr(__func__);
700 return;
703 loginfox("%s: connected to Access Point `%s'", ifp->name, pssid);
706 void
707 dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
708 const char *ifname)
710 struct interface *ifp;
712 ifp = if_find(ctx->ifaces, ifname);
713 if (ifp == NULL ||
714 ifp->options == NULL || !(ifp->options->options & DHCPCD_LINK) ||
715 !ifp->active)
716 return;
718 if (carrier == LINK_UNKNOWN) {
719 if (ifp->wireless) {
720 carrier = LINK_DOWN;
721 ifp->flags = flags;
722 } else
723 carrier = if_carrier(ifp);
724 } else
725 ifp->flags = flags;
726 if (carrier == LINK_UNKNOWN)
727 carrier = IF_UPANDRUNNING(ifp) ? LINK_UP : LINK_DOWN;
729 if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) {
730 if (ifp->carrier != LINK_DOWN) {
731 if (ifp->carrier == LINK_UP)
732 loginfox("%s: carrier lost", ifp->name);
733 #ifdef NOCARRIER_PRESERVE_IP
734 if (ifp->flags & IFF_UP &&
735 !(ifp->options->options & DHCPCD_ANONYMOUS))
736 ifp->carrier = LINK_DOWN_IFFUP;
737 else
738 #endif
739 ifp->carrier = LINK_DOWN;
740 script_runreason(ifp, "NOCARRIER");
741 #ifdef NOCARRIER_PRESERVE_IP
742 if (ifp->flags & IFF_UP &&
743 !(ifp->options->options & DHCPCD_ANONYMOUS))
745 #ifdef ARP
746 arp_drop(ifp);
747 #endif
748 #ifdef INET
749 dhcp_abort(ifp);
750 #endif
751 #ifdef DHCP6
752 dhcp6_abort(ifp);
753 #endif
754 } else
755 #endif
756 dhcpcd_drop(ifp, 0);
757 if (ifp->options->options & DHCPCD_ANONYMOUS) {
758 bool was_up = ifp->flags & IFF_UP;
760 if (was_up)
761 if_down(ifp);
762 if (if_randomisemac(ifp) == -1 && errno != ENXIO)
763 logerr(__func__);
764 if (was_up)
765 if_up(ifp);
768 } else if (carrier == LINK_UP && ifp->flags & IFF_UP) {
769 if (ifp->carrier != LINK_UP) {
770 loginfox("%s: carrier acquired", ifp->name);
771 ifp->carrier = LINK_UP;
772 #if !defined(__linux__) && !defined(__NetBSD__)
773 /* BSD does not emit RTM_NEWADDR or RTM_CHGADDR when the
774 * hardware address changes so we have to go
775 * through the disovery process to work it out. */
776 dhcpcd_handleinterface(ctx, 0, ifp->name);
777 #endif
778 if (ifp->wireless) {
779 uint8_t ossid[IF_SSIDLEN];
780 size_t olen;
782 olen = ifp->ssid_len;
783 memcpy(ossid, ifp->ssid, ifp->ssid_len);
784 if_getssid(ifp);
786 /* If we changed SSID network, drop leases */
787 if (ifp->ssid_len != olen ||
788 memcmp(ifp->ssid, ossid, ifp->ssid_len))
790 dhcpcd_reportssid(ifp);
791 #ifdef NOCARRIER_PRESERVE_IP
792 dhcpcd_drop(ifp, 0);
793 #endif
794 #ifdef IPV4LL
795 ipv4ll_reset(ifp);
796 #endif
799 dhcpcd_initstate(ifp, 0);
800 script_runreason(ifp, "CARRIER");
801 #ifdef INET6
802 #ifdef NOCARRIER_PRESERVE_IP
803 /* Set any IPv6 Routers we remembered to expire
804 * faster than they would normally as we
805 * maybe on a new network. */
806 ipv6nd_startexpire(ifp);
807 #endif
808 #ifdef IPV6_MANAGETEMPADDR
809 /* RFC4941 Section 3.5 */
810 ipv6_regentempaddrs(ifp);
811 #endif
812 #endif
813 dhcpcd_startinterface(ifp);
818 static void
819 warn_iaid_conflict(struct interface *ifp, uint16_t ia_type, uint8_t *iaid)
821 struct interface *ifn;
822 #ifdef INET6
823 size_t i;
824 struct if_ia *ia;
825 #endif
827 TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
828 if (ifn == ifp || !ifn->active)
829 continue;
830 if (ifn->options->options & DHCPCD_ANONYMOUS)
831 continue;
832 if (ia_type == 0 &&
833 memcmp(ifn->options->iaid, iaid,
834 sizeof(ifn->options->iaid)) == 0)
835 break;
836 #ifdef INET6
837 for (i = 0; i < ifn->options->ia_len; i++) {
838 ia = &ifn->options->ia[i];
839 if (ia->ia_type == ia_type &&
840 memcmp(ia->iaid, iaid, sizeof(ia->iaid)) == 0)
841 break;
843 #endif
846 /* This is only a problem if the interfaces are on the same network. */
847 if (ifn)
848 logerrx("%s: IAID conflicts with one assigned to %s",
849 ifp->name, ifn->name);
852 static void
853 dhcpcd_initduid(struct dhcpcd_ctx *ctx, struct interface *ifp)
855 char buf[DUID_LEN * 3];
857 if (ctx->duid != NULL)
858 return;
860 duid_init(ctx, ifp);
861 if (ctx->duid == NULL)
862 return;
864 loginfox("DUID %s",
865 hwaddr_ntoa(ctx->duid, ctx->duid_len, buf, sizeof(buf)));
868 void
869 dhcpcd_startinterface(void *arg)
871 struct interface *ifp = arg;
872 struct if_options *ifo = ifp->options;
874 if (ifo->options & DHCPCD_LINK) {
875 switch (ifp->carrier) {
876 case LINK_UP:
877 break;
878 case LINK_DOWN:
879 loginfox("%s: waiting for carrier", ifp->name);
880 return;
881 case LINK_UNKNOWN:
882 /* No media state available.
883 * Loop until both IFF_UP and IFF_RUNNING are set */
884 if (ifo->poll == 0)
885 if_pollinit(ifp);
886 return;
890 if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6) &&
891 !(ifo->options & DHCPCD_ANONYMOUS))
893 char buf[sizeof(ifo->iaid) * 3];
894 #ifdef INET6
895 size_t i;
896 struct if_ia *ia;
897 #endif
899 /* Try and init DUID from the interface hardware address */
900 dhcpcd_initduid(ifp->ctx, ifp);
902 /* Report IAIDs */
903 loginfox("%s: IAID %s", ifp->name,
904 hwaddr_ntoa(ifo->iaid, sizeof(ifo->iaid),
905 buf, sizeof(buf)));
906 warn_iaid_conflict(ifp, 0, ifo->iaid);
908 #ifdef INET6
909 for (i = 0; i < ifo->ia_len; i++) {
910 ia = &ifo->ia[i];
911 if (memcmp(ifo->iaid, ia->iaid, sizeof(ifo->iaid))) {
912 loginfox("%s: IA type %u IAID %s",
913 ifp->name, ia->ia_type,
914 hwaddr_ntoa(ia->iaid, sizeof(ia->iaid),
915 buf, sizeof(buf)));
916 warn_iaid_conflict(ifp, ia->ia_type, ia->iaid);
919 #endif
922 #ifdef INET6
923 if (ifo->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) {
924 logerr("%s: ipv6_start", ifp->name);
925 ifo->options &= ~DHCPCD_IPV6;
928 if (ifo->options & DHCPCD_IPV6) {
929 if (ifp->active == IF_ACTIVE_USER) {
930 ipv6_startstatic(ifp);
932 if (ifo->options & DHCPCD_IPV6RS)
933 ipv6nd_startrs(ifp);
936 #ifdef DHCP6
937 /* DHCPv6 could be turned off, but the interface
938 * is still delegated to. */
939 if (ifp->active)
940 dhcp6_find_delegates(ifp);
942 if (ifo->options & DHCPCD_DHCP6) {
943 if (ifp->active == IF_ACTIVE_USER) {
944 enum DH6S d6_state;
946 if (ifo->options & DHCPCD_IA_FORCED)
947 d6_state = DH6S_INIT;
948 else if (ifo->options & DHCPCD_INFORM6)
949 d6_state = DH6S_INFORM;
950 else
951 d6_state = DH6S_CONFIRM;
952 if (dhcp6_start(ifp, d6_state) == -1)
953 logerr("%s: dhcp6_start", ifp->name);
956 #endif
958 #endif
960 #ifdef INET
961 if (ifo->options & DHCPCD_IPV4 && ifp->active == IF_ACTIVE_USER) {
962 /* Ensure we have an IPv4 state before starting DHCP */
963 if (ipv4_getstate(ifp) != NULL)
964 dhcp_start(ifp);
966 #endif
969 static void
970 dhcpcd_prestartinterface(void *arg)
972 struct interface *ifp = arg;
973 struct dhcpcd_ctx *ctx = ifp->ctx;
974 bool anondown;
976 if (ifp->carrier == LINK_DOWN &&
977 ifp->options->options & DHCPCD_ANONYMOUS &&
978 ifp->flags & IFF_UP)
980 if_down(ifp);
981 anondown = true;
982 } else
983 anondown = false;
985 if ((!(ctx->options & DHCPCD_MASTER) ||
986 ifp->options->options & DHCPCD_IF_UP || anondown) &&
987 !(ifp->flags & IFF_UP))
989 if (ifp->options->options & DHCPCD_ANONYMOUS &&
990 if_randomisemac(ifp) == -1)
991 logerr(__func__);
992 if (if_up(ifp) == -1)
993 logerr(__func__);
996 if (ifp->options->poll != 0)
997 if_pollinit(ifp);
999 dhcpcd_startinterface(ifp);
1002 static void
1003 run_preinit(struct interface *ifp)
1006 if (ifp->ctx->options & DHCPCD_TEST)
1007 return;
1009 script_runreason(ifp, "PREINIT");
1010 if (ifp->wireless && ifp->carrier == LINK_UP)
1011 dhcpcd_reportssid(ifp);
1012 if (ifp->options->options & DHCPCD_LINK && ifp->carrier != LINK_UNKNOWN)
1013 script_runreason(ifp,
1014 ifp->carrier == LINK_UP ? "CARRIER" : "NOCARRIER");
1017 void
1018 dhcpcd_activateinterface(struct interface *ifp, unsigned long long options)
1021 if (!ifp->active) {
1022 ifp->active = IF_ACTIVE;
1023 dhcpcd_initstate2(ifp, options);
1024 /* It's possible we might not have been able to load
1025 * a config. */
1026 if (ifp->active) {
1027 configure_interface1(ifp);
1028 run_preinit(ifp);
1029 dhcpcd_prestartinterface(ifp);
1035 dhcpcd_handleinterface(void *arg, int action, const char *ifname)
1037 struct dhcpcd_ctx *ctx;
1038 struct ifaddrs *ifaddrs;
1039 struct if_head *ifs;
1040 struct interface *ifp, *iff;
1041 const char * const argv[] = { ifname };
1042 int e;
1044 ctx = arg;
1045 if (action == -1) {
1046 ifp = if_find(ctx->ifaces, ifname);
1047 if (ifp == NULL) {
1048 errno = ESRCH;
1049 return -1;
1051 if (ifp->active) {
1052 logdebugx("%s: interface departed", ifp->name);
1053 ifp->options->options |= DHCPCD_DEPARTED;
1054 stop_interface(ifp);
1056 TAILQ_REMOVE(ctx->ifaces, ifp, next);
1057 if_free(ifp);
1058 return 0;
1061 ifs = if_discover(ctx, &ifaddrs, -1, UNCONST(argv));
1062 if (ifs == NULL) {
1063 logerr(__func__);
1064 return -1;
1067 ifp = if_find(ifs, ifname);
1068 if (ifp == NULL) {
1069 /* This can happen if an interface is quickly added
1070 * and then removed. */
1071 errno = ENOENT;
1072 e = -1;
1073 goto out;
1075 e = 1;
1077 /* Check if we already have the interface */
1078 iff = if_find(ctx->ifaces, ifp->name);
1080 if (iff != NULL) {
1081 if (iff->active)
1082 logdebugx("%s: interface updated", iff->name);
1083 /* The flags and hwaddr could have changed */
1084 iff->flags = ifp->flags;
1085 iff->hwlen = ifp->hwlen;
1086 if (ifp->hwlen != 0)
1087 memcpy(iff->hwaddr, ifp->hwaddr, iff->hwlen);
1088 } else {
1089 TAILQ_REMOVE(ifs, ifp, next);
1090 TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
1091 if (ifp->active) {
1092 logdebugx("%s: interface added", ifp->name);
1093 dhcpcd_initstate(ifp, 0);
1094 run_preinit(ifp);
1096 iff = ifp;
1099 if (action > 0) {
1100 if_learnaddrs(ctx, ifs, &ifaddrs);
1101 if (iff->active)
1102 dhcpcd_prestartinterface(iff);
1105 out:
1106 /* Free our discovered list */
1107 while ((ifp = TAILQ_FIRST(ifs))) {
1108 TAILQ_REMOVE(ifs, ifp, next);
1109 if_free(ifp);
1111 free(ifs);
1113 return e;
1116 static void
1117 dhcpcd_handlelink(void *arg)
1119 struct dhcpcd_ctx *ctx = arg;
1121 if (if_handlelink(ctx) == -1) {
1122 if (errno == ENOBUFS || errno == ENOMEM) {
1123 dhcpcd_linkoverflow(ctx);
1124 return;
1126 if (errno != ENOTSUP)
1127 logerr(__func__);
1131 static void
1132 dhcpcd_checkcarrier(void *arg)
1134 struct interface *ifp = arg;
1135 int carrier;
1137 /* Check carrier here rather than setting LINK_UNKNOWN.
1138 * This is because we force LINK_UNKNOWN as down for wireless which
1139 * we do not want when dealing with a route socket overflow. */
1140 carrier = if_carrier(ifp);
1141 dhcpcd_handlecarrier(ifp->ctx, carrier, ifp->flags, ifp->name);
1144 #ifndef SMALL
1145 static void
1146 dhcpcd_setlinkrcvbuf(struct dhcpcd_ctx *ctx)
1148 socklen_t socklen;
1150 if (ctx->link_rcvbuf == 0)
1151 return;
1153 logdebugx("setting route socket receive buffer size to %d bytes",
1154 ctx->link_rcvbuf);
1156 socklen = sizeof(ctx->link_rcvbuf);
1157 if (setsockopt(ctx->link_fd, SOL_SOCKET,
1158 SO_RCVBUF, &ctx->link_rcvbuf, socklen) == -1)
1159 logerr(__func__);
1161 #endif
1163 static void
1164 dhcpcd_runprestartinterface(void *arg)
1166 struct interface *ifp = arg;
1168 run_preinit(ifp);
1169 dhcpcd_prestartinterface(ifp);
1172 void
1173 dhcpcd_linkoverflow(struct dhcpcd_ctx *ctx)
1175 socklen_t socklen;
1176 int rcvbuflen;
1177 char buf[2048];
1178 ssize_t rlen;
1179 size_t rcnt;
1180 struct if_head *ifaces;
1181 struct ifaddrs *ifaddrs;
1182 struct interface *ifp, *ifn, *ifp1;
1184 socklen = sizeof(rcvbuflen);
1185 if (getsockopt(ctx->link_fd, SOL_SOCKET,
1186 SO_RCVBUF, &rcvbuflen, &socklen) == -1)
1187 rcvbuflen = 0;
1188 #ifdef __linux__
1189 else
1190 rcvbuflen /= 2;
1191 #endif
1193 logerrx("route socket overflowed (rcvbuflen %d)"
1194 " - learning interface state", rcvbuflen);
1196 /* Drain the socket.
1197 * We cannot open a new one due to privsep. */
1198 rcnt = 0;
1199 do {
1200 rlen = read(ctx->link_fd, buf, sizeof(buf));
1201 if (++rcnt % 1000 == 0)
1202 logwarnx("drained %zu messages", rcnt);
1203 } while (rlen != -1 || errno == ENOBUFS || errno == ENOMEM);
1204 if (rcnt % 1000 != 0)
1205 logwarnx("drained %zu messages", rcnt);
1207 /* Work out the current interfaces. */
1208 ifaces = if_discover(ctx, &ifaddrs, ctx->ifc, ctx->ifv);
1209 if (ifaces == NULL) {
1210 logerr(__func__);
1211 return;
1214 /* Punt departed interfaces */
1215 TAILQ_FOREACH_SAFE(ifp, ctx->ifaces, next, ifn) {
1216 if (if_find(ifaces, ifp->name) != NULL)
1217 continue;
1218 dhcpcd_handleinterface(ctx, -1, ifp->name);
1221 /* Add new interfaces */
1222 while ((ifp = TAILQ_FIRST(ifaces)) != NULL ) {
1223 TAILQ_REMOVE(ifaces, ifp, next);
1224 ifp1 = if_find(ctx->ifaces, ifp->name);
1225 if (ifp1 != NULL) {
1226 /* If the interface already exists,
1227 * check carrier state. */
1228 eloop_timeout_add_sec(ctx->eloop, 0,
1229 dhcpcd_checkcarrier, ifp1);
1230 if_free(ifp);
1231 continue;
1233 TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
1234 if (ifp->active) {
1235 dhcpcd_initstate(ifp, 0);
1236 eloop_timeout_add_sec(ctx->eloop, 0,
1237 dhcpcd_runprestartinterface, ifp);
1240 free(ifaces);
1242 /* Update address state. */
1243 if_markaddrsstale(ctx->ifaces);
1244 if_learnaddrs(ctx, ctx->ifaces, &ifaddrs);
1245 if_deletestaleaddrs(ctx->ifaces);
1248 void
1249 dhcpcd_handlehwaddr(struct interface *ifp,
1250 uint16_t hwtype, const void *hwaddr, uint8_t hwlen)
1252 char buf[sizeof(ifp->hwaddr) * 3];
1254 if (hwaddr == NULL || !if_valid_hwaddr(hwaddr, hwlen))
1255 hwlen = 0;
1257 if (hwlen > sizeof(ifp->hwaddr)) {
1258 errno = ENOBUFS;
1259 logerr("%s: %s", __func__, ifp->name);
1260 return;
1263 if (ifp->hwtype != hwtype) {
1264 loginfox("%s: hardware address type changed from %d to %d",
1265 ifp->name, ifp->hwtype, hwtype);
1266 ifp->hwtype = hwtype;
1269 if (ifp->hwlen == hwlen &&
1270 (hwlen == 0 || memcmp(ifp->hwaddr, hwaddr, hwlen) == 0))
1271 return;
1273 loginfox("%s: new hardware address: %s", ifp->name,
1274 hwaddr_ntoa(hwaddr, hwlen, buf, sizeof(buf)));
1275 ifp->hwlen = hwlen;
1276 if (hwaddr != NULL)
1277 memcpy(ifp->hwaddr, hwaddr, hwlen);
1280 static void
1281 if_reboot(struct interface *ifp, int argc, char **argv)
1283 #ifdef INET
1284 unsigned long long oldopts;
1286 oldopts = ifp->options->options;
1287 #endif
1288 script_runreason(ifp, "RECONFIGURE");
1289 dhcpcd_initstate1(ifp, argc, argv, 0);
1290 #ifdef INET
1291 dhcp_reboot_newopts(ifp, oldopts);
1292 #endif
1293 #ifdef DHCP6
1294 dhcp6_reboot(ifp);
1295 #endif
1296 dhcpcd_prestartinterface(ifp);
1299 static void
1300 reload_config(struct dhcpcd_ctx *ctx)
1302 struct if_options *ifo;
1304 free_globals(ctx);
1305 if ((ifo = read_config(ctx, NULL, NULL, NULL)) == NULL)
1306 return;
1307 add_options(ctx, NULL, ifo, ctx->argc, ctx->argv);
1308 /* We need to preserve these options. */
1309 if (ctx->options & DHCPCD_STARTED)
1310 ifo->options |= DHCPCD_STARTED;
1311 if (ctx->options & DHCPCD_MASTER)
1312 ifo->options |= DHCPCD_MASTER;
1313 if (ctx->options & DHCPCD_DAEMONISED)
1314 ifo->options |= DHCPCD_DAEMONISED;
1315 if (ctx->options & DHCPCD_PRIVSEP)
1316 ifo->options |= DHCPCD_PRIVSEP;
1317 ctx->options = ifo->options;
1318 free_options(ctx, ifo);
1321 static void
1322 reconf_reboot(struct dhcpcd_ctx *ctx, int action, int argc, char **argv, int oi)
1324 int i;
1325 struct interface *ifp;
1327 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
1328 for (i = oi; i < argc; i++) {
1329 if (strcmp(ifp->name, argv[i]) == 0)
1330 break;
1332 if (oi != argc && i == argc)
1333 continue;
1334 if (ifp->active == IF_ACTIVE_USER) {
1335 if (action)
1336 if_reboot(ifp, argc, argv);
1337 #ifdef INET
1338 else
1339 ipv4_applyaddr(ifp);
1340 #endif
1341 } else if (i != argc) {
1342 ifp->active = IF_ACTIVE_USER;
1343 dhcpcd_initstate1(ifp, argc, argv, 0);
1344 run_preinit(ifp);
1345 dhcpcd_prestartinterface(ifp);
1350 static void
1351 stop_all_interfaces(struct dhcpcd_ctx *ctx, unsigned long long opts)
1353 struct interface *ifp;
1355 ctx->options |= DHCPCD_EXITING;
1356 if (ctx->ifaces == NULL)
1357 return;
1359 /* Drop the last interface first */
1360 TAILQ_FOREACH_REVERSE(ifp, ctx->ifaces, if_head, next) {
1361 if (!ifp->active)
1362 continue;
1363 ifp->options->options |= opts;
1364 if (ifp->options->options & DHCPCD_RELEASE)
1365 ifp->options->options &= ~DHCPCD_PERSISTENT;
1366 ifp->options->options |= DHCPCD_EXITING;
1367 stop_interface(ifp);
1371 static void
1372 dhcpcd_ifrenew(struct interface *ifp)
1375 if (!ifp->active)
1376 return;
1378 if (ifp->options->options & DHCPCD_LINK &&
1379 ifp->carrier == LINK_DOWN)
1380 return;
1382 #ifdef INET
1383 dhcp_renew(ifp);
1384 #endif
1385 #ifdef INET6
1386 #define DHCPCD_RARENEW (DHCPCD_IPV6 | DHCPCD_IPV6RS)
1387 if ((ifp->options->options & DHCPCD_RARENEW) == DHCPCD_RARENEW)
1388 ipv6nd_startrs(ifp);
1389 #endif
1390 #ifdef DHCP6
1391 dhcp6_renew(ifp);
1392 #endif
1395 static void
1396 dhcpcd_renew(struct dhcpcd_ctx *ctx)
1398 struct interface *ifp;
1400 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
1401 dhcpcd_ifrenew(ifp);
1405 #ifdef USE_SIGNALS
1406 #define sigmsg "received %s, %s"
1407 static void
1408 dhcpcd_signal_cb(int sig, void *arg)
1410 struct dhcpcd_ctx *ctx = arg;
1411 unsigned long long opts;
1412 int exit_code;
1414 if (ctx->options & DHCPCD_DUMPLEASE) {
1415 eloop_exit(ctx->eloop, EXIT_FAILURE);
1416 return;
1419 if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED) {
1420 if (sig == SIGHUP)
1421 return;
1423 pid_t pid = pidfile_read(ctx->pidfile);
1424 if (pid == -1) {
1425 if (errno != ENOENT)
1426 logerr("%s: pidfile_read",__func__);
1427 } else if (pid == 0)
1428 logerr("%s: pid cannot be zero", __func__);
1429 else if (kill(pid, sig) == -1)
1430 logerr("%s: kill", __func__);
1431 return;
1434 opts = 0;
1435 exit_code = EXIT_FAILURE;
1436 switch (sig) {
1437 case SIGINT:
1438 loginfox(sigmsg, "SIGINT", "stopping");
1439 break;
1440 case SIGTERM:
1441 loginfox(sigmsg, "SIGTERM", "stopping");
1442 exit_code = EXIT_SUCCESS;
1443 break;
1444 case SIGALRM:
1445 loginfox(sigmsg, "SIGALRM", "releasing");
1446 opts |= DHCPCD_RELEASE;
1447 exit_code = EXIT_SUCCESS;
1448 break;
1449 case SIGHUP:
1450 loginfox(sigmsg, "SIGHUP", "rebinding");
1451 reload_config(ctx);
1452 /* Preserve any options passed on the commandline
1453 * when we were started. */
1454 reconf_reboot(ctx, 1, ctx->argc, ctx->argv,
1455 ctx->argc - ctx->ifc);
1456 return;
1457 case SIGUSR1:
1458 loginfox(sigmsg, "SIGUSR1", "renewing");
1459 dhcpcd_renew(ctx);
1460 return;
1461 case SIGUSR2:
1462 loginfox(sigmsg, "SIGUSR2", "reopening log");
1463 /* XXX This may not work that well in a chroot */
1464 logclose();
1465 if (logopen(ctx->logfile) == -1)
1466 logerr(__func__);
1467 return;
1468 case SIGCHLD:
1469 while (waitpid(-1, NULL, WNOHANG) > 0)
1471 return;
1472 default:
1473 logerrx("received signal %d but don't know what to do with it",
1474 sig);
1475 return;
1478 if (!(ctx->options & DHCPCD_TEST))
1479 stop_all_interfaces(ctx, opts);
1480 eloop_exit(ctx->eloop, exit_code);
1482 #endif
1485 dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
1486 int argc, char **argv)
1488 struct interface *ifp;
1489 unsigned long long opts;
1490 int opt, oi, do_reboot, do_renew, af = AF_UNSPEC;
1491 size_t len, l, nifaces;
1492 char *tmp, *p;
1494 /* Special commands for our control socket
1495 * as the other end should be blocking until it gets the
1496 * expected reply we should be safely able just to change the
1497 * write callback on the fd */
1498 /* Make any change here in privsep-control.c as well. */
1499 if (strcmp(*argv, "--version") == 0) {
1500 return control_queue(fd, UNCONST(VERSION),
1501 strlen(VERSION) + 1);
1502 } else if (strcmp(*argv, "--getconfigfile") == 0) {
1503 return control_queue(fd, UNCONST(fd->ctx->cffile),
1504 strlen(fd->ctx->cffile) + 1);
1505 } else if (strcmp(*argv, "--getinterfaces") == 0) {
1506 optind = argc = 0;
1507 goto dumplease;
1508 } else if (strcmp(*argv, "--listen") == 0) {
1509 fd->flags |= FD_LISTEN;
1510 return 0;
1513 /* Log the command */
1514 len = 1;
1515 for (opt = 0; opt < argc; opt++)
1516 len += strlen(argv[opt]) + 1;
1517 tmp = malloc(len);
1518 if (tmp == NULL)
1519 return -1;
1520 p = tmp;
1521 for (opt = 0; opt < argc; opt++) {
1522 l = strlen(argv[opt]);
1523 strlcpy(p, argv[opt], len);
1524 len -= l + 1;
1525 p += l;
1526 *p++ = ' ';
1528 *--p = '\0';
1529 loginfox("control command: %s", tmp);
1530 free(tmp);
1532 optind = 0;
1533 oi = 0;
1534 opts = 0;
1535 do_reboot = do_renew = 0;
1536 while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1)
1538 switch (opt) {
1539 case 'g':
1540 /* Assumed if below not set */
1541 break;
1542 case 'k':
1543 opts |= DHCPCD_RELEASE;
1544 break;
1545 case 'n':
1546 do_reboot = 1;
1547 break;
1548 case 'p':
1549 opts |= DHCPCD_PERSISTENT;
1550 break;
1551 case 'x':
1552 opts |= DHCPCD_EXITING;
1553 break;
1554 case 'N':
1555 do_renew = 1;
1556 break;
1557 case 'U':
1558 opts |= DHCPCD_DUMPLEASE;
1559 break;
1560 case '4':
1561 af = AF_INET;
1562 break;
1563 case '6':
1564 af = AF_INET6;
1565 break;
1569 if (opts & DHCPCD_DUMPLEASE) {
1570 ctx->options |= DHCPCD_DUMPLEASE;
1571 dumplease:
1572 nifaces = 0;
1573 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
1574 if (!ifp->active)
1575 continue;
1576 for (oi = optind; oi < argc; oi++) {
1577 if (strcmp(ifp->name, argv[oi]) == 0)
1578 break;
1580 if (optind == argc || oi < argc) {
1581 opt = send_interface(NULL, ifp, af);
1582 if (opt == -1)
1583 goto dumperr;
1584 nifaces += (size_t)opt;
1587 if (write(fd->fd, &nifaces, sizeof(nifaces)) != sizeof(nifaces))
1588 goto dumperr;
1589 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
1590 if (!ifp->active)
1591 continue;
1592 for (oi = optind; oi < argc; oi++) {
1593 if (strcmp(ifp->name, argv[oi]) == 0)
1594 break;
1596 if (optind == argc || oi < argc) {
1597 if (send_interface(fd, ifp, af) == -1)
1598 goto dumperr;
1601 ctx->options &= ~DHCPCD_DUMPLEASE;
1602 return 0;
1603 dumperr:
1604 ctx->options &= ~DHCPCD_DUMPLEASE;
1605 return -1;
1608 /* Only privileged users can control dhcpcd via the socket. */
1609 if (fd->flags & FD_UNPRIV) {
1610 errno = EPERM;
1611 return -1;
1614 if (opts & (DHCPCD_EXITING | DHCPCD_RELEASE)) {
1615 if (optind == argc) {
1616 stop_all_interfaces(ctx, opts);
1617 eloop_exit(ctx->eloop, EXIT_SUCCESS);
1618 return 0;
1620 for (oi = optind; oi < argc; oi++) {
1621 if ((ifp = if_find(ctx->ifaces, argv[oi])) == NULL)
1622 continue;
1623 if (!ifp->active)
1624 continue;
1625 ifp->options->options |= opts;
1626 if (opts & DHCPCD_RELEASE)
1627 ifp->options->options &= ~DHCPCD_PERSISTENT;
1628 stop_interface(ifp);
1630 return 0;
1633 if (do_renew) {
1634 if (optind == argc) {
1635 dhcpcd_renew(ctx);
1636 return 0;
1638 for (oi = optind; oi < argc; oi++) {
1639 if ((ifp = if_find(ctx->ifaces, argv[oi])) == NULL)
1640 continue;
1641 dhcpcd_ifrenew(ifp);
1643 return 0;
1646 reload_config(ctx);
1647 /* XXX: Respect initial commandline options? */
1648 reconf_reboot(ctx, do_reboot, argc, argv, optind - 1);
1649 return 0;
1652 static void dhcpcd_readdump1(void *);
1654 static void
1655 dhcpcd_readdump2(void *arg)
1657 struct dhcpcd_ctx *ctx = arg;
1658 ssize_t len;
1659 int exit_code = EXIT_FAILURE;
1661 len = read(ctx->control_fd, ctx->ctl_buf + ctx->ctl_bufpos,
1662 ctx->ctl_buflen - ctx->ctl_bufpos);
1663 if (len == -1) {
1664 logerr(__func__);
1665 goto finished;
1666 } else if (len == 0)
1667 goto finished;
1668 if ((size_t)len + ctx->ctl_bufpos != ctx->ctl_buflen) {
1669 ctx->ctl_bufpos += (size_t)len;
1670 return;
1673 if (ctx->ctl_buf[ctx->ctl_buflen - 1] != '\0') /* unlikely */
1674 ctx->ctl_buf[ctx->ctl_buflen - 1] = '\0';
1675 script_dump(ctx->ctl_buf, ctx->ctl_buflen);
1676 fflush(stdout);
1677 if (--ctx->ctl_extra != 0) {
1678 putchar('\n');
1679 eloop_event_add(ctx->eloop, ctx->control_fd,
1680 dhcpcd_readdump1, ctx);
1681 return;
1683 exit_code = EXIT_SUCCESS;
1685 finished:
1686 shutdown(ctx->control_fd, SHUT_RDWR);
1687 eloop_exit(ctx->eloop, exit_code);
1690 static void
1691 dhcpcd_readdump1(void *arg)
1693 struct dhcpcd_ctx *ctx = arg;
1694 ssize_t len;
1696 len = read(ctx->control_fd, &ctx->ctl_buflen, sizeof(ctx->ctl_buflen));
1697 if (len != sizeof(ctx->ctl_buflen)) {
1698 if (len != -1)
1699 errno = EINVAL;
1700 goto err;
1702 if (ctx->ctl_buflen > SSIZE_MAX) {
1703 errno = ENOBUFS;
1704 goto err;
1707 free(ctx->ctl_buf);
1708 ctx->ctl_buf = malloc(ctx->ctl_buflen);
1709 if (ctx->ctl_buf == NULL)
1710 goto err;
1712 ctx->ctl_bufpos = 0;
1713 eloop_event_add(ctx->eloop, ctx->control_fd,
1714 dhcpcd_readdump2, ctx);
1715 return;
1717 err:
1718 logerr(__func__);
1719 eloop_exit(ctx->eloop, EXIT_FAILURE);
1722 static void
1723 dhcpcd_readdump0(void *arg)
1725 struct dhcpcd_ctx *ctx = arg;
1726 ssize_t len;
1728 len = read(ctx->control_fd, &ctx->ctl_extra, sizeof(ctx->ctl_extra));
1729 if (len != sizeof(ctx->ctl_extra)) {
1730 if (len != -1)
1731 errno = EINVAL;
1732 logerr(__func__);
1733 eloop_exit(ctx->eloop, EXIT_FAILURE);
1734 return;
1737 if (ctx->ctl_extra == 0) {
1738 eloop_exit(ctx->eloop, EXIT_SUCCESS);
1739 return;
1742 eloop_event_add(ctx->eloop, ctx->control_fd,
1743 dhcpcd_readdump1, ctx);
1746 static void
1747 dhcpcd_readdumptimeout(void *arg)
1749 struct dhcpcd_ctx *ctx = arg;
1751 logerrx(__func__);
1752 eloop_exit(ctx->eloop, EXIT_FAILURE);
1755 static int
1756 dhcpcd_readdump(struct dhcpcd_ctx *ctx)
1759 ctx->options |= DHCPCD_FORKED;
1760 if (eloop_timeout_add_sec(ctx->eloop, 5,
1761 dhcpcd_readdumptimeout, ctx) == -1)
1762 return -1;
1763 return eloop_event_add(ctx->eloop, ctx->control_fd,
1764 dhcpcd_readdump0, ctx);
1767 static void
1768 dhcpcd_fork_cb(void *arg)
1770 struct dhcpcd_ctx *ctx = arg;
1771 int exit_code;
1772 ssize_t len;
1774 len = read(ctx->fork_fd, &exit_code, sizeof(exit_code));
1775 if (len == -1) {
1776 logerr(__func__);
1777 exit_code = EXIT_FAILURE;
1778 } else if ((size_t)len < sizeof(exit_code)) {
1779 logerrx("%s: truncated read %zd (expected %zu)",
1780 __func__, len, sizeof(exit_code));
1781 exit_code = EXIT_FAILURE;
1783 eloop_exit(ctx->eloop, exit_code);
1786 static void
1787 dhcpcd_stderr_cb(void *arg)
1789 struct dhcpcd_ctx *ctx = arg;
1790 char log[BUFSIZ];
1791 ssize_t len;
1793 len = read(ctx->stderr_fd, log, sizeof(log));
1794 if (len == -1) {
1795 if (errno != ECONNRESET)
1796 logerr(__func__);
1797 return;
1800 log[len] = '\0';
1801 fprintf(stderr, "%s", log);
1805 main(int argc, char **argv)
1807 struct dhcpcd_ctx ctx;
1808 struct ifaddrs *ifaddrs = NULL;
1809 struct if_options *ifo;
1810 struct interface *ifp;
1811 sa_family_t family = AF_UNSPEC;
1812 int opt, oi = 0, i;
1813 unsigned int logopts, t;
1814 ssize_t len;
1815 #if defined(USE_SIGNALS) || !defined(THERE_IS_NO_FORK)
1816 pid_t pid;
1817 int fork_fd[2], stderr_fd[2];
1818 #endif
1819 #ifdef USE_SIGNALS
1820 int sig = 0;
1821 const char *siga = NULL;
1822 size_t si;
1823 #endif
1825 /* Test for --help and --version */
1826 if (argc > 1) {
1827 if (strcmp(argv[1], "--help") == 0) {
1828 usage();
1829 return EXIT_SUCCESS;
1830 } else if (strcmp(argv[1], "--version") == 0) {
1831 printf(""PACKAGE" "VERSION"\n%s\n", dhcpcd_copyright);
1832 printf("Compiled in features:"
1833 #ifdef INET
1834 " INET"
1835 #endif
1836 #ifdef ARP
1837 " ARP"
1838 #endif
1839 #ifdef ARPING
1840 " ARPing"
1841 #endif
1842 #ifdef IPV4LL
1843 " IPv4LL"
1844 #endif
1845 #ifdef INET6
1846 " INET6"
1847 #endif
1848 #ifdef DHCP6
1849 " DHCPv6"
1850 #endif
1851 #ifdef AUTH
1852 " AUTH"
1853 #endif
1854 #ifdef PRIVSEP
1855 " PRIVSEP"
1856 #endif
1857 "\n");
1858 return EXIT_SUCCESS;
1862 memset(&ctx, 0, sizeof(ctx));
1864 ifo = NULL;
1865 ctx.cffile = CONFIG;
1866 ctx.script = UNCONST(dhcpcd_default_script);
1867 ctx.control_fd = ctx.control_unpriv_fd = ctx.link_fd = -1;
1868 ctx.pf_inet_fd = -1;
1869 #ifdef PF_LINK
1870 ctx.pf_link_fd = -1;
1871 #endif
1873 TAILQ_INIT(&ctx.control_fds);
1874 #ifdef USE_SIGNALS
1875 ctx.fork_fd = -1;
1876 #endif
1877 #ifdef PLUGIN_DEV
1878 ctx.dev_fd = -1;
1879 #endif
1880 #ifdef INET
1881 ctx.udp_rfd = -1;
1882 ctx.udp_wfd = -1;
1883 #endif
1884 #if defined(INET6) && !defined(__sun)
1885 ctx.nd_fd = -1;
1886 #endif
1887 #ifdef DHCP6
1888 ctx.dhcp6_rfd = -1;
1889 ctx.dhcp6_wfd = -1;
1890 #endif
1891 #ifdef PRIVSEP
1892 ctx.ps_root_fd = ctx.ps_data_fd = -1;
1893 ctx.ps_inet_fd = ctx.ps_control_fd = -1;
1894 TAILQ_INIT(&ctx.ps_processes);
1895 #endif
1896 rt_init(&ctx);
1898 logopts = LOGERR_ERR|LOGERR_LOG|LOGERR_LOG_DATE|LOGERR_LOG_PID;
1899 i = 0;
1900 while ((opt = getopt_long(argc, argv,
1901 ctx.options & DHCPCD_PRINT_PIDFILE ? NOERR_IF_OPTS : IF_OPTS,
1902 cf_options, &oi)) != -1)
1904 switch (opt) {
1905 case '4':
1906 family = AF_INET;
1907 break;
1908 case '6':
1909 family = AF_INET6;
1910 break;
1911 case 'f':
1912 ctx.cffile = optarg;
1913 break;
1914 case 'j':
1915 free(ctx.logfile);
1916 ctx.logfile = strdup(optarg);
1917 break;
1918 #ifdef USE_SIGNALS
1919 case 'k':
1920 sig = SIGALRM;
1921 siga = "ALRM";
1922 break;
1923 case 'n':
1924 sig = SIGHUP;
1925 siga = "HUP";
1926 break;
1927 case 'g':
1928 case 'p':
1929 /* Force going via command socket as we're
1930 * out of user definable signals. */
1931 i = 4;
1932 break;
1933 case 'q':
1934 /* -qq disables console output entirely.
1935 * This is important for systemd because it logs
1936 * both console AND syslog to the same log
1937 * resulting in untold confusion. */
1938 if (logopts & LOGERR_QUIET)
1939 logopts &= ~LOGERR_ERR;
1940 else
1941 logopts |= LOGERR_QUIET;
1942 break;
1943 case 'x':
1944 sig = SIGTERM;
1945 siga = "TERM";
1946 break;
1947 case 'N':
1948 sig = SIGUSR1;
1949 siga = "USR1";
1950 break;
1951 #endif
1952 case 'P':
1953 ctx.options |= DHCPCD_PRINT_PIDFILE;
1954 logopts &= ~(LOGERR_LOG | LOGERR_ERR);
1955 break;
1956 case 'T':
1957 i = 1;
1958 logopts &= ~LOGERR_LOG;
1959 break;
1960 case 'U':
1961 i = 3;
1962 break;
1963 case 'V':
1964 i = 2;
1965 break;
1966 case '?':
1967 if (ctx.options & DHCPCD_PRINT_PIDFILE)
1968 continue;
1969 usage();
1970 goto exit_failure;
1974 logsetopts(logopts);
1975 logopen(ctx.logfile);
1977 ctx.argv = argv;
1978 ctx.argc = argc;
1979 ctx.ifc = argc - optind;
1980 ctx.ifv = argv + optind;
1982 ifo = read_config(&ctx, NULL, NULL, NULL);
1983 if (ifo == NULL) {
1984 if (ctx.options & DHCPCD_PRINT_PIDFILE)
1985 goto printpidfile;
1986 goto exit_failure;
1988 opt = add_options(&ctx, NULL, ifo, argc, argv);
1989 if (opt != 1) {
1990 if (ctx.options & DHCPCD_PRINT_PIDFILE)
1991 goto printpidfile;
1992 if (opt == 0)
1993 usage();
1994 goto exit_failure;
1996 if (i == 2) {
1997 printf("Interface options:\n");
1998 if (optind == argc - 1) {
1999 free_options(&ctx, ifo);
2000 ifo = read_config(&ctx, argv[optind], NULL, NULL);
2001 if (ifo == NULL)
2002 goto exit_failure;
2003 add_options(&ctx, NULL, ifo, argc, argv);
2005 if_printoptions();
2006 #ifdef INET
2007 if (family == 0 || family == AF_INET) {
2008 printf("\nDHCPv4 options:\n");
2009 dhcp_printoptions(&ctx,
2010 ifo->dhcp_override, ifo->dhcp_override_len);
2012 #endif
2013 #ifdef INET6
2014 if (family == 0 || family == AF_INET6) {
2015 printf("\nND options:\n");
2016 ipv6nd_printoptions(&ctx,
2017 ifo->nd_override, ifo->nd_override_len);
2018 #ifdef DHCP6
2019 printf("\nDHCPv6 options:\n");
2020 dhcp6_printoptions(&ctx,
2021 ifo->dhcp6_override, ifo->dhcp6_override_len);
2022 #endif
2024 #endif
2025 goto exit_success;
2027 ctx.options |= ifo->options;
2028 if (i == 1 || i == 3) {
2029 if (i == 1)
2030 ctx.options |= DHCPCD_TEST;
2031 else
2032 ctx.options |= DHCPCD_DUMPLEASE;
2033 ctx.options |= DHCPCD_PERSISTENT;
2034 ctx.options &= ~DHCPCD_DAEMONISE;
2037 #ifdef THERE_IS_NO_FORK
2038 ctx.options &= ~DHCPCD_DAEMONISE;
2039 #endif
2041 if (ctx.options & DHCPCD_DEBUG)
2042 logsetopts(logopts | LOGERR_DEBUG);
2044 if (!(ctx.options & (DHCPCD_TEST | DHCPCD_DUMPLEASE))) {
2045 printpidfile:
2046 /* If we have any other args, we should run as a single dhcpcd
2047 * instance for that interface. */
2048 if (optind == argc - 1 && !(ctx.options & DHCPCD_MASTER)) {
2049 const char *per;
2050 const char *ifname;
2052 ifname = *ctx.ifv;
2053 if (ifname == NULL || strlen(ifname) > IF_NAMESIZE) {
2054 errno = ifname == NULL ? EINVAL : E2BIG;
2055 logerr("%s: ", ifname);
2056 goto exit_failure;
2058 /* Allow a dhcpcd interface per address family */
2059 switch(family) {
2060 case AF_INET:
2061 per = "-4";
2062 break;
2063 case AF_INET6:
2064 per = "-6";
2065 break;
2066 default:
2067 per = "";
2069 snprintf(ctx.pidfile, sizeof(ctx.pidfile),
2070 PIDFILE, ifname, per, ".");
2071 } else {
2072 snprintf(ctx.pidfile, sizeof(ctx.pidfile),
2073 PIDFILE, "", "", "");
2074 ctx.options |= DHCPCD_MASTER;
2076 if (ctx.options & DHCPCD_PRINT_PIDFILE) {
2077 printf("%s\n", ctx.pidfile);
2078 goto exit_success;
2082 if (chdir("/") == -1)
2083 logerr("%s: chdir `/'", __func__);
2085 /* Freeing allocated addresses from dumping leases can trigger
2086 * eloop removals as well, so init here. */
2087 if ((ctx.eloop = eloop_new()) == NULL) {
2088 logerr("%s: eloop_init", __func__);
2089 goto exit_failure;
2092 #ifdef USE_SIGNALS
2093 for (si = 0; si < dhcpcd_signals_ignore_len; si++)
2094 signal(dhcpcd_signals_ignore[si], SIG_IGN);
2096 /* Save signal mask, block and redirect signals to our handler */
2097 eloop_signal_set_cb(ctx.eloop,
2098 dhcpcd_signals, dhcpcd_signals_len,
2099 dhcpcd_signal_cb, &ctx);
2100 if (eloop_signal_mask(ctx.eloop, &ctx.sigset) == -1) {
2101 logerr("%s: eloop_signal_mask", __func__);
2102 goto exit_failure;
2105 if (sig != 0) {
2106 pid = pidfile_read(ctx.pidfile);
2107 if (pid != 0 && pid != -1)
2108 loginfox("sending signal %s to pid %d", siga, pid);
2109 if (pid == 0 || pid == -1 || kill(pid, sig) != 0) {
2110 if (sig != SIGHUP && sig != SIGUSR1 && errno != EPERM)
2111 logerrx(PACKAGE" not running");
2112 if (pid != 0 && pid != -1 && errno != ESRCH) {
2113 logerr("kill");
2114 goto exit_failure;
2116 unlink(ctx.pidfile);
2117 if (sig != SIGHUP && sig != SIGUSR1)
2118 goto exit_failure;
2119 } else {
2120 struct timespec ts;
2122 if (sig == SIGHUP || sig == SIGUSR1)
2123 goto exit_success;
2124 /* Spin until it exits */
2125 loginfox("waiting for pid %d to exit", pid);
2126 ts.tv_sec = 0;
2127 ts.tv_nsec = 100000000; /* 10th of a second */
2128 for(i = 0; i < 100; i++) {
2129 nanosleep(&ts, NULL);
2130 if (pidfile_read(ctx.pidfile) == -1)
2131 goto exit_success;
2133 logerrx("pid %d failed to exit", pid);
2134 goto exit_failure;
2137 #endif
2139 #ifdef PRIVSEP
2140 ps_init(&ctx);
2141 #endif
2143 #ifndef SMALL
2144 if (ctx.options & DHCPCD_DUMPLEASE &&
2145 ioctl(fileno(stdin), FIONREAD, &i, sizeof(i)) == 0 &&
2146 i > 0)
2148 ctx.options |= DHCPCD_FORKED; /* pretend child process */
2149 #ifdef PRIVSEP
2150 if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1)
2151 goto exit_failure;
2152 #endif
2153 ifp = calloc(1, sizeof(*ifp));
2154 if (ifp == NULL) {
2155 logerr(__func__);
2156 goto exit_failure;
2158 ifp->ctx = &ctx;
2159 ifp->options = ifo;
2160 switch (family) {
2161 case AF_INET:
2162 #ifdef INET
2163 if (dhcp_dump(ifp) == -1)
2164 goto exit_failure;
2165 break;
2166 #else
2167 logerrx("No DHCP support");
2168 goto exit_failure;
2169 #endif
2170 case AF_INET6:
2171 #ifdef DHCP6
2172 if (dhcp6_dump(ifp) == -1)
2173 goto exit_failure;
2174 break;
2175 #else
2176 logerrx("No DHCP6 support");
2177 goto exit_failure;
2178 #endif
2179 default:
2180 logerrx("Family not specified. Please use -4 or -6.");
2181 goto exit_failure;
2183 goto exit_success;
2185 #endif
2187 /* Test against siga instead of sig to avoid gcc
2188 * warning about a bogus potential signed overflow.
2189 * The end result will be the same. */
2190 if ((siga == NULL || i == 4 || ctx.ifc != 0) &&
2191 !(ctx.options & DHCPCD_TEST))
2193 ctx.options |= DHCPCD_FORKED; /* avoid socket unlink */
2194 if (!(ctx.options & DHCPCD_MASTER))
2195 ctx.control_fd = control_open(argv[optind], family,
2196 ctx.options & DHCPCD_DUMPLEASE);
2197 if (ctx.control_fd == -1)
2198 ctx.control_fd = control_open(NULL, AF_UNSPEC,
2199 ctx.options & DHCPCD_DUMPLEASE);
2200 if (ctx.control_fd != -1) {
2201 #ifdef PRIVSEP
2202 ctx.options &= ~DHCPCD_FORKED;
2203 if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1) {
2204 ctx.options |= DHCPCD_FORKED;
2205 goto exit_failure;
2207 ctx.options |= DHCPCD_FORKED;
2208 #endif
2209 if (!(ctx.options & DHCPCD_DUMPLEASE))
2210 loginfox("sending commands to dhcpcd process");
2211 len = control_send(&ctx, argc, argv);
2212 if (len > 0)
2213 logdebugx("send OK");
2214 else {
2215 logerr("%s: control_send", __func__);
2216 goto exit_failure;
2218 if (ctx.options & DHCPCD_DUMPLEASE) {
2219 if (dhcpcd_readdump(&ctx) == -1) {
2220 logerr("%s: dhcpcd_readdump", __func__);
2221 goto exit_failure;
2223 goto run_loop;
2225 goto exit_success;
2226 } else {
2227 if (errno != ENOENT)
2228 logerr("%s: control_open", __func__);
2229 if (ctx.options & DHCPCD_DUMPLEASE) {
2230 if (errno == ENOENT)
2231 logerrx("dhcpcd is not running");
2232 goto exit_failure;
2234 if (errno == EPERM || errno == EACCES)
2235 goto exit_failure;
2237 ctx.options &= ~DHCPCD_FORKED;
2240 if (!(ctx.options & DHCPCD_TEST)) {
2241 /* Ensure we have the needed directories */
2242 if (mkdir(DBDIR, 0750) == -1 && errno != EEXIST)
2243 logerr("%s: mkdir `%s'", __func__, DBDIR);
2244 if (mkdir(RUNDIR, 0755) == -1 && errno != EEXIST)
2245 logerr("%s: mkdir `%s'", __func__, RUNDIR);
2246 if ((pid = pidfile_lock(ctx.pidfile)) != 0) {
2247 if (pid == -1)
2248 logerr("%s: pidfile_lock: %s",
2249 __func__, ctx.pidfile);
2250 else
2251 logerrx(PACKAGE
2252 " already running on pid %d (%s)",
2253 pid, ctx.pidfile);
2254 goto exit_failure;
2258 loginfox(PACKAGE "-" VERSION " starting");
2259 if (freopen(_PATH_DEVNULL, "r", stdin) == NULL)
2260 logerr("%s: freopen stdin", __func__);
2262 #if defined(USE_SIGNALS) && !defined(THERE_IS_NO_FORK)
2263 if (xsocketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, fork_fd) == -1 ||
2264 xsocketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, stderr_fd) == -1)
2266 logerr("socketpair");
2267 goto exit_failure;
2269 switch (pid = fork()) {
2270 case -1:
2271 logerr("fork");
2272 goto exit_failure;
2273 case 0:
2274 ctx.fork_fd = fork_fd[1];
2275 close(fork_fd[0]);
2276 #ifdef PRIVSEP_RIGHTS
2277 if (ps_rights_limit_fd(fork_fd[1]) == -1) {
2278 logerr("ps_rights_limit_fdpair");
2279 goto exit_failure;
2281 #endif
2283 * Redirect stderr to the stderr socketpair.
2284 * Redirect stdout as well.
2285 * dhcpcd doesn't output via stdout, but something in
2286 * a called script might.
2288 * Do NOT rights limit this fd as it will affect scripts.
2289 * For example, cmp reports insufficient caps on FreeBSD.
2291 if (dup2(stderr_fd[1], STDERR_FILENO) == -1 ||
2292 dup2(stderr_fd[1], STDOUT_FILENO) == -1)
2293 logerr("dup2");
2294 close(stderr_fd[0]);
2295 close(stderr_fd[1]);
2296 if (setsid() == -1) {
2297 logerr("%s: setsid", __func__);
2298 goto exit_failure;
2300 /* Ensure we can never get a controlling terminal */
2301 switch (pid = fork()) {
2302 case -1:
2303 logerr("fork");
2304 goto exit_failure;
2305 case 0:
2306 break;
2307 default:
2308 ctx.options |= DHCPCD_FORKED; /* A lie */
2309 i = EXIT_SUCCESS;
2310 goto exit1;
2312 break;
2313 default:
2314 ctx.options |= DHCPCD_FORKED; /* A lie */
2315 ctx.fork_fd = fork_fd[0];
2316 close(fork_fd[1]);
2317 ctx.stderr_fd = stderr_fd[0];
2318 close(stderr_fd[1]);
2319 #ifdef PRIVSEP_RIGHTS
2320 if (ps_rights_limit_fd(fork_fd[0]) == -1 ||
2321 ps_rights_limit_fd(stderr_fd[0]) == 1)
2323 logerr("ps_rights_limit_fdpair");
2324 goto exit_failure;
2326 #endif
2327 setproctitle("[launcher]");
2328 eloop_event_add(ctx.eloop, ctx.fork_fd, dhcpcd_fork_cb, &ctx);
2329 eloop_event_add(ctx.eloop, ctx.stderr_fd, dhcpcd_stderr_cb,
2330 &ctx);
2331 goto run_loop;
2334 /* We have now forked, setsid, forked once more.
2335 * From this point on, we are the controlling daemon. */
2336 ctx.options |= DHCPCD_STARTED;
2337 if ((pid = pidfile_lock(ctx.pidfile)) != 0) {
2338 logerr("%s: pidfile_lock %d", __func__, pid);
2339 goto exit_failure;
2341 #endif
2343 #if defined(BSD) && defined(INET6)
2344 /* Disable the kernel RTADV sysctl as early as possible. */
2345 if (ctx.options & DHCPCD_IPV6 && ctx.options & DHCPCD_IPV6RS)
2346 if_disable_rtadv();
2347 #endif
2349 #ifdef PRIVSEP
2350 if (IN_PRIVSEP(&ctx) && ps_start(&ctx) == -1) {
2351 logerr("ps_start");
2352 goto exit_failure;
2354 if (ctx.options & DHCPCD_FORKED)
2355 goto run_loop;
2356 #endif
2358 if (!(ctx.options & DHCPCD_TEST)) {
2359 if (control_start(&ctx,
2360 ctx.options & DHCPCD_MASTER ?
2361 NULL : argv[optind], family) == -1)
2363 logerr("%s: control_start", __func__);
2364 goto exit_failure;
2368 #ifdef PLUGIN_DEV
2369 /* Start any dev listening plugin which may want to
2370 * change the interface name provided by the kernel */
2371 if (!IN_PRIVSEP(&ctx) &&
2372 (ctx.options & (DHCPCD_MASTER | DHCPCD_DEV)) ==
2373 (DHCPCD_MASTER | DHCPCD_DEV))
2374 dev_start(&ctx, dhcpcd_handleinterface);
2375 #endif
2377 setproctitle("%s%s%s",
2378 ctx.options & DHCPCD_MASTER ? "[master]" : argv[optind],
2379 ctx.options & DHCPCD_IPV4 ? " [ip4]" : "",
2380 ctx.options & DHCPCD_IPV6 ? " [ip6]" : "");
2382 if (if_opensockets(&ctx) == -1) {
2383 logerr("%s: if_opensockets", __func__);
2384 goto exit_failure;
2386 #ifndef SMALL
2387 dhcpcd_setlinkrcvbuf(&ctx);
2388 #endif
2390 /* Try and create DUID from the machine UUID. */
2391 dhcpcd_initduid(&ctx, NULL);
2393 /* Cache the default vendor option. */
2394 if (dhcp_vendor(ctx.vendor, sizeof(ctx.vendor)) == -1)
2395 logerr("dhcp_vendor");
2397 /* Start handling kernel messages for interfaces, addresses and
2398 * routes. */
2399 eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx);
2401 #ifdef PRIVSEP
2402 if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1)
2403 goto exit_failure;
2404 #endif
2406 /* When running dhcpcd against a single interface, we need to retain
2407 * the old behaviour of waiting for an IP address */
2408 if (ctx.ifc == 1 && !(ctx.options & DHCPCD_BACKGROUND))
2409 ctx.options |= DHCPCD_WAITIP;
2411 ctx.ifaces = if_discover(&ctx, &ifaddrs, ctx.ifc, ctx.ifv);
2412 if (ctx.ifaces == NULL) {
2413 logerr("%s: if_discover", __func__);
2414 goto exit_failure;
2416 for (i = 0; i < ctx.ifc; i++) {
2417 if ((ifp = if_find(ctx.ifaces, ctx.ifv[i])) == NULL)
2418 logerrx("%s: interface not found",
2419 ctx.ifv[i]);
2420 else if (!ifp->active)
2421 logerrx("%s: interface has an invalid configuration",
2422 ctx.ifv[i]);
2424 TAILQ_FOREACH(ifp, ctx.ifaces, next) {
2425 if (ifp->active == IF_ACTIVE_USER)
2426 break;
2428 if (ifp == NULL) {
2429 if (ctx.ifc == 0) {
2430 int loglevel;
2432 loglevel = ctx.options & DHCPCD_INACTIVE ?
2433 LOG_DEBUG : LOG_ERR;
2434 logmessage(loglevel, "no valid interfaces found");
2435 dhcpcd_daemonise(&ctx);
2436 } else
2437 goto exit_failure;
2438 if (!(ctx.options & DHCPCD_LINK)) {
2439 logerrx("aborting as link detection is disabled");
2440 goto exit_failure;
2444 TAILQ_FOREACH(ifp, ctx.ifaces, next) {
2445 if (ifp->active)
2446 dhcpcd_initstate1(ifp, argc, argv, 0);
2448 if_learnaddrs(&ctx, ctx.ifaces, &ifaddrs);
2450 if (ctx.options & DHCPCD_BACKGROUND)
2451 dhcpcd_daemonise(&ctx);
2453 opt = 0;
2454 TAILQ_FOREACH(ifp, ctx.ifaces, next) {
2455 if (ifp->active) {
2456 run_preinit(ifp);
2457 if (!(ifp->options->options & DHCPCD_LINK) ||
2458 ifp->carrier != LINK_DOWN)
2459 opt = 1;
2463 if (!(ctx.options & DHCPCD_BACKGROUND)) {
2464 if (ctx.options & DHCPCD_MASTER)
2465 t = ifo->timeout;
2466 else {
2467 t = 0;
2468 TAILQ_FOREACH(ifp, ctx.ifaces, next) {
2469 if (ifp->active) {
2470 t = ifp->options->timeout;
2471 break;
2475 if (opt == 0 &&
2476 ctx.options & DHCPCD_LINK &&
2477 !(ctx.options & DHCPCD_WAITIP))
2479 int loglevel;
2481 loglevel = ctx.options & DHCPCD_INACTIVE ?
2482 LOG_DEBUG : LOG_WARNING;
2483 logmessage(loglevel, "no interfaces have a carrier");
2484 dhcpcd_daemonise(&ctx);
2485 } else if (t > 0 &&
2486 /* Test mode removes the daemonise bit, so check for both */
2487 ctx.options & (DHCPCD_DAEMONISE | DHCPCD_TEST))
2489 eloop_timeout_add_sec(ctx.eloop, t,
2490 handle_exit_timeout, &ctx);
2493 free_options(&ctx, ifo);
2494 ifo = NULL;
2496 TAILQ_FOREACH(ifp, ctx.ifaces, next) {
2497 if (ifp->active)
2498 eloop_timeout_add_sec(ctx.eloop, 0,
2499 dhcpcd_prestartinterface, ifp);
2502 run_loop:
2503 i = eloop_start(ctx.eloop, &ctx.sigset);
2504 if (i < 0) {
2505 logerr("%s: eloop_start", __func__);
2506 goto exit_failure;
2508 goto exit1;
2510 exit_success:
2511 i = EXIT_SUCCESS;
2512 goto exit1;
2514 exit_failure:
2515 i = EXIT_FAILURE;
2517 exit1:
2518 if (control_stop(&ctx) == -1)
2519 logerr("%s: control_stop", __func__);
2520 if (ifaddrs != NULL) {
2521 #ifdef PRIVSEP_GETIFADDRS
2522 if (IN_PRIVSEP(&ctx))
2523 free(ifaddrs);
2524 else
2525 #endif
2526 freeifaddrs(ifaddrs);
2528 #ifdef PRIVSEP
2529 ps_stop(&ctx);
2530 #endif
2531 /* Free memory and close fd's */
2532 if (ctx.ifaces) {
2533 while ((ifp = TAILQ_FIRST(ctx.ifaces))) {
2534 TAILQ_REMOVE(ctx.ifaces, ifp, next);
2535 if_free(ifp);
2537 free(ctx.ifaces);
2538 ctx.ifaces = NULL;
2540 free_options(&ctx, ifo);
2541 #ifdef HAVE_OPEN_MEMSTREAM
2542 if (ctx.script_fp)
2543 fclose(ctx.script_fp);
2544 #endif
2545 free(ctx.script_buf);
2546 free(ctx.script_env);
2547 rt_dispose(&ctx);
2548 free(ctx.duid);
2549 if (ctx.link_fd != -1) {
2550 eloop_event_delete(ctx.eloop, ctx.link_fd);
2551 close(ctx.link_fd);
2553 if_closesockets(&ctx);
2554 free_globals(&ctx);
2555 #ifdef INET6
2556 ipv6_ctxfree(&ctx);
2557 #endif
2558 #ifdef PLUGIN_DEV
2559 dev_stop(&ctx);
2560 #endif
2561 #ifdef PRIVSEP
2562 eloop_free(ctx.ps_eloop);
2563 #endif
2564 eloop_free(ctx.eloop);
2565 if (ctx.script != dhcpcd_default_script)
2566 free(ctx.script);
2567 if (ctx.options & DHCPCD_STARTED && !(ctx.options & DHCPCD_FORKED))
2568 loginfox(PACKAGE " exited");
2569 logclose();
2570 free(ctx.logfile);
2571 free(ctx.ctl_buf);
2572 #ifdef SETPROCTITLE_H
2573 setproctitle_free();
2574 #endif
2575 #ifdef USE_SIGNALS
2576 if (ctx.options & DHCPCD_FORKED)
2577 _exit(i); /* so atexit won't remove our pidfile */
2578 else if (ctx.options & DHCPCD_STARTED) {
2579 /* Try to detach from the launch process. */
2580 if (ctx.fork_fd != -1 &&
2581 write(ctx.fork_fd, &i, sizeof(i)) == -1)
2582 logerr("%s: write", __func__);
2584 #endif
2585 return i;