source: rtems-libbsd/dhcpcd/dhcpcd.c @ f724741

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f724741 was f724741, checked in by Sebastian Huber <sebastian.huber@…>, on 01/21/14 at 15:14:42

DHCPCD(8): Add getopt_long_r() support

  • Property mode set to 100644
File size: 35.6 KB
Line 
1/*
2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2014 Roy Marples <roy@marples.name>
4 * All rights reserved
5
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28const char dhcpcd_copyright[] = "Copyright (c) 2006-2014 Roy Marples";
29
30#include <sys/file.h>
31#include <sys/socket.h>
32#include <sys/stat.h>
33#include <sys/time.h>
34#include <sys/types.h>
35#include <sys/uio.h>
36#include <sys/utsname.h>
37
38#include <ctype.h>
39#include <errno.h>
40#ifdef __rtems__
41#define __need_getopt_newlib
42#endif /* __rtems__ */
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>
53
54#include "config.h"
55#include "arp.h"
56#include "common.h"
57#include "control.h"
58#include "dev.h"
59#include "dhcpcd.h"
60#include "dhcp6.h"
61#include "duid.h"
62#include "eloop.h"
63#include "if-options.h"
64#include "if-pref.h"
65#include "ipv4.h"
66#include "ipv6.h"
67#include "ipv6nd.h"
68#include "net.h"
69#include "platform.h"
70#include "script.h"
71
72struct if_head *ifaces = NULL;
73char vendor[VENDORCLASSID_MAX_LEN];
74int pidfd = -1;
75struct if_options *if_options = NULL;
76int ifac = 0;
77char **ifav = NULL;
78int ifdc = 0;
79char **ifdv = NULL;
80
81sigset_t dhcpcd_sigset;
82const int handle_sigs[] = {
83        SIGALRM,
84        SIGHUP,
85        SIGINT,
86        SIGPIPE,
87        SIGTERM,
88        SIGUSR1,
89        0
90};
91
92static char *cffile;
93static char *pidfile;
94static int linkfd = -1;
95static char **ifv;
96static int ifc;
97static char **margv;
98static int margc;
99
100static pid_t
101read_pid(void)
102{
103        FILE *fp;
104        pid_t pid;
105
106        if ((fp = fopen(pidfile, "r")) == NULL) {
107                errno = ENOENT;
108                return 0;
109        }
110        if (fscanf(fp, "%d", &pid) != 1)
111                pid = 0;
112        fclose(fp);
113        return pid;
114}
115
116static void
117usage(void)
118{
119
120printf("usage: "PACKAGE"\t[-46ABbDdEGgHJKkLnpqTVw]\n"
121        "\t\t[-C, --nohook hook] [-c, --script script]\n"
122        "\t\t[-e, --env value] [-F, --fqdn FQDN] [-f, --config file]\n"
123        "\t\t[-h, --hostname hostname] [-I, --clientid clientid]\n"
124        "\t\t[-i, --vendorclassid vendorclassid] [-l, --leasetime seconds]\n"
125        "\t\t[-m, --metric metric] [-O, --nooption option]\n"
126        "\t\t[-o, --option option] [-Q, --require option]\n"
127        "\t\t[-r, --request address] [-S, --static value]\n"
128        "\t\t[-s, --inform address[/cidr]] [-t, --timeout seconds]\n"
129        "\t\t[-u, --userclass class] [-v, --vendor code, value]\n"
130        "\t\t[-W, --whitelist address[/cidr]] [-y, --reboot seconds]\n"
131        "\t\t[-X, --blacklist address[/cidr]] [-Z, --denyinterfaces pattern]\n"
132        "\t\t[-z, --allowinterfaces pattern] [interface] [...]\n"
133        "       "PACKAGE"\t-k, --release [interface]\n"
134        "       "PACKAGE"\t-U, --dumplease interface\n"
135        "       "PACKAGE"\t--version\n"
136        "       "PACKAGE"\t-x, --exit [interface]\n");
137}
138
139static void
140free_globals(void)
141{
142        int i;
143        size_t n;
144        struct dhcp_opt *opt;
145
146        for (i = 0; i < ifac; i++)
147                free(ifav[i]);
148        free(ifav);
149        for (i = 0; i < ifdc; i++)
150                free(ifdv[i]);
151        free(ifdv);
152
153#ifdef INET
154        for (n = 0, opt = dhcp_opts; n < dhcp_opts_len; n++, opt++)
155                free_dhcp_opt_embenc(opt);
156        free(dhcp_opts);
157#endif
158#ifdef INET6
159        for (n = 0, opt = dhcp6_opts; n < dhcp6_opts_len; n++, opt++)
160                free_dhcp_opt_embenc(opt);
161        free(dhcp6_opts);
162#endif
163        for (n = 0, opt = vivso; n < vivso_len; n++, opt++)
164                free_dhcp_opt_embenc(opt);
165        free(vivso);
166}
167
168static void
169cleanup(void)
170{
171#ifdef DEBUG_MEMORY
172        struct interface *ifp;
173
174        free(duid);
175        free_options(if_options);
176
177        if (ifaces) {
178                while ((ifp = TAILQ_FIRST(ifaces))) {
179                        TAILQ_REMOVE(ifaces, ifp, next);
180                        free_interface(ifp);
181                }
182                free(ifaces);
183        }
184
185        free_globals();
186#endif
187
188        if (!(options & DHCPCD_FORKED))
189                dev_stop();
190        if (linkfd != -1)
191                close(linkfd);
192        if (pidfd > -1) {
193                if (options & DHCPCD_MASTER) {
194                        if (control_stop() == -1)
195                                syslog(LOG_ERR, "control_stop: %m");
196                }
197                close(pidfd);
198                unlink(pidfile);
199        }
200#ifdef DEBUG_MEMORY
201        free(pidfile);
202#endif
203
204        if (options & DHCPCD_STARTED && !(options & DHCPCD_FORKED))
205                syslog(LOG_INFO, "exited");
206}
207
208/* ARGSUSED */
209static void
210handle_exit_timeout(__unused void *arg)
211{
212        int timeout;
213
214        syslog(LOG_ERR, "timed out");
215        if (!(options & DHCPCD_IPV4) || !(options & DHCPCD_TIMEOUT_IPV4LL)) {
216                if (options & DHCPCD_MASTER) {
217                        /* We've timed out, so remove the waitip requirements.
218                         * If the user doesn't like this they can always set
219                         * an infinite timeout. */
220                        options &=
221                            ~(DHCPCD_WAITIP | DHCPCD_WAITIP4 | DHCPCD_WAITIP6);
222                        daemonise();
223                        return;
224                } else
225                        exit(EXIT_FAILURE);
226        }
227        options &= ~DHCPCD_TIMEOUT_IPV4LL;
228        timeout = (PROBE_NUM * PROBE_MAX) + (PROBE_WAIT * 2);
229        syslog(LOG_WARNING, "allowing %d seconds for IPv4LL timeout", timeout);
230        eloop_timeout_add_sec(timeout, handle_exit_timeout, NULL);
231}
232
233pid_t
234daemonise(void)
235{
236#ifdef THERE_IS_NO_FORK
237        return -1;
238#else
239        pid_t pid;
240        char buf = '\0';
241        int sidpipe[2], fd;
242
243        if (options & DHCPCD_DAEMONISE && !(options & DHCPCD_DAEMONISED)) {
244                if (options & DHCPCD_WAITIP4 &&
245                    !ipv4_addrexists(NULL))
246                        return -1;
247                if (options & DHCPCD_WAITIP6 &&
248                    !ipv6nd_addrexists(NULL) &&
249                    !dhcp6_addrexists(NULL))
250                        return -1;
251                if ((options &
252                    (DHCPCD_WAITIP | DHCPCD_WAITIP4 | DHCPCD_WAITIP6)) ==
253                    DHCPCD_WAITIP &&
254                    !ipv4_addrexists(NULL) &&
255                    !ipv6nd_addrexists(NULL) &&
256                    !dhcp6_addrexists(NULL))
257                        return -1;
258        }
259
260        eloop_timeout_delete(handle_exit_timeout, NULL);
261        if (options & DHCPCD_DAEMONISED || !(options & DHCPCD_DAEMONISE))
262                return 0;
263        /* Setup a signal pipe so parent knows when to exit. */
264        if (pipe(sidpipe) == -1) {
265                syslog(LOG_ERR, "pipe: %m");
266                return -1;
267        }
268        syslog(LOG_DEBUG, "forking to background");
269        switch (pid = fork()) {
270        case -1:
271                syslog(LOG_ERR, "fork: %m");
272                exit(EXIT_FAILURE);
273                /* NOTREACHED */
274        case 0:
275                setsid();
276                /* Notify parent it's safe to exit as we've detached. */
277                close(sidpipe[0]);
278                if (write(sidpipe[1], &buf, 1) == -1)
279                        syslog(LOG_ERR, "failed to notify parent: %m");
280                close(sidpipe[1]);
281                if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
282                        dup2(fd, STDIN_FILENO);
283                        dup2(fd, STDOUT_FILENO);
284                        dup2(fd, STDERR_FILENO);
285                        close(fd);
286                }
287                break;
288        default:
289                /* Wait for child to detach */
290                close(sidpipe[1]);
291                if (read(sidpipe[0], &buf, 1) == -1)
292                        syslog(LOG_ERR, "failed to read child: %m");
293                close(sidpipe[0]);
294                break;
295        }
296        /* Done with the fd now */
297        if (pid != 0) {
298                syslog(LOG_INFO, "forked to background, child pid %d",pid);
299                writepid(pidfd, pid);
300                close(pidfd);
301                pidfd = -1;
302                options |= DHCPCD_FORKED;
303                exit(EXIT_SUCCESS);
304        }
305        options |= DHCPCD_DAEMONISED;
306        return pid;
307#endif
308}
309
310struct interface *
311find_interface(const char *ifname)
312{
313        struct interface *ifp;
314
315        TAILQ_FOREACH(ifp, ifaces, next) {
316                if (strcmp(ifp->name, ifname) == 0)
317                        return ifp;
318        }
319        return NULL;
320}
321
322static void
323stop_interface(struct interface *ifp)
324{
325
326        syslog(LOG_INFO, "%s: removing interface", ifp->name);
327        ifp->options->options |= DHCPCD_STOPPING;
328
329        // Remove the interface from our list
330        TAILQ_REMOVE(ifaces, ifp, next);
331        dhcp6_drop(ifp, NULL);
332        ipv6nd_drop(ifp);
333        dhcp_drop(ifp, "STOP");
334        dhcp_close(ifp);
335        eloop_timeout_delete(NULL, ifp);
336        if (ifp->options->options & DHCPCD_DEPARTED)
337                script_runreason(ifp, "DEPARTED");
338        free_interface(ifp);
339        if (!(options & (DHCPCD_MASTER | DHCPCD_TEST)))
340                exit(EXIT_FAILURE);
341}
342
343static void
344configure_interface1(struct interface *ifp)
345{
346        struct if_options *ifo = ifp->options;
347        int ra_global, ra_iface;
348
349        /* Do any platform specific configuration */
350        if_conf(ifp);
351
352        /* If we want to release a lease, we can't really persist the
353         * address either. */
354        if (ifo->options & DHCPCD_RELEASE)
355                ifo->options &= ~DHCPCD_PERSISTENT;
356
357        if (ifp->flags & IFF_POINTOPOINT && !(ifo->options & DHCPCD_INFORM))
358                ifo->options |= DHCPCD_STATIC;
359        if (ifp->flags & IFF_NOARP ||
360            ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))
361                ifo->options &= ~(DHCPCD_ARP | DHCPCD_IPV4LL);
362        if (!(ifp->flags & (IFF_POINTOPOINT | IFF_LOOPBACK | IFF_MULTICAST)))
363                ifo->options &= ~DHCPCD_IPV6RS;
364        if (ifo->options & DHCPCD_LINK && carrier_status(ifp) == LINK_UNKNOWN)
365                ifo->options &= ~DHCPCD_LINK;
366
367        if (ifo->metric != -1)
368                ifp->metric = ifo->metric;
369
370        if (!(ifo->options & DHCPCD_IPV6))
371                ifo->options &= ~DHCPCD_IPV6RS;
372
373        /* We want to disable kernel interface RA as early as possible. */
374        if (ifo->options & DHCPCD_IPV6RS) {
375                ra_global = check_ipv6(NULL, options & DHCPCD_IPV6RA_OWN ? 1:0);
376                ra_iface = check_ipv6(ifp->name,
377                    ifp->options->options & DHCPCD_IPV6RA_OWN ? 1 : 0);
378                if (ra_global == -1 || ra_iface == -1)
379                        ifo->options &= ~DHCPCD_IPV6RS;
380                else if (ra_iface == 0)
381                        ifo->options |= DHCPCD_IPV6RA_OWN;
382        }
383
384        /* If we haven't specified a ClientID and our hardware address
385         * length is greater than DHCP_CHADDR_LEN then we enforce a ClientID
386         * of the hardware address family and the hardware address. */
387        if (ifp->hwlen > DHCP_CHADDR_LEN)
388                ifo->options |= DHCPCD_CLIENTID;
389
390        /* Firewire and InfiniBand interfaces require ClientID and
391         * the broadcast option being set. */
392        switch (ifp->family) {
393        case ARPHRD_IEEE1394:   /* FALLTHROUGH */
394        case ARPHRD_INFINIBAND:
395                ifo->options |= DHCPCD_CLIENTID | DHCPCD_BROADCAST;
396                break;
397        }
398
399        if (!(ifo->options & DHCPCD_IAID)) {
400                /*
401                 * An IAID is for identifying a unqiue interface within
402                 * the client. It is 4 bytes long. Working out a default
403                 * value is problematic.
404                 *
405                 * Interface name and number are not stable
406                 * between different OS's. Some OS's also cannot make
407                 * up their mind what the interface should be called
408                 * (yes, udev, I'm looking at you).
409                 * Also, the name could be longer than 4 bytes.
410                 * Also, with pluggable interfaces the name and index
411                 * could easily get swapped per actual interface.
412                 *
413                 * The MAC address is 6 bytes long, the final 3
414                 * being unique to the manufacturer and the initial 3
415                 * being unique to the organisation which makes it.
416                 * We could use the last 4 bytes of the MAC address
417                 * as the IAID as it's the most stable part given the
418                 * above, but equally it's not guaranteed to be
419                 * unique.
420                 *
421                 * Given the above, and our need to reliably work
422                 * between reboots without persitent storage,
423                 * generating the IAID from the MAC address is the only
424                 * logical default.
425                 *
426                 * dhclient uses the last 4 bytes of the MAC address.
427                 * dibbler uses an increamenting counter.
428                 * wide-dhcpv6 uses 0 or a configured value.
429                 * odhcp6c uses 1.
430                 * Windows 7 uses the first 3 bytes of the MAC address
431                 * and an unknown byte.
432                 * dhcpcd-6.1.0 and earlier used the interface name,
433                 * falling back to interface index if name > 4.
434                 */
435                memcpy(ifo->iaid, ifp->hwaddr + ifp->hwlen - sizeof(ifo->iaid),
436                    sizeof(ifo->iaid));
437#if 0
438                len = strlen(ifp->name);
439                if (len <= sizeof(ifo->iaid)) {
440                        memcpy(ifo->iaid, ifp->name, len);
441                        memset(ifo->iaid + len, 0, sizeof(ifo->iaid) - len);
442                } else {
443                        /* IAID is the same size as a uint32_t */
444                        len = htonl(ifp->index);
445                        memcpy(ifo->iaid, &len, sizeof(len));
446                }
447#endif
448                ifo->options |= DHCPCD_IAID;
449        }
450
451#ifdef INET6
452        if (ifo->ia == NULL && ifo->options & DHCPCD_IPV6) {
453                ifo->ia = malloc(sizeof(*ifo->ia));
454                if (ifo->ia == NULL)
455                        syslog(LOG_ERR, "%s: %m", __func__);
456                else {
457                        if (ifo->ia_type == 0)
458                                ifo->ia_type = D6_OPTION_IA_NA;
459                        memcpy(ifo->ia->iaid, ifo->iaid, sizeof(ifo->iaid));
460                        ifo->ia_len = 1;
461                        ifo->ia->sla = NULL;
462                        ifo->ia->sla_len = 0;
463                }
464        }
465#endif
466
467        /* If we are not sending an authentication option, don't require it */
468        if (!(ifo->auth.options & DHCPCD_AUTH_SEND))
469                ifo->auth.options &= ~DHCPCD_AUTH_REQUIRE;
470
471}
472
473int
474select_profile(struct interface *ifp, const char *profile)
475{
476        struct if_options *ifo;
477        int ret;
478
479        ret = 0;
480        ifo = read_config(cffile, ifp->name, ifp->ssid, profile);
481        if (ifo == NULL) {
482                syslog(LOG_DEBUG, "%s: no profile %s", ifp->name, profile);
483                ret = -1;
484                goto exit;
485        }
486        if (profile != NULL) {
487                strlcpy(ifp->profile, profile, sizeof(ifp->profile));
488                syslog(LOG_INFO, "%s: selected profile %s",
489                    ifp->name, profile);
490        } else
491                *ifp->profile = '\0';
492        free_options(ifp->options);
493        ifp->options = ifo;
494
495exit:
496        if (profile)
497                configure_interface1(ifp);
498        return ret;
499}
500
501static void
502configure_interface(struct interface *ifp, int argc, char **argv)
503{
504
505        select_profile(ifp, NULL);
506        add_options(ifp->name, ifp->options, argc, argv);
507        configure_interface1(ifp);
508}
509
510void
511handle_carrier(int carrier, int flags, const char *ifname)
512{
513        struct interface *ifp;
514
515        ifp = find_interface(ifname);
516        if (ifp == NULL || !(ifp->options->options & DHCPCD_LINK))
517                return;
518
519        if (carrier == LINK_UNKNOWN)
520                carrier = carrier_status(ifp); /* will set ifp->flags */
521        else
522                ifp->flags = flags;
523
524        if (carrier == LINK_UNKNOWN)
525                syslog(LOG_ERR, "%s: carrier_status: %m", ifname);
526        /* IFF_RUNNING is checked, if needed, earlier and is OS dependant */
527        else if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) {
528                if (ifp->carrier != LINK_DOWN) {
529                        if (ifp->carrier == LINK_UP)
530                                syslog(LOG_INFO, "%s: carrier lost", ifp->name);
531                        ifp->carrier = LINK_DOWN;
532                        dhcp_close(ifp);
533                        dhcp6_drop(ifp, "EXPIRE6");
534                        ipv6nd_drop(ifp);
535                        /* Don't blindly delete our knowledge of LL addresses.
536                         * We need to listen to what the kernel does with
537                         * them as some OS's will remove, mark tentative or
538                         * do nothing. */
539                        ipv6_free_ll_callbacks(ifp);
540                        dhcp_drop(ifp, "NOCARRIER");
541                }
542        } else if (carrier == LINK_UP && ifp->flags & IFF_UP) {
543                if (ifp->carrier != LINK_UP) {
544                        syslog(LOG_INFO, "%s: carrier acquired", ifp->name);
545                        ifp->carrier = LINK_UP;
546#if !defined(__linux__) && !defined(__NetBSD__)
547                        /* BSD does not emit RTM_NEWADDR or RTM_CHGADDR when the
548                         * hardware address changes so we have to go
549                         * through the disovery process to work it out. */
550                        handle_interface(0, ifp->name);
551#endif
552                        if (ifp->wireless)
553                                getifssid(ifp->name, ifp->ssid);
554                        configure_interface(ifp, margc, margv);
555                        script_runreason(ifp, "CARRIER");
556                        start_interface(ifp);
557                }
558        }
559}
560
561static void
562warn_iaid_conflict(struct interface *ifp, uint8_t *iaid)
563{
564        struct interface *ifn;
565        size_t i;
566
567        TAILQ_FOREACH(ifn, ifaces, next) {
568                if (ifn == ifp)
569                        continue;
570                if (memcmp(ifn->options->iaid, iaid,
571                    sizeof(ifn->options->iaid)) == 0)
572                        break;
573                for (i = 0; i < ifn->options->ia_len; i++) {
574                        if (memcmp(&ifn->options->ia[i].iaid, iaid,
575                            sizeof(ifn->options->ia[i].iaid)) == 0)
576                                break;
577                }
578        }
579
580        /* This is only a problem if the interfaces are on the same network. */
581        if (ifn)
582                syslog(LOG_ERR,
583                    "%s: IAID conflicts with one assigned to %s",
584                    ifp->name, ifn->name);
585}
586
587void
588start_interface(void *arg)
589{
590        struct interface *ifp = arg;
591        struct if_options *ifo = ifp->options;
592        int nolease;
593        size_t i;
594
595        handle_carrier(LINK_UNKNOWN, 0, ifp->name);
596        if (ifp->carrier == LINK_DOWN) {
597                syslog(LOG_INFO, "%s: waiting for carrier", ifp->name);
598                return;
599        }
600
601        if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6)) {
602                /* Report client DUID */
603                if (duid == NULL) {
604                        if (duid_init(ifp) == 0)
605                                return;
606                        syslog(LOG_INFO, "DUID %s",
607                            hwaddr_ntoa(duid, duid_len));
608                }
609
610                /* Report IAIDs */
611                syslog(LOG_INFO, "%s: IAID %s", ifp->name,
612                    hwaddr_ntoa(ifo->iaid, sizeof(ifo->iaid)));
613                warn_iaid_conflict(ifp, ifo->iaid);
614                for (i = 0; i < ifo->ia_len; i++) {
615                        if (memcmp(ifo->iaid, ifo->ia[i].iaid,
616                            sizeof(ifo->iaid)))
617                        {
618                                syslog(LOG_INFO, "%s: IAID %s", ifp->name,
619                                    hwaddr_ntoa(ifo->ia[i].iaid,
620                                    sizeof(ifo->ia[i].iaid)));
621                                warn_iaid_conflict(ifp, ifo->ia[i].iaid);
622                        }
623                }
624        }
625
626        if (ifo->options & DHCPCD_IPV6) {
627                if (ifo->options & DHCPCD_IPV6RS &&
628                    !(ifo->options & DHCPCD_INFORM))
629                        ipv6nd_startrs(ifp);
630
631                if (!(ifo->options & DHCPCD_IPV6RS)) {
632                        if (ifo->options & DHCPCD_IA_FORCED)
633                                nolease = dhcp6_start(ifp, DH6S_INIT);
634                        else {
635                                nolease = dhcp6_find_delegates(ifp);
636                                /* Enabling the below doesn't really make
637                                 * sense as there is currently no standard
638                                 * to push routes via DHCPv6.
639                                 * (There is an expired working draft,
640                                 * maybe abandoned?)
641                                 * You can also get it to work by forcing
642                                 * an IA as shown above. */
643#if 0
644                                /* With no RS or delegates we might
645                                 * as well try and solicit a DHCPv6 address */
646                                if (nolease == 0)
647                                        nolease = dhcp6_start(ifp, DH6S_INIT);
648#endif
649                        }
650                        if (nolease == -1)
651                                syslog(LOG_ERR,
652                                    "%s: dhcp6_start: %m", ifp->name);
653                }
654        }
655
656        if (ifo->options & DHCPCD_IPV4)
657                dhcp_start(ifp);
658}
659
660/* ARGSUSED */
661static void
662handle_link(__unused void *arg)
663{
664
665        if (manage_link(linkfd) == -1 && errno != ENXIO && errno != ENODEV)
666                syslog(LOG_ERR, "manage_link: %m");
667}
668
669static void
670init_state(struct interface *ifp, int argc, char **argv)
671{
672        struct if_options *ifo;
673        const char *reason = NULL;
674
675        configure_interface(ifp, argc, argv);
676        ifo = ifp->options;
677
678        if (ifo->options & DHCPCD_IPV4 && ipv4_init() == -1) {
679                syslog(LOG_ERR, "ipv4_init: %m");
680                ifo->options &= ~DHCPCD_IPV4;
681        }
682        if (ifo->options & DHCPCD_IPV6 && ipv6_init() == -1) {
683                syslog(LOG_ERR, "ipv6_init: %m");
684                ifo->options &= ~DHCPCD_IPV6RS;
685        }
686
687        if (!(options & DHCPCD_TEST))
688                script_runreason(ifp, "PREINIT");
689
690        if (ifo->options & DHCPCD_LINK) {
691                switch (carrier_status(ifp)) {
692                case LINK_DOWN:
693                        ifp->carrier = LINK_DOWN;
694                        reason = "NOCARRIER";
695                        break;
696                case LINK_UP:
697                        ifp->carrier = LINK_UP;
698                        reason = "CARRIER";
699                        break;
700                default:
701                        ifp->carrier = LINK_UNKNOWN;
702                        return;
703                }
704                if (reason && !(options & DHCPCD_TEST))
705                        script_runreason(ifp, reason);
706        } else
707                ifp->carrier = LINK_UNKNOWN;
708}
709
710void
711handle_interface(int action, const char *ifname)
712{
713        struct if_head *ifs;
714        struct interface *ifp, *ifn, *ifl = NULL;
715        const char * const argv[] = { ifname };
716        int i;
717
718        if (action == -1) {
719                ifp = find_interface(ifname);
720                if (ifp != NULL) {
721                        ifp->options->options |= DHCPCD_DEPARTED;
722                        stop_interface(ifp);
723                }
724                return;
725        }
726
727        /* If running off an interface list, check it's in it. */
728        if (ifc) {
729                for (i = 0; i < ifc; i++)
730                        if (strcmp(ifv[i], ifname) == 0)
731                                break;
732                if (i >= ifc)
733                        return;
734        }
735
736        ifs = discover_interfaces(-1, UNCONST(argv));
737        TAILQ_FOREACH_SAFE(ifp, ifs, next, ifn) {
738                if (strcmp(ifp->name, ifname) != 0)
739                        continue;
740                /* Check if we already have the interface */
741                ifl = find_interface(ifp->name);
742                if (ifl) {
743                        /* The flags and hwaddr could have changed */
744                        ifl->flags = ifp->flags;
745                        ifl->hwlen = ifp->hwlen;
746                        if (ifp->hwlen != 0)
747                                memcpy(ifl->hwaddr, ifp->hwaddr, ifl->hwlen);
748                } else {
749                        TAILQ_REMOVE(ifs, ifp, next);
750                        TAILQ_INSERT_TAIL(ifaces, ifp, next);
751                }
752                if (action == 1) {
753                        init_state(ifp, margc, margv);
754                        start_interface(ifp);
755                }
756        }
757
758        /* Free our discovered list */
759        while ((ifp = TAILQ_FIRST(ifs))) {
760                TAILQ_REMOVE(ifs, ifp, next);
761                free_interface(ifp);
762        }
763        free(ifs);
764}
765
766void
767handle_hwaddr(const char *ifname, const uint8_t *hwaddr, size_t hwlen)
768{
769        struct interface *ifp;
770
771        ifp = find_interface(ifname);
772        if (ifp == NULL)
773                return;
774
775        if (hwlen > sizeof(ifp->hwaddr)) {
776                errno = ENOBUFS;
777                syslog(LOG_ERR, "%s: %s: %m", ifp->name, __func__);
778                return;
779        }
780
781        if (ifp->hwlen == hwlen && memcmp(ifp->hwaddr, hwaddr, hwlen) == 0)
782                return;
783
784        syslog(LOG_INFO, "%s: new hardware address: %s", ifp->name,
785            hwaddr_ntoa(hwaddr, hwlen));
786        ifp->hwlen = hwlen;
787        memcpy(ifp->hwaddr, hwaddr, hwlen);
788}
789
790static void
791if_reboot(struct interface *ifp, int argc, char **argv)
792{
793        int oldopts;
794
795        oldopts = ifp->options->options;
796        script_runreason(ifp, "RECONFIGURE");
797        configure_interface(ifp, argc, argv);
798        dhcp_reboot_newopts(ifp, oldopts);
799        dhcp6_reboot(ifp);
800        start_interface(ifp);
801}
802
803static void
804reconf_reboot(int action, int argc, char **argv, int oi)
805{
806        struct if_head *ifs;
807        struct interface *ifn, *ifp;
808
809        ifs = discover_interfaces(argc - oi, argv + oi);
810        if (ifs == NULL)
811                return;
812
813        while ((ifp = TAILQ_FIRST(ifs))) {
814                TAILQ_REMOVE(ifs, ifp, next);
815                ifn = find_interface(ifp->name);
816                if (ifn) {
817                        if (action)
818                                if_reboot(ifn, argc, argv);
819                        else
820                                ipv4_applyaddr(ifn);
821                        free_interface(ifp);
822                } else {
823                        init_state(ifp, argc, argv);
824                        TAILQ_INSERT_TAIL(ifaces, ifp, next);
825                        start_interface(ifp);
826                }
827        }
828        free(ifs);
829
830        sort_interfaces();
831}
832
833/* ARGSUSED */
834static void
835sig_reboot(void *arg)
836{
837        siginfo_t *siginfo = arg;
838        struct if_options *ifo;
839
840        syslog(LOG_INFO, "received SIGALRM from PID %d, rebinding",
841            (int)siginfo->si_pid);
842
843        free_globals();
844        ifav = NULL;
845        ifac = 0;
846        ifdc = 0;
847        ifdv = NULL;
848
849        ifo = read_config(cffile, NULL, NULL, NULL);
850        add_options(NULL, ifo, margc, margv);
851        /* We need to preserve these two options. */
852        if (options & DHCPCD_MASTER)
853                ifo->options |= DHCPCD_MASTER;
854        if (options & DHCPCD_DAEMONISED)
855                ifo->options |= DHCPCD_DAEMONISED;
856        options = ifo->options;
857        free_options(ifo);
858        reconf_reboot(1, ifc, ifv, 0);
859}
860
861static void
862sig_reconf(void *arg)
863{
864        siginfo_t *siginfo = arg;
865        struct interface *ifp;
866
867        syslog(LOG_INFO, "received SIGUSR from PID %d, reconfiguring",
868            (int)siginfo->si_pid);
869        TAILQ_FOREACH(ifp, ifaces, next) {
870                ipv4_applyaddr(ifp);
871        }
872}
873
874static void
875handle_signal(int sig, siginfo_t *siginfo, __unused void *context)
876{
877        struct interface *ifp;
878        int do_release;
879
880        do_release = 0;
881        switch (sig) {
882        case SIGINT:
883                syslog(LOG_INFO, "received SIGINT from PID %d, stopping",
884                    (int)siginfo->si_pid);
885                break;
886        case SIGTERM:
887                syslog(LOG_INFO, "received SIGTERM from PID %d, stopping",
888                    (int)siginfo->si_pid);
889                break;
890        case SIGALRM:
891                eloop_timeout_add_now(sig_reboot, siginfo);
892                return;
893        case SIGHUP:
894                syslog(LOG_INFO, "received SIGHUP from PID %d, releasing",
895                    (int)siginfo->si_pid);
896                do_release = 1;
897                break;
898        case SIGUSR1:
899                eloop_timeout_add_now(sig_reconf, siginfo);
900                return;
901        case SIGPIPE:
902                syslog(LOG_WARNING, "received SIGPIPE");
903                return;
904        default:
905                syslog(LOG_ERR,
906                    "received signal %d from PID %d, "
907                    "but don't know what to do with it",
908                    sig, (int)siginfo->si_pid);
909                return;
910        }
911
912        if (options & DHCPCD_TEST)
913                exit(EXIT_FAILURE);
914
915        /* As drop_dhcp could re-arrange the order, we do it like this. */
916        for (;;) {
917                /* Be sane and drop the last config first */
918                ifp = TAILQ_LAST(ifaces, if_head);
919                if (ifp == NULL)
920                        break;
921                if (do_release) {
922                        ifp->options->options |= DHCPCD_RELEASE;
923                        ifp->options->options &= ~DHCPCD_PERSISTENT;
924                }
925                ifp->options->options |= DHCPCD_EXITING;
926                stop_interface(ifp);
927        }
928        exit(EXIT_FAILURE);
929}
930
931int
932handle_args(struct fd_list *fd, int argc, char **argv)
933{
934        struct interface *ifp;
935        int do_exit = 0, do_release = 0, do_reboot = 0;
936        int opt, oi = 0;
937        ssize_t len;
938        size_t l;
939        struct iovec iov[2];
940        char *tmp, *p;
941
942        if (fd != NULL) {
943                /* Special commands for our control socket */
944                if (strcmp(*argv, "--version") == 0) {
945                        len = strlen(VERSION) + 1;
946                        iov[0].iov_base = &len;
947                        iov[0].iov_len = sizeof(ssize_t);
948                        iov[1].iov_base = UNCONST(VERSION);
949                        iov[1].iov_len = len;
950                        if (writev(fd->fd, iov, 2) == -1) {
951                                syslog(LOG_ERR, "writev: %m");
952                                return -1;
953                        }
954                        return 0;
955                } else if (strcmp(*argv, "--getconfigfile") == 0) {
956                        len = strlen(cffile ? cffile : CONFIG) + 1;
957                        iov[0].iov_base = &len;
958                        iov[0].iov_len = sizeof(ssize_t);
959                        iov[1].iov_base = cffile ? cffile : UNCONST(CONFIG);
960                        iov[1].iov_len = len;
961                        if (writev(fd->fd, iov, 2) == -1) {
962                                syslog(LOG_ERR, "writev: %m");
963                                return -1;
964                        }
965                        return 0;
966                } else if (strcmp(*argv, "--getinterfaces") == 0) {
967                        len = 0;
968                        if (argc == 1) {
969                                TAILQ_FOREACH(ifp, ifaces, next) {
970                                        len++;
971                                        if (D6_STATE_RUNNING(ifp))
972                                                len++;
973                                        if (ipv6nd_has_ra(ifp))
974                                                len++;
975                                }
976                                len = write(fd->fd, &len, sizeof(len));
977                                if (len != sizeof(len))
978                                        return -1;
979                                TAILQ_FOREACH(ifp, ifaces, next) {
980                                        send_interface(fd->fd, ifp);
981                                }
982                                return 0;
983                        }
984                        opt = 0;
985                        while (argv[++opt] != NULL) {
986                                TAILQ_FOREACH(ifp, ifaces, next) {
987                                        if (strcmp(argv[opt], ifp->name) == 0) {
988                                                len++;
989                                                if (D6_STATE_RUNNING(ifp))
990                                                        len++;
991                                                if (ipv6nd_has_ra(ifp))
992                                                        len++;
993                                        }
994                                }
995                        }
996                        len = write(fd->fd, &len, sizeof(len));
997                        if (len != sizeof(len))
998                                return -1;
999                        opt = 0;
1000                        while (argv[++opt] != NULL) {
1001                                TAILQ_FOREACH(ifp, ifaces, next) {
1002                                        if (strcmp(argv[opt], ifp->name) == 0)
1003                                                send_interface(fd->fd, ifp);
1004                                }
1005                        }
1006                        return 0;
1007                } else if (strcmp(*argv, "--listen") == 0) {
1008                        fd->listener = 1;
1009                        return 0;
1010                }
1011        }
1012
1013        /* Log the command */
1014        len = 0;
1015        for (opt = 0; opt < argc; opt++)
1016                len += strlen(argv[opt]) + 1;
1017        tmp = p = malloc(len + 1);
1018        if (tmp == NULL) {
1019                syslog(LOG_ERR, "%s: %m", __func__);
1020                return -1;
1021        }
1022        for (opt = 0; opt < argc; opt++) {
1023                l = strlen(argv[opt]);
1024                strlcpy(p, argv[opt], l + 1);
1025                p += l;
1026                *p++ = ' ';
1027        }
1028        *--p = '\0';
1029        syslog(LOG_INFO, "control command: %s", tmp);
1030        free(tmp);
1031
1032        optind = 0;
1033        while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1)
1034        {
1035                switch (opt) {
1036                case 'g':
1037                        /* Assumed if below not set */
1038                        break;
1039                case 'k':
1040                        do_release = 1;
1041                        break;
1042                case 'n':
1043                        do_reboot = 1;
1044                        break;
1045                case 'x':
1046                        do_exit = 1;
1047                        break;
1048                }
1049        }
1050
1051        /* We need at least one interface */
1052        if (optind == argc) {
1053                syslog(LOG_ERR, "%s: no interface", __func__);
1054                return -1;
1055        }
1056
1057        if (do_release || do_exit) {
1058                for (oi = optind; oi < argc; oi++) {
1059                        if ((ifp = find_interface(argv[oi])) == NULL)
1060                                continue;
1061                        if (do_release) {
1062                                ifp->options->options |= DHCPCD_RELEASE;
1063                                ifp->options->options &= ~DHCPCD_PERSISTENT;
1064                        }
1065                        ifp->options->options |= DHCPCD_EXITING;
1066                        stop_interface(ifp);
1067                }
1068                return 0;
1069        }
1070
1071        reconf_reboot(do_reboot, argc, argv, optind);
1072        return 0;
1073}
1074
1075static int
1076signal_init(void (*func)(int, siginfo_t *, void *), sigset_t *oldset)
1077{
1078        unsigned int i;
1079        struct sigaction sa;
1080        sigset_t newset;
1081
1082        sigfillset(&newset);
1083        if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1)
1084                return -1;
1085
1086        memset(&sa, 0, sizeof(sa));
1087        sa.sa_sigaction = func;
1088        sa.sa_flags = SA_SIGINFO;
1089        sigemptyset(&sa.sa_mask);
1090
1091        for (i = 0; handle_sigs[i]; i++) {
1092                if (sigaction(handle_sigs[i], &sa, NULL) == -1)
1093                        return -1;
1094        }
1095        return 0;
1096}
1097
1098#ifdef __rtems__
1099#include <rtems/libio.h>
1100
1101struct getopt_data dhcpcd_getopt_data;
1102
1103static int
1104main(int argc, char **argv);
1105
1106int rtems_bsd_command_dhcpcd(int argc, char **argv)
1107{
1108        int exit_code;
1109
1110        rtems_mkdir(DBDIR, S_IRWXU | S_IRWXG | S_IRWXO);
1111
1112        exit_code = rtems_bsd_program_call_main("dhcpcd", main, argc, argv);
1113
1114        return exit_code;
1115}
1116#endif /* __rtems__ */
1117
1118int
1119main(int argc, char **argv)
1120{
1121        struct interface *ifp;
1122        uint16_t family = 0;
1123        int opt, oi = 0, sig = 0, i, control_fd;
1124        size_t len;
1125        pid_t pid;
1126        struct timespec ts;
1127        struct utsname utn;
1128        const char *platform;
1129
1130        closefrom(3);
1131        openlog(PACKAGE, LOG_PERROR | LOG_PID, LOG_DAEMON);
1132        setlogmask(LOG_UPTO(LOG_INFO));
1133
1134        /* Test for --help and --version */
1135        if (argc > 1) {
1136                if (strcmp(argv[1], "--help") == 0) {
1137                        usage();
1138                        exit(EXIT_SUCCESS);
1139                } else if (strcmp(argv[1], "--version") == 0) {
1140                        printf(""PACKAGE" "VERSION"\n%s\n", dhcpcd_copyright);
1141                        exit(EXIT_SUCCESS);
1142                }
1143        }
1144
1145        platform = hardware_platform();
1146        if (uname(&utn) == 0)
1147                snprintf(vendor, VENDORCLASSID_MAX_LEN,
1148                    "%s-%s:%s-%s:%s%s%s", PACKAGE, VERSION,
1149                    utn.sysname, utn.release, utn.machine,
1150                    platform ? ":" : "", platform ? platform : "");
1151        else
1152                snprintf(vendor, VENDORCLASSID_MAX_LEN,
1153                    "%s-%s", PACKAGE, VERSION);
1154
1155        i = 0;
1156        while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1)
1157        {
1158                switch (opt) {
1159                case '4':
1160                        family = AF_INET;
1161                        break;
1162                case '6':
1163                        family = AF_INET6;
1164                        break;
1165                case 'f':
1166                        cffile = optarg;
1167                        break;
1168                case 'g':
1169                        sig = SIGUSR1;
1170                        break;
1171                case 'k':
1172                        sig = SIGHUP;
1173                        break;
1174                case 'n':
1175                        sig = SIGALRM;
1176                        break;
1177                case 'x':
1178                        sig = SIGTERM;
1179                        break;
1180                case 'T':
1181                        i = 1;
1182                        break;
1183                case 'U':
1184                        i = 2;
1185                        break;
1186                case 'V':
1187                        i = 3;
1188                        break;
1189                case '?':
1190                        usage();
1191                        exit(EXIT_FAILURE);
1192                }
1193        }
1194
1195        margv = argv;
1196        margc = argc;
1197        if_options = read_config(cffile, NULL, NULL, NULL);
1198        opt = add_options(NULL, if_options, argc, argv);
1199        if (opt != 1) {
1200                if (opt == 0)
1201                        usage();
1202                exit(EXIT_FAILURE);
1203        }
1204        if (i == 3) {
1205                printf("Interface options:\n");
1206                if_printoptions();
1207#ifdef INET
1208                if (family == 0 || family == AF_INET) {
1209                        printf("\nDHCPv4 options:\n");
1210                        dhcp_printoptions();
1211                }
1212#endif
1213#ifdef INET6
1214                if (family == 0 || family == AF_INET6) {
1215                        printf("\nDHCPv6 options:\n");
1216                        dhcp6_printoptions();
1217                }
1218#endif
1219#ifdef DEBUG_MEMORY
1220                cleanup();
1221#endif
1222                exit(EXIT_SUCCESS);
1223        }
1224        options = if_options->options;
1225        if (i != 0) {
1226                if (i == 1)
1227                        options |= DHCPCD_TEST;
1228                else
1229                        options |= DHCPCD_DUMPLEASE;
1230                options |= DHCPCD_PERSISTENT;
1231                options &= ~DHCPCD_DAEMONISE;
1232        }
1233
1234#ifdef THERE_IS_NO_FORK
1235        options &= ~DHCPCD_DAEMONISE;
1236#endif
1237
1238        if (options & DHCPCD_DEBUG)
1239                setlogmask(LOG_UPTO(LOG_DEBUG));
1240        if (options & DHCPCD_QUIET) {
1241                i = open(_PATH_DEVNULL, O_RDWR);
1242                if (i == -1)
1243                        syslog(LOG_ERR, "%s: open: %m", __func__);
1244                else {
1245                        dup2(i, STDERR_FILENO);
1246                        close(i);
1247                }
1248        }
1249
1250        if (!(options & (DHCPCD_TEST | DHCPCD_DUMPLEASE))) {
1251                /* If we have any other args, we should run as a single dhcpcd
1252                 *  instance for that interface. */
1253                len = strlen(PIDFILE) + IF_NAMESIZE + 2;
1254                pidfile = malloc(len);
1255                if (pidfile == NULL) {
1256                        syslog(LOG_ERR, "%s: %m", __func__);
1257                        exit(EXIT_FAILURE);
1258                }
1259                if (optind == argc - 1)
1260                        snprintf(pidfile, len, PIDFILE, "-", argv[optind]);
1261                else {
1262                        snprintf(pidfile, len, PIDFILE, "", "");
1263                        options |= DHCPCD_MASTER;
1264                }
1265        }
1266
1267        if (chdir("/") == -1)
1268                syslog(LOG_ERR, "chdir `/': %m");
1269        atexit(cleanup);
1270
1271        if (options & DHCPCD_DUMPLEASE) {
1272                if (optind != argc - 1) {
1273                        syslog(LOG_ERR, "dumplease requires an interface");
1274                        exit(EXIT_FAILURE);
1275                }
1276                if (dhcp_dump(argv[optind]) == -1)
1277                        exit(EXIT_FAILURE);
1278                exit(EXIT_SUCCESS);
1279        }
1280
1281        if (!(options & (DHCPCD_MASTER | DHCPCD_TEST))) {
1282                control_fd = control_open();
1283                if (control_fd != -1) {
1284                        syslog(LOG_INFO,
1285                            "sending commands to master dhcpcd process");
1286                        i = control_send(argc, argv);
1287                        if (i > 0) {
1288                                syslog(LOG_DEBUG, "send OK");
1289                                exit(EXIT_SUCCESS);
1290                        } else {
1291                                syslog(LOG_ERR, "failed to send commands");
1292                                exit(EXIT_FAILURE);
1293                        }
1294                } else {
1295                        if (errno != ENOENT)
1296                                syslog(LOG_ERR, "control_open: %m");
1297                }
1298        }
1299
1300        if (geteuid())
1301                syslog(LOG_WARNING,
1302                    PACKAGE " will not work correctly unless run as root");
1303
1304        if (sig != 0) {
1305                pid = read_pid();
1306                if (pid != 0)
1307                        syslog(LOG_INFO, "sending signal %d to pid %d",
1308                            sig, pid);
1309                if (pid == 0 || kill(pid, sig) != 0) {
1310                        if (sig != SIGALRM && errno != EPERM)
1311                                syslog(LOG_ERR, ""PACKAGE" not running");
1312                        if (pid != 0 && errno != ESRCH) {
1313                                syslog(LOG_ERR, "kill: %m");
1314                                exit(EXIT_FAILURE);
1315                        }
1316                        unlink(pidfile);
1317                        if (sig != SIGALRM)
1318                                exit(EXIT_FAILURE);
1319                } else {
1320                        if (sig == SIGALRM || sig == SIGUSR1)
1321                                exit(EXIT_SUCCESS);
1322                        /* Spin until it exits */
1323                        syslog(LOG_INFO, "waiting for pid %d to exit", pid);
1324                        ts.tv_sec = 0;
1325                        ts.tv_nsec = 100000000; /* 10th of a second */
1326                        for(i = 0; i < 100; i++) {
1327                                nanosleep(&ts, NULL);
1328                                if (read_pid() == 0)
1329                                        exit(EXIT_SUCCESS);
1330                        }
1331                        syslog(LOG_ERR, "pid %d failed to exit", pid);
1332                        exit(EXIT_FAILURE);
1333                }
1334        }
1335
1336        if (!(options & DHCPCD_TEST)) {
1337                if ((pid = read_pid()) > 0 &&
1338                    kill(pid, 0) == 0)
1339                {
1340                        syslog(LOG_ERR, ""PACKAGE
1341                            " already running on pid %d (%s)",
1342                            pid, pidfile);
1343                        exit(EXIT_FAILURE);
1344                }
1345
1346                /* Ensure we have the needed directories */
1347                if (mkdir(RUNDIR, 0755) == -1 && errno != EEXIST)
1348                        syslog(LOG_ERR, "mkdir `%s': %m", RUNDIR);
1349                if (mkdir(DBDIR, 0755) == -1 && errno != EEXIST)
1350                        syslog(LOG_ERR, "mkdir `%s': %m", DBDIR);
1351
1352                pidfd = open(pidfile, O_WRONLY | O_CREAT | O_NONBLOCK, 0664);
1353                if (pidfd == -1)
1354                        syslog(LOG_ERR, "open `%s': %m", pidfile);
1355                else {
1356                        /* Lock the file so that only one instance of dhcpcd
1357                         * runs on an interface */
1358                        if (flock(pidfd, LOCK_EX | LOCK_NB) == -1) {
1359                                syslog(LOG_ERR, "flock `%s': %m", pidfile);
1360                                exit(EXIT_FAILURE);
1361                        }
1362                        if (set_cloexec(pidfd) == -1)
1363                                exit(EXIT_FAILURE);
1364                        writepid(pidfd, getpid());
1365                }
1366        }
1367
1368        syslog(LOG_INFO, "version " VERSION " starting");
1369        options |= DHCPCD_STARTED;
1370
1371#ifdef DEBUG_MEMORY
1372        eloop_init();
1373#endif
1374
1375        /* Save signal mask, block and redirect signals to our handler */
1376        if (signal_init(handle_signal, &dhcpcd_sigset) == -1) {
1377                syslog(LOG_ERR, "signal_setup: %m");
1378                exit(EXIT_FAILURE);
1379        }
1380
1381        if (options & DHCPCD_MASTER) {
1382                if (control_start() == -1)
1383                        syslog(LOG_ERR, "control_start: %m");
1384        }
1385
1386        if (open_sockets() == -1) {
1387                syslog(LOG_ERR, "open_sockets: %m");
1388                exit(EXIT_FAILURE);
1389        }
1390
1391#if 0
1392        if (options & DHCPCD_IPV6RS && disable_rtadv() == -1) {
1393                syslog(LOG_ERR, "disable_rtadvd: %m");
1394                options &= ~DHCPCD_IPV6RS;
1395        }
1396#endif
1397
1398        ifc = argc - optind;
1399        ifv = argv + optind;
1400
1401        /* When running dhcpcd against a single interface, we need to retain
1402         * the old behaviour of waiting for an IP address */
1403        if (ifc == 1 && !(options & DHCPCD_BACKGROUND))
1404                options |= DHCPCD_WAITIP;
1405
1406        /* RTM_NEWADDR goes through the link socket as well which we
1407         * need for IPv6 DAD, so we check for DHCPCD_LINK in handle_carrier
1408         * instead.
1409         * We also need to open this before checking for interfaces below
1410         * so that we pickup any new addresses during the discover phase. */
1411        if (linkfd == -1) {
1412                linkfd = open_link_socket();
1413                if (linkfd == -1)
1414                        syslog(LOG_ERR, "open_link_socket: %m");
1415                else
1416                        eloop_event_add(linkfd, handle_link, NULL);
1417        }
1418
1419        /* Start any dev listening plugin which may want to
1420         * change the interface name provided by the kernel */
1421        if ((options & (DHCPCD_MASTER | DHCPCD_DEV)) ==
1422            (DHCPCD_MASTER | DHCPCD_DEV))
1423                dev_start(dev_load);
1424
1425        ifaces = discover_interfaces(ifc, ifv);
1426        for (i = 0; i < ifc; i++) {
1427                if (find_interface(ifv[i]) == NULL)
1428                        syslog(LOG_ERR, "%s: interface not found or invalid",
1429                            ifv[i]);
1430        }
1431        if (ifaces == NULL || TAILQ_FIRST(ifaces) == NULL) {
1432                if (ifc == 0)
1433                        syslog(LOG_ERR, "no valid interfaces found");
1434                else
1435                        exit(EXIT_FAILURE);
1436                if (!(options & DHCPCD_LINK)) {
1437                        syslog(LOG_ERR,
1438                            "aborting as link detection is disabled");
1439                        exit(EXIT_FAILURE);
1440                }
1441        }
1442
1443        if (options & DHCPCD_BACKGROUND)
1444                daemonise();
1445
1446        opt = 0;
1447        TAILQ_FOREACH(ifp, ifaces, next) {
1448                init_state(ifp, argc, argv);
1449                if (ifp->carrier != LINK_DOWN)
1450                        opt = 1;
1451        }
1452
1453        if (!(options & DHCPCD_BACKGROUND)) {
1454                /* If we don't have a carrier, we may have to wait for a second
1455                 * before one becomes available if we brought an interface up */
1456                if (opt == 0 &&
1457                    options & DHCPCD_LINK &&
1458                    options & DHCPCD_WAITUP &&
1459                    !(options & DHCPCD_WAITIP))
1460                {
1461                        ts.tv_sec = 1;
1462                        ts.tv_nsec = 0;
1463                        nanosleep(&ts, NULL);
1464                        TAILQ_FOREACH(ifp, ifaces, next) {
1465                                handle_carrier(LINK_UNKNOWN, 0, ifp->name);
1466                                if (ifp->carrier != LINK_DOWN) {
1467                                        opt = 1;
1468                                        break;
1469                                }
1470                        }
1471                }
1472                if (options & DHCPCD_MASTER)
1473                        i = if_options->timeout;
1474                else if ((ifp = TAILQ_FIRST(ifaces)))
1475                        i = ifp->options->timeout;
1476                else
1477                        i = 0;
1478                if (opt == 0 &&
1479                    options & DHCPCD_LINK &&
1480                    !(options & DHCPCD_WAITIP))
1481                {
1482                        syslog(LOG_WARNING, "no interfaces have a carrier");
1483                        daemonise();
1484                } else if (i > 0) {
1485                        if (options & DHCPCD_IPV4LL)
1486                                options |= DHCPCD_TIMEOUT_IPV4LL;
1487                        eloop_timeout_add_sec(i, handle_exit_timeout, NULL);
1488                }
1489        }
1490        free_options(if_options);
1491        if_options = NULL;
1492
1493        sort_interfaces();
1494        TAILQ_FOREACH(ifp, ifaces, next) {
1495                eloop_timeout_add_sec(0, start_interface, ifp);
1496        }
1497
1498        eloop_start(&dhcpcd_sigset);
1499        exit(EXIT_SUCCESS);
1500}
Note: See TracBrowser for help on using the repository browser.