source: rtems-libbsd/dhcpcd/dhcp.c @ 81fc57d

55-freebsd-126-freebsd-12
Last change on this file since 81fc57d was ddd16bc, checked in by Christian Mauderer <Christian.Mauderer@…>, on 11/07/17 at 10:54:39

dhcpcd: Don't ignore interface on transient errors.

In case of WPA on a WiFi? interface, the interface isn't yet ready when
the dhcpcd starts. Sending a packet during that time returns with a
ENOBUFS. That caused the interface to be ignored.

On the upstream repository of dhcpcd, that transient error (and some
others) are already ignored.

  • Property mode set to 100644
File size: 65.4 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
28#include <sys/param.h>
29#include <sys/socket.h>
30#include <sys/stat.h>
31
32#ifdef __linux__
33#  include <asm/types.h> /* for systems with broken headers */
34#  include <linux/rtnetlink.h>
35#endif
36
37#include <arpa/inet.h>
38#include <net/route.h>
39
40#include <netinet/in_systm.h>
41#include <netinet/in.h>
42#include <netinet/ip.h>
43#define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */
44#include <netinet/udp.h>
45#undef __FAVOR_BSD
46
47#include <ctype.h>
48#include <errno.h>
49#include <fcntl.h>
50#include <inttypes.h>
51#include <stddef.h>
52#include <stdlib.h>
53#include <string.h>
54#include <syslog.h>
55#include <unistd.h>
56
57#include "config.h"
58#include "arp.h"
59#include "common.h"
60#include "dhcp.h"
61#include "dhcpcd.h"
62#include "dhcp-common.h"
63#include "duid.h"
64#include "eloop.h"
65#include "ipv4.h"
66#include "ipv4ll.h"
67#include "script.h"
68
69#define DAD             "Duplicate address detected"
70#define DHCP_MIN_LEASE  20
71
72static uint8_t *packet;
73
74/* Our aggregate option buffer.
75 * We ONLY use this when options are split, which for most purposes is
76 * practically never. See RFC3396 for details. */
77static uint8_t *opt_buffer;
78
79#define IPV4A           ADDRIPV4 | ARRAY
80#define IPV4R           ADDRIPV4 | REQUEST
81
82/* We should define a maximum for the NAK exponential backoff */
83#define NAKOFF_MAX              60
84
85/* Wait N nanoseconds between sending a RELEASE and dropping the address.
86 * This gives the kernel enough time to actually send it. */
87#define RELEASE_DELAY_S         0
88#define RELEASE_DELAY_NS        10000000
89
90struct dhcp_op {
91        uint8_t value;
92        const char *name;
93};
94
95static const struct dhcp_op dhcp_ops[] = {
96        { DHCP_DISCOVER, "DISCOVER" },
97        { DHCP_OFFER,    "OFFER" },
98        { DHCP_REQUEST,  "REQUEST" },
99        { DHCP_DECLINE,  "DECLINE" },
100        { DHCP_ACK,      "ACK" },
101        { DHCP_NAK,      "NAK" },
102        { DHCP_RELEASE,  "RELEASE" },
103        { DHCP_INFORM,   "INFORM" },
104        { 0, NULL }
105};
106
107static const char * const dhcp_params[] = {
108        "ip_address",
109        "subnet_cidr",
110        "network_number",
111        "filename",
112        "server_name",
113        NULL
114};
115
116struct udp_dhcp_packet
117{
118        struct ip ip;
119        struct udphdr udp;
120        struct dhcp_message dhcp;
121};
122
123struct dhcp_opt *dhcp_opts = NULL;
124size_t dhcp_opts_len = 0;
125
126static const size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet);
127
128static int dhcp_open(struct interface *);
129
130void
131dhcp_printoptions(void)
132{
133        const char * const *p;
134        size_t i;
135        const struct dhcp_opt *opt;
136
137        for (p = dhcp_params; *p; p++)
138                printf("    %s\n", *p);
139
140        for (i = 0, opt = dhcp_opts; i < dhcp_opts_len; i++, opt++)
141                printf("%03d %s\n", opt->option, opt->var);
142}
143
144#ifdef DEBUG_MEMORY
145static void
146dhcp_cleanup(void)
147{
148
149        free(packet);
150        free(opt_buffer);
151}
152#endif
153
154#define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL)
155static const uint8_t *
156get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len)
157{
158        const uint8_t *p = dhcp->options;
159        const uint8_t *e = p + sizeof(dhcp->options);
160        uint8_t l, ol = 0;
161        uint8_t o = 0;
162        uint8_t overl = 0;
163        uint8_t *bp = NULL;
164        const uint8_t *op = NULL;
165        int bl = 0;
166
167        while (p < e) {
168                o = *p++;
169                if (o == opt) {
170                        if (op) {
171                                if (!opt_buffer) {
172                                        opt_buffer = malloc(sizeof(*dhcp));
173                                        if (opt_buffer == NULL)
174                                                return NULL;
175                                }
176                                if (!bp)
177                                        bp = opt_buffer;
178                                memcpy(bp, op, ol);
179                                bp += ol;
180                        }
181                        ol = *p;
182                        if (p + ol > e) {
183                                errno = EINVAL;
184                                return NULL;
185                        }
186                        op = p + 1;
187                        bl += ol;
188                }
189                switch (o) {
190                case DHO_PAD:
191                        continue;
192                case DHO_END:
193                        if (overl & 1) {
194                                /* bit 1 set means parse boot file */
195                                overl &= ~1;
196                                p = dhcp->bootfile;
197                                e = p + sizeof(dhcp->bootfile);
198                        } else if (overl & 2) {
199                                /* bit 2 set means parse server name */
200                                overl &= ~2;
201                                p = dhcp->servername;
202                                e = p + sizeof(dhcp->servername);
203                        } else
204                                goto exit;
205                        break;
206                case DHO_OPTIONSOVERLOADED:
207                        /* Ensure we only get this option once */
208                        if (!overl)
209                                overl = p[1];
210                        break;
211                }
212                l = *p++;
213                p += l;
214        }
215
216exit:
217        if (len)
218                *len = bl;
219        if (bp) {
220                memcpy(bp, op, ol);
221                return (const uint8_t *)opt_buffer;
222        }
223        if (op)
224                return op;
225        errno = ENOENT;
226        return NULL;
227}
228
229int
230get_option_addr(struct in_addr *a, const struct dhcp_message *dhcp,
231    uint8_t option)
232{
233        const uint8_t *p;
234        int len;
235
236        p = get_option(dhcp, option, &len);
237        if (!p || len < (ssize_t)sizeof(a->s_addr))
238                return -1;
239        memcpy(&a->s_addr, p, sizeof(a->s_addr));
240        return 0;
241}
242
243static int
244get_option_uint32(uint32_t *i, const struct dhcp_message *dhcp, uint8_t option)
245{
246        const uint8_t *p;
247        int len;
248        uint32_t d;
249
250        p = get_option(dhcp, option, &len);
251        if (!p || len < (ssize_t)sizeof(d))
252                return -1;
253        memcpy(&d, p, sizeof(d));
254        if (i)
255                *i = ntohl(d);
256        return 0;
257}
258
259static int
260get_option_uint8(uint8_t *i, const struct dhcp_message *dhcp, uint8_t option)
261{
262        const uint8_t *p;
263        int len;
264
265        p = get_option(dhcp, option, &len);
266        if (!p || len < (ssize_t)sizeof(*p))
267                return -1;
268        if (i)
269                *i = *(p);
270        return 0;
271}
272
273ssize_t
274decode_rfc3442(char *out, ssize_t len, int pl, const uint8_t *p)
275{
276        const uint8_t *e;
277        ssize_t b, bytes = 0, ocets;
278        uint8_t cidr;
279        struct in_addr addr;
280        char *o = out;
281
282        /* Minimum is 5 -first is CIDR and a router length of 4 */
283        if (pl < 5) {
284                errno = EINVAL;
285                return -1;
286        }
287
288        e = p + pl;
289        while (p < e) {
290                cidr = *p++;
291                if (cidr > 32) {
292                        errno = EINVAL;
293                        return -1;
294                }
295                ocets = (cidr + 7) / 8;
296                if (!out) {
297                        p += 4 + ocets;
298                        bytes += ((4 * 4) * 2) + 4;
299                        continue;
300                }
301                if ((((4 * 4) * 2) + 4) > len) {
302                        errno = ENOBUFS;
303                        return -1;
304                }
305                if (o != out) {
306                        *o++ = ' ';
307                        len--;
308                }
309                /* If we have ocets then we have a destination and netmask */
310                if (ocets > 0) {
311                        addr.s_addr = 0;
312                        memcpy(&addr.s_addr, p, ocets);
313                        b = snprintf(o, len, "%s/%d", inet_ntoa(addr), cidr);
314                        p += ocets;
315                } else
316                        b = snprintf(o, len, "0.0.0.0/0");
317                o += b;
318                len -= b;
319
320                /* Finally, snag the router */
321                memcpy(&addr.s_addr, p, 4);
322                p += 4;
323                b = snprintf(o, len, " %s", inet_ntoa(addr));
324                o += b;
325                len -= b;
326        }
327
328        if (out)
329                return o - out;
330        return bytes;
331}
332
333static struct rt_head *
334decode_rfc3442_rt(int dl, const uint8_t *data)
335{
336        const uint8_t *p = data;
337        const uint8_t *e;
338        uint8_t cidr;
339        size_t ocets;
340        struct rt_head *routes;
341        struct rt *rt = NULL;
342
343        /* Minimum is 5 -first is CIDR and a router length of 4 */
344        if (dl < 5)
345                return NULL;
346
347        routes = malloc(sizeof(*routes));
348        TAILQ_INIT(routes);
349        e = p + dl;
350        while (p < e) {
351                cidr = *p++;
352                if (cidr > 32) {
353                        ipv4_freeroutes(routes);
354                        errno = EINVAL;
355                        return NULL;
356                }
357
358                rt = calloc(1, sizeof(*rt));
359                if (rt == NULL) {
360                        syslog(LOG_ERR, "%s: %m", __func__);
361                        ipv4_freeroutes(routes);
362                        return NULL;
363                }
364                TAILQ_INSERT_TAIL(routes, rt, next);
365
366                ocets = (cidr + 7) / 8;
367                /* If we have ocets then we have a destination and netmask */
368                if (ocets > 0) {
369                        memcpy(&rt->dest.s_addr, p, ocets);
370                        p += ocets;
371                        rt->net.s_addr = htonl(~0U << (32 - cidr));
372                }
373
374                /* Finally, snag the router */
375                memcpy(&rt->gate.s_addr, p, 4);
376                p += 4;
377        }
378        return routes;
379}
380
381char *
382decode_rfc3361(int dl, const uint8_t *data)
383{
384        uint8_t enc;
385        unsigned int l;
386        char *sip = NULL;
387        struct in_addr addr;
388        char *p;
389
390        if (dl < 2) {
391                errno = EINVAL;
392                return 0;
393        }
394
395        enc = *data++;
396        dl--;
397        switch (enc) {
398        case 0:
399                if ((l = decode_rfc3397(NULL, 0, dl, data)) > 0) {
400                        sip = malloc(l);
401                        if (sip == NULL)
402                                return 0;
403                        decode_rfc3397(sip, l, dl, data);
404                }
405                break;
406        case 1:
407                if (dl == 0 || dl % 4 != 0) {
408                        errno = EINVAL;
409                        break;
410                }
411                addr.s_addr = INADDR_BROADCAST;
412                l = ((dl / sizeof(addr.s_addr)) * ((4 * 4) + 1)) + 1;
413                sip = p = malloc(l);
414                if (sip == NULL)
415                        return 0;
416                while (dl != 0) {
417                        memcpy(&addr.s_addr, data, sizeof(addr.s_addr));
418                        data += sizeof(addr.s_addr);
419                        p += snprintf(p, l - (p - sip), "%s ", inet_ntoa(addr));
420                        dl -= sizeof(addr.s_addr);
421                }
422                *--p = '\0';
423                break;
424        default:
425                errno = EINVAL;
426                return 0;
427        }
428
429        return sip;
430}
431
432/* Decode an RFC5969 6rd order option into a space
433 * separated string. Returns length of string (including
434 * terminating zero) or zero on error. */
435ssize_t
436decode_rfc5969(char *out, ssize_t len, int pl, const uint8_t *p)
437{
438        uint8_t ipv4masklen, ipv6prefixlen;
439        uint8_t ipv6prefix[16];
440        uint8_t br[4];
441        int i;
442        ssize_t b, bytes = 0;
443
444        if (pl < 22) {
445                errno = EINVAL;
446                return 0;
447        }
448
449        ipv4masklen = *p++;
450        pl--;
451        ipv6prefixlen = *p++;
452        pl--;
453
454        for (i = 0; i < 16; i++) {
455                ipv6prefix[i] = *p++;
456                pl--;
457        }
458        if (out) {
459                b= snprintf(out, len,
460                    "%d %d "
461                    "%02x%02x:%02x%02x:"
462                    "%02x%02x:%02x%02x:"
463                    "%02x%02x:%02x%02x:"
464                    "%02x%02x:%02x%02x",
465                    ipv4masklen, ipv6prefixlen,
466                    ipv6prefix[0], ipv6prefix[1], ipv6prefix[2], ipv6prefix[3],
467                    ipv6prefix[4], ipv6prefix[5], ipv6prefix[6], ipv6prefix[7],
468                    ipv6prefix[8], ipv6prefix[9], ipv6prefix[10],ipv6prefix[11],
469                    ipv6prefix[12],ipv6prefix[13],ipv6prefix[14], ipv6prefix[15]
470                );
471
472                len -= b;
473                out += b;
474                bytes += b;
475        } else {
476                bytes += 16 * 2 + 8 + 2 + 1 + 2;
477        }
478
479        while (pl >= 4) {
480                br[0] = *p++;
481                br[1] = *p++;
482                br[2] = *p++;
483                br[3] = *p++;
484                pl -= 4;
485
486                if (out) {
487                        b= snprintf(out, len, " %d.%d.%d.%d",
488                            br[0], br[1], br[2], br[3]);
489                        len -= b;
490                        out += b;
491                        bytes += b;
492                } else {
493                        bytes += (4 * 4);
494                }
495        }
496
497        return bytes;
498}
499
500char *
501get_option_string(const struct dhcp_message *dhcp, uint8_t option)
502{
503        int len;
504        const uint8_t *p;
505        char *s;
506
507        p = get_option(dhcp, option, &len);
508        if (!p || len == 0 || *p == '\0')
509                return NULL;
510
511        s = malloc(sizeof(char) * (len + 1));
512        if (s) {
513                memcpy(s, p, len);
514                s[len] = '\0';
515        }
516        return s;
517}
518
519/* This calculates the netmask that we should use for static routes.
520 * This IS different from the calculation used to calculate the netmask
521 * for an interface address. */
522static uint32_t
523route_netmask(uint32_t ip_in)
524{
525        /* used to be unsigned long - check if error */
526        uint32_t p = ntohl(ip_in);
527        uint32_t t;
528
529        if (IN_CLASSA(p))
530                t = ~IN_CLASSA_NET;
531        else {
532                if (IN_CLASSB(p))
533                        t = ~IN_CLASSB_NET;
534                else {
535                        if (IN_CLASSC(p))
536                                t = ~IN_CLASSC_NET;
537                        else
538                                t = 0;
539                }
540        }
541
542        while (t & p)
543                t >>= 1;
544
545        return (htonl(~t));
546}
547
548/* We need to obey routing options.
549 * If we have a CSR then we only use that.
550 * Otherwise we add static routes and then routers. */
551struct rt_head *
552get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp)
553{
554        struct if_options *ifo = ifp->options;
555        const uint8_t *p;
556        const uint8_t *e;
557        struct rt_head *routes = NULL;
558        struct rt *route = NULL;
559        int len;
560        const char *csr = "";
561
562        /* If we have CSR's then we MUST use these only */
563        if (!has_option_mask(ifo->nomask, DHO_CSR))
564                p = get_option(dhcp, DHO_CSR, &len);
565        else
566                p = NULL;
567        /* Check for crappy MS option */
568        if (!p && !has_option_mask(ifo->nomask, DHO_MSCSR)) {
569                p = get_option(dhcp, DHO_MSCSR, &len);
570                if (p)
571                        csr = "MS ";
572        }
573        if (p) {
574                routes = decode_rfc3442_rt(len, p);
575                if (routes) {
576                        if (!(ifo->options & DHCPCD_CSR_WARNED)) {
577                                syslog(LOG_DEBUG,
578                                    "%s: using %sClassless Static Routes",
579                                    ifp->name, csr);
580                                ifo->options |= DHCPCD_CSR_WARNED;
581                        }
582                        return routes;
583                }
584        }
585
586        /* OK, get our static routes first. */
587        routes = malloc(sizeof(*routes));
588        if (routes == NULL) {
589                syslog(LOG_ERR, "%s: %m", __func__);
590                return NULL;
591        }
592        TAILQ_INIT(routes);
593        if (!has_option_mask(ifo->nomask, DHO_STATICROUTE))
594                p = get_option(dhcp, DHO_STATICROUTE, &len);
595        else
596                p = NULL;
597        if (p) {
598                e = p + len;
599                while (p < e) {
600                        route = calloc(1, sizeof(*route));
601                        if (route == NULL) {
602                                syslog(LOG_ERR, "%s: %m", __func__);
603                                ipv4_freeroutes(routes);
604                                return NULL;
605                        }
606                        memcpy(&route->dest.s_addr, p, 4);
607                        p += 4;
608                        memcpy(&route->gate.s_addr, p, 4);
609                        p += 4;
610                        route->net.s_addr = route_netmask(route->dest.s_addr);
611                        TAILQ_INSERT_TAIL(routes, route, next);
612                }
613        }
614
615        /* Now grab our routers */
616        if (!has_option_mask(ifo->nomask, DHO_ROUTER))
617                p = get_option(dhcp, DHO_ROUTER, &len);
618        else
619                p = NULL;
620        if (p) {
621                e = p + len;
622                while (p < e) {
623                        route = calloc(1, sizeof(*route));
624                        if (route == NULL) {
625                                syslog(LOG_ERR, "%s: %m", __func__);
626                                ipv4_freeroutes(routes);
627                                return NULL;
628                        }
629                        memcpy(&route->gate.s_addr, p, 4);
630                        p += 4;
631                        TAILQ_INSERT_TAIL(routes, route, next);
632                }
633        }
634
635        return routes;
636}
637
638#define PUTADDR(_type, _val)                                                  \
639        {                                                                     \
640                *p++ = _type;                                                 \
641                *p++ = 4;                                                     \
642                memcpy(p, &_val.s_addr, 4);                                   \
643                p += 4;                                                       \
644        }
645
646int
647dhcp_message_add_addr(struct dhcp_message *dhcp,
648    uint8_t type, struct in_addr addr)
649{
650        uint8_t *p;
651        size_t len;
652
653        p = dhcp->options;
654        while (*p != DHO_END) {
655                p++;
656                p += *p + 1;
657        }
658
659        len = p - (uint8_t *)dhcp;
660        if (len + 6 > sizeof(*dhcp)) {
661                errno = ENOMEM;
662                return -1;
663        }
664
665        PUTADDR(type, addr);
666        *p = DHO_END;
667        return 0;
668}
669
670ssize_t
671make_message(struct dhcp_message **message,
672    const struct interface *iface,
673    uint8_t type)
674{
675        struct dhcp_message *dhcp;
676        uint8_t *m, *lp, *p, *auth;
677        uint8_t *n_params = NULL;
678        uint32_t ul;
679        uint16_t sz;
680        size_t len, i;
681        int auth_len;
682        const struct dhcp_opt *opt;
683        const struct if_options *ifo = iface->options;
684        const struct dhcp_state *state = D_CSTATE(iface);
685        const struct dhcp_lease *lease = &state->lease;
686        time_t up = uptime() - state->start_uptime;
687        const char *hostname;
688        const struct vivco *vivco;
689
690        dhcp = calloc(1, sizeof (*dhcp));
691        if (dhcp == NULL)
692                return -1;
693        m = (uint8_t *)dhcp;
694        p = dhcp->options;
695
696        if ((type == DHCP_INFORM || type == DHCP_RELEASE ||
697                (type == DHCP_REQUEST &&
698                    state->net.s_addr == lease->net.s_addr &&
699                    (state->new == NULL ||
700                        state->new->cookie == htonl(MAGIC_COOKIE)))))
701        {
702                dhcp->ciaddr = state->addr.s_addr;
703                /* In-case we haven't actually configured the address yet */
704                if (type == DHCP_INFORM && state->addr.s_addr == 0)
705                        dhcp->ciaddr = lease->addr.s_addr;
706        }
707
708        dhcp->op = DHCP_BOOTREQUEST;
709        dhcp->hwtype = iface->family;
710        switch (iface->family) {
711        case ARPHRD_ETHER:
712        case ARPHRD_IEEE802:
713                dhcp->hwlen = iface->hwlen;
714                memcpy(&dhcp->chaddr, &iface->hwaddr, iface->hwlen);
715                break;
716        }
717
718        if (ifo->options & DHCPCD_BROADCAST &&
719            dhcp->ciaddr == 0 &&
720            type != DHCP_DECLINE &&
721            type != DHCP_RELEASE)
722                dhcp->flags = htons(BROADCAST_FLAG);
723
724        if (type != DHCP_DECLINE && type != DHCP_RELEASE) {
725                if (up < 0 || up > (time_t)UINT16_MAX)
726                        dhcp->secs = htons((uint16_t)UINT16_MAX);
727                else
728                        dhcp->secs = htons(up);
729        }
730        dhcp->xid = htonl(state->xid);
731        dhcp->cookie = htonl(MAGIC_COOKIE);
732
733        *p++ = DHO_MESSAGETYPE;
734        *p++ = 1;
735        *p++ = type;
736
737        if (state->clientid) {
738                *p++ = DHO_CLIENTID;
739                memcpy(p, state->clientid, state->clientid[0] + 1);
740                p += state->clientid[0] + 1;
741        }
742
743        if (lease->addr.s_addr && lease->cookie == htonl(MAGIC_COOKIE)) {
744                if (type == DHCP_DECLINE ||
745                    (type == DHCP_REQUEST &&
746                        lease->addr.s_addr != state->addr.s_addr))
747                {
748                        PUTADDR(DHO_IPADDRESS, lease->addr);
749                        if (lease->server.s_addr)
750                                PUTADDR(DHO_SERVERID, lease->server);
751                }
752
753                if (type == DHCP_RELEASE) {
754                        if (lease->server.s_addr)
755                                PUTADDR(DHO_SERVERID, lease->server);
756                }
757        }
758
759        if (type == DHCP_DECLINE) {
760                *p++ = DHO_MESSAGE;
761                len = strlen(DAD);
762                *p++ = len;
763                memcpy(p, DAD, len);
764                p += len;
765        }
766
767        if (type == DHCP_DISCOVER &&
768            !(options & DHCPCD_TEST) &&
769            has_option_mask(ifo->requestmask, DHO_RAPIDCOMMIT))
770        {
771                /* RFC 4039 Section 3 */
772                *p++ = DHO_RAPIDCOMMIT;
773                *p++ = 0;
774        }
775
776        if (type == DHCP_DISCOVER && ifo->options & DHCPCD_REQUEST)
777                PUTADDR(DHO_IPADDRESS, ifo->req_addr);
778
779        if (type == DHCP_DISCOVER ||
780            type == DHCP_INFORM ||
781            type == DHCP_REQUEST)
782        {
783                *p++ = DHO_MAXMESSAGESIZE;
784                *p++ = 2;
785                sz = get_mtu(iface->name);
786                if (sz < MTU_MIN) {
787                        if (set_mtu(iface->name, MTU_MIN) == 0)
788                                sz = MTU_MIN;
789                } else if (sz > MTU_MAX) {
790                        /* Even though our MTU could be greater than
791                         * MTU_MAX (1500) dhcpcd does not presently
792                         * handle DHCP packets any bigger. */
793                        sz = MTU_MAX;
794                }
795                sz = htons(sz);
796                memcpy(p, &sz, 2);
797                p += 2;
798
799                if (ifo->userclass[0]) {
800                        *p++ = DHO_USERCLASS;
801                        memcpy(p, ifo->userclass, ifo->userclass[0] + 1);
802                        p += ifo->userclass[0] + 1;
803                }
804
805                if (ifo->vendorclassid[0]) {
806                        *p++ = DHO_VENDORCLASSID;
807                        memcpy(p, ifo->vendorclassid,
808                            ifo->vendorclassid[0] + 1);
809                        p += ifo->vendorclassid[0] + 1;
810                }
811
812
813                if (type != DHCP_INFORM) {
814                        if (ifo->leasetime != 0) {
815                                *p++ = DHO_LEASETIME;
816                                *p++ = 4;
817                                ul = htonl(ifo->leasetime);
818                                memcpy(p, &ul, 4);
819                                p += 4;
820                        }
821                }
822
823                if (ifo->hostname[0] == '\0')
824                        hostname = get_hostname(ifo->options &
825                            DHCPCD_HOSTNAME_SHORT ? 1 : 0);
826                else
827                        hostname = ifo->hostname;
828                if (ifo->fqdn != FQDN_DISABLE) {
829                        /* IETF DHC-FQDN option (81), RFC4702 */
830                        *p++ = DHO_FQDN;
831                        lp = p;
832                        *p++ = 3;
833                        /*
834                         * Flags: 0000NEOS
835                         * S: 1 => Client requests Server to update
836                         *         a RR in DNS as well as PTR
837                         * O: 1 => Server indicates to client that
838                         *         DNS has been updated
839                         * E: 1 => Name data is DNS format
840                         * N: 1 => Client requests Server to not
841                         *         update DNS
842                         */
843                        if (hostname)
844                                *p++ = (ifo->fqdn & 0x09) | 0x04;
845                        else
846                                *p++ = (FQDN_NONE & 0x09) | 0x04;
847                        *p++ = 0; /* from server for PTR RR */
848                        *p++ = 0; /* from server for A RR if S=1 */
849                        if (hostname) {
850                                ul = encode_rfc1035(hostname, p);
851                                *lp += ul;
852                                p += ul;
853                        }
854                } else if (ifo->options & DHCPCD_HOSTNAME && hostname) {
855                        *p++ = DHO_HOSTNAME;
856                        len = strlen(hostname);
857                        *p++ = len;
858                        memcpy(p, hostname, len);
859                        p += len;
860                }
861
862                /* vendor is already encoded correctly, so just add it */
863                if (ifo->vendor[0]) {
864                        *p++ = DHO_VENDOR;
865                        memcpy(p, ifo->vendor, ifo->vendor[0] + 1);
866                        p += ifo->vendor[0] + 1;
867                }
868
869                if (ifo->vivco_len) {
870                        *p++ = DHO_VIVCO;
871                        lp = p++;
872                        *lp = sizeof(ul);
873                        ul = htonl(ifo->vivco_en);
874                        memcpy(p, &ul, sizeof(ul));
875                        p += sizeof(ul);
876                        for (i = 0, vivco = ifo->vivco;
877                            i < ifo->vivco_len;
878                            i++, vivco++)
879                        {
880                                len = (p - m) + vivco->len + 1;
881                                if (len > sizeof(*dhcp))
882                                        goto toobig;
883                                if (vivco->len + 2 + *lp > 255) {
884                                        syslog(LOG_ERR,
885                                            "%s: VIVCO option too big",
886                                            iface->name);
887                                        free(dhcp);
888                                        return -1;
889                                }
890                                *p++ = (uint8_t)vivco->len;
891                                memcpy(p, vivco->data, vivco->len);
892                                p += vivco->len;
893                                *lp += (uint8_t)vivco->len + 1;
894                        }
895                }
896
897                len = (p - m) + 3;
898                if (len > sizeof(*dhcp))
899                        goto toobig;
900                *p++ = DHO_PARAMETERREQUESTLIST;
901                n_params = p;
902                *p++ = 0;
903                for (i = 0, opt = dhcp_opts; i < dhcp_opts_len; i++, opt++) {
904                        if (!(opt->type & REQUEST ||
905                                has_option_mask(ifo->requestmask, opt->option)))
906                                continue;
907                        if (opt->type & NOREQ)
908                                continue;
909                        if (type == DHCP_INFORM &&
910                            (opt->option == DHO_RENEWALTIME ||
911                                opt->option == DHO_REBINDTIME))
912                                continue;
913                        len = (p - m) + 2;
914                        if (len > sizeof(*dhcp))
915                                goto toobig;
916                        *p++ = opt->option;
917                }
918                *n_params = p - n_params - 1;
919        }
920
921        /* silence GCC */
922        auth_len = 0;
923        auth = NULL;
924
925        if (ifo->auth.options & DHCPCD_AUTH_SEND) {
926                auth_len = dhcp_auth_encode(&ifo->auth, state->auth.token,
927                    NULL, 0, 4, type, NULL, 0);
928                if (auth_len > 0) {
929                        len = (p + auth_len) - m;
930                        if (auth_len > 255 || len > sizeof(*dhcp))
931                                goto toobig;
932                        *p++ = DHO_AUTHENTICATION;
933                        *p++ = (uint8_t)auth_len;
934                        auth = p;
935                        p += auth_len;
936                } else if (auth_len == -1)
937                        syslog(LOG_ERR, "%s: dhcp_auth_encode: %m",
938                            iface->name);
939        }
940
941        *p++ = DHO_END;
942
943#ifdef BOOTP_MESSAGE_LENTH_MIN
944        /* Some crappy DHCP servers think they have to obey the BOOTP minimum
945         * message length.
946         * They are wrong, but we should still cater for them. */
947        while (p - m < BOOTP_MESSAGE_LENTH_MIN)
948                *p++ = DHO_PAD;
949#endif
950
951        len = p - m;
952        if (ifo->auth.options & DHCPCD_AUTH_SEND && auth_len > 0)
953                dhcp_auth_encode(&ifo->auth, state->auth.token,
954                    m, len, 4, type, auth, auth_len);
955
956        *message = dhcp;
957        return len;
958
959toobig:
960        syslog(LOG_ERR, "%s: DHCP messge too big", iface->name);
961        free(dhcp);
962        return -1;
963}
964
965ssize_t
966write_lease(const struct interface *ifp, const struct dhcp_message *dhcp)
967{
968        int fd;
969        ssize_t bytes = sizeof(*dhcp);
970        const uint8_t *p = dhcp->options;
971        const uint8_t *e = p + sizeof(dhcp->options);
972        uint8_t l;
973        uint8_t o = 0;
974        const struct dhcp_state *state = D_CSTATE(ifp);
975
976        /* We don't write BOOTP leases */
977        if (is_bootp(dhcp)) {
978                unlink(state->leasefile);
979                return 0;
980        }
981
982        syslog(LOG_DEBUG, "%s: writing lease `%s'",
983            ifp->name, state->leasefile);
984
985        fd = open(state->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
986        if (fd == -1)
987                return -1;
988
989        /* Only write as much as we need */
990        while (p < e) {
991                o = *p;
992                if (o == DHO_END) {
993                        bytes = p - (const uint8_t *)dhcp;
994                        break;
995                }
996                p++;
997                if (o != DHO_PAD) {
998                        l = *p++;
999                        p += l;
1000                }
1001        }
1002        bytes = write(fd, dhcp, bytes);
1003        close(fd);
1004        return bytes;
1005}
1006
1007struct dhcp_message *
1008read_lease(struct interface *ifp)
1009{
1010        int fd;
1011        struct dhcp_message *dhcp;
1012        struct dhcp_state *state = D_STATE(ifp);
1013        ssize_t bytes;
1014        const uint8_t *auth;
1015        uint8_t type;
1016        int auth_len;
1017
1018        fd = open(state->leasefile, O_RDONLY);
1019        if (fd == -1) {
1020                if (errno != ENOENT)
1021                        syslog(LOG_ERR, "%s: open `%s': %m",
1022                            ifp->name, state->leasefile);
1023                return NULL;
1024        }
1025        syslog(LOG_DEBUG, "%s: reading lease `%s'",
1026            ifp->name, state->leasefile);
1027        dhcp = calloc(1, sizeof(*dhcp));
1028        if (dhcp == NULL) {
1029                close(fd);
1030                return NULL;
1031        }
1032        bytes = read(fd, dhcp, sizeof(*dhcp));
1033        close(fd);
1034        if (bytes < 0) {
1035                free(dhcp);
1036                return NULL;
1037        }
1038
1039        /* We may have found a BOOTP server */
1040        if (get_option_uint8(&type, dhcp, DHO_MESSAGETYPE) == -1)
1041                type = 0;
1042        /* Authenticate the message */
1043        auth = get_option(dhcp, DHO_AUTHENTICATION, &auth_len);
1044        if (auth) {
1045                if (dhcp_auth_validate(&state->auth, &ifp->options->auth,
1046                    (uint8_t *)dhcp, sizeof(*dhcp), 4, type,
1047                    auth, auth_len) == NULL)
1048                {
1049                        syslog(LOG_DEBUG, "%s: dhcp_auth_validate: %m",
1050                            ifp->name);
1051                        free(dhcp);
1052                        return NULL;
1053                }
1054                syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32,
1055                    ifp->name, state->auth.token->secretid);
1056        }
1057
1058        return dhcp;
1059}
1060
1061static const struct dhcp_opt *
1062dhcp_getoverride(const struct if_options *ifo, uint16_t o)
1063{
1064        size_t i;
1065        const struct dhcp_opt *opt;
1066
1067        for (i = 0, opt = ifo->dhcp_override;
1068            i < ifo->dhcp_override_len;
1069            i++, opt++)
1070        {
1071                if (opt->option == o)
1072                        return opt;
1073        }
1074        return NULL;
1075}
1076
1077static const uint8_t *
1078dhcp_getoption(unsigned int *os, unsigned int *code, unsigned int *len,
1079    const uint8_t *od, unsigned int ol, struct dhcp_opt **oopt)
1080{
1081        size_t i;
1082        struct dhcp_opt *opt;
1083
1084        if (od) {
1085                if (ol < 2) {
1086                        errno = EINVAL;
1087                        return NULL;
1088                }
1089                *os = 2; /* code + len */
1090                *code = (int)*od++;
1091                *len = (int)*od++;
1092                if (*len > ol) {
1093                        errno = EINVAL;
1094                        return NULL;
1095                }
1096        }
1097
1098        for (i = 0, opt = dhcp_opts; i < dhcp_opts_len; i++, opt++) {
1099                if (opt->option == *code) {
1100                        *oopt = opt;
1101                        break;
1102                }
1103        }
1104
1105        return od;
1106}
1107
1108ssize_t
1109dhcp_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
1110    const struct interface *ifp)
1111{
1112        const struct if_options *ifo;
1113        const uint8_t *p;
1114        int pl;
1115        struct in_addr addr;
1116        struct in_addr net;
1117        struct in_addr brd;
1118        struct dhcp_opt *opt, *vo;
1119        ssize_t e = 0;
1120        char **ep;
1121        char cidr[4];
1122        uint8_t overl = 0;
1123        size_t i;
1124        uint32_t en;
1125
1126        ifo = ifp->options;
1127        get_option_uint8(&overl, dhcp, DHO_OPTIONSOVERLOADED);
1128
1129        if (!env) {
1130                if (dhcp->yiaddr || dhcp->ciaddr)
1131                        e += 5;
1132                if (*dhcp->bootfile && !(overl & 1))
1133                        e++;
1134                if (*dhcp->servername && !(overl & 2))
1135                        e++;
1136                for (i = 0, opt = dhcp_opts;
1137                    i < dhcp_opts_len;
1138                    i++, opt++)
1139                {
1140                        if (has_option_mask(ifo->nomask, opt->option))
1141                                continue;
1142                        if (dhcp_getoverride(ifo, opt->option))
1143                                continue;
1144                        p = get_option(dhcp, opt->option, &pl);
1145                        if (!p)
1146                                continue;
1147                        e += dhcp_envoption(NULL, NULL, ifp->name,
1148                            opt, dhcp_getoption, p, pl);
1149                }
1150                for (i = 0, opt = ifo->dhcp_override;
1151                    i < ifo->dhcp_override_len;
1152                    i++, opt++)
1153                {
1154                        if (has_option_mask(ifo->nomask, opt->option))
1155                                continue;
1156                        p = get_option(dhcp, opt->option, &pl);
1157                        if (!p)
1158                                continue;
1159                        e += dhcp_envoption(NULL, NULL, ifp->name,
1160                            opt, dhcp_getoption, p, pl);
1161                }
1162                return e;
1163        }
1164
1165        ep = env;
1166        if (dhcp->yiaddr || dhcp->ciaddr) {
1167                /* Set some useful variables that we derive from the DHCP
1168                 * message but are not necessarily in the options */
1169                addr.s_addr = dhcp->yiaddr ? dhcp->yiaddr : dhcp->ciaddr;
1170                setvar(&ep, prefix, "ip_address", inet_ntoa(addr));
1171                if (get_option_addr(&net, dhcp, DHO_SUBNETMASK) == -1) {
1172                        net.s_addr = ipv4_getnetmask(addr.s_addr);
1173                        setvar(&ep, prefix, "subnet_mask", inet_ntoa(net));
1174                }
1175                snprintf(cidr, sizeof(cidr), "%d", inet_ntocidr(net));
1176                setvar(&ep, prefix, "subnet_cidr", cidr);
1177                if (get_option_addr(&brd, dhcp, DHO_BROADCAST) == -1) {
1178                        brd.s_addr = addr.s_addr | ~net.s_addr;
1179                        setvar(&ep, prefix, "broadcast_address",
1180                            inet_ntoa(brd));
1181                }
1182                addr.s_addr = dhcp->yiaddr & net.s_addr;
1183                setvar(&ep, prefix, "network_number", inet_ntoa(addr));
1184        }
1185
1186        if (*dhcp->bootfile && !(overl & 1))
1187                setvar(&ep, prefix, "filename", (const char *)dhcp->bootfile);
1188        if (*dhcp->servername && !(overl & 2))
1189                setvar(&ep, prefix, "server_name",
1190                    (const char *)dhcp->servername);
1191
1192        /* Zero our indexes */
1193        if (env) {
1194                for (i = 0, opt = dhcp_opts; i < dhcp_opts_len; i++, opt++)
1195                        dhcp_zero_index(opt);
1196                for (i = 0, opt = ifp->options->dhcp_override;
1197                    i < ifp->options->dhcp_override_len;
1198                    i++, opt++)
1199                        dhcp_zero_index(opt);
1200                for (i = 0, opt = vivso; i < vivso_len; i++, opt++)
1201                        dhcp_zero_index(opt);
1202        }
1203
1204        for (i = 0, opt = dhcp_opts;
1205            i < dhcp_opts_len;
1206            i++, opt++)
1207        {
1208                if (has_option_mask(ifo->nomask, opt->option))
1209                        continue;
1210                if (dhcp_getoverride(ifo, opt->option))
1211                        continue;
1212                if ((p = get_option(dhcp, opt->option, &pl))) {
1213                        ep += dhcp_envoption(ep, prefix, ifp->name,
1214                            opt, dhcp_getoption, p, pl);
1215                        if (opt->option == DHO_VIVSO &&
1216                            pl > (int)sizeof(uint32_t))
1217                        {
1218                                memcpy(&en, p, sizeof(en));
1219                                en = ntohl(en);
1220                                vo = vivso_find(en, ifp);
1221                                if (vo) {
1222                                        /* Skip over en + total size */
1223                                        p += sizeof(en) + 1;
1224                                        pl -= sizeof(en) + 1;
1225                                        ep += dhcp_envoption(ep, prefix,
1226                                            ifp->name,
1227                                            vo, dhcp_getoption, p, pl);
1228                                }
1229                        }
1230                }
1231        }
1232
1233        for (i = 0, opt = ifo->dhcp_override;
1234            i < ifo->dhcp_override_len;
1235            i++, opt++)
1236        {
1237                if (has_option_mask(ifo->nomask, opt->option))
1238                        continue;
1239                if ((p = get_option(dhcp, opt->option, &pl)))
1240                        ep += dhcp_envoption(ep, prefix, ifp->name,
1241                            opt, dhcp_getoption, p, pl);
1242        }
1243
1244        return ep - env;
1245}
1246
1247void
1248get_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp)
1249{
1250        struct timeval now;
1251
1252        lease->cookie = dhcp->cookie;
1253        /* BOOTP does not set yiaddr for replies when ciaddr is set. */
1254        if (dhcp->yiaddr)
1255                lease->addr.s_addr = dhcp->yiaddr;
1256        else
1257                lease->addr.s_addr = dhcp->ciaddr;
1258        if (get_option_addr(&lease->net, dhcp, DHO_SUBNETMASK) == -1)
1259                lease->net.s_addr = ipv4_getnetmask(lease->addr.s_addr);
1260        if (get_option_addr(&lease->brd, dhcp, DHO_BROADCAST) == -1)
1261                lease->brd.s_addr = lease->addr.s_addr | ~lease->net.s_addr;
1262        if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) == 0) {
1263                /* Ensure that we can use the lease */
1264                get_monotonic(&now);
1265                if (now.tv_sec + (time_t)lease->leasetime < now.tv_sec)
1266                        lease->leasetime = ~0U; /* Infinite lease */
1267        } else
1268                lease->leasetime = ~0U; /* Default to infinite lease */
1269        if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0)
1270                lease->renewaltime = 0;
1271        if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0)
1272                lease->rebindtime = 0;
1273        if (get_option_addr(&lease->server, dhcp, DHO_SERVERID) != 0)
1274                lease->server.s_addr = INADDR_ANY;
1275}
1276
1277static const char *
1278get_dhcp_op(uint8_t type)
1279{
1280        const struct dhcp_op *d;
1281
1282        for (d = dhcp_ops; d->name; d++)
1283                if (d->value == type)
1284                        return d->name;
1285        return NULL;
1286}
1287
1288static void
1289dhcp_fallback(void *arg)
1290{
1291        struct interface *iface;
1292
1293        iface = (struct interface *)arg;
1294        select_profile(iface, iface->options->fallback);
1295        start_interface(iface);
1296}
1297
1298uint32_t
1299dhcp_xid(const struct interface *ifp)
1300{
1301        uint32_t xid;
1302
1303        if (ifp->options->options & DHCPCD_XID_HWADDR &&
1304            ifp->hwlen >= sizeof(xid))
1305                /* The lower bits are probably more unique on the network */
1306                memcpy(&xid, (ifp->hwaddr + ifp->hwlen) - sizeof(xid),
1307                    sizeof(xid));
1308        else
1309                xid = arc4random();
1310
1311        return xid;
1312}
1313
1314void
1315dhcp_close(struct interface *ifp)
1316{
1317        struct dhcp_state *state = D_STATE(ifp);
1318
1319        if (state == NULL)
1320                return;
1321
1322        if (state->arp_fd != -1) {
1323                eloop_event_delete(state->arp_fd);
1324                close(state->arp_fd);
1325                state->arp_fd = -1;
1326        }
1327        if (state->raw_fd != -1) {
1328                eloop_event_delete(state->raw_fd);
1329                close(state->raw_fd);
1330                state->raw_fd = -1;
1331        }
1332        if (state->udp_fd != -1) {
1333                /* we don't listen to events on the udp */
1334                close(state->udp_fd);
1335                state->udp_fd = -1;
1336        }
1337
1338        state->interval = 0;
1339}
1340
1341static int
1342dhcp_openudp(struct interface *iface)
1343{
1344        int s;
1345        struct sockaddr_in sin;
1346        int n;
1347        struct dhcp_state *state;
1348#ifdef SO_BINDTODEVICE
1349        struct ifreq ifr;
1350        char *p;
1351#endif
1352
1353        if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
1354                return -1;
1355
1356        n = 1;
1357        if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
1358                goto eexit;
1359#ifdef SO_BINDTODEVICE
1360        memset(&ifr, 0, sizeof(ifr));
1361        strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
1362        /* We can only bind to the real device */
1363        p = strchr(ifr.ifr_name, ':');
1364        if (p)
1365            *p = '\0';
1366        if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &ifr,
1367                    sizeof(ifr)) == -1)
1368                goto eexit;
1369#endif
1370        /* As we don't use this socket for receiving, set the
1371         * receive buffer to 1 */
1372        n = 1;
1373        if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1)
1374                goto eexit;
1375        state = D_STATE(iface);
1376        memset(&sin, 0, sizeof(sin));
1377        sin.sin_family = AF_INET;
1378        sin.sin_port = htons(DHCP_CLIENT_PORT);
1379        sin.sin_addr.s_addr = state->addr.s_addr;
1380        if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
1381                goto eexit;
1382
1383        state->udp_fd = s;
1384        set_cloexec(s);
1385        return 0;
1386
1387eexit:
1388        close(s);
1389        return -1;
1390}
1391
1392static ssize_t
1393dhcp_sendpacket(const struct interface *iface, struct in_addr to,
1394    const uint8_t *data, ssize_t len)
1395{
1396        struct sockaddr_in sin;
1397
1398        memset(&sin, 0, sizeof(sin));
1399        sin.sin_family = AF_INET;
1400        sin.sin_addr.s_addr = to.s_addr;
1401        sin.sin_port = htons(DHCP_SERVER_PORT);
1402        return sendto(D_CSTATE(iface)->udp_fd, data, len, 0,
1403            (struct sockaddr *)&sin, sizeof(sin));
1404}
1405
1406static uint16_t
1407checksum(const void *data, uint16_t len)
1408{
1409        const uint8_t *addr = data;
1410        uint32_t sum = 0;
1411
1412        while (len > 1) {
1413                sum += addr[0] * 256 + addr[1];
1414                addr += 2;
1415                len -= 2;
1416        }
1417
1418        if (len == 1)
1419                sum += *addr * 256;
1420
1421        sum = (sum >> 16) + (sum & 0xffff);
1422        sum += (sum >> 16);
1423
1424        sum = htons(sum);
1425
1426        return ~sum;
1427}
1428
1429static ssize_t
1430dhcp_makeudppacket(uint8_t **p, const uint8_t *data, size_t length,
1431        struct in_addr source, struct in_addr dest)
1432{
1433        struct udp_dhcp_packet *udpp;
1434        struct ip *ip;
1435        struct udphdr *udp;
1436
1437        udpp = calloc(1, sizeof(*udpp));
1438        if (udpp == NULL)
1439                return -1;
1440        ip = &udpp->ip;
1441        udp = &udpp->udp;
1442
1443        /* OK, this is important :)
1444         * We copy the data to our packet and then create a small part of the
1445         * ip structure and an invalid ip_len (basically udp length).
1446         * We then fill the udp structure and put the checksum
1447         * of the whole packet into the udp checksum.
1448         * Finally we complete the ip structure and ip checksum.
1449         * If we don't do the ordering like so then the udp checksum will be
1450         * broken, so find another way of doing it! */
1451
1452        memcpy(&udpp->dhcp, data, length);
1453
1454        ip->ip_p = IPPROTO_UDP;
1455        ip->ip_src.s_addr = source.s_addr;
1456        if (dest.s_addr == 0)
1457                ip->ip_dst.s_addr = INADDR_BROADCAST;
1458        else
1459                ip->ip_dst.s_addr = dest.s_addr;
1460
1461        udp->uh_sport = htons(DHCP_CLIENT_PORT);
1462        udp->uh_dport = htons(DHCP_SERVER_PORT);
1463        udp->uh_ulen = htons(sizeof(*udp) + length);
1464        ip->ip_len = udp->uh_ulen;
1465        udp->uh_sum = checksum(udpp, sizeof(*udpp));
1466
1467        ip->ip_v = IPVERSION;
1468        ip->ip_hl = sizeof(*ip) >> 2;
1469        ip->ip_id = arc4random() & UINT16_MAX;
1470        ip->ip_ttl = IPDEFTTL;
1471        ip->ip_len = htons(sizeof(*ip) + sizeof(*udp) + length);
1472        ip->ip_sum = checksum(ip, sizeof(*ip));
1473
1474        *p = (uint8_t *)udpp;
1475        return sizeof(*ip) + sizeof(*udp) + length;
1476}
1477
1478static void
1479send_message(struct interface *iface, int type,
1480    void (*callback)(void *))
1481{
1482        struct dhcp_state *state = D_STATE(iface);
1483        struct if_options *ifo = iface->options;
1484        struct dhcp_message *dhcp;
1485        uint8_t *udp;
1486        ssize_t len, r;
1487        struct in_addr from, to;
1488        in_addr_t a = 0;
1489        struct timeval tv;
1490#ifdef __rtems__
1491        int errno_save;
1492#endif /* __rtems__ */
1493
1494        if (!callback)
1495                syslog(LOG_DEBUG, "%s: sending %s with xid 0x%x",
1496                    iface->name, get_dhcp_op(type), state->xid);
1497        else {
1498                if (state->interval == 0)
1499                        state->interval = 4;
1500                else {
1501                        state->interval *= 2;
1502                        if (state->interval > 64)
1503                                state->interval = 64;
1504                }
1505                tv.tv_sec = state->interval + DHCP_RAND_MIN;
1506                tv.tv_usec = arc4random() % (DHCP_RAND_MAX_U - DHCP_RAND_MIN_U);
1507                timernorm(&tv);
1508                syslog(LOG_DEBUG,
1509                    "%s: sending %s (xid 0x%x), next in %0.1f seconds",
1510                    iface->name, get_dhcp_op(type), state->xid,
1511                    timeval_to_double(&tv));
1512        }
1513
1514        /* Ensure sockets are open. */
1515        if (dhcp_open(iface) == -1) {
1516                if (!(options & DHCPCD_TEST))
1517                        dhcp_drop(iface, "FAIL");
1518                return;
1519        }
1520
1521        /* If we couldn't open a UDP port for our IP address
1522         * then we cannot renew.
1523         * This could happen if our IP was pulled out from underneath us.
1524         * Also, we should not unicast from a BOOTP lease. */
1525        if (state->udp_fd == -1 ||
1526            (!(ifo->options & DHCPCD_INFORM) && is_bootp(state->new)))
1527        {
1528                a = state->addr.s_addr;
1529                state->addr.s_addr = 0;
1530        }
1531        len = make_message(&dhcp, iface, type);
1532        if (a)
1533                state->addr.s_addr = a;
1534        from.s_addr = dhcp->ciaddr;
1535        if (from.s_addr)
1536                to.s_addr = state->lease.server.s_addr;
1537        else
1538                to.s_addr = 0;
1539        if (to.s_addr && to.s_addr != INADDR_BROADCAST) {
1540                r = dhcp_sendpacket(iface, to, (uint8_t *)dhcp, len);
1541                if (r == -1) {
1542                        syslog(LOG_ERR, "%s: dhcp_sendpacket: %m", iface->name);
1543                        dhcp_close(iface);
1544                }
1545        } else {
1546                len = dhcp_makeudppacket(&udp, (uint8_t *)dhcp, len, from, to);
1547                if (len == -1)
1548                        return;
1549                r = ipv4_sendrawpacket(iface, ETHERTYPE_IP, udp, len);
1550#ifdef __rtems__
1551                errno_save = errno;
1552#endif /* __rtems__ */
1553                free(udp);
1554                /* If we failed to send a raw packet this normally means
1555                 * we don't have the ability to work beneath the IP layer
1556                 * for this interface.
1557                 * As such we remove it from consideration without actually
1558                 * stopping the interface. */
1559                if (r == -1) {
1560                        syslog(LOG_ERR, "%s: ipv4_sendrawpacket: %m",
1561                            iface->name);
1562#ifdef __rtems__
1563                        if (errno_save != ENETDOWN &&
1564                            errno_save != ENETRESET &&
1565                            errno_save != ENETUNREACH &&
1566                            errno_save != ENOBUFS) {
1567#endif /* __rtems__ */
1568                        if (!(options & DHCPCD_TEST))
1569                                dhcp_drop(iface, "FAIL");
1570                        dhcp_close(iface);
1571                        eloop_timeout_delete(NULL, iface);
1572                        callback = NULL;
1573#ifdef __rtems__
1574                        }
1575#endif /* __rtems__ */
1576                }
1577        }
1578        free(dhcp);
1579
1580        /* Even if we fail to send a packet we should continue as we are
1581         * as our failure timeouts will change out codepath when needed. */
1582        if (callback)
1583                eloop_timeout_add_tv(&tv, callback, iface);
1584}
1585
1586static void
1587send_inform(void *arg)
1588{
1589
1590        send_message((struct interface *)arg, DHCP_INFORM, send_inform);
1591}
1592
1593static void
1594send_discover(void *arg)
1595{
1596
1597        send_message((struct interface *)arg, DHCP_DISCOVER, send_discover);
1598}
1599
1600static void
1601send_request(void *arg)
1602{
1603
1604        send_message((struct interface *)arg, DHCP_REQUEST, send_request);
1605}
1606
1607static void
1608send_renew(void *arg)
1609{
1610
1611        send_message((struct interface *)arg, DHCP_REQUEST, send_renew);
1612}
1613
1614static void
1615send_rebind(void *arg)
1616{
1617
1618        send_message((struct interface *)arg, DHCP_REQUEST, send_rebind);
1619}
1620
1621void
1622dhcp_discover(void *arg)
1623{
1624        struct interface *iface = arg;
1625        struct dhcp_state *state = D_STATE(iface);
1626        struct if_options *ifo = iface->options;
1627        int timeout = ifo->timeout;
1628
1629        /* If we're rebooting and we're not daemonised then we need
1630         * to shorten the normal timeout to ensure we try correctly
1631         * for a fallback or IPv4LL address. */
1632        if (state->state == DHS_REBOOT && !(options & DHCPCD_DAEMONISED)) {
1633                timeout -= ifo->reboot;
1634                if (timeout <= 0)
1635                        timeout = 2;
1636        }
1637
1638        state->state = DHS_DISCOVER;
1639        state->xid = dhcp_xid(iface);
1640        eloop_timeout_delete(NULL, iface);
1641        if (ifo->fallback)
1642                eloop_timeout_add_sec(timeout, dhcp_fallback, iface);
1643        else if (ifo->options & DHCPCD_IPV4LL &&
1644            !IN_LINKLOCAL(htonl(state->addr.s_addr)))
1645        {
1646                if (IN_LINKLOCAL(htonl(state->fail.s_addr)))
1647                        eloop_timeout_add_sec(RATE_LIMIT_INTERVAL,
1648                            ipv4ll_start, iface);
1649                else
1650                        eloop_timeout_add_sec(timeout, ipv4ll_start, iface);
1651        }
1652        if (ifo->options & DHCPCD_REQUEST)
1653                syslog(LOG_INFO, "%s: soliciting a DHCP lease (requesting %s)",
1654                    iface->name, inet_ntoa(ifo->req_addr));
1655        else
1656                syslog(LOG_INFO, "%s: soliciting a DHCP lease", iface->name);
1657        send_discover(iface);
1658}
1659
1660static void
1661dhcp_request(void *arg)
1662{
1663        struct interface *ifp = arg;
1664        struct dhcp_state *state = D_STATE(ifp);
1665
1666        state->state = DHS_REQUEST;
1667        send_request(ifp);
1668}
1669
1670static void
1671dhcp_expire(void *arg)
1672{
1673        struct interface *ifp = arg;
1674        struct dhcp_state *state = D_STATE(ifp);
1675
1676        syslog(LOG_ERR, "%s: DHCP lease expired", ifp->name);
1677        eloop_timeout_delete(NULL, ifp);
1678        dhcp_drop(ifp, "EXPIRE");
1679        unlink(state->leasefile);
1680
1681        state->interval = 0;
1682        dhcp_discover(ifp);
1683}
1684
1685void
1686dhcp_decline(struct interface *ifp)
1687{
1688
1689        send_message(ifp, DHCP_DECLINE, NULL);
1690}
1691
1692static void
1693dhcp_renew(void *arg)
1694{
1695        struct interface *ifp = arg;
1696        struct dhcp_state *state = D_STATE(ifp);
1697        struct dhcp_lease *lease = &state->lease;
1698
1699        syslog(LOG_DEBUG, "%s: renewing lease of %s",
1700            ifp->name, inet_ntoa(lease->addr));
1701        syslog(LOG_DEBUG, "%s: rebind in %"PRIu32" seconds,"
1702            " expire in %"PRIu32" seconds",
1703            ifp->name, lease->rebindtime - lease->renewaltime,
1704            lease->leasetime - lease->renewaltime);
1705        state->state = DHS_RENEW;
1706        state->xid = dhcp_xid(ifp);
1707        send_renew(ifp);
1708}
1709
1710static void
1711dhcp_rebind(void *arg)
1712{
1713        struct interface *ifp = arg;
1714        struct dhcp_state *state = D_STATE(ifp);
1715        struct dhcp_lease *lease = &state->lease;
1716
1717        syslog(LOG_WARNING, "%s: failed to renew DHCP, rebinding",
1718            ifp->name);
1719        syslog(LOG_DEBUG, "%s: expire in %"PRIu32" seconds",
1720            ifp->name, lease->leasetime - lease->rebindtime);
1721        state->state = DHS_REBIND;
1722        eloop_timeout_delete(send_renew, ifp);
1723        state->lease.server.s_addr = 0;
1724        ifp->options->options &= ~ DHCPCD_CSR_WARNED;
1725        send_rebind(ifp);
1726}
1727
1728void
1729dhcp_bind(void *arg)
1730{
1731        struct interface *iface = arg;
1732        struct dhcp_state *state = D_STATE(iface);
1733        struct if_options *ifo = iface->options;
1734        struct dhcp_lease *lease = &state->lease;
1735        struct timeval tv;
1736
1737        /* We're binding an address now - ensure that sockets are closed */
1738        dhcp_close(iface);
1739        state->reason = NULL;
1740        if (clock_monotonic)
1741                get_monotonic(&lease->boundtime);
1742        state->xid = 0;
1743        free(state->old);
1744        state->old = state->new;
1745        state->new = state->offer;
1746        state->offer = NULL;
1747        get_lease(lease, state->new);
1748        if (ifo->options & DHCPCD_STATIC) {
1749                syslog(LOG_INFO, "%s: using static address %s/%d",
1750                    iface->name, inet_ntoa(lease->addr),
1751                    inet_ntocidr(lease->net));
1752                lease->leasetime = ~0U;
1753                state->reason = "STATIC";
1754        } else if (state->new->cookie != htonl(MAGIC_COOKIE)) {
1755                syslog(LOG_INFO, "%s: using IPv4LL address %s",
1756                    iface->name, inet_ntoa(lease->addr));
1757                lease->leasetime = ~0U;
1758                state->reason = "IPV4LL";
1759        } else if (ifo->options & DHCPCD_INFORM) {
1760                if (ifo->req_addr.s_addr != 0)
1761                        lease->addr.s_addr = ifo->req_addr.s_addr;
1762                else
1763                        lease->addr.s_addr = state->addr.s_addr;
1764                syslog(LOG_INFO, "%s: received approval for %s", iface->name,
1765                    inet_ntoa(lease->addr));
1766                lease->leasetime = ~0U;
1767                state->reason = "INFORM";
1768        } else {
1769                if (gettimeofday(&tv, NULL) == 0)
1770                        lease->leasedfrom = tv.tv_sec;
1771                else if (lease->frominfo)
1772                        state->reason = "TIMEOUT";
1773                if (lease->leasetime == ~0U) {
1774                        lease->renewaltime =
1775                            lease->rebindtime =
1776                            lease->leasetime;
1777                        syslog(LOG_INFO, "%s: leased %s for infinity",
1778                            iface->name, inet_ntoa(lease->addr));
1779                } else {
1780                        if (lease->leasetime < DHCP_MIN_LEASE) {
1781                                syslog(LOG_WARNING,
1782                                    "%s: minimum lease is %d seconds",
1783                                    iface->name, DHCP_MIN_LEASE);
1784                                lease->leasetime = DHCP_MIN_LEASE;
1785                        }
1786                        if (lease->rebindtime == 0)
1787                                lease->rebindtime = lease->leasetime * T2;
1788                        else if (lease->rebindtime >= lease->leasetime) {
1789                                lease->rebindtime = lease->leasetime * T2;
1790                                syslog(LOG_WARNING,
1791                                    "%s: rebind time greater than lease "
1792                                    "time, forcing to %"PRIu32" seconds",
1793                                    iface->name, lease->rebindtime);
1794                        }
1795                        if (lease->renewaltime == 0)
1796                                lease->renewaltime = lease->leasetime * T1;
1797                        else if (lease->renewaltime > lease->rebindtime) {
1798                                lease->renewaltime = lease->leasetime * T1;
1799                                syslog(LOG_WARNING,
1800                                    "%s: renewal time greater than rebind "
1801                                    "time, forcing to %"PRIu32" seconds",
1802                                    iface->name, lease->renewaltime);
1803                        }
1804                        syslog(lease->addr.s_addr == state->addr.s_addr ?
1805                            LOG_DEBUG : LOG_INFO,
1806                            "%s: leased %s for %"PRIu32" seconds", iface->name,
1807                            inet_ntoa(lease->addr), lease->leasetime);
1808                }
1809        }
1810        if (options & DHCPCD_TEST) {
1811                state->reason = "TEST";
1812                script_runreason(iface, state->reason);
1813                exit(EXIT_SUCCESS);
1814        }
1815        if (state->reason == NULL) {
1816                if (state->old) {
1817                        if (state->old->yiaddr == state->new->yiaddr &&
1818                            lease->server.s_addr)
1819                                state->reason = "RENEW";
1820                        else
1821                                state->reason = "REBIND";
1822                } else if (state->state == DHS_REBOOT)
1823                        state->reason = "REBOOT";
1824                else
1825                        state->reason = "BOUND";
1826        }
1827        if (lease->leasetime == ~0U)
1828                lease->renewaltime = lease->rebindtime = lease->leasetime;
1829        else {
1830                eloop_timeout_add_sec(lease->renewaltime, dhcp_renew, iface);
1831                eloop_timeout_add_sec(lease->rebindtime, dhcp_rebind, iface);
1832                eloop_timeout_add_sec(lease->leasetime, dhcp_expire, iface);
1833                syslog(LOG_DEBUG,
1834                    "%s: renew in %"PRIu32" seconds, rebind in %"PRIu32
1835                    " seconds",
1836                    iface->name, lease->renewaltime, lease->rebindtime);
1837        }
1838        ipv4_applyaddr(iface);
1839        daemonise();
1840        state->state = DHS_BOUND;
1841        if (ifo->options & DHCPCD_ARP) {
1842                state->claims = 0;
1843                arp_announce(iface);
1844        }
1845}
1846
1847static void
1848dhcp_timeout(void *arg)
1849{
1850        struct interface *ifp = arg;
1851        struct dhcp_state *state = D_STATE(ifp);
1852
1853        dhcp_bind(ifp);
1854        state->interval = 0;
1855        dhcp_discover(ifp);
1856}
1857
1858struct dhcp_message *
1859dhcp_message_new(const struct in_addr *addr, const struct in_addr *mask)
1860{
1861        struct dhcp_message *dhcp;
1862        uint8_t *p;
1863
1864        dhcp = calloc(1, sizeof(*dhcp));
1865        if (dhcp == NULL)
1866                return NULL;
1867        dhcp->yiaddr = addr->s_addr;
1868        p = dhcp->options;
1869        if (mask && mask->s_addr != INADDR_ANY) {
1870                *p++ = DHO_SUBNETMASK;
1871                *p++ = sizeof(mask->s_addr);
1872                memcpy(p, &mask->s_addr, sizeof(mask->s_addr));
1873                p+= sizeof(mask->s_addr);
1874        }
1875        *p++ = DHO_END;
1876        return dhcp;
1877}
1878
1879static void
1880dhcp_static(struct interface *ifp)
1881{
1882        struct if_options *ifo;
1883        struct dhcp_state *state;
1884
1885        state = D_STATE(ifp);
1886        ifo = ifp->options;
1887        if (ifo->req_addr.s_addr == INADDR_ANY) {
1888                syslog(LOG_INFO,
1889                    "%s: waiting for 3rd party to "
1890                    "configure IP address",
1891                    ifp->name);
1892                state->reason = "3RDPARTY";
1893                script_runreason(ifp, state->reason);
1894                return;
1895        }
1896        state->offer = dhcp_message_new(&ifo->req_addr, &ifo->req_mask);
1897        if (state->offer) {
1898                eloop_timeout_delete(NULL, ifp);
1899                dhcp_bind(ifp);
1900        }
1901}
1902
1903void
1904dhcp_inform(struct interface *ifp)
1905{
1906        struct dhcp_state *state;
1907        struct if_options *ifo;
1908        struct ipv4_addr *ap;
1909
1910        state = D_STATE(ifp);
1911        ifo = ifp->options;
1912        if (options & DHCPCD_TEST) {
1913                state->addr.s_addr = ifo->req_addr.s_addr;
1914                state->net.s_addr = ifo->req_mask.s_addr;
1915        } else {
1916                if (ifo->req_addr.s_addr == INADDR_ANY) {
1917                        state = D_STATE(ifp);
1918                        ap = ipv4_findaddr(ifp, NULL, NULL);
1919                        if (ap == NULL) {
1920                                syslog(LOG_INFO,
1921                                        "%s: waiting for 3rd party to "
1922                                        "configure IP address",
1923                                        ifp->name);
1924                                state->reason = "3RDPARTY";
1925                                script_runreason(ifp, state->reason);
1926                                return;
1927                        }
1928                        state->offer =
1929                            dhcp_message_new(&ap->addr, &ap->net);
1930                } else
1931                        state->offer =
1932                            dhcp_message_new(&ifo->req_addr, &ifo->req_mask);
1933                if (state->offer) {
1934                        ifo->options |= DHCPCD_STATIC;
1935                        dhcp_bind(ifp);
1936                        ifo->options &= ~DHCPCD_STATIC;
1937                }
1938        }
1939
1940        state->state = DHS_INFORM;
1941        state->xid = dhcp_xid(ifp);
1942        send_inform(ifp);
1943}
1944
1945void
1946dhcp_reboot_newopts(struct interface *ifp, int oldopts)
1947{
1948        struct if_options *ifo;
1949        struct dhcp_state *state = D_STATE(ifp);
1950
1951        if (state == NULL)
1952                return;
1953        ifo = ifp->options;
1954        if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC) &&
1955                state->addr.s_addr != ifo->req_addr.s_addr) ||
1956            (oldopts & (DHCPCD_INFORM | DHCPCD_STATIC) &&
1957                !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))))
1958        {
1959                dhcp_drop(ifp, "EXPIRE");
1960        }
1961}
1962
1963static void
1964dhcp_reboot(struct interface *ifp)
1965{
1966        struct if_options *ifo;
1967        struct dhcp_state *state = D_STATE(ifp);
1968
1969        if (state == NULL)
1970                return;
1971        ifo = ifp->options;
1972        state->interval = 0;
1973
1974        if (ifo->options & DHCPCD_LINK && ifp->carrier == LINK_DOWN) {
1975                syslog(LOG_INFO, "%s: waiting for carrier", ifp->name);
1976                return;
1977        }
1978        if (ifo->options & DHCPCD_STATIC) {
1979                dhcp_static(ifp);
1980                return;
1981        }
1982        if (ifo->reboot == 0 || state->offer == NULL) {
1983                dhcp_discover(ifp);
1984                return;
1985        }
1986        if (ifo->options & DHCPCD_INFORM) {
1987                syslog(LOG_INFO, "%s: informing address of %s",
1988                    ifp->name, inet_ntoa(state->lease.addr));
1989        } else if (state->offer->cookie == 0) {
1990                if (ifo->options & DHCPCD_IPV4LL) {
1991                        state->claims = 0;
1992                        arp_announce(ifp);
1993                } else
1994                        dhcp_discover(ifp);
1995                return;
1996        } else {
1997                syslog(LOG_INFO, "%s: rebinding lease of %s",
1998                    ifp->name, inet_ntoa(state->lease.addr));
1999        }
2000        state->state = DHS_REBOOT;
2001        state->xid = dhcp_xid(ifp);
2002        state->lease.server.s_addr = 0;
2003        eloop_timeout_delete(NULL, ifp);
2004        if (ifo->fallback)
2005                eloop_timeout_add_sec(ifo->reboot, dhcp_fallback, ifp);
2006        else if (ifo->options & DHCPCD_LASTLEASE && state->lease.frominfo)
2007                eloop_timeout_add_sec(ifo->reboot, dhcp_timeout, ifp);
2008        else if (!(ifo->options & DHCPCD_INFORM &&
2009            options & (DHCPCD_MASTER | DHCPCD_DAEMONISED)))
2010                eloop_timeout_add_sec(ifo->reboot, dhcp_expire, ifp);
2011        /* Don't bother ARP checking as the server could NAK us first. */
2012        if (ifo->options & DHCPCD_INFORM)
2013                dhcp_inform(ifp);
2014        else
2015                dhcp_request(ifp);
2016}
2017
2018void
2019dhcp_drop(struct interface *ifp, const char *reason)
2020{
2021        struct dhcp_state *state;
2022#ifdef RELEASE_SLOW
2023        struct timespec ts;
2024#endif
2025
2026        state = D_STATE(ifp);
2027        if (state == NULL)
2028                return;
2029        eloop_timeouts_delete(ifp, dhcp_expire, NULL);
2030        if (ifp->options->options & DHCPCD_RELEASE) {
2031                unlink(state->leasefile);
2032                if (ifp->carrier != LINK_DOWN &&
2033                    state->new != NULL &&
2034                    state->new->cookie == htonl(MAGIC_COOKIE))
2035                {
2036                        syslog(LOG_INFO, "%s: releasing lease of %s",
2037                            ifp->name, inet_ntoa(state->lease.addr));
2038                        state->xid = dhcp_xid(ifp);
2039                        send_message(ifp, DHCP_RELEASE, NULL);
2040#ifdef RELEASE_SLOW
2041                        /* Give the packet a chance to go */
2042                        ts.tv_sec = RELEASE_DELAY_S;
2043                        ts.tv_nsec = RELEASE_DELAY_NS;
2044                        nanosleep(&ts, NULL);
2045#endif
2046                }
2047        }
2048        free(state->old);
2049        state->old = state->new;
2050        state->new = NULL;
2051        state->reason = reason;
2052        ipv4_applyaddr(ifp);
2053        free(state->old);
2054        state->old = NULL;
2055        state->lease.addr.s_addr = 0;
2056        ifp->options->options &= ~ DHCPCD_CSR_WARNED;
2057        state->auth.token = NULL;
2058        state->auth.replay = 0;
2059        free(state->auth.reconf);
2060        state->auth.reconf = NULL;
2061}
2062
2063static void
2064log_dhcp(int lvl, const char *msg,
2065    const struct interface *iface, const struct dhcp_message *dhcp,
2066    const struct in_addr *from)
2067{
2068        const char *tfrom;
2069        char *a;
2070        struct in_addr addr;
2071        int r;
2072
2073        if (strcmp(msg, "NAK:") == 0)
2074                a = get_option_string(dhcp, DHO_MESSAGE);
2075        else if (dhcp->yiaddr != 0) {
2076                addr.s_addr = dhcp->yiaddr;
2077                a = strdup(inet_ntoa(addr));
2078                if (a == NULL) {
2079                        syslog(LOG_ERR, "%s: %m", __func__);
2080                        return;
2081                }
2082        } else
2083                a = NULL;
2084
2085        tfrom = "from";
2086        r = get_option_addr(&addr, dhcp, DHO_SERVERID);
2087        if (dhcp->servername[0] && r == 0)
2088                syslog(lvl, "%s: %s %s %s %s `%s'", iface->name, msg, a,
2089                    tfrom, inet_ntoa(addr), dhcp->servername);
2090        else {
2091                if (r != 0) {
2092                        tfrom = "via";
2093                        addr = *from;
2094                }
2095                if (a == NULL)
2096                        syslog(lvl, "%s: %s %s %s",
2097                            iface->name, msg, tfrom, inet_ntoa(addr));
2098                else
2099                        syslog(lvl, "%s: %s %s %s %s",
2100                            iface->name, msg, a, tfrom, inet_ntoa(addr));
2101        }
2102        free(a);
2103}
2104
2105static int
2106blacklisted_ip(const struct if_options *ifo, in_addr_t addr)
2107{
2108        size_t i;
2109
2110        for (i = 0; i < ifo->blacklist_len; i += 2)
2111                if (ifo->blacklist[i] == (addr & ifo->blacklist[i + 1]))
2112                        return 1;
2113        return 0;
2114}
2115
2116static int
2117whitelisted_ip(const struct if_options *ifo, in_addr_t addr)
2118{
2119        size_t i;
2120
2121        if (ifo->whitelist_len == 0)
2122                return -1;
2123        for (i = 0; i < ifo->whitelist_len; i += 2)
2124                if (ifo->whitelist[i] == (addr & ifo->whitelist[i + 1]))
2125                        return 1;
2126        return 0;
2127}
2128
2129static void
2130dhcp_handledhcp(struct interface *iface, struct dhcp_message **dhcpp,
2131    const struct in_addr *from)
2132{
2133        struct dhcp_state *state = D_STATE(iface);
2134        struct if_options *ifo = iface->options;
2135        struct dhcp_message *dhcp = *dhcpp;
2136        struct dhcp_lease *lease = &state->lease;
2137        uint8_t type, tmp;
2138        const uint8_t *auth;
2139        struct in_addr addr;
2140        size_t i;
2141        int auth_len;
2142
2143        /* We may have found a BOOTP server */
2144        if (get_option_uint8(&type, dhcp, DHO_MESSAGETYPE) == -1)
2145                type = 0;
2146
2147        /* Authenticate the message */
2148        auth = get_option(dhcp, DHO_AUTHENTICATION, &auth_len);
2149        if (auth) {
2150                if (dhcp_auth_validate(&state->auth, &ifo->auth,
2151                    (uint8_t *)*dhcpp, sizeof(**dhcpp), 4, type,
2152                    auth, auth_len) == NULL)
2153                {
2154                        syslog(LOG_DEBUG, "%s: dhcp_auth_validate: %m",
2155                            iface->name);
2156                        log_dhcp(LOG_ERR, "authentication failed",
2157                            iface, dhcp, from);
2158                        return;
2159                }
2160                syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32,
2161                    iface->name, state->auth.token->secretid);
2162        } else if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) {
2163                log_dhcp(LOG_ERR, "missing authentiation", iface, dhcp, from);
2164                return;
2165        }
2166
2167        /* reset the message counter */
2168        state->interval = 0;
2169
2170        if (type == DHCP_NAK) {
2171                /* For NAK, only check if we require the ServerID */
2172                if (has_option_mask(ifo->requiremask, DHO_SERVERID) &&
2173                    get_option_addr(&addr, dhcp, DHO_SERVERID) == -1)
2174                {
2175                        log_dhcp(LOG_WARNING, "reject NAK", iface, dhcp, from);
2176                        return;
2177                }
2178                /* We should restart on a NAK */
2179                log_dhcp(LOG_WARNING, "NAK:", iface, dhcp, from);
2180                if (!(options & DHCPCD_TEST)) {
2181                        dhcp_drop(iface, "NAK");
2182                        unlink(state->leasefile);
2183                }
2184                dhcp_close(iface);
2185                /* If we constantly get NAKS then we should slowly back off */
2186                eloop_timeout_add_sec(state->nakoff, dhcp_discover, iface);
2187                if (state->nakoff == 0)
2188                        state->nakoff = 1;
2189                else {
2190                        state->nakoff *= 2;
2191                        if (state->nakoff > NAKOFF_MAX)
2192                                state->nakoff = NAKOFF_MAX;
2193                }
2194                return;
2195        }
2196
2197        /* Ensure that all required options are present */
2198        for (i = 1; i < 255; i++) {
2199                if (has_option_mask(ifo->requiremask, i) &&
2200                    get_option_uint8(&tmp, dhcp, i) != 0)
2201                {
2202                        /* If we are bootp, then ignore the need for serverid.
2203                         * To ignore bootp, require dhcp_message_type. */
2204                        if (type == 0 && i == DHO_SERVERID)
2205                                continue;
2206                        log_dhcp(LOG_WARNING, "reject DHCP", iface, dhcp, from);
2207                        return;
2208                }
2209        }
2210
2211        /* Ensure that the address offered is valid */
2212        if ((type == 0 || type == DHCP_OFFER || type == DHCP_ACK) &&
2213            (dhcp->ciaddr == INADDR_ANY || dhcp->ciaddr == INADDR_BROADCAST) &&
2214            (dhcp->yiaddr == INADDR_ANY || dhcp->yiaddr == INADDR_BROADCAST))
2215        {
2216                log_dhcp(LOG_WARNING, "reject invalid address",
2217                    iface, dhcp, from);
2218                return;
2219        }
2220
2221        if ((type == 0 || type == DHCP_OFFER) &&
2222            state->state == DHS_DISCOVER)
2223        {
2224                lease->frominfo = 0;
2225                lease->addr.s_addr = dhcp->yiaddr;
2226                lease->cookie = dhcp->cookie;
2227                if (type == 0 ||
2228                    get_option_addr(&lease->server, dhcp, DHO_SERVERID) != 0)
2229                        lease->server.s_addr = INADDR_ANY;
2230                log_dhcp(LOG_INFO, "offered", iface, dhcp, from);
2231                free(state->offer);
2232                state->offer = dhcp;
2233                *dhcpp = NULL;
2234                if (options & DHCPCD_TEST) {
2235                        free(state->old);
2236                        state->old = state->new;
2237                        state->new = state->offer;
2238                        state->offer = NULL;
2239                        state->reason = "TEST";
2240                        script_runreason(iface, state->reason);
2241                        exit(EXIT_SUCCESS);
2242                }
2243                eloop_timeout_delete(send_discover, iface);
2244                /* We don't request BOOTP addresses */
2245                if (type) {
2246                        /* We used to ARP check here, but that seems to be in
2247                         * violation of RFC2131 where it only describes
2248                         * DECLINE after REQUEST.
2249                         * It also seems that some MS DHCP servers actually
2250                         * ignore DECLINE if no REQUEST, ie we decline a
2251                         * DISCOVER. */
2252                        dhcp_request(iface);
2253                        return;
2254                }
2255        }
2256
2257        if (type) {
2258                if (type == DHCP_OFFER) {
2259                        log_dhcp(LOG_WARNING, "ignoring offer of",
2260                            iface, dhcp, from);
2261                        return;
2262                }
2263
2264                /* We should only be dealing with acks */
2265                if (type != DHCP_ACK) {
2266                        log_dhcp(LOG_ERR, "not ACK or OFFER",
2267                            iface, dhcp, from);
2268                        return;
2269                }
2270
2271                if (!(ifo->options & DHCPCD_INFORM))
2272                        log_dhcp(LOG_DEBUG, "acknowledged", iface, dhcp, from);
2273                else
2274                    ifo->options &= ~DHCPCD_STATIC;
2275        }
2276
2277
2278        /* No NAK, so reset the backoff
2279         * We don't reset on an OFFER message because the server could
2280         * potentially NAK the REQUEST. */
2281        state->nakoff = 0;
2282
2283        /* BOOTP could have already assigned this above, so check we still
2284         * have a pointer. */
2285        if (*dhcpp) {
2286                free(state->offer);
2287                state->offer = dhcp;
2288                *dhcpp = NULL;
2289        }
2290
2291        lease->frominfo = 0;
2292        eloop_timeout_delete(NULL, iface);
2293
2294        /* We now have an offer, so close the DHCP sockets.
2295         * This allows us to safely ARP when broken DHCP servers send an ACK
2296         * follows by an invalid NAK. */
2297        dhcp_close(iface);
2298
2299        if (ifo->options & DHCPCD_ARP &&
2300            state->addr.s_addr != state->offer->yiaddr)
2301        {
2302                /* If the interface already has the address configured
2303                 * then we can't ARP for duplicate detection. */
2304                addr.s_addr = state->offer->yiaddr;
2305                if (!ipv4_findaddr(iface, &addr, NULL)) {
2306                        state->claims = 0;
2307                        state->probes = 0;
2308                        state->conflicts = 0;
2309                        state->state = DHS_PROBE;
2310                        arp_probe(iface);
2311                        return;
2312                }
2313        }
2314
2315        dhcp_bind(iface);
2316}
2317
2318static ssize_t
2319get_udp_data(const uint8_t **data, const uint8_t *udp)
2320{
2321        struct udp_dhcp_packet p;
2322
2323        memcpy(&p, udp, sizeof(p));
2324        *data = udp + offsetof(struct udp_dhcp_packet, dhcp);
2325        return ntohs(p.ip.ip_len) - sizeof(p.ip) - sizeof(p.udp);
2326}
2327
2328static int
2329valid_udp_packet(const uint8_t *data, size_t data_len, struct in_addr *from,
2330    int noudpcsum)
2331{
2332        struct udp_dhcp_packet p;
2333        uint16_t bytes, udpsum;
2334
2335        if (data_len < sizeof(p.ip)) {
2336                if (from)
2337                        from->s_addr = INADDR_ANY;
2338                errno = EINVAL;
2339                return -1;
2340        }
2341        memcpy(&p, data, MIN(data_len, sizeof(p)));
2342        if (from)
2343                from->s_addr = p.ip.ip_src.s_addr;
2344        if (data_len > sizeof(p)) {
2345                errno = EINVAL;
2346                return -1;
2347        }
2348        if (checksum(&p.ip, sizeof(p.ip)) != 0) {
2349                errno = EINVAL;
2350                return -1;
2351        }
2352
2353        bytes = ntohs(p.ip.ip_len);
2354        if (data_len < bytes) {
2355                errno = EINVAL;
2356                return -1;
2357        }
2358
2359        if (noudpcsum == 0) {
2360                udpsum = p.udp.uh_sum;
2361                p.udp.uh_sum = 0;
2362                p.ip.ip_hl = 0;
2363                p.ip.ip_v = 0;
2364                p.ip.ip_tos = 0;
2365                p.ip.ip_len = p.udp.uh_ulen;
2366                p.ip.ip_id = 0;
2367                p.ip.ip_off = 0;
2368                p.ip.ip_ttl = 0;
2369                p.ip.ip_sum = 0;
2370                if (udpsum && checksum(&p, bytes) != udpsum) {
2371                        errno = EINVAL;
2372                        return -1;
2373                }
2374        }
2375
2376        return 0;
2377}
2378
2379static void
2380dhcp_handlepacket(void *arg)
2381{
2382        struct interface *iface = arg;
2383        struct dhcp_message *dhcp = NULL;
2384        const uint8_t *pp;
2385        ssize_t bytes;
2386        struct in_addr from;
2387        int i, partialcsum = 0;
2388        const struct dhcp_state *state = D_CSTATE(iface);
2389
2390        /* We loop through until our buffer is empty.
2391         * The benefit is that if we get >1 DHCP packet in our buffer and
2392         * the first one fails for any reason, we can use the next. */
2393        for(;;) {
2394                bytes = ipv4_getrawpacket(iface, ETHERTYPE_IP,
2395                    packet, udp_dhcp_len, &partialcsum);
2396                if (bytes == 0 || bytes == -1)
2397                        break;
2398                if (valid_udp_packet(packet, bytes, &from, partialcsum) == -1) {
2399                        syslog(LOG_ERR, "%s: invalid UDP packet from %s",
2400                            iface->name, inet_ntoa(from));
2401                        continue;
2402                }
2403                i = whitelisted_ip(iface->options, from.s_addr);
2404                if (i == 0) {
2405                        syslog(LOG_WARNING,
2406                            "%s: non whitelisted DHCP packet from %s",
2407                            iface->name, inet_ntoa(from));
2408                        continue;
2409                } else if (i != 1 &&
2410                    blacklisted_ip(iface->options, from.s_addr) == 1)
2411                {
2412                        syslog(LOG_WARNING,
2413                            "%s: blacklisted DHCP packet from %s",
2414                            iface->name, inet_ntoa(from));
2415                        continue;
2416                }
2417                if (iface->flags & IFF_POINTOPOINT &&
2418                    state->dst.s_addr != from.s_addr)
2419                {
2420                        syslog(LOG_WARNING,
2421                            "%s: server %s is not destination",
2422                            iface->name, inet_ntoa(from));
2423                }
2424                bytes = get_udp_data(&pp, packet);
2425                if ((size_t)bytes > sizeof(*dhcp)) {
2426                        syslog(LOG_ERR,
2427                            "%s: packet greater than DHCP size from %s",
2428                            iface->name, inet_ntoa(from));
2429                        continue;
2430                }
2431                if (dhcp == NULL) {
2432                        dhcp = calloc(1, sizeof(*dhcp));
2433                        if (dhcp == NULL) {
2434                                syslog(LOG_ERR, "%s: calloc: %m", __func__);
2435                                break;
2436                        }
2437                }
2438                memcpy(dhcp, pp, bytes);
2439                if (dhcp->cookie != htonl(MAGIC_COOKIE)) {
2440                        syslog(LOG_DEBUG, "%s: bogus cookie from %s",
2441                            iface->name, inet_ntoa(from));
2442                        continue;
2443                }
2444                /* Ensure it's the right transaction */
2445                if (state->xid != ntohl(dhcp->xid)) {
2446                        syslog(LOG_DEBUG,
2447                            "%s: wrong xid 0x%x (expecting 0x%x) from %s",
2448                            iface->name, ntohl(dhcp->xid), state->xid,
2449                            inet_ntoa(from));
2450                        continue;
2451                }
2452                /* Ensure packet is for us */
2453                if (iface->hwlen <= sizeof(dhcp->chaddr) &&
2454                    memcmp(dhcp->chaddr, iface->hwaddr, iface->hwlen))
2455                {
2456                        syslog(LOG_DEBUG, "%s: xid 0x%x is not for hwaddr %s",
2457                            iface->name, ntohl(dhcp->xid),
2458                            hwaddr_ntoa(dhcp->chaddr, sizeof(dhcp->chaddr)));
2459                        continue;
2460                }
2461                dhcp_handledhcp(iface, &dhcp, &from);
2462                if (state->raw_fd == -1)
2463                        break;
2464        }
2465        free(dhcp);
2466}
2467
2468static int
2469dhcp_open(struct interface *ifp)
2470{
2471        struct dhcp_state *state;
2472
2473        if (packet == NULL) {
2474                packet = malloc(udp_dhcp_len);
2475                if (packet == NULL) {
2476                        syslog(LOG_ERR, "%s: %m", __func__);
2477                        return -1;
2478                }
2479#ifdef DEBUG_MEMORY
2480                atexit(dhcp_cleanup);
2481#endif
2482        }
2483
2484        state = D_STATE(ifp);
2485        if (state->raw_fd == -1) {
2486                state->raw_fd = ipv4_opensocket(ifp, ETHERTYPE_IP);
2487                if (state->raw_fd == -1) {
2488                        syslog(LOG_ERR, "%s: %s: %m", __func__, ifp->name);
2489                        return -1;
2490                }
2491                eloop_event_add(state->raw_fd, dhcp_handlepacket, ifp);
2492        }
2493        if (state->udp_fd == -1 &&
2494            state->addr.s_addr != 0 &&
2495            state->new != NULL &&
2496            (state->new->cookie == htonl(MAGIC_COOKIE) ||
2497            ifp->options->options & DHCPCD_INFORM))
2498        {
2499                if (dhcp_openudp(ifp) == -1 && errno != EADDRINUSE) {
2500                        syslog(LOG_ERR, "%s: dhcp_openudp: %m", ifp->name);
2501                        return -1;
2502                }
2503        }
2504        return 0;
2505}
2506
2507int
2508dhcp_dump(const char *ifname)
2509{
2510        struct interface *ifp;
2511        struct dhcp_state *state;
2512
2513        ifaces = malloc(sizeof(*ifaces));
2514        if (ifaces == NULL)
2515                goto eexit;
2516        TAILQ_INIT(ifaces);
2517        ifp = calloc(1, sizeof(*ifp));
2518        if (ifp == NULL)
2519                goto eexit;
2520        TAILQ_INSERT_HEAD(ifaces, ifp, next);
2521        ifp->if_data[IF_DATA_DHCP] = state = calloc(1, sizeof(*state));
2522        if (state == NULL)
2523                goto eexit;
2524        ifp->options = calloc(1, sizeof(*ifp->options));
2525        if (ifp->options == NULL)
2526                goto eexit;
2527        strlcpy(ifp->name, ifname, sizeof(ifp->name));
2528        snprintf(state->leasefile, sizeof(state->leasefile),
2529            LEASEFILE, ifp->name);
2530        strlcpy(ifp->options->script, if_options->script,
2531            sizeof(ifp->options->script));
2532        state->new = read_lease(ifp);
2533        if (state->new == NULL && errno == ENOENT) {
2534                strlcpy(state->leasefile, ifname, sizeof(state->leasefile));
2535                state->new = read_lease(ifp);
2536        }
2537        if (state->new == NULL) {
2538                if (errno == ENOENT)
2539                        syslog(LOG_ERR, "%s: no lease to dump", ifname);
2540                return -1;
2541        }
2542        state->reason = "DUMP";
2543        return script_runreason(ifp, state->reason);
2544
2545eexit:
2546        syslog(LOG_ERR, "%s: %m", __func__);
2547        return -1;
2548}
2549
2550void
2551dhcp_free(struct interface *ifp)
2552{
2553        struct dhcp_state *state = D_STATE(ifp);
2554
2555        if (state) {
2556                free(state->old);
2557                free(state->new);
2558                free(state->offer);
2559                free(state->buffer);
2560                free(state->clientid);
2561                free(state);
2562                ifp->if_data[IF_DATA_DHCP] = NULL;
2563        }
2564}
2565
2566static int
2567dhcp_init(struct interface *ifp)
2568{
2569        struct dhcp_state *state;
2570        const struct if_options *ifo;
2571        size_t len;
2572
2573        state = D_STATE(ifp);
2574        if (state == NULL) {
2575                ifp->if_data[IF_DATA_DHCP] = calloc(1, sizeof(*state));
2576                state = D_STATE(ifp);
2577                if (state == NULL)
2578                        return -1;
2579                /* 0 is a valid fd, so init to -1 */
2580                state->raw_fd = state->udp_fd = state->arp_fd = -1;
2581        }
2582
2583        state->state = DHS_INIT;
2584        state->reason = "PREINIT";
2585        state->nakoff = 0;
2586        snprintf(state->leasefile, sizeof(state->leasefile),
2587            LEASEFILE, ifp->name);
2588
2589        ifo = ifp->options;
2590        /* We need to drop the leasefile so that start_interface
2591         * doesn't load it. */
2592        if (ifo->options & DHCPCD_REQUEST)
2593                unlink(state->leasefile);
2594
2595        free(state->clientid);
2596        state->clientid = NULL;
2597
2598        if (*ifo->clientid) {
2599                state->clientid = malloc(ifo->clientid[0] + 1);
2600                if (state->clientid == NULL)
2601                        goto eexit;
2602                memcpy(state->clientid, ifo->clientid, ifo->clientid[0] + 1);
2603        } else if (ifo->options & DHCPCD_CLIENTID) {
2604                if (ifo->options & DHCPCD_DUID) {
2605                        state->clientid = malloc(duid_len + 6);
2606                        if (state->clientid == NULL)
2607                                goto eexit;
2608                        state->clientid[0] = duid_len + 5;
2609                        state->clientid[1] = 255; /* RFC 4361 */
2610                        memcpy(state->clientid + 2, ifo->iaid, 4);
2611                        memcpy(state->clientid + 6, duid, duid_len);
2612                } else {
2613                        len = ifp->hwlen + 1;
2614                        state->clientid = malloc(len + 1);
2615                        if (state->clientid == NULL)
2616                                goto eexit;
2617                        state->clientid[0] = len;
2618                        state->clientid[1] = ifp->family;
2619                        memcpy(state->clientid + 2, ifp->hwaddr,
2620                            ifp->hwlen);
2621                }
2622        }
2623
2624        if (ifo->options & DHCPCD_DUID)
2625                /* Don't bother logging as DUID and IAID are reported
2626                 * at device start. */
2627                return 0;
2628
2629        if (ifo->options & DHCPCD_CLIENTID)
2630                syslog(LOG_DEBUG, "%s: using ClientID %s", ifp->name,
2631                    hwaddr_ntoa(state->clientid + 1, state->clientid[0]));
2632        else if (ifp->hwlen)
2633                syslog(LOG_DEBUG, "%s: using hwaddr %s", ifp->name,
2634                    hwaddr_ntoa(ifp->hwaddr, ifp->hwlen));
2635        return 0;
2636
2637eexit:
2638        syslog(LOG_ERR, "%s: Error making ClientID: %m", __func__);
2639        return -1;
2640}
2641
2642void
2643dhcp_start(struct interface *ifp)
2644{
2645        struct if_options *ifo = ifp->options;
2646        struct dhcp_state *state;
2647        struct stat st;
2648        struct timeval now;
2649        uint32_t l;
2650        int nolease;
2651
2652        if (!(ifo->options & DHCPCD_IPV4))
2653                return;
2654
2655        if (dhcp_init(ifp) == -1) {
2656                syslog(LOG_ERR, "%s: dhcp_init: %m", ifp->name);
2657                return;
2658        }
2659
2660        /* Close any pre-existing sockets as we're starting over */
2661        dhcp_close(ifp);
2662
2663        state = D_STATE(ifp);
2664        state->start_uptime = uptime();
2665        free(state->offer);
2666        state->offer = NULL;
2667
2668        if (state->arping_index < ifo->arping_len) {
2669                arp_start(ifp);
2670                return;
2671        }
2672
2673        if (ifo->options & DHCPCD_STATIC) {
2674                dhcp_static(ifp);
2675                return;
2676        }
2677
2678        if (ifo->options & DHCPCD_DHCP && dhcp_open(ifp) == -1)
2679                return;
2680
2681        if (ifo->options & DHCPCD_INFORM) {
2682                dhcp_inform(ifp);
2683                return;
2684        }
2685        if (ifp->hwlen == 0 && ifo->clientid[0] == '\0') {
2686                syslog(LOG_WARNING, "%s: needs a clientid to configure",
2687                    ifp->name);
2688                dhcp_drop(ifp, "FAIL");
2689                dhcp_close(ifp);
2690                eloop_timeout_delete(NULL, ifp);
2691                return;
2692        }
2693        /* We don't want to read the old lease if we NAK an old test */
2694        nolease = state->offer && options & DHCPCD_TEST;
2695        if (!nolease)
2696                state->offer = read_lease(ifp);
2697        if (state->offer) {
2698                get_lease(&state->lease, state->offer);
2699                state->lease.frominfo = 1;
2700                if (state->offer->cookie == 0) {
2701                        if (state->offer->yiaddr == state->addr.s_addr) {
2702                                free(state->offer);
2703                                state->offer = NULL;
2704                        }
2705                } else if (state->lease.leasetime != ~0U &&
2706                    stat(state->leasefile, &st) == 0)
2707                {
2708                        /* Offset lease times and check expiry */
2709                        gettimeofday(&now, NULL);
2710                        if ((time_t)state->lease.leasetime <
2711                            now.tv_sec - st.st_mtime)
2712                        {
2713                                syslog(LOG_DEBUG,
2714                                    "%s: discarding expired lease",
2715                                    ifp->name);
2716                                free(state->offer);
2717                                state->offer = NULL;
2718                                state->lease.addr.s_addr = 0;
2719                        } else {
2720                                l = now.tv_sec - st.st_mtime;
2721                                state->lease.leasetime -= l;
2722                                state->lease.renewaltime -= l;
2723                                state->lease.rebindtime -= l;
2724                        }
2725                }
2726        }
2727
2728        if (!(ifo->options & DHCPCD_DHCP)) {
2729                if (ifo->options & DHCPCD_IPV4LL) {
2730                        if (state->offer && state->offer->cookie != 0) {
2731                                free(state->offer);
2732                                state->offer = NULL;
2733                        }
2734                        ipv4ll_start(ifp);
2735                }
2736                return;
2737        }
2738
2739        if (state->offer == NULL)
2740                dhcp_discover(ifp);
2741        else if (state->offer->cookie == 0 && ifo->options & DHCPCD_IPV4LL)
2742                ipv4ll_start(ifp);
2743        else
2744                dhcp_reboot(ifp);
2745}
2746
2747void
2748dhcp_handleifa(int type, struct interface *ifp,
2749        const struct in_addr *addr,
2750        const struct in_addr *net,
2751        const struct in_addr *dst)
2752{
2753        struct dhcp_state *state;
2754        struct if_options *ifo;
2755        int i;
2756
2757        state = D_STATE(ifp);
2758        if (state == NULL)
2759                return;
2760
2761        if (type == RTM_DELADDR) {
2762                if (state->new &&
2763                    (state->new->yiaddr == addr->s_addr ||
2764                    (state->new->yiaddr == INADDR_ANY &&
2765                     state->new->ciaddr == addr->s_addr)))
2766                {
2767                        syslog(LOG_INFO, "%s: removing IP address %s/%d",
2768                            ifp->name, inet_ntoa(state->lease.addr),
2769                            inet_ntocidr(state->lease.net));
2770                        dhcp_drop(ifp, "EXPIRE");
2771                }
2772                return;
2773        }
2774
2775        if (type != RTM_NEWADDR)
2776                return;
2777
2778        ifo = ifp->options;
2779        if (ifo->options & DHCPCD_INFORM) {
2780                if (state->state != DHS_INFORM)
2781                        dhcp_inform(ifp);
2782                return;
2783        }
2784
2785        if (!(ifo->options & DHCPCD_STATIC))
2786                return;
2787        if (ifo->req_addr.s_addr != INADDR_ANY)
2788                return;
2789
2790        free(state->old);
2791        state->old = state->new;
2792        state->new = dhcp_message_new(addr, net);
2793        if (state->new == NULL)
2794                return;
2795        state->dst.s_addr = dst ? dst->s_addr : INADDR_ANY;
2796        if (dst) {
2797                for (i = 1; i < 255; i++)
2798                        if (i != DHO_ROUTER && has_option_mask(ifo->dstmask,i))
2799                                dhcp_message_add_addr(state->new, i, *dst);
2800        }
2801        state->reason = "STATIC";
2802        ipv4_buildroutes();
2803        script_runreason(ifp, state->reason);
2804        if (ifo->options & DHCPCD_INFORM) {
2805                state->state = DHS_INFORM;
2806                state->xid = dhcp_xid(ifp);
2807                state->lease.server.s_addr = dst ? dst->s_addr : INADDR_ANY;
2808                state->addr = *addr;
2809                state->net = *net;
2810                dhcp_inform(ifp);
2811        }
2812}
Note: See TracBrowser for help on using the repository browser.