"Fossies" - the Fresh Open Source Software Archive

Member "dhcpcd-9.4.1/src/dhcp6.c" (22 Oct 2021, 104279 Bytes) of package /linux/misc/dhcpcd-9.4.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dhcp6.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 9.4.0_vs_9.4.1.

    1 /* SPDX-License-Identifier: BSD-2-Clause */
    2 /*
    3  * dhcpcd - DHCP client daemon
    4  * Copyright (c) 2006-2021 Roy Marples <roy@marples.name>
    5  * All rights reserved
    6 
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/utsname.h>
   30 #include <sys/types.h>
   31 
   32 #include <netinet/in.h>
   33 #include <netinet/ip6.h>
   34 
   35 #include <assert.h>
   36 #include <ctype.h>
   37 #include <errno.h>
   38 #include <fcntl.h>
   39 #include <inttypes.h>
   40 #include <stdbool.h>
   41 #include <stddef.h>
   42 #include <stdlib.h>
   43 #include <string.h>
   44 #include <unistd.h>
   45 #include <fcntl.h>
   46 #include <syslog.h>
   47 
   48 #define ELOOP_QUEUE ELOOP_DHCP6
   49 #include "config.h"
   50 #include "common.h"
   51 #include "dhcp.h"
   52 #include "dhcp6.h"
   53 #include "duid.h"
   54 #include "eloop.h"
   55 #include "if.h"
   56 #include "if-options.h"
   57 #include "ipv6nd.h"
   58 #include "logerr.h"
   59 #include "privsep.h"
   60 #include "script.h"
   61 
   62 #ifdef HAVE_SYS_BITOPS_H
   63 #include <sys/bitops.h>
   64 #else
   65 #include "compat/bitops.h"
   66 #endif
   67 
   68 /* DHCPCD Project has been assigned an IANA PEN of 40712 */
   69 #define DHCPCD_IANA_PEN 40712
   70 
   71 /* Unsure if I want this */
   72 //#define VENDOR_SPLIT
   73 
   74 /* Support older systems with different defines */
   75 #if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO)
   76 #define IPV6_RECVPKTINFO IPV6_PKTINFO
   77 #endif
   78 
   79 #ifdef DHCP6
   80 
   81 /* Assert the correct structure size for on wire */
   82 struct dhcp6_message {
   83     uint8_t type;
   84     uint8_t xid[3];
   85     /* followed by options */
   86 };
   87 __CTASSERT(sizeof(struct dhcp6_message) == 4);
   88 
   89 struct dhcp6_option {
   90     uint16_t code;
   91     uint16_t len;
   92     /* followed by data */
   93 };
   94 __CTASSERT(sizeof(struct dhcp6_option) == 4);
   95 
   96 struct dhcp6_ia_na {
   97     uint8_t iaid[4];
   98     uint32_t t1;
   99     uint32_t t2;
  100 };
  101 __CTASSERT(sizeof(struct dhcp6_ia_na) == 12);
  102 
  103 struct dhcp6_ia_ta {
  104     uint8_t iaid[4];
  105 };
  106 __CTASSERT(sizeof(struct dhcp6_ia_ta) == 4);
  107 
  108 struct dhcp6_ia_addr {
  109     struct in6_addr addr;
  110     uint32_t pltime;
  111     uint32_t vltime;
  112 };
  113 __CTASSERT(sizeof(struct dhcp6_ia_addr) == 16 + 8);
  114 
  115 /* XXX FIXME: This is the only packed structure and it does not align.
  116  * Maybe manually decode it? */
  117 struct dhcp6_pd_addr {
  118     uint32_t pltime;
  119     uint32_t vltime;
  120     uint8_t prefix_len;
  121     struct in6_addr prefix;
  122 } __packed;
  123 __CTASSERT(sizeof(struct dhcp6_pd_addr) == 8 + 1 + 16);
  124 
  125 struct dhcp6_op {
  126     uint16_t type;
  127     const char *name;
  128 };
  129 
  130 static const struct dhcp6_op dhcp6_ops[] = {
  131     { DHCP6_SOLICIT, "SOLICIT6" },
  132     { DHCP6_ADVERTISE, "ADVERTISE6" },
  133     { DHCP6_REQUEST, "REQUEST6" },
  134     { DHCP6_REPLY, "REPLY6" },
  135     { DHCP6_RENEW, "RENEW6" },
  136     { DHCP6_REBIND, "REBIND6" },
  137     { DHCP6_CONFIRM, "CONFIRM6" },
  138     { DHCP6_INFORMATION_REQ, "INFORM6" },
  139     { DHCP6_RELEASE, "RELEASE6" },
  140     { DHCP6_RECONFIGURE, "RECONFIGURE6" },
  141     { DHCP6_DECLINE, "DECLINE6" },
  142     { 0, NULL }
  143 };
  144 
  145 struct dhcp_compat {
  146     uint8_t dhcp_opt;
  147     uint16_t dhcp6_opt;
  148 };
  149 
  150 static const struct dhcp_compat dhcp_compats[] = {
  151     { DHO_DNSSERVER,    D6_OPTION_DNS_SERVERS },
  152     { DHO_HOSTNAME,     D6_OPTION_FQDN },
  153     { DHO_DNSDOMAIN,    D6_OPTION_FQDN },
  154     { DHO_NISSERVER,    D6_OPTION_NIS_SERVERS },
  155     { DHO_NTPSERVER,    D6_OPTION_SNTP_SERVERS },
  156     { DHO_RAPIDCOMMIT,  D6_OPTION_RAPID_COMMIT },
  157     { DHO_FQDN,     D6_OPTION_FQDN },
  158     { DHO_VIVCO,        D6_OPTION_VENDOR_CLASS },
  159     { DHO_VIVSO,        D6_OPTION_VENDOR_OPTS },
  160     { DHO_DNSSEARCH,    D6_OPTION_DOMAIN_LIST },
  161     { 0, 0 }
  162 };
  163 
  164 static const char * const dhcp6_statuses[] = {
  165     "Success",
  166     "Unspecified Failure",
  167     "No Addresses Available",
  168     "No Binding",
  169     "Not On Link",
  170     "Use Multicast",
  171     "No Prefix Available"
  172 };
  173 
  174 static void dhcp6_bind(struct interface *, const char *, const char *);
  175 static void dhcp6_failinform(void *);
  176 static void dhcp6_recvaddr(void *);
  177 static void dhcp6_startdecline(struct interface *);
  178 
  179 #ifdef SMALL
  180 #define dhcp6_hasprefixdelegation(a)    (0)
  181 #else
  182 static int dhcp6_hasprefixdelegation(struct interface *);
  183 #endif
  184 
  185 #define DECLINE_IA(ia) \
  186     ((ia)->addr_flags & IN6_IFF_DUPLICATED && \
  187     (ia)->ia_type != 0 && (ia)->ia_type != D6_OPTION_IA_PD && \
  188     !((ia)->flags & IPV6_AF_STALE) && \
  189     (ia)->prefix_vltime != 0)
  190 
  191 void
  192 dhcp6_printoptions(const struct dhcpcd_ctx *ctx,
  193     const struct dhcp_opt *opts, size_t opts_len)
  194 {
  195     size_t i, j;
  196     const struct dhcp_opt *opt, *opt2;
  197     int cols;
  198 
  199     for (i = 0, opt = ctx->dhcp6_opts;
  200         i < ctx->dhcp6_opts_len; i++, opt++)
  201     {
  202         for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
  203             if (opt2->option == opt->option)
  204                 break;
  205         if (j == opts_len) {
  206             cols = printf("%05d %s", opt->option, opt->var);
  207             dhcp_print_option_encoding(opt, cols);
  208         }
  209     }
  210     for (i = 0, opt = opts; i < opts_len; i++, opt++) {
  211         cols = printf("%05d %s", opt->option, opt->var);
  212         dhcp_print_option_encoding(opt, cols);
  213     }
  214 }
  215 
  216 static size_t
  217 dhcp6_makeuser(void *data, const struct interface *ifp)
  218 {
  219     const struct if_options *ifo = ifp->options;
  220     struct dhcp6_option o;
  221     uint8_t *p;
  222     const uint8_t *up, *ue;
  223     uint16_t ulen, unlen;
  224     size_t olen;
  225 
  226     /* Convert the DHCPv4 user class option to DHCPv6 */
  227     up = ifo->userclass;
  228     ulen = *up++;
  229     if (ulen == 0)
  230         return 0;
  231 
  232     p = data;
  233     olen = 0;
  234     if (p != NULL)
  235         p += sizeof(o);
  236 
  237     ue = up + ulen;
  238     for (; up < ue; up += ulen) {
  239         ulen = *up++;
  240         olen += sizeof(ulen) + ulen;
  241         if (data == NULL)
  242             continue;
  243         unlen = htons(ulen);
  244         memcpy(p, &unlen, sizeof(unlen));
  245         p += sizeof(unlen);
  246         memcpy(p, up, ulen);
  247         p += ulen;
  248     }
  249     if (data != NULL) {
  250         o.code = htons(D6_OPTION_USER_CLASS);
  251         o.len = htons((uint16_t)olen);
  252         memcpy(data, &o, sizeof(o));
  253     }
  254 
  255     return sizeof(o) + olen;
  256 }
  257 
  258 static size_t
  259 dhcp6_makevendor(void *data, const struct interface *ifp)
  260 {
  261     const struct if_options *ifo;
  262     size_t len, vlen, i;
  263     uint8_t *p;
  264     const struct vivco *vivco;
  265     struct dhcp6_option o;
  266 
  267     ifo = ifp->options;
  268     len = sizeof(uint32_t); /* IANA PEN */
  269     if (ifo->vivco_en) {
  270         vlen = 0;
  271         for (i = 0, vivco = ifo->vivco;
  272             i < ifo->vivco_len;
  273             i++, vivco++)
  274             vlen += sizeof(uint16_t) + vivco->len;
  275         len += vlen;
  276     } else if (ifo->vendorclassid[0] != '\0') {
  277         /* dhcpcd owns DHCPCD_IANA_PEN.
  278          * If you need your own string, get your own IANA PEN. */
  279         vlen = strlen(ifp->ctx->vendor);
  280         len += sizeof(uint16_t) + vlen;
  281     } else
  282         return 0;
  283 
  284     if (len > UINT16_MAX) {
  285         logerrx("%s: DHCPv6 Vendor Class too big", ifp->name);
  286         return 0;
  287     }
  288 
  289     if (data != NULL) {
  290         uint32_t pen;
  291         uint16_t hvlen;
  292 
  293         p = data;
  294         o.code = htons(D6_OPTION_VENDOR_CLASS);
  295         o.len = htons((uint16_t)len);
  296         memcpy(p, &o, sizeof(o));
  297         p += sizeof(o);
  298         pen = htonl(ifo->vivco_en ? ifo->vivco_en : DHCPCD_IANA_PEN);
  299         memcpy(p, &pen, sizeof(pen));
  300         p += sizeof(pen);
  301 
  302         if (ifo->vivco_en) {
  303             for (i = 0, vivco = ifo->vivco;
  304                 i < ifo->vivco_len;
  305                 i++, vivco++)
  306             {
  307                 hvlen = htons((uint16_t)vivco->len);
  308                 memcpy(p, &hvlen, sizeof(hvlen));
  309                 p += sizeof(hvlen);
  310                 memcpy(p, vivco->data, vivco->len);
  311                 p += vivco->len;
  312             }
  313         } else if (ifo->vendorclassid[0] != '\0') {
  314             hvlen = htons((uint16_t)vlen);
  315             memcpy(p, &hvlen, sizeof(hvlen));
  316             p += sizeof(hvlen);
  317             memcpy(p, ifp->ctx->vendor, vlen);
  318         }
  319     }
  320 
  321     return sizeof(o) + len;
  322 }
  323 
  324 static void *
  325 dhcp6_findoption(void *data, size_t data_len, uint16_t code, uint16_t *len)
  326 {
  327     uint8_t *d;
  328     struct dhcp6_option o;
  329 
  330     code = htons(code);
  331     for (d = data; data_len != 0; d += o.len, data_len -= o.len) {
  332         if (data_len < sizeof(o)) {
  333             errno = EINVAL;
  334             return NULL;
  335         }
  336         memcpy(&o, d, sizeof(o));
  337         d += sizeof(o);
  338         data_len -= sizeof(o);
  339         o.len = htons(o.len);
  340         if (data_len < o.len) {
  341             errno = EINVAL;
  342             return NULL;
  343         }
  344         if (o.code == code) {
  345             if (len != NULL)
  346                 *len = o.len;
  347             return d;
  348         }
  349     }
  350 
  351     errno = ENOENT;
  352     return NULL;
  353 }
  354 
  355 static void *
  356 dhcp6_findmoption(void *data, size_t data_len, uint16_t code,
  357     uint16_t *len)
  358 {
  359     uint8_t *d;
  360 
  361     if (data_len < sizeof(struct dhcp6_message)) {
  362         errno = EINVAL;
  363         return false;
  364     }
  365     d = data;
  366     d += sizeof(struct dhcp6_message);
  367     data_len -= sizeof(struct dhcp6_message);
  368     return dhcp6_findoption(d, data_len, code, len);
  369 }
  370 
  371 static const uint8_t *
  372 dhcp6_getoption(struct dhcpcd_ctx *ctx,
  373     size_t *os, unsigned int *code, size_t *len,
  374     const uint8_t *od, size_t ol, struct dhcp_opt **oopt)
  375 {
  376     struct dhcp6_option o;
  377     size_t i;
  378     struct dhcp_opt *opt;
  379 
  380     if (od != NULL) {
  381         *os = sizeof(o);
  382         if (ol < *os) {
  383             errno = EINVAL;
  384             return NULL;
  385         }
  386         memcpy(&o, od, sizeof(o));
  387         *len = ntohs(o.len);
  388         if (*len > ol - *os) {
  389             errno = ERANGE;
  390             return NULL;
  391         }
  392         *code = ntohs(o.code);
  393     }
  394 
  395     *oopt = NULL;
  396     for (i = 0, opt = ctx->dhcp6_opts;
  397         i < ctx->dhcp6_opts_len; i++, opt++)
  398     {
  399         if (opt->option == *code) {
  400             *oopt = opt;
  401             break;
  402         }
  403     }
  404 
  405     if (od != NULL)
  406         return od + sizeof(o);
  407     return NULL;
  408 }
  409 
  410 static bool
  411 dhcp6_updateelapsed(struct interface *ifp, struct dhcp6_message *m, size_t len)
  412 {
  413     uint8_t *opt;
  414     uint16_t opt_len;
  415     struct dhcp6_state *state;
  416     struct timespec tv;
  417     unsigned long long hsec;
  418     uint16_t sec;
  419 
  420     opt = dhcp6_findmoption(m, len, D6_OPTION_ELAPSED, &opt_len);
  421     if (opt == NULL)
  422         return false;
  423     if (opt_len != sizeof(sec)) {
  424         errno = EINVAL;
  425         return false;
  426     }
  427 
  428     state = D6_STATE(ifp);
  429     clock_gettime(CLOCK_MONOTONIC, &tv);
  430     if (state->RTC == 0) {
  431         /* An RTC of zero means we're the first message
  432          * out of the door, so the elapsed time is zero. */
  433         state->started = tv;
  434         hsec = 0;
  435     } else {
  436         unsigned long long secs;
  437         unsigned int nsecs;
  438 
  439         secs = eloop_timespec_diff(&tv, &state->started, &nsecs);
  440         /* Elapsed time is measured in centiseconds.
  441          * We need to be sure it will not potentially overflow. */
  442         if (secs >= (UINT16_MAX / CSEC_PER_SEC) + 1)
  443             hsec = UINT16_MAX;
  444         else {
  445             hsec = (secs * CSEC_PER_SEC) +
  446                 (nsecs / NSEC_PER_CSEC);
  447             if (hsec > UINT16_MAX)
  448                 hsec = UINT16_MAX;
  449         }
  450     }
  451     sec = htons((uint16_t)hsec);
  452     memcpy(opt, &sec, sizeof(sec));
  453     return true;
  454 }
  455 
  456 static void
  457 dhcp6_newxid(const struct interface *ifp, struct dhcp6_message *m)
  458 {
  459     const struct interface *ifp1;
  460     const struct dhcp6_state *state1;
  461     uint32_t xid;
  462 
  463     if (ifp->options->options & DHCPCD_XID_HWADDR &&
  464         ifp->hwlen >= sizeof(xid))
  465         /* The lower bits are probably more unique on the network */
  466         memcpy(&xid, (ifp->hwaddr + ifp->hwlen) - sizeof(xid),
  467             sizeof(xid));
  468     else {
  469 again:
  470         xid = arc4random();
  471     }
  472 
  473     m->xid[0] = (xid >> 16) & 0xff;
  474     m->xid[1] = (xid >> 8) & 0xff;
  475     m->xid[2] = xid & 0xff;
  476 
  477     /* Ensure it's unique */
  478     TAILQ_FOREACH(ifp1, ifp->ctx->ifaces, next) {
  479         if (ifp == ifp1)
  480             continue;
  481         if ((state1 = D6_CSTATE(ifp1)) == NULL)
  482             continue;
  483         if (state1->send != NULL &&
  484             state1->send->xid[0] == m->xid[0] &&
  485             state1->send->xid[1] == m->xid[1] &&
  486             state1->send->xid[2] == m->xid[2])
  487             break;
  488     }
  489 
  490     if (ifp1 != NULL) {
  491         if (ifp->options->options & DHCPCD_XID_HWADDR &&
  492             ifp->hwlen >= sizeof(xid))
  493         {
  494             logerrx("%s: duplicate xid on %s",
  495                 ifp->name, ifp1->name);
  496                 return;
  497         }
  498         goto again;
  499     }
  500 }
  501 
  502 #ifndef SMALL
  503 static const struct if_sla *
  504 dhcp6_findselfsla(struct interface *ifp)
  505 {
  506     size_t i, j;
  507     struct if_ia *ia;
  508 
  509     for (i = 0; i < ifp->options->ia_len; i++) {
  510         ia = &ifp->options->ia[i];
  511         if (ia->ia_type != D6_OPTION_IA_PD)
  512             continue;
  513         for (j = 0; j < ia->sla_len; j++) {
  514             if (strcmp(ia->sla[j].ifname, ifp->name) == 0)
  515                 return &ia->sla[j];
  516         }
  517     }
  518     return NULL;
  519 }
  520 
  521 static int
  522 dhcp6_delegateaddr(struct in6_addr *addr, struct interface *ifp,
  523     const struct ipv6_addr *prefix, const struct if_sla *sla, struct if_ia *ia)
  524 {
  525     struct dhcp6_state *state;
  526     struct if_sla asla;
  527     char sabuf[INET6_ADDRSTRLEN];
  528     const char *sa;
  529 
  530     state = D6_STATE(ifp);
  531     if (state == NULL) {
  532         ifp->if_data[IF_DATA_DHCP6] = calloc(1, sizeof(*state));
  533         state = D6_STATE(ifp);
  534         if (state == NULL) {
  535             logerr(__func__);
  536             return -1;
  537         }
  538 
  539         TAILQ_INIT(&state->addrs);
  540         state->state = DH6S_DELEGATED;
  541         state->reason = "DELEGATED6";
  542     }
  543 
  544     if (sla == NULL || !sla->sla_set) {
  545         /* No SLA set, so make an assumption of
  546          * desired SLA and prefix length. */
  547         asla.sla = ifp->index;
  548         asla.prefix_len = 0;
  549         asla.sla_set = false;
  550         sla = &asla;
  551     } else if (sla->prefix_len == 0) {
  552         /* An SLA was given, but prefix length was not.
  553          * We need to work out a suitable prefix length for
  554          * potentially more than one interface. */
  555         asla.sla = sla->sla;
  556         asla.prefix_len = 0;
  557         asla.sla_set = sla->sla_set;
  558         sla = &asla;
  559     }
  560 
  561     if (sla->prefix_len == 0) {
  562         uint32_t sla_max;
  563         int bits;
  564 
  565         sla_max = ia->sla_max;
  566         if (sla_max == 0 && (sla == NULL || !sla->sla_set)) {
  567             const struct interface *ifi;
  568 
  569             TAILQ_FOREACH(ifi, ifp->ctx->ifaces, next) {
  570                 if (ifi->index > sla_max)
  571                     sla_max = ifi->index;
  572             }
  573         }
  574 
  575         bits = fls32(sla_max);
  576 
  577         if (prefix->prefix_len + bits > (int)UINT8_MAX)
  578             asla.prefix_len = UINT8_MAX;
  579         else {
  580             asla.prefix_len = (uint8_t)(prefix->prefix_len + bits);
  581 
  582             /* Make a 64 prefix by default, as this makes SLAAC
  583              * possible.
  584              * Otherwise round up to the nearest 4 bits. */
  585             if (asla.prefix_len <= 64)
  586                 asla.prefix_len = 64;
  587             else
  588                 asla.prefix_len =
  589                     (uint8_t)ROUNDUP4(asla.prefix_len);
  590         }
  591 
  592 #define BIT(n) (1UL << (n))
  593 #define BIT_MASK(len) (BIT(len) - 1)
  594         if (ia->sla_max == 0) {
  595             /* Work out the real sla_max from our bits used */
  596             bits = asla.prefix_len - prefix->prefix_len;
  597             /* Make static analysis happy.
  598              * Bits cannot be bigger than 32 thanks to fls32. */
  599             assert(bits <= 32);
  600             ia->sla_max = (uint32_t)BIT_MASK(bits);
  601         }
  602     }
  603 
  604     if (ipv6_userprefix(&prefix->prefix, prefix->prefix_len,
  605         sla->sla, addr, sla->prefix_len) == -1)
  606     {
  607         sa = inet_ntop(AF_INET6, &prefix->prefix,
  608             sabuf, sizeof(sabuf));
  609         logerr("%s: invalid prefix %s/%d + %d/%d",
  610             ifp->name, sa, prefix->prefix_len,
  611             sla->sla, sla->prefix_len);
  612         return -1;
  613     }
  614 
  615     if (prefix->prefix_exclude_len &&
  616         IN6_ARE_ADDR_EQUAL(addr, &prefix->prefix_exclude))
  617     {
  618         sa = inet_ntop(AF_INET6, &prefix->prefix_exclude,
  619             sabuf, sizeof(sabuf));
  620         logerrx("%s: cannot delegate excluded prefix %s/%d",
  621             ifp->name, sa, prefix->prefix_exclude_len);
  622         return -1;
  623     }
  624 
  625     return sla->prefix_len;
  626 }
  627 #endif
  628 
  629 static int
  630 dhcp6_makemessage(struct interface *ifp)
  631 {
  632     struct dhcp6_state *state;
  633     struct dhcp6_message *m;
  634     struct dhcp6_option o;
  635     uint8_t *p, *si, *unicast, IA;
  636     size_t n, l, len, ml, hl;
  637     uint8_t type;
  638     uint16_t si_len, uni_len, n_options;
  639     uint8_t *o_lenp;
  640     struct if_options *ifo = ifp->options;
  641     const struct dhcp_opt *opt, *opt2;
  642     const struct ipv6_addr *ap;
  643     char hbuf[HOSTNAME_MAX_LEN + 1];
  644     const char *hostname;
  645     int fqdn;
  646     struct dhcp6_ia_na ia_na;
  647     uint16_t ia_na_len;
  648     struct if_ia *ifia;
  649 #ifdef AUTH
  650     uint16_t auth_len;
  651 #endif
  652     uint8_t duid[DUID_LEN];
  653     size_t duid_len = 0;
  654 
  655     state = D6_STATE(ifp);
  656     if (state->send) {
  657         free(state->send);
  658         state->send = NULL;
  659     }
  660 
  661     switch(state->state) {
  662     case DH6S_INIT: /* FALLTHROUGH */
  663     case DH6S_DISCOVER:
  664         type = DHCP6_SOLICIT;
  665         break;
  666     case DH6S_REQUEST:
  667         type = DHCP6_REQUEST;
  668         break;
  669     case DH6S_CONFIRM:
  670         type = DHCP6_CONFIRM;
  671         break;
  672     case DH6S_REBIND:
  673         type = DHCP6_REBIND;
  674         break;
  675     case DH6S_RENEW:
  676         type = DHCP6_RENEW;
  677         break;
  678     case DH6S_INFORM:
  679         type = DHCP6_INFORMATION_REQ;
  680         break;
  681     case DH6S_RELEASE:
  682         type = DHCP6_RELEASE;
  683         break;
  684     case DH6S_DECLINE:
  685         type = DHCP6_DECLINE;
  686         break;
  687     default:
  688         errno = EINVAL;
  689         return -1;
  690     }
  691 
  692     /* RFC 4704 Section 5 says we can only send FQDN for these
  693      * message types. */
  694     switch(type) {
  695     case DHCP6_SOLICIT:
  696     case DHCP6_REQUEST:
  697     case DHCP6_RENEW:
  698     case DHCP6_REBIND:
  699         fqdn = ifo->fqdn;
  700         break;
  701     default:
  702         fqdn = FQDN_DISABLE;
  703         break;
  704     }
  705 
  706     if (fqdn == FQDN_DISABLE && ifo->options & DHCPCD_HOSTNAME) {
  707         /* We're sending the DHCPv4 hostname option, so send FQDN as
  708          * DHCPv6 has no FQDN option and DHCPv4 must not send
  709          * hostname and FQDN according to RFC4702 */
  710         fqdn = FQDN_BOTH;
  711     }
  712     if (fqdn != FQDN_DISABLE)
  713         hostname = dhcp_get_hostname(hbuf, sizeof(hbuf), ifo);
  714     else
  715         hostname = NULL; /* appearse gcc */
  716 
  717     /* Work out option size first */
  718     n_options = 0;
  719     len = 0;
  720     si = NULL;
  721     hl = 0; /* Appease gcc */
  722     if (state->state != DH6S_RELEASE && state->state != DH6S_DECLINE) {
  723         for (l = 0, opt = ifp->ctx->dhcp6_opts;
  724             l < ifp->ctx->dhcp6_opts_len;
  725             l++, opt++)
  726         {
  727             for (n = 0, opt2 = ifo->dhcp6_override;
  728                 n < ifo->dhcp6_override_len;
  729                 n++, opt2++)
  730             {
  731                 if (opt->option == opt2->option)
  732                     break;
  733             }
  734             if (n < ifo->dhcp6_override_len)
  735                 continue;
  736             if (!DHC_REQOPT(opt, ifo->requestmask6, ifo->nomask6))
  737                 continue;
  738             n_options++;
  739             len += sizeof(o.len);
  740         }
  741 #ifndef SMALL
  742         for (l = 0, opt = ifo->dhcp6_override;
  743             l < ifo->dhcp6_override_len;
  744             l++, opt++)
  745         {
  746             if (!DHC_REQOPT(opt, ifo->requestmask6, ifo->nomask6))
  747                 continue;
  748             n_options++;
  749             len += sizeof(o.len);
  750         }
  751         if (dhcp6_findselfsla(ifp)) {
  752             n_options++;
  753             len += sizeof(o.len);
  754         }
  755 #endif
  756         if (len)
  757             len += sizeof(o);
  758 
  759         if (fqdn != FQDN_DISABLE) {
  760             hl = encode_rfc1035(hostname, NULL);
  761             len += sizeof(o) + 1 + hl;
  762         }
  763 
  764         if (!has_option_mask(ifo->nomask6, D6_OPTION_MUDURL) &&
  765             ifo->mudurl[0])
  766             len += sizeof(o) + ifo->mudurl[0];
  767 
  768 #ifdef AUTH
  769         if ((ifo->auth.options & DHCPCD_AUTH_SENDREQUIRE) !=
  770             DHCPCD_AUTH_SENDREQUIRE &&
  771             DHC_REQ(ifo->requestmask6, ifo->nomask6,
  772             D6_OPTION_RECONF_ACCEPT))
  773             len += sizeof(o); /* Reconfigure Accept */
  774 #endif
  775     }
  776 
  777     len += sizeof(*state->send);
  778     len += sizeof(o) + sizeof(uint16_t); /* elapsed */
  779 
  780     if (ifo->options & DHCPCD_ANONYMOUS) {
  781         duid_len = duid_make(duid, ifp, DUID_LL);
  782         len += sizeof(o) + duid_len;
  783     } else {
  784         len += sizeof(o) + ifp->ctx->duid_len;
  785     }
  786 
  787     if (!has_option_mask(ifo->nomask6, D6_OPTION_USER_CLASS))
  788         len += dhcp6_makeuser(NULL, ifp);
  789     if (!has_option_mask(ifo->nomask6, D6_OPTION_VENDOR_CLASS))
  790         len += dhcp6_makevendor(NULL, ifp);
  791 
  792     /* IA */
  793     m = NULL;
  794     ml = 0;
  795     switch(state->state) {
  796     case DH6S_REQUEST:
  797         m = state->recv;
  798         ml = state->recv_len;
  799         /* FALLTHROUGH */
  800     case DH6S_DECLINE:
  801         /* FALLTHROUGH */
  802     case DH6S_RELEASE:
  803         /* FALLTHROUGH */
  804     case DH6S_RENEW:
  805         if (m == NULL) {
  806             m = state->new;
  807             ml = state->new_len;
  808         }
  809         si = dhcp6_findmoption(m, ml, D6_OPTION_SERVERID, &si_len);
  810         if (si == NULL)
  811             return -1;
  812         len += sizeof(o) + si_len;
  813         /* FALLTHROUGH */
  814     case DH6S_REBIND:
  815         /* FALLTHROUGH */
  816     case DH6S_CONFIRM:
  817         /* FALLTHROUGH */
  818     case DH6S_DISCOVER:
  819         if (m == NULL) {
  820             m = state->new;
  821             ml = state->new_len;
  822         }
  823         TAILQ_FOREACH(ap, &state->addrs, next) {
  824             if (ap->flags & IPV6_AF_STALE)
  825                 continue;
  826             if (!(ap->flags & IPV6_AF_REQUEST) &&
  827                 (ap->prefix_vltime == 0 ||
  828                 state->state == DH6S_DISCOVER))
  829                 continue;
  830             if (DECLINE_IA(ap) && state->state != DH6S_DECLINE)
  831                 continue;
  832             if (ap->ia_type == D6_OPTION_IA_PD) {
  833 #ifndef SMALL
  834                 len += sizeof(o) + sizeof(struct dhcp6_pd_addr);
  835                 if (ap->prefix_exclude_len)
  836                     len += sizeof(o) + 1 +
  837                         (uint8_t)((ap->prefix_exclude_len -
  838                         ap->prefix_len - 1) / NBBY) + 1;
  839 #endif
  840             } else
  841                 len += sizeof(o) + sizeof(struct dhcp6_ia_addr);
  842         }
  843         /* FALLTHROUGH */
  844     case DH6S_INIT:
  845         for (l = 0; l < ifo->ia_len; l++) {
  846             len += sizeof(o) + sizeof(uint32_t); /* IAID */
  847             /* IA_TA does not have T1 or T2 timers */
  848             if (ifo->ia[l].ia_type != D6_OPTION_IA_TA)
  849                 len += sizeof(uint32_t) + sizeof(uint32_t);
  850         }
  851         IA = 1;
  852         break;
  853     default:
  854         IA = 0;
  855     }
  856 
  857     if (state->state == DH6S_DISCOVER &&
  858         !(ifp->ctx->options & DHCPCD_TEST) &&
  859         DHC_REQ(ifo->requestmask6, ifo->nomask6, D6_OPTION_RAPID_COMMIT))
  860         len += sizeof(o);
  861 
  862     if (m == NULL) {
  863         m = state->new;
  864         ml = state->new_len;
  865     }
  866 
  867     switch(state->state) {
  868     case DH6S_REQUEST: /* FALLTHROUGH */
  869     case DH6S_RENEW:   /* FALLTHROUGH */
  870     case DH6S_RELEASE:
  871         if (has_option_mask(ifo->nomask6, D6_OPTION_UNICAST)) {
  872             unicast = NULL;
  873             break;
  874         }
  875         unicast = dhcp6_findmoption(m, ml, D6_OPTION_UNICAST, &uni_len);
  876         break;
  877     default:
  878         unicast = NULL;
  879         break;
  880     }
  881 
  882     /* In non manager mode we listen and send from fixed addresses.
  883      * We should try and match an address we have to unicast to,
  884      * but for now this is the safest policy. */
  885     if (unicast != NULL && !(ifp->ctx->options & DHCPCD_MANAGER)) {
  886         logdebugx("%s: ignoring unicast option as not manager",
  887             ifp->name);
  888         unicast = NULL;
  889     }
  890 
  891 #ifdef AUTH
  892     auth_len = 0;
  893     if (ifo->auth.options & DHCPCD_AUTH_SEND) {
  894         ssize_t alen = dhcp_auth_encode(ifp->ctx, &ifo->auth,
  895             state->auth.token, NULL, 0, 6, type, NULL, 0);
  896         if (alen != -1 && alen > UINT16_MAX) {
  897             errno = ERANGE;
  898             alen = -1;
  899         }
  900         if (alen == -1)
  901             logerr("%s: %s: dhcp_auth_encode", __func__, ifp->name);
  902         else if (alen != 0) {
  903             auth_len = (uint16_t)alen;
  904             len += sizeof(o) + auth_len;
  905         }
  906     }
  907 #endif
  908 
  909     state->send = malloc(len);
  910     if (state->send == NULL)
  911         return -1;
  912 
  913     state->send_len = len;
  914     state->send->type = type;
  915 
  916     /* If we found a unicast option, copy it to our state for sending */
  917     if (unicast && uni_len == sizeof(state->unicast))
  918         memcpy(&state->unicast, unicast, sizeof(state->unicast));
  919     else
  920         state->unicast = in6addr_any;
  921 
  922     dhcp6_newxid(ifp, state->send);
  923 
  924 #define COPYIN1(_code, _len)        {   \
  925     o.code = htons((_code));        \
  926     o.len = htons((_len));          \
  927     memcpy(p, &o, sizeof(o));       \
  928     p += sizeof(o);             \
  929 }
  930 #define COPYIN(_code, _data, _len)  do {    \
  931     COPYIN1((_code), (_len));       \
  932     if ((_len) != 0) {          \
  933         memcpy(p, (_data), (_len)); \
  934         p += (_len);            \
  935     }                   \
  936 } while (0 /* CONSTCOND */)
  937 #define NEXTLEN (p + offsetof(struct dhcp6_option, len))
  938 
  939     /* Options are listed in numerical order as per RFC 7844 Section 4.1
  940      * XXX: They should be randomised. */
  941 
  942     p = (uint8_t *)state->send + sizeof(*state->send);
  943     if (ifo->options & DHCPCD_ANONYMOUS)
  944         COPYIN(D6_OPTION_CLIENTID, duid,
  945             (uint16_t)duid_len);
  946     else
  947         COPYIN(D6_OPTION_CLIENTID, ifp->ctx->duid,
  948             (uint16_t)ifp->ctx->duid_len);
  949 
  950     if (si != NULL)
  951         COPYIN(D6_OPTION_SERVERID, si, si_len);
  952 
  953     for (l = 0; IA && l < ifo->ia_len; l++) {
  954         ifia = &ifo->ia[l];
  955         o_lenp = NEXTLEN;
  956         /* TA structure is the same as the others,
  957          * it just lacks the T1 and T2 timers.
  958          * These happen to be at the end of the struct,
  959          * so we just don't copy them in. */
  960         if (ifia->ia_type == D6_OPTION_IA_TA)
  961             ia_na_len = sizeof(struct dhcp6_ia_ta);
  962         else
  963             ia_na_len = sizeof(ia_na);
  964         memcpy(ia_na.iaid, ifia->iaid, sizeof(ia_na.iaid));
  965         ia_na.t1 = 0;
  966         ia_na.t2 = 0;
  967         COPYIN(ifia->ia_type, &ia_na, ia_na_len);
  968         TAILQ_FOREACH(ap, &state->addrs, next) {
  969             if (ap->flags & IPV6_AF_STALE)
  970                 continue;
  971             if (!(ap->flags & IPV6_AF_REQUEST) &&
  972                 (ap->prefix_vltime == 0 ||
  973                 state->state == DH6S_DISCOVER))
  974                 continue;
  975             if (DECLINE_IA(ap) && state->state != DH6S_DECLINE)
  976                 continue;
  977             if (ap->ia_type != ifia->ia_type)
  978                 continue;
  979             if (memcmp(ap->iaid, ifia->iaid, sizeof(ap->iaid)))
  980                 continue;
  981             if (ap->ia_type == D6_OPTION_IA_PD) {
  982 #ifndef SMALL
  983                 struct dhcp6_pd_addr pdp;
  984 
  985                 pdp.pltime = htonl(ap->prefix_pltime);
  986                 pdp.vltime = htonl(ap->prefix_vltime);
  987                 pdp.prefix_len = ap->prefix_len;
  988                 /* pdp.prefix is not aligned, so copy it in. */
  989                 memcpy(&pdp.prefix, &ap->prefix, sizeof(pdp.prefix));
  990                 COPYIN(D6_OPTION_IAPREFIX, &pdp, sizeof(pdp));
  991                 ia_na_len = (uint16_t)
  992                     (ia_na_len + sizeof(o) + sizeof(pdp));
  993 
  994                 /* RFC6603 Section 4.2 */
  995                 if (ap->prefix_exclude_len) {
  996                     uint8_t exb[16], *ep, u8;
  997                     const uint8_t *pp;
  998 
  999                     n = (size_t)((ap->prefix_exclude_len -
 1000                         ap->prefix_len - 1) / NBBY) + 1;
 1001                     ep = exb;
 1002                     *ep++ = (uint8_t)ap->prefix_exclude_len;
 1003                     pp = ap->prefix_exclude.s6_addr;
 1004                     pp += (size_t)
 1005                         ((ap->prefix_len - 1) / NBBY) +
 1006                         (n - 1);
 1007                     u8 = ap->prefix_len % NBBY;
 1008                     if (u8)
 1009                         n--;
 1010                     while (n-- > 0)
 1011                         *ep++ = *pp--;
 1012                     if (u8)
 1013                         *ep = (uint8_t)(*pp << u8);
 1014                     n++;
 1015                     COPYIN(D6_OPTION_PD_EXCLUDE, exb,
 1016                         (uint16_t)n);
 1017                     ia_na_len = (uint16_t)
 1018                         (ia_na_len + sizeof(o) + n);
 1019                 }
 1020 #endif
 1021             } else {
 1022                 struct dhcp6_ia_addr ia;
 1023 
 1024                 ia.addr = ap->addr;
 1025                 ia.pltime = htonl(ap->prefix_pltime);
 1026                 ia.vltime = htonl(ap->prefix_vltime);
 1027                 COPYIN(D6_OPTION_IA_ADDR, &ia, sizeof(ia));
 1028                 ia_na_len = (uint16_t)
 1029                     (ia_na_len + sizeof(o) + sizeof(ia));
 1030             }
 1031         }
 1032 
 1033         /* Update the total option lenth. */
 1034         ia_na_len = htons(ia_na_len);
 1035         memcpy(o_lenp, &ia_na_len, sizeof(ia_na_len));
 1036     }
 1037 
 1038     if (state->send->type != DHCP6_RELEASE &&
 1039         state->send->type != DHCP6_DECLINE &&
 1040         n_options)
 1041     {
 1042         o_lenp = NEXTLEN;
 1043         o.len = 0;
 1044         COPYIN1(D6_OPTION_ORO, 0);
 1045         for (l = 0, opt = ifp->ctx->dhcp6_opts;
 1046             l < ifp->ctx->dhcp6_opts_len;
 1047             l++, opt++)
 1048         {
 1049 #ifndef SMALL
 1050             for (n = 0, opt2 = ifo->dhcp6_override;
 1051                 n < ifo->dhcp6_override_len;
 1052                 n++, opt2++)
 1053             {
 1054                 if (opt->option == opt2->option)
 1055                     break;
 1056             }
 1057             if (n < ifo->dhcp6_override_len)
 1058                 continue;
 1059 #endif
 1060             if (!DHC_REQOPT(opt, ifo->requestmask6, ifo->nomask6))
 1061                 continue;
 1062             o.code = htons((uint16_t)opt->option);
 1063             memcpy(p, &o.code, sizeof(o.code));
 1064             p += sizeof(o.code);
 1065             o.len = (uint16_t)(o.len + sizeof(o.code));
 1066         }
 1067 #ifndef SMALL
 1068         for (l = 0, opt = ifo->dhcp6_override;
 1069             l < ifo->dhcp6_override_len;
 1070             l++, opt++)
 1071         {
 1072             if (!DHC_REQOPT(opt, ifo->requestmask6, ifo->nomask6))
 1073                 continue;
 1074             o.code = htons((uint16_t)opt->option);
 1075             memcpy(p, &o.code, sizeof(o.code));
 1076             p += sizeof(o.code);
 1077             o.len = (uint16_t)(o.len + sizeof(o.code));
 1078         }
 1079         if (dhcp6_findselfsla(ifp)) {
 1080             o.code = htons(D6_OPTION_PD_EXCLUDE);
 1081             memcpy(p, &o.code, sizeof(o.code));
 1082             p += sizeof(o.code);
 1083             o.len = (uint16_t)(o.len + sizeof(o.code));
 1084         }
 1085 #endif
 1086         o.len = htons(o.len);
 1087         memcpy(o_lenp, &o.len, sizeof(o.len));
 1088     }
 1089 
 1090     si_len = 0;
 1091     COPYIN(D6_OPTION_ELAPSED, &si_len, sizeof(si_len));
 1092 
 1093     if (state->state == DH6S_DISCOVER &&
 1094         !(ifp->ctx->options & DHCPCD_TEST) &&
 1095         DHC_REQ(ifo->requestmask6, ifo->nomask6, D6_OPTION_RAPID_COMMIT))
 1096         COPYIN1(D6_OPTION_RAPID_COMMIT, 0);
 1097 
 1098     if (!has_option_mask(ifo->nomask6, D6_OPTION_USER_CLASS))
 1099         p += dhcp6_makeuser(p, ifp);
 1100     if (!has_option_mask(ifo->nomask6, D6_OPTION_VENDOR_CLASS))
 1101         p += dhcp6_makevendor(p, ifp);
 1102 
 1103     if (state->send->type != DHCP6_RELEASE &&
 1104         state->send->type != DHCP6_DECLINE)
 1105     {
 1106         if (fqdn != FQDN_DISABLE) {
 1107             o_lenp = NEXTLEN;
 1108             COPYIN1(D6_OPTION_FQDN, 0);
 1109             if (hl == 0)
 1110                 *p = D6_FQDN_NONE;
 1111             else {
 1112                 switch (fqdn) {
 1113                 case FQDN_BOTH:
 1114                     *p = D6_FQDN_BOTH;
 1115                     break;
 1116                 case FQDN_PTR:
 1117                     *p = D6_FQDN_PTR;
 1118                     break;
 1119                 default:
 1120                     *p = D6_FQDN_NONE;
 1121                     break;
 1122                 }
 1123             }
 1124             p++;
 1125             encode_rfc1035(hostname, p);
 1126             p += hl;
 1127             o.len = htons((uint16_t)(hl + 1));
 1128             memcpy(o_lenp, &o.len, sizeof(o.len));
 1129         }
 1130 
 1131         if (!has_option_mask(ifo->nomask6, D6_OPTION_MUDURL) &&
 1132             ifo->mudurl[0])
 1133             COPYIN(D6_OPTION_MUDURL,
 1134                 ifo->mudurl + 1, ifo->mudurl[0]);
 1135 
 1136 #ifdef AUTH
 1137         if ((ifo->auth.options & DHCPCD_AUTH_SENDREQUIRE) !=
 1138             DHCPCD_AUTH_SENDREQUIRE &&
 1139             DHC_REQ(ifo->requestmask6, ifo->nomask6,
 1140             D6_OPTION_RECONF_ACCEPT))
 1141             COPYIN1(D6_OPTION_RECONF_ACCEPT, 0);
 1142 #endif
 1143 
 1144     }
 1145 
 1146 #ifdef AUTH
 1147     /* This has to be the last option */
 1148     if (ifo->auth.options & DHCPCD_AUTH_SEND && auth_len != 0) {
 1149         COPYIN1(D6_OPTION_AUTH, auth_len);
 1150         /* data will be filled at send message time */
 1151     }
 1152 #endif
 1153 
 1154     return 0;
 1155 }
 1156 
 1157 static const char *
 1158 dhcp6_get_op(uint16_t type)
 1159 {
 1160     const struct dhcp6_op *d;
 1161 
 1162     for (d = dhcp6_ops; d->name; d++)
 1163         if (d->type == type)
 1164             return d->name;
 1165     return NULL;
 1166 }
 1167 
 1168 static void
 1169 dhcp6_freedrop_addrs(struct interface *ifp, int drop,
 1170     const struct interface *ifd)
 1171 {
 1172     struct dhcp6_state *state;
 1173 
 1174     state = D6_STATE(ifp);
 1175     if (state) {
 1176         ipv6_freedrop_addrs(&state->addrs, drop, ifd);
 1177         if (drop)
 1178             rt_build(ifp->ctx, AF_INET6);
 1179     }
 1180 }
 1181 
 1182 #ifndef SMALL
 1183 static void dhcp6_delete_delegates(struct interface *ifp)
 1184 {
 1185     struct interface *ifp0;
 1186 
 1187     if (ifp->ctx->ifaces) {
 1188         TAILQ_FOREACH(ifp0, ifp->ctx->ifaces, next) {
 1189             if (ifp0 != ifp)
 1190                 dhcp6_freedrop_addrs(ifp0, 1, ifp);
 1191         }
 1192     }
 1193 }
 1194 #endif
 1195 
 1196 #ifdef AUTH
 1197 static ssize_t
 1198 dhcp6_update_auth(struct interface *ifp, struct dhcp6_message *m, size_t len)
 1199 {
 1200     struct dhcp6_state *state;
 1201     uint8_t *opt;
 1202     uint16_t opt_len;
 1203 
 1204     opt = dhcp6_findmoption(m, len, D6_OPTION_AUTH, &opt_len);
 1205     if (opt == NULL)
 1206         return -1;
 1207 
 1208     state = D6_STATE(ifp);
 1209     return dhcp_auth_encode(ifp->ctx, &ifp->options->auth,
 1210         state->auth.token, (uint8_t *)state->send, state->send_len, 6,
 1211         state->send->type, opt, opt_len);
 1212 }
 1213 #endif
 1214 
 1215 static const struct in6_addr alldhcp = IN6ADDR_LINKLOCAL_ALLDHCP_INIT;
 1216 static int
 1217 dhcp6_sendmessage(struct interface *ifp, void (*callback)(void *))
 1218 {
 1219     struct dhcp6_state *state = D6_STATE(ifp);
 1220     struct dhcpcd_ctx *ctx = ifp->ctx;
 1221     unsigned int RT;
 1222     bool broadcast = true;
 1223     struct sockaddr_in6 dst = {
 1224         .sin6_family = AF_INET6,
 1225         /* Setting the port on Linux gives EINVAL when sending.
 1226          * This looks like a kernel bug as the equivalent works
 1227          * fine with the DHCP counterpart. */
 1228 #ifndef __linux__
 1229         .sin6_port = htons(DHCP6_SERVER_PORT),
 1230 #endif
 1231     };
 1232     struct udphdr udp = {
 1233         .uh_sport = htons(DHCP6_CLIENT_PORT),
 1234         .uh_dport = htons(DHCP6_SERVER_PORT),
 1235         .uh_ulen = htons((uint16_t)(sizeof(udp) + state->send_len)),
 1236     };
 1237     struct iovec iov[] = {
 1238         { .iov_base = &udp, .iov_len = sizeof(udp), },
 1239         { .iov_base = state->send, .iov_len = state->send_len, },
 1240     };
 1241     union {
 1242         struct cmsghdr hdr;
 1243         uint8_t buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
 1244     } cmsgbuf = { .buf = { 0 } };
 1245     struct msghdr msg = {
 1246         .msg_name = &dst, .msg_namelen = sizeof(dst),
 1247         .msg_iov = iov, .msg_iovlen = __arraycount(iov),
 1248     };
 1249     char uaddr[INET6_ADDRSTRLEN];
 1250 
 1251     if (!callback && !if_is_link_up(ifp))
 1252         return 0;
 1253 
 1254     if (!IN6_IS_ADDR_UNSPECIFIED(&state->unicast)) {
 1255         switch (state->send->type) {
 1256         case DHCP6_SOLICIT: /* FALLTHROUGH */
 1257         case DHCP6_CONFIRM: /* FALLTHROUGH */
 1258         case DHCP6_REBIND:
 1259             /* Unicasting is denied for these types. */
 1260             break;
 1261         default:
 1262             broadcast = false;
 1263             inet_ntop(AF_INET6, &state->unicast, uaddr,
 1264                 sizeof(uaddr));
 1265             break;
 1266         }
 1267     }
 1268     dst.sin6_addr = broadcast ? alldhcp : state->unicast;
 1269 
 1270     if (!callback) {
 1271         logdebugx("%s: %s %s with xid 0x%02x%02x%02x%s%s",
 1272             ifp->name,
 1273             broadcast ? "broadcasting" : "unicasting",
 1274             dhcp6_get_op(state->send->type),
 1275             state->send->xid[0],
 1276             state->send->xid[1],
 1277             state->send->xid[2],
 1278             !broadcast ? " " : "",
 1279             !broadcast ? uaddr : "");
 1280         RT = 0;
 1281     } else {
 1282         if (state->IMD &&
 1283             !(ifp->options->options & DHCPCD_INITIAL_DELAY))
 1284             state->IMD = 0;
 1285         if (state->IMD) {
 1286             state->RT = state->IMD * MSEC_PER_SEC;
 1287             /* Some buggy PPP servers close the link too early
 1288              * after sending an invalid status in their reply
 1289              * which means this host won't see it.
 1290              * 1 second grace seems to be the sweet spot. */
 1291             if (ifp->flags & IFF_POINTOPOINT)
 1292                 state->RT += MSEC_PER_SEC;
 1293         } else if (state->RTC == 0)
 1294             state->RT = state->IRT * MSEC_PER_SEC;
 1295 
 1296         if (state->MRT != 0) {
 1297             unsigned int mrt = state->MRT * MSEC_PER_SEC;
 1298 
 1299             if (state->RT > mrt)
 1300                 state->RT = mrt;
 1301         }
 1302 
 1303         /* Add -.1 to .1 * RT randomness as per RFC8415 section 15 */
 1304         uint32_t lru = arc4random_uniform(
 1305             state->RTC == 0 ? DHCP6_RAND_MAX
 1306             : DHCP6_RAND_MAX - DHCP6_RAND_MIN);
 1307         int lr = (int)lru - (state->RTC == 0 ? 0 : DHCP6_RAND_MAX);
 1308         RT = state->RT
 1309             + (unsigned int)((float)state->RT
 1310             * ((float)lr / DHCP6_RAND_DIV));
 1311 
 1312         if (if_is_link_up(ifp))
 1313             logdebugx("%s: %s %s (xid 0x%02x%02x%02x)%s%s,"
 1314                 " next in %0.1f seconds",
 1315                 ifp->name,
 1316                 state->IMD != 0 ? "delaying" :
 1317                 broadcast ? "broadcasting" : "unicasting",
 1318                 dhcp6_get_op(state->send->type),
 1319                 state->send->xid[0],
 1320                 state->send->xid[1],
 1321                 state->send->xid[2],
 1322                 state->IMD == 0 && !broadcast ? " " : "",
 1323                 state->IMD == 0 && !broadcast ? uaddr : "",
 1324                 (float)RT / MSEC_PER_SEC);
 1325 
 1326         /* Wait the initial delay */
 1327         if (state->IMD != 0) {
 1328             state->IMD = 0;
 1329             eloop_timeout_add_msec(ctx->eloop, RT, callback, ifp);
 1330             return 0;
 1331         }
 1332     }
 1333 
 1334     if (!if_is_link_up(ifp))
 1335         return 0;
 1336 
 1337     /* Update the elapsed time */
 1338     dhcp6_updateelapsed(ifp, state->send, state->send_len);
 1339 #ifdef AUTH
 1340     if (ifp->options->auth.options & DHCPCD_AUTH_SEND &&
 1341         dhcp6_update_auth(ifp, state->send, state->send_len) == -1)
 1342     {
 1343         logerr("%s: %s: dhcp6_updateauth", __func__, ifp->name);
 1344         if (errno != ESRCH)
 1345             return -1;
 1346     }
 1347 #endif
 1348 
 1349     /* Set the outbound interface */
 1350     if (broadcast) {
 1351         struct cmsghdr *cm;
 1352         struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
 1353 
 1354         dst.sin6_scope_id = ifp->index;
 1355         msg.msg_control = cmsgbuf.buf;
 1356         msg.msg_controllen = sizeof(cmsgbuf.buf);
 1357         cm = CMSG_FIRSTHDR(&msg);
 1358         if (cm == NULL) /* unlikely */
 1359             return -1;
 1360         cm->cmsg_level = IPPROTO_IPV6;
 1361         cm->cmsg_type = IPV6_PKTINFO;
 1362         cm->cmsg_len = CMSG_LEN(sizeof(pi));
 1363         memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
 1364     }
 1365 
 1366 #ifdef PRIVSEP
 1367     if (IN_PRIVSEP(ifp->ctx)) {
 1368         if (ps_inet_senddhcp6(ifp, &msg) == -1)
 1369             logerr(__func__);
 1370         goto sent;
 1371     }
 1372 #endif
 1373 
 1374     if (sendmsg(ctx->dhcp6_wfd, &msg, 0) == -1) {
 1375         logerr("%s: %s: sendmsg", __func__, ifp->name);
 1376         /* Allow DHCPv6 to continue .... the errors
 1377          * would be rate limited by the protocol.
 1378          * Generally the error is ENOBUFS when struggling to
 1379          * associate with an access point. */
 1380     }
 1381 
 1382 #ifdef PRIVSEP
 1383 sent:
 1384 #endif
 1385     state->RTC++;
 1386     if (callback) {
 1387         state->RT = RT * 2;
 1388         if (state->RT < RT) /* Check overflow */
 1389             state->RT = RT;
 1390         if (state->MRC == 0 || state->RTC < state->MRC)
 1391             eloop_timeout_add_msec(ctx->eloop,
 1392                 RT, callback, ifp);
 1393         else if (state->MRC != 0 && state->MRCcallback)
 1394             eloop_timeout_add_msec(ctx->eloop,
 1395                 RT, state->MRCcallback, ifp);
 1396         else
 1397             logwarnx("%s: sent %d times with no reply",
 1398                 ifp->name, state->RTC);
 1399     }
 1400     return 0;
 1401 }
 1402 
 1403 static void
 1404 dhcp6_sendinform(void *arg)
 1405 {
 1406 
 1407     dhcp6_sendmessage(arg, dhcp6_sendinform);
 1408 }
 1409 
 1410 static void
 1411 dhcp6_senddiscover(void *arg)
 1412 {
 1413 
 1414     dhcp6_sendmessage(arg, dhcp6_senddiscover);
 1415 }
 1416 
 1417 static void
 1418 dhcp6_sendrequest(void *arg)
 1419 {
 1420 
 1421     dhcp6_sendmessage(arg, dhcp6_sendrequest);
 1422 }
 1423 
 1424 static void
 1425 dhcp6_sendrebind(void *arg)
 1426 {
 1427 
 1428     dhcp6_sendmessage(arg, dhcp6_sendrebind);
 1429 }
 1430 
 1431 static void
 1432 dhcp6_sendrenew(void *arg)
 1433 {
 1434 
 1435     dhcp6_sendmessage(arg, dhcp6_sendrenew);
 1436 }
 1437 
 1438 static void
 1439 dhcp6_sendconfirm(void *arg)
 1440 {
 1441 
 1442     dhcp6_sendmessage(arg, dhcp6_sendconfirm);
 1443 }
 1444 
 1445 static void
 1446 dhcp6_senddecline(void *arg)
 1447 {
 1448 
 1449     dhcp6_sendmessage(arg, dhcp6_senddecline);
 1450 }
 1451 
 1452 static void
 1453 dhcp6_sendrelease(void *arg)
 1454 {
 1455 
 1456     dhcp6_sendmessage(arg, dhcp6_sendrelease);
 1457 }
 1458 
 1459 static void
 1460 dhcp6_startrenew(void *arg)
 1461 {
 1462     struct interface *ifp;
 1463     struct dhcp6_state *state;
 1464 
 1465     ifp = arg;
 1466     if ((state = D6_STATE(ifp)) == NULL)
 1467         return;
 1468 
 1469     /* Only renew in the bound or renew states */
 1470     if (state->state != DH6S_BOUND &&
 1471         state->state != DH6S_RENEW)
 1472         return;
 1473 
 1474     /* Remove the timeout as the renew may have been forced. */
 1475     eloop_timeout_delete(ifp->ctx->eloop, dhcp6_startrenew, ifp);
 1476 
 1477     state->state = DH6S_RENEW;
 1478     state->RTC = 0;
 1479     state->IMD = REN_MAX_DELAY;
 1480     state->IRT = REN_TIMEOUT;
 1481     state->MRT = REN_MAX_RT;
 1482     state->MRC = 0;
 1483 
 1484     if (dhcp6_makemessage(ifp) == -1)
 1485         logerr("%s: %s", __func__, ifp->name);
 1486     else
 1487         dhcp6_sendrenew(ifp);
 1488 }
 1489 
 1490 void dhcp6_renew(struct interface *ifp)
 1491 {
 1492 
 1493     dhcp6_startrenew(ifp);
 1494 }
 1495 
 1496 bool
 1497 dhcp6_dadcompleted(const struct interface *ifp)
 1498 {
 1499     const struct dhcp6_state *state;
 1500     const struct ipv6_addr *ap;
 1501 
 1502     state = D6_CSTATE(ifp);
 1503     TAILQ_FOREACH(ap, &state->addrs, next) {
 1504         if (ap->flags & IPV6_AF_ADDED &&
 1505             !(ap->flags & IPV6_AF_DADCOMPLETED))
 1506             return false;
 1507     }
 1508     return true;
 1509 }
 1510 
 1511 static void
 1512 dhcp6_dadcallback(void *arg)
 1513 {
 1514     struct ipv6_addr *ia = arg;
 1515     struct interface *ifp;
 1516     struct dhcp6_state *state;
 1517     struct ipv6_addr *ia2;
 1518     bool completed, valid, oneduplicated;
 1519 
 1520     completed = (ia->flags & IPV6_AF_DADCOMPLETED);
 1521     ia->flags |= IPV6_AF_DADCOMPLETED;
 1522     if (ia->addr_flags & IN6_IFF_DUPLICATED)
 1523         logwarnx("%s: DAD detected %s", ia->iface->name, ia->saddr);
 1524 
 1525 #ifdef ND6_ADVERTISE
 1526     else
 1527         ipv6nd_advertise(ia);
 1528 #endif
 1529     if (completed)
 1530         return;
 1531 
 1532     ifp = ia->iface;
 1533     state = D6_STATE(ifp);
 1534     if (state->state != DH6S_BOUND && state->state != DH6S_DELEGATED)
 1535         return;
 1536 
 1537 #ifdef SMALL
 1538     valid = true;
 1539 #else
 1540     valid = (ia->delegating_prefix == NULL);
 1541 #endif
 1542     completed = true;
 1543     oneduplicated = false;
 1544     TAILQ_FOREACH(ia2, &state->addrs, next) {
 1545         if (ia2->flags & IPV6_AF_ADDED &&
 1546             !(ia2->flags & IPV6_AF_DADCOMPLETED))
 1547         {
 1548             completed = false;
 1549             break;
 1550         }
 1551         if (DECLINE_IA(ia))
 1552             oneduplicated = true;
 1553     }
 1554     if (!completed)
 1555         return;
 1556 
 1557     logdebugx("%s: DHCPv6 DAD completed", ifp->name);
 1558 
 1559     if (oneduplicated && state->state == DH6S_BOUND) {
 1560         dhcp6_startdecline(ifp);
 1561         return;
 1562     }
 1563 
 1564     script_runreason(ifp,
 1565 #ifndef SMALL
 1566         ia->delegating_prefix ? "DELEGATED6" :
 1567 #endif
 1568         state->reason);
 1569     if (valid)
 1570         dhcpcd_daemonise(ifp->ctx);
 1571 }
 1572 
 1573 static void
 1574 dhcp6_addrequestedaddrs(struct interface *ifp)
 1575 {
 1576     struct dhcp6_state *state;
 1577     size_t i;
 1578     struct if_ia *ia;
 1579     struct ipv6_addr *a;
 1580 
 1581     state = D6_STATE(ifp);
 1582     /* Add any requested prefixes / addresses */
 1583     for (i = 0; i < ifp->options->ia_len; i++) {
 1584         ia = &ifp->options->ia[i];
 1585         if (!((ia->ia_type == D6_OPTION_IA_PD && ia->prefix_len) ||
 1586             !IN6_IS_ADDR_UNSPECIFIED(&ia->addr)))
 1587             continue;
 1588         a = ipv6_newaddr(ifp, &ia->addr,
 1589             /*
 1590              * RFC 5942 Section 5
 1591              * We cannot assume any prefix length, nor tie the
 1592              * address to an existing one as it could expire
 1593              * before the address.
 1594              * As such we just give it a 128 prefix.
 1595              */
 1596             ia->ia_type == D6_OPTION_IA_PD ? ia->prefix_len : 128,
 1597             IPV6_AF_REQUEST);
 1598         if (a == NULL)
 1599             continue;
 1600         a->dadcallback = dhcp6_dadcallback;
 1601         memcpy(&a->iaid, &ia->iaid, sizeof(a->iaid));
 1602         a->ia_type = ia->ia_type;
 1603         TAILQ_INSERT_TAIL(&state->addrs, a, next);
 1604     }
 1605 }
 1606 
 1607 static void
 1608 dhcp6_startdiscover(void *arg)
 1609 {
 1610     struct interface *ifp;
 1611     struct dhcp6_state *state;
 1612     int llevel;
 1613 
 1614     ifp = arg;
 1615     state = D6_STATE(ifp);
 1616 #ifndef SMALL
 1617     if (state->reason == NULL || strcmp(state->reason, "TIMEOUT6") != 0)
 1618         dhcp6_delete_delegates(ifp);
 1619 #endif
 1620     if (state->new == NULL && !state->failed)
 1621         llevel = LOG_INFO;
 1622     else
 1623         llevel = LOG_DEBUG;
 1624     logmessage(llevel, "%s: soliciting a DHCPv6 lease", ifp->name);
 1625     state->state = DH6S_DISCOVER;
 1626     state->RTC = 0;
 1627     state->IMD = SOL_MAX_DELAY;
 1628     state->IRT = SOL_TIMEOUT;
 1629     state->MRT = state->sol_max_rt;
 1630     state->MRC = SOL_MAX_RC;
 1631 
 1632     eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 1633     free(state->new);
 1634     state->new = NULL;
 1635     state->new_len = 0;
 1636 
 1637     if (dhcp6_makemessage(ifp) == -1)
 1638         logerr("%s: %s", __func__, ifp->name);
 1639     else
 1640         dhcp6_senddiscover(ifp);
 1641 }
 1642 
 1643 static void
 1644 dhcp6_startinform(void *arg)
 1645 {
 1646     struct interface *ifp;
 1647     struct dhcp6_state *state;
 1648     int llevel;
 1649 
 1650     ifp = arg;
 1651     state = D6_STATE(ifp);
 1652     if (state->new_start || (state->new == NULL && !state->failed))
 1653         llevel = LOG_INFO;
 1654     else
 1655         llevel = LOG_DEBUG;
 1656     logmessage(llevel, "%s: requesting DHCPv6 information", ifp->name);
 1657     state->state = DH6S_INFORM;
 1658     state->RTC = 0;
 1659     state->IMD = INF_MAX_DELAY;
 1660     state->IRT = INF_TIMEOUT;
 1661     state->MRT = state->inf_max_rt;
 1662     state->MRC = 0;
 1663 
 1664     eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 1665     if (dhcp6_makemessage(ifp) == -1) {
 1666         logerr("%s: %s", __func__, ifp->name);
 1667         return;
 1668     }
 1669     dhcp6_sendinform(ifp);
 1670     /* RFC3315 18.1.2 says that if CONFIRM failed then the prior addresses
 1671      * SHOULD be used. The wording here is poor, because the addresses are
 1672      * merely one facet of the lease as a whole.
 1673      * This poor wording might explain the lack of similar text for INFORM
 1674      * in 18.1.5 because there are no addresses in the INFORM message. */
 1675     eloop_timeout_add_sec(ifp->ctx->eloop,
 1676         INF_MAX_RD, dhcp6_failinform, ifp);
 1677 }
 1678 
 1679 static bool
 1680 dhcp6_startdiscoinform(struct interface *ifp)
 1681 {
 1682     unsigned long long opts = ifp->options->options;
 1683 
 1684     if (opts & DHCPCD_IA_FORCED || ipv6nd_hasradhcp(ifp, true))
 1685         dhcp6_startdiscover(ifp);
 1686     else if (opts & DHCPCD_INFORM6 || ipv6nd_hasradhcp(ifp, false))
 1687         dhcp6_startinform(ifp);
 1688     else
 1689         return false;
 1690     return true;
 1691 }
 1692 
 1693 static void
 1694 dhcp6_leaseextend(struct interface *ifp)
 1695 {
 1696     struct dhcp6_state *state = D6_STATE(ifp);
 1697     struct ipv6_addr *ia;
 1698 
 1699     logwarnx("%s: extending DHCPv6 lease", ifp->name);
 1700     TAILQ_FOREACH(ia, &state->addrs, next) {
 1701         ia->flags |= IPV6_AF_EXTENDED;
 1702         /* Set infinite lifetimes. */
 1703         ia->prefix_pltime = ND6_INFINITE_LIFETIME;
 1704         ia->prefix_vltime = ND6_INFINITE_LIFETIME;
 1705     }
 1706 }
 1707 
 1708 static void
 1709 dhcp6_fail(struct interface *ifp)
 1710 {
 1711     struct dhcp6_state *state = D6_STATE(ifp);
 1712 
 1713     state->failed = true;
 1714 
 1715     /* RFC3315 18.1.2 says that prior addresses SHOULD be used on failure.
 1716      * RFC2131 3.2.3 says that MAY chose to use the prior address.
 1717      * Because dhcpcd was written first for RFC2131, we have the LASTLEASE
 1718      * option which defaults to off as that makes the most sense for
 1719      * mobile clients.
 1720      * dhcpcd also has LASTLEASE_EXTEND to extend this lease past it's
 1721      * expiry, but this is strictly not RFC compliant in any way or form. */
 1722     if (state->new != NULL &&
 1723         ifp->options->options & DHCPCD_LASTLEASE_EXTEND)
 1724     {
 1725         dhcp6_leaseextend(ifp);
 1726         dhcp6_bind(ifp, NULL, NULL);
 1727     } else {
 1728         dhcp6_freedrop_addrs(ifp, 1, NULL);
 1729 #ifndef SMALL
 1730         dhcp6_delete_delegates(ifp);
 1731 #endif
 1732         free(state->old);
 1733         state->old = state->new;
 1734         state->old_len = state->new_len;
 1735         state->new = NULL;
 1736         state->new_len = 0;
 1737         if (state->old != NULL)
 1738             script_runreason(ifp, "EXPIRE6");
 1739         dhcp_unlink(ifp->ctx, state->leasefile);
 1740         dhcp6_addrequestedaddrs(ifp);
 1741     }
 1742 
 1743     if (!dhcp6_startdiscoinform(ifp)) {
 1744         logwarnx("%s: no advertising IPv6 router wants DHCP",ifp->name);
 1745         state->state = DH6S_INIT;
 1746         eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 1747     }
 1748 }
 1749 
 1750 static int
 1751 dhcp6_failloglevel(struct interface *ifp)
 1752 {
 1753     const struct dhcp6_state *state = D6_CSTATE(ifp);
 1754 
 1755     return state->failed ? LOG_DEBUG : LOG_ERR;
 1756 }
 1757 
 1758 static void
 1759 dhcp6_failconfirm(void *arg)
 1760 {
 1761     struct interface *ifp = arg;
 1762     int llevel = dhcp6_failloglevel(ifp);
 1763 
 1764     logmessage(llevel, "%s: failed to confirm prior DHCPv6 address",
 1765         ifp->name);
 1766     dhcp6_fail(ifp);
 1767 }
 1768 
 1769 static void
 1770 dhcp6_failrequest(void *arg)
 1771 {
 1772     struct interface *ifp = arg;
 1773     int llevel = dhcp6_failloglevel(ifp);
 1774 
 1775     logmessage(llevel, "%s: failed to request DHCPv6 address", ifp->name);
 1776     dhcp6_fail(ifp);
 1777 }
 1778 
 1779 static void
 1780 dhcp6_failinform(void *arg)
 1781 {
 1782     struct interface *ifp = arg;
 1783     int llevel = dhcp6_failloglevel(ifp);
 1784 
 1785     logmessage(llevel, "%s: failed to request DHCPv6 information",
 1786         ifp->name);
 1787     dhcp6_fail(ifp);
 1788 }
 1789 
 1790 #ifndef SMALL
 1791 static void
 1792 dhcp6_failrebind(void *arg)
 1793 {
 1794     struct interface *ifp = arg;
 1795 
 1796     logerrx("%s: failed to rebind prior DHCPv6 delegation", ifp->name);
 1797     dhcp6_fail(ifp);
 1798 }
 1799 
 1800 static int
 1801 dhcp6_hasprefixdelegation(struct interface *ifp)
 1802 {
 1803     size_t i;
 1804     uint16_t t;
 1805 
 1806     t = 0;
 1807     for (i = 0; i < ifp->options->ia_len; i++) {
 1808         if (t && t != ifp->options->ia[i].ia_type) {
 1809             if (t == D6_OPTION_IA_PD ||
 1810                 ifp->options->ia[i].ia_type == D6_OPTION_IA_PD)
 1811                 return 2;
 1812         }
 1813         t = ifp->options->ia[i].ia_type;
 1814     }
 1815     return t == D6_OPTION_IA_PD ? 1 : 0;
 1816 }
 1817 #endif
 1818 
 1819 static void
 1820 dhcp6_startrebind(void *arg)
 1821 {
 1822     struct interface *ifp;
 1823     struct dhcp6_state *state;
 1824 #ifndef SMALL
 1825     int pd;
 1826 #endif
 1827 
 1828     ifp = arg;
 1829     eloop_timeout_delete(ifp->ctx->eloop, dhcp6_sendrenew, ifp);
 1830     state = D6_STATE(ifp);
 1831     if (state->state == DH6S_RENEW)
 1832         logwarnx("%s: failed to renew DHCPv6, rebinding", ifp->name);
 1833     else
 1834         loginfox("%s: rebinding prior DHCPv6 lease", ifp->name);
 1835     state->state = DH6S_REBIND;
 1836     state->RTC = 0;
 1837     state->MRC = 0;
 1838 
 1839 #ifndef SMALL
 1840     /* RFC 3633 section 12.1 */
 1841     pd = dhcp6_hasprefixdelegation(ifp);
 1842     if (pd) {
 1843         state->IMD = CNF_MAX_DELAY;
 1844         state->IRT = CNF_TIMEOUT;
 1845         state->MRT = CNF_MAX_RT;
 1846     } else
 1847 #endif
 1848     {
 1849         state->IMD = REB_MAX_DELAY;
 1850         state->IRT = REB_TIMEOUT;
 1851         state->MRT = REB_MAX_RT;
 1852     }
 1853 
 1854     if (dhcp6_makemessage(ifp) == -1)
 1855         logerr("%s: %s", __func__, ifp->name);
 1856     else
 1857         dhcp6_sendrebind(ifp);
 1858 
 1859 #ifndef SMALL
 1860     /* RFC 3633 section 12.1 */
 1861     if (pd)
 1862         eloop_timeout_add_sec(ifp->ctx->eloop,
 1863             CNF_MAX_RD, dhcp6_failrebind, ifp);
 1864 #endif
 1865 }
 1866 
 1867 
 1868 static void
 1869 dhcp6_startrequest(struct interface *ifp)
 1870 {
 1871     struct dhcp6_state *state;
 1872 
 1873     eloop_timeout_delete(ifp->ctx->eloop, dhcp6_senddiscover, ifp);
 1874     state = D6_STATE(ifp);
 1875     state->state = DH6S_REQUEST;
 1876     state->RTC = 0;
 1877     state->IMD = 0;
 1878     state->IRT = REQ_TIMEOUT;
 1879     state->MRT = REQ_MAX_RT;
 1880     state->MRC = REQ_MAX_RC;
 1881     state->MRCcallback = dhcp6_failrequest;
 1882 
 1883     if (dhcp6_makemessage(ifp) == -1) {
 1884         logerr("%s: %s", __func__, ifp->name);
 1885         return;
 1886     }
 1887 
 1888     dhcp6_sendrequest(ifp);
 1889 }
 1890 
 1891 static void
 1892 dhcp6_startconfirm(struct interface *ifp)
 1893 {
 1894     struct dhcp6_state *state;
 1895     struct ipv6_addr *ia;
 1896 
 1897     state = D6_STATE(ifp);
 1898 
 1899     TAILQ_FOREACH(ia, &state->addrs, next) {
 1900         if (!DECLINE_IA(ia))
 1901             continue;
 1902         logerrx("%s: prior DHCPv6 has a duplicated address", ifp->name);
 1903         dhcp6_startdecline(ifp);
 1904         return;
 1905     }
 1906 
 1907     state->state = DH6S_CONFIRM;
 1908     state->RTC = 0;
 1909     state->IMD = CNF_MAX_DELAY;
 1910     state->IRT = CNF_TIMEOUT;
 1911     state->MRT = CNF_MAX_RT;
 1912     state->MRC = CNF_MAX_RC;
 1913 
 1914     loginfox("%s: confirming prior DHCPv6 lease", ifp->name);
 1915 
 1916     if (dhcp6_makemessage(ifp) == -1) {
 1917         logerr("%s: %s", __func__, ifp->name);
 1918         return;
 1919     }
 1920     dhcp6_sendconfirm(ifp);
 1921     eloop_timeout_add_sec(ifp->ctx->eloop,
 1922         CNF_MAX_RD, dhcp6_failconfirm, ifp);
 1923 }
 1924 
 1925 static void
 1926 dhcp6_startexpire(void *arg)
 1927 {
 1928     struct interface *ifp;
 1929 
 1930     ifp = arg;
 1931     eloop_timeout_delete(ifp->ctx->eloop, dhcp6_sendrebind, ifp);
 1932 
 1933     logerrx("%s: DHCPv6 lease expired", ifp->name);
 1934     dhcp6_fail(ifp);
 1935 }
 1936 
 1937 static void
 1938 dhcp6_faildecline(void *arg)
 1939 {
 1940     struct interface *ifp = arg;
 1941 
 1942     logerrx("%s: failed to decline duplicated DHCPv6 addresses", ifp->name);
 1943     dhcp6_fail(ifp);
 1944 }
 1945 
 1946 static void
 1947 dhcp6_startdecline(struct interface *ifp)
 1948 {
 1949     struct dhcp6_state *state;
 1950 
 1951     state = D6_STATE(ifp);
 1952     loginfox("%s: declining failed DHCPv6 addresses", ifp->name);
 1953     state->state = DH6S_DECLINE;
 1954     state->RTC = 0;
 1955     state->IMD = 0;
 1956     state->IRT = DEC_TIMEOUT;
 1957     state->MRT = 0;
 1958     state->MRC = DEC_MAX_RC;
 1959     state->MRCcallback = dhcp6_faildecline;
 1960 
 1961     if (dhcp6_makemessage(ifp) == -1)
 1962         logerr("%s: %s", __func__, ifp->name);
 1963     else
 1964         dhcp6_senddecline(ifp);
 1965 }
 1966 
 1967 static void
 1968 dhcp6_finishrelease(void *arg)
 1969 {
 1970     struct interface *ifp;
 1971     struct dhcp6_state *state;
 1972 
 1973     ifp = (struct interface *)arg;
 1974     if ((state = D6_STATE(ifp)) != NULL) {
 1975         state->state = DH6S_RELEASED;
 1976         dhcp6_drop(ifp, "RELEASE6");
 1977     }
 1978 }
 1979 
 1980 static void
 1981 dhcp6_startrelease(struct interface *ifp)
 1982 {
 1983     struct dhcp6_state *state;
 1984 
 1985     state = D6_STATE(ifp);
 1986     if (state->state != DH6S_BOUND)
 1987         return;
 1988 
 1989     state->state = DH6S_RELEASE;
 1990     state->RTC = 0;
 1991     state->IMD = REL_MAX_DELAY;
 1992     state->IRT = REL_TIMEOUT;
 1993     state->MRT = REL_MAX_RT;
 1994     /* MRC of REL_MAX_RC is optional in RFC 3315 18.1.6 */
 1995 #if 0
 1996     state->MRC = REL_MAX_RC;
 1997     state->MRCcallback = dhcp6_finishrelease;
 1998 #else
 1999     state->MRC = 0;
 2000     state->MRCcallback = NULL;
 2001 #endif
 2002 
 2003     if (dhcp6_makemessage(ifp) == -1)
 2004         logerr("%s: %s", __func__, ifp->name);
 2005     else {
 2006         dhcp6_sendrelease(ifp);
 2007         dhcp6_finishrelease(ifp);
 2008     }
 2009 }
 2010 
 2011 static int
 2012 dhcp6_checkstatusok(const struct interface *ifp,
 2013     struct dhcp6_message *m, uint8_t *p, size_t len)
 2014 {
 2015     struct dhcp6_state *state;
 2016     uint8_t *opt;
 2017     uint16_t opt_len, code;
 2018     size_t mlen;
 2019     void * (*f)(void *, size_t, uint16_t, uint16_t *), *farg;
 2020     char buf[32], *sbuf;
 2021     const char *status;
 2022     int loglevel;
 2023 
 2024     state = D6_STATE(ifp);
 2025     f = p ? dhcp6_findoption : dhcp6_findmoption;
 2026     if (p)
 2027         farg = p;
 2028     else
 2029         farg = m;
 2030     if ((opt = f(farg, len, D6_OPTION_STATUS_CODE, &opt_len)) == NULL) {
 2031         //logdebugx("%s: no status", ifp->name);
 2032         state->lerror = 0;
 2033         errno = ESRCH;
 2034         return 0;
 2035     }
 2036 
 2037     if (opt_len < sizeof(code)) {
 2038         logerrx("%s: status truncated", ifp->name);
 2039         return -1;
 2040     }
 2041     memcpy(&code, opt, sizeof(code));
 2042     code = ntohs(code);
 2043     if (code == D6_STATUS_OK) {
 2044         state->lerror = 0;
 2045         errno = 0;
 2046         return 0;
 2047     }
 2048 
 2049     /* Anything after the code is a message. */
 2050     opt += sizeof(code);
 2051     mlen = opt_len - sizeof(code);
 2052     if (mlen == 0) {
 2053         sbuf = NULL;
 2054         if (code < sizeof(dhcp6_statuses) / sizeof(char *))
 2055             status = dhcp6_statuses[code];
 2056         else {
 2057             snprintf(buf, sizeof(buf), "Unknown Status (%d)", code);
 2058             status = buf;
 2059         }
 2060     } else {
 2061         if ((sbuf = malloc(mlen + 1)) == NULL) {
 2062             logerr(__func__);
 2063             return -1;
 2064         }
 2065         memcpy(sbuf, opt, mlen);
 2066         sbuf[mlen] = '\0';
 2067         status = sbuf;
 2068     }
 2069 
 2070     if (state->lerror == code || state->state == DH6S_INIT)
 2071         loglevel = LOG_DEBUG;
 2072     else
 2073         loglevel = LOG_ERR;
 2074     logmessage(loglevel, "%s: DHCPv6 REPLY: %s", ifp->name, status);
 2075     free(sbuf);
 2076     state->lerror = code;
 2077     errno = 0;
 2078 
 2079     /* code cannot be D6_STATUS_OK, so there is a failure */
 2080     if (ifp->ctx->options & DHCPCD_TEST)
 2081         eloop_exit(ifp->ctx->eloop, EXIT_FAILURE);
 2082 
 2083     return (int)code;
 2084 }
 2085 
 2086 const struct ipv6_addr *
 2087 dhcp6_iffindaddr(const struct interface *ifp, const struct in6_addr *addr,
 2088     unsigned int flags)
 2089 {
 2090     const struct dhcp6_state *state;
 2091     const struct ipv6_addr *ap;
 2092 
 2093     if ((state = D6_STATE(ifp)) != NULL) {
 2094         TAILQ_FOREACH(ap, &state->addrs, next) {
 2095             if (ipv6_findaddrmatch(ap, addr, flags))
 2096                 return ap;
 2097         }
 2098     }
 2099     return NULL;
 2100 }
 2101 
 2102 struct ipv6_addr *
 2103 dhcp6_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr,
 2104     unsigned int flags)
 2105 {
 2106     struct interface *ifp;
 2107     struct ipv6_addr *ap;
 2108     struct dhcp6_state *state;
 2109 
 2110     TAILQ_FOREACH(ifp, ctx->ifaces, next) {
 2111         if ((state = D6_STATE(ifp)) != NULL) {
 2112             TAILQ_FOREACH(ap, &state->addrs, next) {
 2113                 if (ipv6_findaddrmatch(ap, addr, flags))
 2114                     return ap;
 2115             }
 2116         }
 2117     }
 2118     return NULL;
 2119 }
 2120 
 2121 static int
 2122 dhcp6_findna(struct interface *ifp, uint16_t ot, const uint8_t *iaid,
 2123     uint8_t *d, size_t l, const struct timespec *acquired)
 2124 {
 2125     struct dhcp6_state *state;
 2126     uint8_t *o, *nd;
 2127     uint16_t ol;
 2128     struct ipv6_addr *a;
 2129     int i;
 2130     struct dhcp6_ia_addr ia;
 2131 
 2132     i = 0;
 2133     state = D6_STATE(ifp);
 2134     while ((o = dhcp6_findoption(d, l, D6_OPTION_IA_ADDR, &ol))) {
 2135         /* Set d and l first to ensure we find the next option. */
 2136         nd = o + ol;
 2137         l -= (size_t)(nd - d);
 2138         d = nd;
 2139         if (ol < sizeof(ia)) {
 2140             errno = EINVAL;
 2141             logerrx("%s: IA Address option truncated", ifp->name);
 2142             continue;
 2143         }
 2144         memcpy(&ia, o, sizeof(ia));
 2145         ia.pltime = ntohl(ia.pltime);
 2146         ia.vltime = ntohl(ia.vltime);
 2147         /* RFC 3315 22.6 */
 2148         if (ia.pltime > ia.vltime) {
 2149             errno = EINVAL;
 2150             logerr("%s: IA Address pltime %"PRIu32
 2151                 " > vltime %"PRIu32,
 2152                 ifp->name, ia.pltime, ia.vltime);
 2153             continue;
 2154         }
 2155         TAILQ_FOREACH(a, &state->addrs, next) {
 2156             if (ipv6_findaddrmatch(a, &ia.addr, 0))
 2157                 break;
 2158         }
 2159         if (a == NULL) {
 2160             /*
 2161              * RFC 5942 Section 5
 2162              * We cannot assume any prefix length, nor tie the
 2163              * address to an existing one as it could expire
 2164              * before the address.
 2165              * As such we just give it a 128 prefix.
 2166              */
 2167             a = ipv6_newaddr(ifp, &ia.addr, 128, IPV6_AF_ONLINK);
 2168             a->dadcallback = dhcp6_dadcallback;
 2169             a->ia_type = ot;
 2170             memcpy(a->iaid, iaid, sizeof(a->iaid));
 2171             a->created = *acquired;
 2172 
 2173             TAILQ_INSERT_TAIL(&state->addrs, a, next);
 2174         } else {
 2175             if (!(a->flags & IPV6_AF_ONLINK))
 2176                 a->flags |= IPV6_AF_ONLINK | IPV6_AF_NEW;
 2177             a->flags &= ~(IPV6_AF_STALE | IPV6_AF_EXTENDED);
 2178         }
 2179         a->acquired = *acquired;
 2180         a->prefix_pltime = ia.pltime;
 2181         if (a->prefix_vltime != ia.vltime) {
 2182             a->flags |= IPV6_AF_NEW;
 2183             a->prefix_vltime = ia.vltime;
 2184         }
 2185         if (a->prefix_pltime && a->prefix_pltime < state->lowpl)
 2186             state->lowpl = a->prefix_pltime;
 2187         if (a->prefix_vltime && a->prefix_vltime > state->expire)
 2188             state->expire = a->prefix_vltime;
 2189         i++;
 2190     }
 2191     return i;
 2192 }
 2193 
 2194 #ifndef SMALL
 2195 static int
 2196 dhcp6_findpd(struct interface *ifp, const uint8_t *iaid,
 2197     uint8_t *d, size_t l, const struct timespec *acquired)
 2198 {
 2199     struct dhcp6_state *state;
 2200     uint8_t *o, *nd;
 2201     struct ipv6_addr *a;
 2202     int i;
 2203     uint8_t nb, *pw;
 2204     uint16_t ol;
 2205     struct dhcp6_pd_addr pdp;
 2206     struct in6_addr pdp_prefix;
 2207 
 2208     i = 0;
 2209     state = D6_STATE(ifp);
 2210     while ((o = dhcp6_findoption(d, l, D6_OPTION_IAPREFIX, &ol))) {
 2211         /* Set d and l first to ensure we find the next option. */
 2212         nd = o + ol;
 2213         l -= (size_t)(nd - d);
 2214         d = nd;
 2215         if (ol < sizeof(pdp)) {
 2216             errno = EINVAL;
 2217             logerrx("%s: IA Prefix option truncated", ifp->name);
 2218             continue;
 2219         }
 2220 
 2221         memcpy(&pdp, o, sizeof(pdp));
 2222         pdp.pltime = ntohl(pdp.pltime);
 2223         pdp.vltime = ntohl(pdp.vltime);
 2224         /* RFC 3315 22.6 */
 2225         if (pdp.pltime > pdp.vltime) {
 2226             errno = EINVAL;
 2227             logerrx("%s: IA Prefix pltime %"PRIu32
 2228                 " > vltime %"PRIu32,
 2229                 ifp->name, pdp.pltime, pdp.vltime);
 2230             continue;
 2231         }
 2232 
 2233         o += sizeof(pdp);
 2234         ol = (uint16_t)(ol - sizeof(pdp));
 2235 
 2236         /* pdp.prefix is not aligned so copy it out. */
 2237         memcpy(&pdp_prefix, &pdp.prefix, sizeof(pdp_prefix));
 2238         TAILQ_FOREACH(a, &state->addrs, next) {
 2239             if (IN6_ARE_ADDR_EQUAL(&a->prefix, &pdp_prefix))
 2240                 break;
 2241         }
 2242 
 2243         if (a == NULL) {
 2244             a = ipv6_newaddr(ifp, &pdp_prefix, pdp.prefix_len,
 2245                 IPV6_AF_DELEGATEDPFX);
 2246             if (a == NULL)
 2247                 break;
 2248             a->created = *acquired;
 2249             a->dadcallback = dhcp6_dadcallback;
 2250             a->ia_type = D6_OPTION_IA_PD;
 2251             memcpy(a->iaid, iaid, sizeof(a->iaid));
 2252             TAILQ_INSERT_TAIL(&state->addrs, a, next);
 2253         } else {
 2254             if (!(a->flags & IPV6_AF_DELEGATEDPFX))
 2255                 a->flags |= IPV6_AF_NEW | IPV6_AF_DELEGATEDPFX;
 2256             a->flags &= ~(IPV6_AF_STALE |
 2257                           IPV6_AF_EXTENDED |
 2258                           IPV6_AF_REQUEST);
 2259             if (a->prefix_vltime != pdp.vltime)
 2260                 a->flags |= IPV6_AF_NEW;
 2261         }
 2262 
 2263         a->acquired = *acquired;
 2264         a->prefix_pltime = pdp.pltime;
 2265         a->prefix_vltime = pdp.vltime;
 2266 
 2267         if (a->prefix_pltime && a->prefix_pltime < state->lowpl)
 2268             state->lowpl = a->prefix_pltime;
 2269         if (a->prefix_vltime && a->prefix_vltime > state->expire)
 2270             state->expire = a->prefix_vltime;
 2271         i++;
 2272 
 2273         a->prefix_exclude_len = 0;
 2274         memset(&a->prefix_exclude, 0, sizeof(a->prefix_exclude));
 2275         o = dhcp6_findoption(o, ol, D6_OPTION_PD_EXCLUDE, &ol);
 2276         if (o == NULL)
 2277             continue;
 2278 
 2279         /* RFC 6603 4.2 says option length MUST be between 2 and 17.
 2280          * This allows 1 octet for prefix length and 16 for the
 2281          * subnet ID. */
 2282         if (ol < 2 || ol > 17) {
 2283             logerrx("%s: invalid PD Exclude option", ifp->name);
 2284             continue;
 2285         }
 2286 
 2287         /* RFC 6603 4.2 says prefix length MUST be between the
 2288          * length of the IAPREFIX prefix length + 1 and 128. */
 2289         if (*o < a->prefix_len + 1 || *o > 128) {
 2290             logerrx("%s: invalid PD Exclude length", ifp->name);
 2291             continue;
 2292         }
 2293 
 2294         ol--;
 2295         /* Check option length matches prefix length. */
 2296         if (((*o - a->prefix_len - 1) / NBBY) + 1 != ol) {
 2297             logerrx("%s: PD Exclude length mismatch", ifp->name);
 2298             continue;
 2299         }
 2300         a->prefix_exclude_len = *o++;
 2301 
 2302         memcpy(&a->prefix_exclude, &a->prefix,
 2303             sizeof(a->prefix_exclude));
 2304         nb = a->prefix_len % NBBY;
 2305         if (nb)
 2306             ol--;
 2307         pw = a->prefix_exclude.s6_addr +
 2308             (a->prefix_exclude_len / NBBY) - 1;
 2309         while (ol-- > 0)
 2310             *pw-- = *o++;
 2311         if (nb)
 2312             *pw = (uint8_t)(*pw | (*o >> nb));
 2313     }
 2314     return i;
 2315 }
 2316 #endif
 2317 
 2318 static int
 2319 dhcp6_findia(struct interface *ifp, struct dhcp6_message *m, size_t l,
 2320     const char *sfrom, const struct timespec *acquired)
 2321 {
 2322     struct dhcp6_state *state;
 2323     const struct if_options *ifo;
 2324     struct dhcp6_option o;
 2325     uint8_t *d, *p;
 2326     struct dhcp6_ia_na ia;
 2327     int i, e, error;
 2328     size_t j;
 2329     uint16_t nl;
 2330     uint8_t iaid[4];
 2331     char buf[sizeof(iaid) * 3];
 2332     struct ipv6_addr *ap;
 2333     struct if_ia *ifia;
 2334 
 2335     if (l < sizeof(*m)) {
 2336         /* Should be impossible with guards at packet in
 2337          * and reading leases */
 2338         errno = EINVAL;
 2339         return -1;
 2340     }
 2341 
 2342     ifo = ifp->options;
 2343     i = e = 0;
 2344     state = D6_STATE(ifp);
 2345     TAILQ_FOREACH(ap, &state->addrs, next) {
 2346         if (!(ap->flags & IPV6_AF_DELEGATED))
 2347             ap->flags |= IPV6_AF_STALE;
 2348     }
 2349 
 2350     d = (uint8_t *)m + sizeof(*m);
 2351     l -= sizeof(*m);
 2352     while (l > sizeof(o)) {
 2353         memcpy(&o, d, sizeof(o));
 2354         o.len = ntohs(o.len);
 2355         if (o.len > l || sizeof(o) + o.len > l) {
 2356             errno = EINVAL;
 2357             logerrx("%s: option overflow", ifp->name);
 2358             break;
 2359         }
 2360         p = d + sizeof(o);
 2361         d = p + o.len;
 2362         l -= sizeof(o) + o.len;
 2363 
 2364         o.code = ntohs(o.code);
 2365         switch(o.code) {
 2366         case D6_OPTION_IA_TA:
 2367             nl = 4;
 2368             break;
 2369         case D6_OPTION_IA_NA:
 2370         case D6_OPTION_IA_PD:
 2371             nl = 12;
 2372             break;
 2373         default:
 2374             continue;
 2375         }
 2376         if (o.len < nl) {
 2377             errno = EINVAL;
 2378             logerrx("%s: IA option truncated", ifp->name);
 2379             continue;
 2380         }
 2381 
 2382         memcpy(&ia, p, nl);
 2383         p += nl;
 2384         o.len = (uint16_t)(o.len - nl);
 2385 
 2386         for (j = 0; j < ifo->ia_len; j++) {
 2387             ifia = &ifo->ia[j];
 2388             if (ifia->ia_type == o.code &&
 2389                 memcmp(ifia->iaid, ia.iaid, sizeof(ia.iaid)) == 0)
 2390                 break;
 2391         }
 2392         if (j == ifo->ia_len &&
 2393             !(ifo->ia_len == 0 && ifp->ctx->options & DHCPCD_DUMPLEASE))
 2394         {
 2395             logdebugx("%s: ignoring unrequested IAID %s",
 2396                 ifp->name,
 2397                 hwaddr_ntoa(ia.iaid, sizeof(ia.iaid),
 2398                 buf, sizeof(buf)));
 2399             continue;
 2400         }
 2401 
 2402         if (o.code != D6_OPTION_IA_TA) {
 2403             ia.t1 = ntohl(ia.t1);
 2404             ia.t2 = ntohl(ia.t2);
 2405             /* RFC 3315 22.4 */
 2406             if (ia.t2 > 0 && ia.t1 > ia.t2) {
 2407                 logwarnx("%s: IAID %s T1(%d) > T2(%d) from %s",
 2408                     ifp->name,
 2409                     hwaddr_ntoa(iaid, sizeof(iaid), buf,
 2410                                 sizeof(buf)),
 2411                     ia.t1, ia.t2, sfrom);
 2412                 continue;
 2413             }
 2414         } else
 2415             ia.t1 = ia.t2 = 0; /* appease gcc */
 2416         if ((error = dhcp6_checkstatusok(ifp, NULL, p, o.len)) != 0) {
 2417             if (error == D6_STATUS_NOBINDING)
 2418                 state->has_no_binding = true;
 2419             e = 1;
 2420             continue;
 2421         }
 2422         if (o.code == D6_OPTION_IA_PD) {
 2423 #ifndef SMALL
 2424             if (dhcp6_findpd(ifp, ia.iaid, p, o.len,
 2425                      acquired) == 0)
 2426             {
 2427                 logwarnx("%s: %s: DHCPv6 REPLY missing Prefix",
 2428                     ifp->name, sfrom);
 2429                 continue;
 2430             }
 2431 #endif
 2432         } else {
 2433             if (dhcp6_findna(ifp, o.code, ia.iaid, p, o.len,
 2434                      acquired) == 0)
 2435             {
 2436                 logwarnx("%s: %s: DHCPv6 REPLY missing "
 2437                     "IA Address",
 2438                     ifp->name, sfrom);
 2439                 continue;
 2440             }
 2441         }
 2442         if (o.code != D6_OPTION_IA_TA) {
 2443             if (ia.t1 != 0 &&
 2444                 (ia.t1 < state->renew || state->renew == 0))
 2445                 state->renew = ia.t1;
 2446             if (ia.t2 != 0 &&
 2447                 (ia.t2 < state->rebind || state->rebind == 0))
 2448                 state->rebind = ia.t2;
 2449         }
 2450         i++;
 2451     }
 2452 
 2453     if (i == 0 && e)
 2454         return -1;
 2455     return i;
 2456 }
 2457 
 2458 #ifndef SMALL
 2459 static void
 2460 dhcp6_deprecatedele(struct ipv6_addr *ia)
 2461 {
 2462     struct ipv6_addr *da, *dan, *dda;
 2463     struct timespec now;
 2464     struct dhcp6_state *state;
 2465 
 2466     timespecclear(&now);
 2467     TAILQ_FOREACH_SAFE(da, &ia->pd_pfxs, pd_next, dan) {
 2468         if (ia->prefix_vltime == 0) {
 2469             if (da->prefix_vltime != 0)
 2470                 da->prefix_vltime = 0;
 2471             else
 2472                 continue;
 2473         } else if (da->prefix_pltime != 0)
 2474             da->prefix_pltime = 0;
 2475         else
 2476             continue;
 2477 
 2478         if (ipv6_doaddr(da, &now) != -1)
 2479             continue;
 2480 
 2481         /* Delegation deleted, forget it. */
 2482         TAILQ_REMOVE(&ia->pd_pfxs, da, pd_next);
 2483 
 2484         /* Delete it from the interface. */
 2485         state = D6_STATE(da->iface);
 2486         TAILQ_FOREACH(dda, &state->addrs, next) {
 2487             if (IN6_ARE_ADDR_EQUAL(&dda->addr, &da->addr))
 2488                 break;
 2489         }
 2490         if (dda != NULL) {
 2491             TAILQ_REMOVE(&state->addrs, dda, next);
 2492             ipv6_freeaddr(dda);
 2493         }
 2494     }
 2495 }
 2496 #endif
 2497 
 2498 static void
 2499 dhcp6_deprecateaddrs(struct ipv6_addrhead *addrs)
 2500 {
 2501     struct ipv6_addr *ia, *ian;
 2502 
 2503     TAILQ_FOREACH_SAFE(ia, addrs, next, ian) {
 2504         if (ia->flags & IPV6_AF_EXTENDED)
 2505             ;
 2506         else if (ia->flags & IPV6_AF_STALE) {
 2507             if (ia->prefix_vltime != 0)
 2508                 logdebugx("%s: %s: became stale",
 2509                     ia->iface->name, ia->saddr);
 2510             /* Technically this violates RFC 8415 18.2.10.1,
 2511              * but we need a mechanism to tell the kernel to
 2512              * try and prefer other addresses. */
 2513             ia->prefix_pltime = 0;
 2514         } else if (ia->prefix_vltime == 0)
 2515             loginfox("%s: %s: no valid lifetime",
 2516                 ia->iface->name, ia->saddr);
 2517         else
 2518             continue;
 2519 
 2520 #ifndef SMALL
 2521         /* If we delegated from this prefix, deprecate or remove
 2522          * the delegations. */
 2523         if (ia->flags & IPV6_AF_DELEGATEDPFX)
 2524             dhcp6_deprecatedele(ia);
 2525 #endif
 2526 
 2527         if (ia->flags & IPV6_AF_REQUEST) {
 2528             ia->prefix_vltime = ia->prefix_pltime = 0;
 2529             eloop_q_timeout_delete(ia->iface->ctx->eloop,
 2530                 ELOOP_QUEUE_ALL, NULL, ia);
 2531             continue;
 2532         }
 2533         TAILQ_REMOVE(addrs, ia, next);
 2534         if (ia->flags & IPV6_AF_EXTENDED)
 2535             ipv6_deleteaddr(ia);
 2536         ipv6_freeaddr(ia);
 2537     }
 2538 }
 2539 
 2540 static int
 2541 dhcp6_validatelease(struct interface *ifp,
 2542     struct dhcp6_message *m, size_t len,
 2543     const char *sfrom, const struct timespec *acquired)
 2544 {
 2545     struct dhcp6_state *state;
 2546     int nia, ok_errno;
 2547     struct timespec aq;
 2548 
 2549     if (len <= sizeof(*m)) {
 2550         logerrx("%s: DHCPv6 lease truncated", ifp->name);
 2551         return -1;
 2552     }
 2553 
 2554     state = D6_STATE(ifp);
 2555     errno = 0;
 2556     if (dhcp6_checkstatusok(ifp, m, NULL, len) != 0)
 2557         return -1;
 2558     ok_errno = errno;
 2559 
 2560     state->renew = state->rebind = state->expire = 0;
 2561     state->lowpl = ND6_INFINITE_LIFETIME;
 2562     if (!acquired) {
 2563         clock_gettime(CLOCK_MONOTONIC, &aq);
 2564         acquired = &aq;
 2565     }
 2566     state->has_no_binding = false;
 2567     nia = dhcp6_findia(ifp, m, len, sfrom, acquired);
 2568     if (nia == 0) {
 2569         if (state->state != DH6S_CONFIRM && ok_errno != 0) {
 2570             logerrx("%s: no useable IA found in lease", ifp->name);
 2571             return -1;
 2572         }
 2573 
 2574         /* We are confirming and have an OK,
 2575          * so look for ia's in our old lease.
 2576          * IA's must have existed here otherwise we would
 2577          * have rejected it earlier. */
 2578         assert(state->new != NULL && state->new_len != 0);
 2579         state->has_no_binding = false;
 2580         nia = dhcp6_findia(ifp, state->new, state->new_len,
 2581             sfrom, acquired);
 2582     }
 2583     return nia;
 2584 }
 2585 
 2586 static ssize_t
 2587 dhcp6_readlease(struct interface *ifp, int validate)
 2588 {
 2589     union {
 2590         struct dhcp6_message dhcp6;
 2591         uint8_t buf[UDPLEN_MAX];
 2592     } buf;
 2593     struct dhcp6_state *state;
 2594     ssize_t bytes;
 2595     int fd;
 2596     time_t mtime, now;
 2597 #ifdef AUTH
 2598     uint8_t *o;
 2599     uint16_t ol;
 2600 #endif
 2601 
 2602     state = D6_STATE(ifp);
 2603     if (state->leasefile[0] == '\0') {
 2604         logdebugx("reading standard input");
 2605         bytes = read(fileno(stdin), buf.buf, sizeof(buf.buf));
 2606     } else {
 2607         logdebugx("%s: reading lease: %s",
 2608             ifp->name, state->leasefile);
 2609         bytes = dhcp_readfile(ifp->ctx, state->leasefile,
 2610             buf.buf, sizeof(buf.buf));
 2611     }
 2612     if (bytes == -1)
 2613         goto ex;
 2614 
 2615     if (ifp->ctx->options & DHCPCD_DUMPLEASE || state->leasefile[0] == '\0')
 2616         goto out;
 2617 
 2618     if (bytes == 0)
 2619         goto ex;
 2620 
 2621     /* If not validating IA's and if they have expired,
 2622      * skip to the auth check. */
 2623     if (!validate)
 2624         goto auth;
 2625 
 2626     if (dhcp_filemtime(ifp->ctx, state->leasefile, &mtime) == -1)
 2627         goto ex;
 2628     clock_gettime(CLOCK_MONOTONIC, &state->acquired);
 2629     if ((now = time(NULL)) == -1)
 2630         goto ex;
 2631     state->acquired.tv_sec -= now - mtime;
 2632 
 2633     /* Check to see if the lease is still valid */
 2634     fd = dhcp6_validatelease(ifp, &buf.dhcp6, (size_t)bytes, NULL,
 2635         &state->acquired);
 2636     if (fd == -1)
 2637         goto ex;
 2638 
 2639     if (state->expire != ND6_INFINITE_LIFETIME &&
 2640         (time_t)state->expire < now - mtime &&
 2641         !(ifp->options->options & DHCPCD_LASTLEASE_EXTEND))
 2642     {
 2643         logdebugx("%s: discarding expired lease", ifp->name);
 2644         bytes = 0;
 2645         goto ex;
 2646     }
 2647 
 2648 auth:
 2649 #ifdef AUTH
 2650     /* Authenticate the message */
 2651     o = dhcp6_findmoption(&buf.dhcp6, (size_t)bytes, D6_OPTION_AUTH, &ol);
 2652     if (o) {
 2653         if (dhcp_auth_validate(&state->auth, &ifp->options->auth,
 2654             buf.buf, (size_t)bytes, 6, buf.dhcp6.type, o, ol) == NULL)
 2655         {
 2656             logerr("%s: authentication failed", ifp->name);
 2657             bytes = 0;
 2658             goto ex;
 2659         }
 2660         if (state->auth.token)
 2661             logdebugx("%s: validated using 0x%08" PRIu32,
 2662                 ifp->name, state->auth.token->secretid);
 2663         else
 2664             loginfox("%s: accepted reconfigure key", ifp->name);
 2665     } else if ((ifp->options->auth.options & DHCPCD_AUTH_SENDREQUIRE) ==
 2666         DHCPCD_AUTH_SENDREQUIRE)
 2667     {
 2668         logerrx("%s: authentication now required", ifp->name);
 2669         goto ex;
 2670     }
 2671 #endif
 2672 
 2673 out:
 2674     free(state->new);
 2675     state->new = malloc((size_t)bytes);
 2676     if (state->new == NULL) {
 2677         logerr(__func__);
 2678         goto ex;
 2679     }
 2680 
 2681     memcpy(state->new, buf.buf, (size_t)bytes);
 2682     state->new_len = (size_t)bytes;
 2683     return bytes;
 2684 
 2685 ex:
 2686     dhcp6_freedrop_addrs(ifp, 0, NULL);
 2687     dhcp_unlink(ifp->ctx, state->leasefile);
 2688     free(state->new);
 2689     state->new = NULL;
 2690     state->new_len = 0;
 2691     dhcp6_addrequestedaddrs(ifp);
 2692     return bytes == 0 ? 0 : -1;
 2693 }
 2694 
 2695 static void
 2696 dhcp6_startinit(struct interface *ifp)
 2697 {
 2698     struct dhcp6_state *state;
 2699     ssize_t r;
 2700     uint8_t has_ta, has_non_ta;
 2701     size_t i;
 2702 
 2703     state = D6_STATE(ifp);
 2704     state->state = DH6S_INIT;
 2705     state->expire = ND6_INFINITE_LIFETIME;
 2706     state->lowpl = ND6_INFINITE_LIFETIME;
 2707 
 2708     dhcp6_addrequestedaddrs(ifp);
 2709     has_ta = has_non_ta = 0;
 2710     for (i = 0; i < ifp->options->ia_len; i++) {
 2711         switch (ifp->options->ia[i].ia_type) {
 2712         case D6_OPTION_IA_TA:
 2713             has_ta = 1;
 2714             break;
 2715         default:
 2716             has_non_ta = 1;
 2717         }
 2718     }
 2719 
 2720     if (!(ifp->ctx->options & DHCPCD_TEST) &&
 2721         !(has_ta && !has_non_ta) &&
 2722         ifp->options->reboot != 0)
 2723     {
 2724         r = dhcp6_readlease(ifp, 1);
 2725         if (r == -1) {
 2726             if (errno != ENOENT && errno != ESRCH)
 2727                 logerr("%s: %s", __func__, state->leasefile);
 2728         } else if (r != 0 &&
 2729             !(ifp->options->options & DHCPCD_ANONYMOUS))
 2730         {
 2731             /* RFC 3633 section 12.1 */
 2732 #ifndef SMALL
 2733             if (dhcp6_hasprefixdelegation(ifp))
 2734                 dhcp6_startrebind(ifp);
 2735             else
 2736 #endif
 2737                 dhcp6_startconfirm(ifp);
 2738             return;
 2739         }
 2740     }
 2741     dhcp6_startdiscoinform(ifp);
 2742 }
 2743 
 2744 #ifndef SMALL
 2745 static struct ipv6_addr *
 2746 dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix,
 2747     const struct if_sla *sla, struct if_ia *if_ia)
 2748 {
 2749     struct dhcp6_state *state;
 2750     struct in6_addr addr, daddr;
 2751     struct ipv6_addr *ia;
 2752     int pfxlen, dadcounter;
 2753     uint64_t vl;
 2754 
 2755     /* RFC6603 Section 4.2 */
 2756     if (strcmp(ifp->name, prefix->iface->name) == 0) {
 2757         if (prefix->prefix_exclude_len == 0) {
 2758             /* Don't spam the log automatically */
 2759             if (sla != NULL)
 2760                 logwarnx("%s: DHCPv6 server does not support "
 2761                     "OPTION_PD_EXCLUDE",
 2762                     ifp->name);
 2763             return NULL;
 2764         }
 2765         pfxlen = prefix->prefix_exclude_len;
 2766         memcpy(&addr, &prefix->prefix_exclude, sizeof(addr));
 2767     } else if ((pfxlen = dhcp6_delegateaddr(&addr, ifp, prefix,
 2768         sla, if_ia)) == -1)
 2769         return NULL;
 2770 
 2771     if (sla != NULL && fls64(sla->suffix) > 128 - pfxlen) {
 2772         logerrx("%s: suffix %" PRIu64 " + prefix_len %d > 128",
 2773             ifp->name, sla->suffix, pfxlen);
 2774         return NULL;
 2775     }
 2776 
 2777     /* Add our suffix */
 2778     if (sla != NULL && sla->suffix != 0) {
 2779         daddr = addr;
 2780         vl = be64dec(addr.s6_addr + 8);
 2781         vl |= sla->suffix;
 2782         be64enc(daddr.s6_addr + 8, vl);
 2783     } else {
 2784         dadcounter = ipv6_makeaddr(&daddr, ifp, &addr, pfxlen, 0);
 2785         if (dadcounter == -1) {
 2786             logerrx("%s: error adding slaac to prefix_len %d",
 2787                 ifp->name, pfxlen);
 2788             return NULL;
 2789         }
 2790     }
 2791 
 2792     /* Find an existing address */
 2793     state = D6_STATE(ifp);
 2794     TAILQ_FOREACH(ia, &state->addrs, next) {
 2795         if (IN6_ARE_ADDR_EQUAL(&ia->addr, &daddr))
 2796             break;
 2797     }
 2798     if (ia == NULL) {
 2799         ia = ipv6_newaddr(ifp, &daddr, (uint8_t)pfxlen, IPV6_AF_ONLINK);
 2800         if (ia == NULL)
 2801             return NULL;
 2802         ia->dadcallback = dhcp6_dadcallback;
 2803         memcpy(&ia->iaid, &prefix->iaid, sizeof(ia->iaid));
 2804         ia->created = prefix->acquired;
 2805 
 2806         TAILQ_INSERT_TAIL(&state->addrs, ia, next);
 2807         TAILQ_INSERT_TAIL(&prefix->pd_pfxs, ia, pd_next);
 2808     }
 2809     ia->delegating_prefix = prefix;
 2810     ia->prefix = addr;
 2811     ia->prefix_len = (uint8_t)pfxlen;
 2812     ia->acquired = prefix->acquired;
 2813     ia->prefix_pltime = prefix->prefix_pltime;
 2814     ia->prefix_vltime = prefix->prefix_vltime;
 2815 
 2816     /* If the prefix length hasn't changed,
 2817      * don't install a reject route. */
 2818     if (prefix->prefix_len == pfxlen)
 2819         prefix->flags |= IPV6_AF_NOREJECT;
 2820     else
 2821         prefix->flags &= ~IPV6_AF_NOREJECT;
 2822 
 2823     return ia;
 2824 }
 2825 #endif
 2826 
 2827 static void
 2828 dhcp6_script_try_run(struct interface *ifp, int delegated)
 2829 {
 2830     struct dhcp6_state *state;
 2831     struct ipv6_addr *ap;
 2832     int completed;
 2833 
 2834     state = D6_STATE(ifp);
 2835     completed = 1;
 2836     /* If all addresses have completed DAD run the script */
 2837     TAILQ_FOREACH(ap, &state->addrs, next) {
 2838         if (!(ap->flags & IPV6_AF_ADDED))
 2839             continue;
 2840         if (ap->flags & IPV6_AF_ONLINK) {
 2841             if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
 2842                 ipv6_iffindaddr(ap->iface, &ap->addr,
 2843                                 IN6_IFF_TENTATIVE))
 2844                 ap->flags |= IPV6_AF_DADCOMPLETED;
 2845             if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0
 2846 #ifndef SMALL
 2847                 && ((delegated && ap->delegating_prefix) ||
 2848                 (!delegated && !ap->delegating_prefix))
 2849 #endif
 2850                 )
 2851             {
 2852                 completed = 0;
 2853                 break;
 2854             }
 2855         }
 2856     }
 2857     if (completed) {
 2858         script_runreason(ifp, delegated ? "DELEGATED6" : state->reason);
 2859         if (!delegated)
 2860             dhcpcd_daemonise(ifp->ctx);
 2861     } else
 2862         logdebugx("%s: waiting for DHCPv6 DAD to complete", ifp->name);
 2863 }
 2864 
 2865 #ifdef SMALL
 2866 size_t
 2867 dhcp6_find_delegates(__unused struct interface *ifp)
 2868 {
 2869 
 2870     return 0;
 2871 }
 2872 #else
 2873 static void
 2874 dhcp6_delegate_prefix(struct interface *ifp)
 2875 {
 2876     struct if_options *ifo;
 2877     struct dhcp6_state *state;
 2878     struct ipv6_addr *ap;
 2879     size_t i, j, k;
 2880     struct if_ia *ia;
 2881     struct if_sla *sla;
 2882     struct interface *ifd;
 2883     bool carrier_warned;
 2884 
 2885     ifo = ifp->options;
 2886     state = D6_STATE(ifp);
 2887 
 2888     /* Clear the logged flag. */
 2889     TAILQ_FOREACH(ap, &state->addrs, next) {
 2890         ap->flags &= ~IPV6_AF_DELEGATEDLOG;
 2891     }
 2892 
 2893     TAILQ_FOREACH(ifd, ifp->ctx->ifaces, next) {
 2894         if (!ifd->active)
 2895             continue;
 2896         if (!(ifd->options->options & DHCPCD_CONFIGURE))
 2897             continue;
 2898         k = 0;
 2899         carrier_warned = false;
 2900         TAILQ_FOREACH(ap, &state->addrs, next) {
 2901             if (!(ap->flags & IPV6_AF_DELEGATEDPFX))
 2902                 continue;
 2903             if (!(ap->flags & IPV6_AF_DELEGATEDLOG)) {
 2904                 int loglevel;
 2905 
 2906                 if (ap->flags & IPV6_AF_NEW)
 2907                     loglevel = LOG_INFO;
 2908                 else
 2909                     loglevel = LOG_DEBUG;
 2910                 /* We only want to log this the once as we loop
 2911                  * through many interfaces first. */
 2912                 ap->flags |= IPV6_AF_DELEGATEDLOG;
 2913                 logmessage(loglevel, "%s: delegated prefix %s",
 2914                     ifp->name, ap->saddr);
 2915                 ap->flags &= ~IPV6_AF_NEW;
 2916             }
 2917             for (i = 0; i < ifo->ia_len; i++) {
 2918                 ia = &ifo->ia[i];
 2919                 if (ia->ia_type != D6_OPTION_IA_PD)
 2920                     continue;
 2921                 if (memcmp(ia->iaid, ap->iaid,
 2922                     sizeof(ia->iaid)))
 2923                     continue;
 2924                 if (ia->sla_len == 0) {
 2925                     /* no SLA configured, so lets
 2926                      * automate it */
 2927                     if (!if_is_link_up(ifd)) {
 2928                         logdebugx(
 2929                             "%s: has no carrier, cannot"
 2930                             " delegate addresses",
 2931                             ifd->name);
 2932                         carrier_warned = true;
 2933                         break;
 2934                     }
 2935                     if (dhcp6_ifdelegateaddr(ifd, ap,
 2936                         NULL, ia))
 2937                         k++;
 2938                 }
 2939                 for (j = 0; j < ia->sla_len; j++) {
 2940                     sla = &ia->sla[j];
 2941                     if (strcmp(ifd->name, sla->ifname))
 2942                         continue;
 2943                     if (!if_is_link_up(ifd)) {
 2944                         logdebugx(
 2945                             "%s: has no carrier, cannot"
 2946                             " delegate addresses",
 2947                             ifd->name);
 2948                         carrier_warned = true;
 2949                         break;
 2950                     }
 2951                     if (dhcp6_ifdelegateaddr(ifd, ap,
 2952                         sla, ia))
 2953                         k++;
 2954                 }
 2955                 if (carrier_warned)
 2956                     break;
 2957             }
 2958             if (carrier_warned)
 2959                 break;
 2960         }
 2961         if (k && !carrier_warned) {
 2962             struct dhcp6_state *s = D6_STATE(ifd);
 2963 
 2964             ipv6_addaddrs(&s->addrs);
 2965             dhcp6_script_try_run(ifd, 1);
 2966         }
 2967     }
 2968 
 2969     /* Now all addresses have been added, rebuild the routing table. */
 2970     rt_build(ifp->ctx, AF_INET6);
 2971 }
 2972 
 2973 static void
 2974 dhcp6_find_delegates1(void *arg)
 2975 {
 2976 
 2977     dhcp6_find_delegates(arg);
 2978 }
 2979 
 2980 size_t
 2981 dhcp6_find_delegates(struct interface *ifp)
 2982 {
 2983     struct if_options *ifo;
 2984     struct dhcp6_state *state;
 2985     struct ipv6_addr *ap;
 2986     size_t i, j, k;
 2987     struct if_ia *ia;
 2988     struct if_sla *sla;
 2989     struct interface *ifd;
 2990 
 2991     if (ifp->options != NULL &&
 2992         !(ifp->options->options & DHCPCD_CONFIGURE))
 2993         return 0;
 2994 
 2995     k = 0;
 2996     TAILQ_FOREACH(ifd, ifp->ctx->ifaces, next) {
 2997         ifo = ifd->options;
 2998         state = D6_STATE(ifd);
 2999         if (state == NULL || state->state != DH6S_BOUND)
 3000             continue;
 3001         TAILQ_FOREACH(ap, &state->addrs, next) {
 3002             if (!(ap->flags & IPV6_AF_DELEGATEDPFX))
 3003                 continue;
 3004             for (i = 0; i < ifo->ia_len; i++) {
 3005                 ia = &ifo->ia[i];
 3006                 if (ia->ia_type != D6_OPTION_IA_PD)
 3007                     continue;
 3008                 if (memcmp(ia->iaid, ap->iaid,
 3009                     sizeof(ia->iaid)))
 3010                     continue;
 3011                 for (j = 0; j < ia->sla_len; j++) {
 3012                     sla = &ia->sla[j];
 3013                     if (strcmp(ifp->name, sla->ifname))
 3014                         continue;
 3015                     if (ipv6_linklocal(ifp) == NULL) {
 3016                         logdebugx(
 3017                             "%s: delaying adding"
 3018                             " delegated addresses for"
 3019                             " LL address",
 3020                             ifp->name);
 3021                         ipv6_addlinklocalcallback(ifp,
 3022                             dhcp6_find_delegates1, ifp);
 3023                         return 1;
 3024                     }
 3025                     if (dhcp6_ifdelegateaddr(ifp, ap,
 3026                         sla, ia))
 3027                         k++;
 3028                 }
 3029             }
 3030         }
 3031     }
 3032 
 3033     if (k) {
 3034         loginfox("%s: adding delegated prefixes", ifp->name);
 3035         state = D6_STATE(ifp);
 3036         state->state = DH6S_DELEGATED;
 3037         ipv6_addaddrs(&state->addrs);
 3038         rt_build(ifp->ctx, AF_INET6);
 3039         dhcp6_script_try_run(ifp, 1);
 3040     }
 3041     return k;
 3042 }
 3043 #endif
 3044 
 3045 static void
 3046 dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom)
 3047 {
 3048     struct dhcp6_state *state = D6_STATE(ifp);
 3049     bool timedout = (op == NULL), confirmed;
 3050     struct ipv6_addr *ia;
 3051     int loglevel;
 3052     struct timespec now;
 3053 
 3054     if (state->state == DH6S_RENEW && !state->new_start) {
 3055         loglevel = LOG_DEBUG;
 3056         TAILQ_FOREACH(ia, &state->addrs, next) {
 3057             if (ia->flags & IPV6_AF_NEW) {
 3058                 loglevel = LOG_INFO;
 3059                 break;
 3060             }
 3061         }
 3062     } else if (state->state == DH6S_INFORM)
 3063         loglevel = state->new_start ? LOG_INFO : LOG_DEBUG;
 3064     else
 3065         loglevel = LOG_INFO;
 3066     state->new_start = false;
 3067 
 3068     if (!timedout) {
 3069         logmessage(loglevel, "%s: %s received from %s",
 3070             ifp->name, op, sfrom);
 3071 #ifndef SMALL
 3072         /* If we delegated from an unconfirmed lease we MUST drop
 3073          * them now. Hopefully we have new delegations. */
 3074         if (state->reason != NULL &&
 3075             strcmp(state->reason, "TIMEOUT6") == 0)
 3076             dhcp6_delete_delegates(ifp);
 3077 #endif
 3078         state->reason = NULL;
 3079     } else
 3080         state->reason = "TIMEOUT6";
 3081 
 3082     eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 3083     clock_gettime(CLOCK_MONOTONIC, &now);
 3084 
 3085     switch(state->state) {
 3086     case DH6S_INFORM:
 3087     {
 3088         struct dhcp6_option *o;
 3089         uint16_t ol;
 3090 
 3091         if (state->reason == NULL)
 3092             state->reason = "INFORM6";
 3093         o = dhcp6_findmoption(state->new, state->new_len,
 3094                               D6_OPTION_INFO_REFRESH_TIME, &ol);
 3095         if (o == NULL || ol != sizeof(uint32_t))
 3096             state->renew = IRT_DEFAULT;
 3097         else {
 3098             memcpy(&state->renew, o, ol);
 3099             state->renew = ntohl(state->renew);
 3100             if (state->renew < IRT_MINIMUM)
 3101                 state->renew = IRT_MINIMUM;
 3102         }
 3103         state->rebind = 0;
 3104         state->expire = ND6_INFINITE_LIFETIME;
 3105         state->lowpl = ND6_INFINITE_LIFETIME;
 3106     }
 3107         break;
 3108 
 3109     case DH6S_REQUEST:
 3110         if (state->reason == NULL)
 3111             state->reason = "BOUND6";
 3112         /* FALLTHROUGH */
 3113     case DH6S_RENEW:
 3114         if (state->reason == NULL)
 3115             state->reason = "RENEW6";
 3116         /* FALLTHROUGH */
 3117     case DH6S_REBIND:
 3118         if (state->reason == NULL)
 3119             state->reason = "REBIND6";
 3120         /* FALLTHROUGH */
 3121     case DH6S_CONFIRM:
 3122         if (state->reason == NULL)
 3123             state->reason = "REBOOT6";
 3124         if (state->renew != 0) {
 3125             bool all_expired = true;
 3126 
 3127             TAILQ_FOREACH(ia, &state->addrs, next) {
 3128                 if (ia->flags & IPV6_AF_STALE)
 3129                     continue;
 3130                 if (!(state->renew == ND6_INFINITE_LIFETIME
 3131                     && ia->prefix_vltime == ND6_INFINITE_LIFETIME)
 3132                     && ia->prefix_vltime != 0
 3133                     && ia->prefix_vltime <= state->renew)
 3134                     logwarnx(
 3135                         "%s: %s will expire before renewal",
 3136                         ifp->name, ia->saddr);
 3137                 else
 3138                     all_expired = false;
 3139             }
 3140             if (all_expired) {
 3141                 /* All address's vltime happens at or before
 3142                  * the configured T1 in the IA.
 3143                  * This is a badly configured server and we
 3144                  * have to use our own notion of what
 3145                  * T1 and T2 should be as a result.
 3146                  *
 3147                  * Doing this violates RFC 3315 22.4:
 3148                  * In a message sent by a server to a client,
 3149                  * the client MUST use the values in the T1
 3150                  * and T2 fields for the T1 and T2 parameters,
 3151                  * unless those values in those fields are 0.
 3152                  */
 3153                 logwarnx("%s: ignoring T1 %"PRIu32
 3154                     " due to address expiry",
 3155                     ifp->name, state->renew);
 3156                 state->renew = state->rebind = 0;
 3157             }
 3158         }
 3159         if (state->renew == 0 && state->lowpl != ND6_INFINITE_LIFETIME)
 3160             state->renew = (uint32_t)(state->lowpl * 0.5);
 3161         if (state->rebind == 0 && state->lowpl != ND6_INFINITE_LIFETIME)
 3162             state->rebind = (uint32_t)(state->lowpl * 0.8);
 3163         break;
 3164     default:
 3165         state->reason = "UNKNOWN6";
 3166         break;
 3167     }
 3168 
 3169     if (state->state != DH6S_CONFIRM && !timedout) {
 3170         state->acquired = now;
 3171         free(state->old);
 3172         state->old = state->new;
 3173         state->old_len = state->new_len;
 3174         state->new = state->recv;
 3175         state->new_len = state->recv_len;
 3176         state->recv = NULL;
 3177         state->recv_len = 0;
 3178         confirmed = false;
 3179     } else {
 3180         /* Reduce timers based on when we got the lease. */
 3181         uint32_t elapsed;
 3182 
 3183         elapsed = (uint32_t)eloop_timespec_diff(&now,
 3184             &state->acquired, NULL);
 3185         if (state->renew && state->renew != ND6_INFINITE_LIFETIME) {
 3186             if (state->renew > elapsed)
 3187                 state->renew -= elapsed;
 3188             else
 3189                 state->renew = 0;
 3190         }
 3191         if (state->rebind && state->rebind != ND6_INFINITE_LIFETIME) {
 3192             if (state->rebind > elapsed)
 3193                 state->rebind -= elapsed;
 3194             else
 3195                 state->rebind = 0;
 3196         }
 3197         if (state->expire && state->expire != ND6_INFINITE_LIFETIME) {
 3198             if (state->expire > elapsed)
 3199                 state->expire -= elapsed;
 3200             else
 3201                 state->expire = 0;
 3202         }
 3203         confirmed = true;
 3204     }
 3205 
 3206     if (ifp->ctx->options & DHCPCD_TEST)
 3207         script_runreason(ifp, "TEST");
 3208     else {
 3209         if (state->state == DH6S_INFORM)
 3210             state->state = DH6S_INFORMED;
 3211         else
 3212             state->state = DH6S_BOUND;
 3213         state->failed = false;
 3214 
 3215         if (state->renew && state->renew != ND6_INFINITE_LIFETIME)
 3216             eloop_timeout_add_sec(ifp->ctx->eloop,
 3217                 state->renew,
 3218                 state->state == DH6S_INFORMED ?
 3219                 dhcp6_startinform : dhcp6_startrenew, ifp);
 3220         if (state->rebind && state->rebind != ND6_INFINITE_LIFETIME)
 3221             eloop_timeout_add_sec(ifp->ctx->eloop,
 3222                 state->rebind, dhcp6_startrebind, ifp);
 3223         if (state->expire != ND6_INFINITE_LIFETIME)
 3224             eloop_timeout_add_sec(ifp->ctx->eloop,
 3225                 state->expire, dhcp6_startexpire, ifp);
 3226 
 3227         if (ifp->options->options & DHCPCD_CONFIGURE) {
 3228             ipv6_addaddrs(&state->addrs);
 3229             if (!timedout)
 3230                 dhcp6_deprecateaddrs(&state->addrs);
 3231         }
 3232 
 3233         if (state->state == DH6S_INFORMED)
 3234             logmessage(loglevel, "%s: refresh in %"PRIu32" seconds",
 3235                 ifp->name, state->renew);
 3236         else if (state->renew == ND6_INFINITE_LIFETIME)
 3237             logmessage(loglevel, "%s: leased for infinity",
 3238                 ifp->name);
 3239         else if (state->renew || state->rebind)
 3240             logmessage(loglevel, "%s: renew in %"PRIu32", "
 3241                 "rebind in %"PRIu32", "
 3242                 "expire in %"PRIu32" seconds",
 3243                 ifp->name,
 3244                 state->renew, state->rebind, state->expire);
 3245         else if (state->expire == 0)
 3246             logmessage(loglevel, "%s: will expire", ifp->name);
 3247         else
 3248             logmessage(loglevel, "%s: expire in %"PRIu32" seconds",
 3249                 ifp->name, state->expire);
 3250         rt_build(ifp->ctx, AF_INET6);
 3251         if (!confirmed && !timedout) {
 3252             logdebugx("%s: writing lease: %s",
 3253                 ifp->name, state->leasefile);
 3254             if (dhcp_writefile(ifp->ctx, state->leasefile, 0640,
 3255                 state->new, state->new_len) == -1)
 3256                 logerr("dhcp_writefile: %s",state->leasefile);
 3257         }
 3258 #ifndef SMALL
 3259         dhcp6_delegate_prefix(ifp);
 3260 #endif
 3261         dhcp6_script_try_run(ifp, 0);
 3262     }
 3263 
 3264     if (ifp->ctx->options & DHCPCD_TEST ||
 3265         (ifp->options->options & DHCPCD_INFORM &&
 3266         !(ifp->ctx->options & DHCPCD_MANAGER)))
 3267     {
 3268         eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
 3269     }
 3270 }
 3271 
 3272 static void
 3273 dhcp6_recvif(struct interface *ifp, const char *sfrom,
 3274     struct dhcp6_message *r, size_t len)
 3275 {
 3276     struct dhcpcd_ctx *ctx;
 3277     size_t i;
 3278     const char *op;
 3279     struct dhcp6_state *state;
 3280     uint8_t *o;
 3281     uint16_t ol;
 3282     const struct dhcp_opt *opt;
 3283     const struct if_options *ifo;
 3284     bool valid_op;
 3285 #ifdef AUTH
 3286     uint8_t *auth;
 3287     uint16_t auth_len;
 3288 #endif
 3289 
 3290     ctx = ifp->ctx;
 3291     state = D6_STATE(ifp);
 3292     if (state == NULL || state->send == NULL) {
 3293         logdebugx("%s: DHCPv6 reply received but not running",
 3294             ifp->name);
 3295         return;
 3296     }
 3297 
 3298     /* We're already bound and this message is for another machine */
 3299     /* XXX DELEGATED? */
 3300     if (r->type != DHCP6_RECONFIGURE &&
 3301         (state->state == DH6S_BOUND || state->state == DH6S_INFORMED))
 3302     {
 3303         logdebugx("%s: DHCPv6 reply received but already bound",
 3304             ifp->name);
 3305         return;
 3306     }
 3307 
 3308     if (dhcp6_findmoption(r, len, D6_OPTION_SERVERID, NULL) == NULL) {
 3309         logdebugx("%s: no DHCPv6 server ID from %s", ifp->name, sfrom);
 3310         return;
 3311     }
 3312 
 3313     ifo = ifp->options;
 3314     for (i = 0, opt = ctx->dhcp6_opts;
 3315         i < ctx->dhcp6_opts_len;
 3316         i++, opt++)
 3317     {
 3318         if (has_option_mask(ifo->requiremask6, opt->option) &&
 3319             !dhcp6_findmoption(r, len, (uint16_t)opt->option, NULL))
 3320         {
 3321             logwarnx("%s: reject DHCPv6 (no option %s) from %s",
 3322                 ifp->name, opt->var, sfrom);
 3323             return;
 3324         }
 3325         if (has_option_mask(ifo->rejectmask6, opt->option) &&
 3326             dhcp6_findmoption(r, len, (uint16_t)opt->option, NULL))
 3327         {
 3328             logwarnx("%s: reject DHCPv6 (option %s) from %s",
 3329                 ifp->name, opt->var, sfrom);
 3330             return;
 3331         }
 3332     }
 3333 
 3334 #ifdef AUTH
 3335     /* Authenticate the message */
 3336     auth = dhcp6_findmoption(r, len, D6_OPTION_AUTH, &auth_len);
 3337     if (auth != NULL) {
 3338         if (dhcp_auth_validate(&state->auth, &ifo->auth,
 3339             (uint8_t *)r, len, 6, r->type, auth, auth_len) == NULL)
 3340         {
 3341             logerr("%s: authentication failed from %s",
 3342                 ifp->name, sfrom);
 3343             return;
 3344         }
 3345         if (state->auth.token)
 3346             logdebugx("%s: validated using 0x%08" PRIu32,
 3347                 ifp->name, state->auth.token->secretid);
 3348         else
 3349             loginfox("%s: accepted reconfigure key", ifp->name);
 3350     } else if (ifo->auth.options & DHCPCD_AUTH_SEND) {
 3351         if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) {
 3352             logerrx("%s: no authentication from %s",
 3353                 ifp->name, sfrom);
 3354             return;
 3355         }
 3356         logwarnx("%s: no authentication from %s", ifp->name, sfrom);
 3357     }
 3358 #endif
 3359 
 3360     op = dhcp6_get_op(r->type);
 3361     valid_op = op != NULL;
 3362     switch(r->type) {
 3363     case DHCP6_REPLY:
 3364         switch(state->state) {
 3365         case DH6S_INFORM:
 3366             if (dhcp6_checkstatusok(ifp, r, NULL, len) != 0)
 3367                 return;
 3368             break;
 3369         case DH6S_CONFIRM:
 3370             if (dhcp6_validatelease(ifp, r, len, sfrom, NULL) == -1)
 3371             {
 3372                 dhcp6_startdiscoinform(ifp);
 3373                 return;
 3374             }
 3375             break;
 3376         case DH6S_DISCOVER:
 3377             /* Only accept REPLY in DISCOVER for RAPID_COMMIT.
 3378              * Normally we get an ADVERTISE for a DISCOVER. */
 3379             if (!has_option_mask(ifo->requestmask6,
 3380                 D6_OPTION_RAPID_COMMIT) ||
 3381                 !dhcp6_findmoption(r, len, D6_OPTION_RAPID_COMMIT,
 3382                           NULL))
 3383             {
 3384                 valid_op = false;
 3385                 break;
 3386             }
 3387             /* Validate lease before setting state to REQUEST. */
 3388             /* FALLTHROUGH */
 3389         case DH6S_REQUEST: /* FALLTHROUGH */
 3390         case DH6S_RENEW: /* FALLTHROUGH */
 3391         case DH6S_REBIND:
 3392             if (dhcp6_validatelease(ifp, r, len, sfrom, NULL) == -1)
 3393             {
 3394                 /*
 3395                  * If we can't use the lease, fallback to
 3396                  * DISCOVER and try and get a new one.
 3397                  *
 3398                  * This is needed become some servers
 3399                  * renumber the prefix or address
 3400                  * and deny the current one before it expires
 3401                  * rather than sending it back with a zero
 3402                  * lifetime along with the new prefix or
 3403                  * address to use.
 3404                  * This behavior is wrong, but moving to the
 3405                  * DISCOVER phase works around it.
 3406                  *
 3407                  * The currently held lease is still valid
 3408                  * until a new one is found.
 3409                  */
 3410                 if (state->state != DH6S_DISCOVER)
 3411                     dhcp6_startdiscoinform(ifp);
 3412                 return;
 3413             }
 3414             /* RFC8415 18.2.10.1 */
 3415             if ((state->state == DH6S_RENEW ||
 3416                 state->state == DH6S_REBIND) &&
 3417                 state->has_no_binding)
 3418             {
 3419                 dhcp6_startrequest(ifp);
 3420                 return;
 3421             }
 3422             if (state->state == DH6S_DISCOVER)
 3423                 state->state = DH6S_REQUEST;
 3424             break;
 3425         case DH6S_DECLINE:
 3426             /* This isnt really a failure, but an
 3427              * acknowledgement of one. */
 3428             loginfox("%s: %s acknowledged DECLINE6",
 3429                 ifp->name, sfrom);
 3430             dhcp6_fail(ifp);
 3431             return;
 3432         default:
 3433             valid_op = false;
 3434             break;
 3435         }
 3436         break;
 3437     case DHCP6_ADVERTISE:
 3438         if (state->state != DH6S_DISCOVER) {
 3439             valid_op = false;
 3440             break;
 3441         }
 3442         /* RFC7083 */
 3443         o = dhcp6_findmoption(r, len, D6_OPTION_SOL_MAX_RT, &ol);
 3444         if (o && ol == sizeof(uint32_t)) {
 3445             uint32_t max_rt;
 3446 
 3447             memcpy(&max_rt, o, sizeof(max_rt));
 3448             max_rt = ntohl(max_rt);
 3449             if (max_rt >= 60 && max_rt <= 86400) {
 3450                 logdebugx("%s: SOL_MAX_RT %llu -> %u",
 3451                     ifp->name,
 3452                     (unsigned long long)state->sol_max_rt,
 3453                     max_rt);
 3454                 state->sol_max_rt = max_rt;
 3455             } else
 3456                 logerr("%s: invalid SOL_MAX_RT %u",
 3457                     ifp->name, max_rt);
 3458         }
 3459         o = dhcp6_findmoption(r, len, D6_OPTION_INF_MAX_RT, &ol);
 3460         if (o && ol == sizeof(uint32_t)) {
 3461             uint32_t max_rt;
 3462 
 3463             memcpy(&max_rt, o, sizeof(max_rt));
 3464             max_rt = ntohl(max_rt);
 3465             if (max_rt >= 60 && max_rt <= 86400) {
 3466                 logdebugx("%s: INF_MAX_RT %llu -> %u",
 3467                     ifp->name,
 3468                     (unsigned long long)state->inf_max_rt,
 3469                     max_rt);
 3470                 state->inf_max_rt = max_rt;
 3471             } else
 3472                 logerrx("%s: invalid INF_MAX_RT %u",
 3473                     ifp->name, max_rt);
 3474         }
 3475         if (dhcp6_validatelease(ifp, r, len, sfrom, NULL) == -1)
 3476             return;
 3477         break;
 3478     case DHCP6_RECONFIGURE:
 3479 #ifdef AUTH
 3480         if (auth == NULL) {
 3481 #endif
 3482             logerrx("%s: unauthenticated %s from %s",
 3483                 ifp->name, op, sfrom);
 3484             if (ifo->auth.options & DHCPCD_AUTH_REQUIRE)
 3485                 return;
 3486 #ifdef AUTH
 3487         }
 3488         loginfox("%s: %s from %s", ifp->name, op, sfrom);
 3489         o = dhcp6_findmoption(r, len, D6_OPTION_RECONF_MSG, &ol);
 3490         if (o == NULL) {
 3491             logerrx("%s: missing Reconfigure Message option",
 3492                 ifp->name);
 3493             return;
 3494         }
 3495         if (ol != 1) {
 3496             logerrx("%s: missing Reconfigure Message type",
 3497                 ifp->name);
 3498             return;
 3499         }
 3500         switch(*o) {
 3501         case DHCP6_RENEW:
 3502             if (state->state != DH6S_BOUND) {
 3503                 logerrx("%s: not bound, ignoring %s",
 3504                     ifp->name, op);
 3505                 return;
 3506             }
 3507             dhcp6_startrenew(ifp);
 3508             break;
 3509         case DHCP6_INFORMATION_REQ:
 3510             if (state->state != DH6S_INFORMED) {
 3511                 logerrx("%s: not informed, ignoring %s",
 3512                     ifp->name, op);
 3513                 return;
 3514             }
 3515             eloop_timeout_delete(ifp->ctx->eloop,
 3516                 dhcp6_sendinform, ifp);
 3517             dhcp6_startinform(ifp);
 3518             break;
 3519         default:
 3520             logerr("%s: unsupported %s type %d",
 3521                 ifp->name, op, *o);
 3522             break;
 3523         }
 3524         return;
 3525 #else
 3526         break;
 3527 #endif
 3528     default:
 3529         logerrx("%s: invalid DHCP6 type %s (%d)",
 3530             ifp->name, op, r->type);
 3531         return;
 3532     }
 3533     if (!valid_op) {
 3534         logwarnx("%s: invalid state for DHCP6 type %s (%d)",
 3535             ifp->name, op, r->type);
 3536         return;
 3537     }
 3538 
 3539     if (state->recv_len < (size_t)len) {
 3540         free(state->recv);
 3541         state->recv = malloc(len);
 3542         if (state->recv == NULL) {
 3543             logerr(__func__);
 3544             return;
 3545         }
 3546     }
 3547     memcpy(state->recv, r, len);
 3548     state->recv_len = len;
 3549 
 3550     if (r->type == DHCP6_ADVERTISE) {
 3551         struct ipv6_addr *ia;
 3552 
 3553         if (state->state == DH6S_REQUEST) /* rapid commit */
 3554             goto bind;
 3555         TAILQ_FOREACH(ia, &state->addrs, next) {
 3556             if (!(ia->flags & (IPV6_AF_STALE | IPV6_AF_REQUEST)))
 3557                 break;
 3558         }
 3559         if (ia == NULL)
 3560             ia = TAILQ_FIRST(&state->addrs);
 3561         if (ia == NULL)
 3562             loginfox("%s: ADV (no address) from %s",
 3563                 ifp->name, sfrom);
 3564         else
 3565             loginfox("%s: ADV %s from %s",
 3566                 ifp->name, ia->saddr, sfrom);
 3567         dhcp6_startrequest(ifp);
 3568         return;
 3569     }
 3570 
 3571 bind:
 3572     dhcp6_bind(ifp, op, sfrom);
 3573 }
 3574 
 3575 void
 3576 dhcp6_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, struct ipv6_addr *ia)
 3577 {
 3578     struct sockaddr_in6 *from = msg->msg_name;
 3579     size_t len = msg->msg_iov[0].iov_len;
 3580     char sfrom[INET6_ADDRSTRLEN];
 3581     struct interface *ifp;
 3582     struct dhcp6_message *r;
 3583     const struct dhcp6_state *state;
 3584     uint8_t *o;
 3585     uint16_t ol;
 3586 
 3587     inet_ntop(AF_INET6, &from->sin6_addr, sfrom, sizeof(sfrom));
 3588     if (len < sizeof(struct dhcp6_message)) {
 3589         logerrx("DHCPv6 packet too short from %s", sfrom);
 3590         return;
 3591     }
 3592 
 3593     if (ia != NULL)
 3594         ifp = ia->iface;
 3595     else {
 3596         ifp = if_findifpfromcmsg(ctx, msg, NULL);
 3597         if (ifp == NULL) {
 3598             logerr(__func__);
 3599             return;
 3600         }
 3601     }
 3602 
 3603     r = (struct dhcp6_message *)msg->msg_iov[0].iov_base;
 3604 
 3605     uint8_t duid[DUID_LEN], *dp;
 3606     size_t duid_len;
 3607     o = dhcp6_findmoption(r, len, D6_OPTION_CLIENTID, &ol);
 3608     if (ifp->options->options & DHCPCD_ANONYMOUS) {
 3609         duid_len = duid_make(duid, ifp, DUID_LL);
 3610         dp = duid;
 3611     } else {
 3612         duid_len = ctx->duid_len;
 3613         dp = ctx->duid;
 3614     }
 3615     if (o == NULL || ol != duid_len || memcmp(o, dp, ol) != 0) {
 3616         logdebugx("%s: incorrect client ID from %s",
 3617             ifp->name, sfrom);
 3618         return;
 3619     }
 3620 
 3621     if (dhcp6_findmoption(r, len, D6_OPTION_SERVERID, NULL) == NULL) {
 3622         logdebugx("%s: no DHCPv6 server ID from %s",
 3623             ifp->name, sfrom);
 3624         return;
 3625     }
 3626 
 3627     if (r->type == DHCP6_RECONFIGURE) {
 3628         if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) {
 3629             logerrx("%s: RECONFIGURE6 recv from %s, not LL",
 3630                 ifp->name, sfrom);
 3631             return;
 3632         }
 3633         goto recvif;
 3634     }
 3635 
 3636     state = D6_CSTATE(ifp);
 3637     if (state == NULL ||
 3638         r->xid[0] != state->send->xid[0] ||
 3639         r->xid[1] != state->send->xid[1] ||
 3640         r->xid[2] != state->send->xid[2])
 3641     {
 3642         struct interface *ifp1;
 3643         const struct dhcp6_state *state1;
 3644 
 3645         /* Find an interface with a matching xid. */
 3646         TAILQ_FOREACH(ifp1, ctx->ifaces, next) {
 3647             state1 = D6_CSTATE(ifp1);
 3648             if (state1 == NULL || state1->send == NULL)
 3649                 continue;
 3650             if (r->xid[0] == state1->send->xid[0] &&
 3651                 r->xid[1] == state1->send->xid[1] &&
 3652                 r->xid[2] == state1->send->xid[2])
 3653                 break;
 3654         }
 3655 
 3656         if (ifp1 == NULL) {
 3657             if (state != NULL)
 3658                 logdebugx("%s: wrong xid 0x%02x%02x%02x"
 3659                     " (expecting 0x%02x%02x%02x) from %s",
 3660                     ifp->name,
 3661                     r->xid[0], r->xid[1], r->xid[2],
 3662                     state->send->xid[0],
 3663                     state->send->xid[1],
 3664                     state->send->xid[2],
 3665                     sfrom);
 3666             return;
 3667         }
 3668         logdebugx("%s: redirecting DHCP6 message to %s",
 3669             ifp->name, ifp1->name);
 3670         ifp = ifp1;
 3671     }
 3672 
 3673 #if 0
 3674     /*
 3675      * Handy code to inject raw DHCPv6 packets over responses
 3676      * from our server.
 3677      * This allows me to take a 3rd party wireshark trace and
 3678      * replay it in my code.
 3679      */
 3680     static int replyn = 0;
 3681     char fname[PATH_MAX], tbuf[UDPLEN_MAX];
 3682     int fd;
 3683     ssize_t tlen;
 3684     uint8_t *si1, *si2;
 3685     uint16_t si_len1, si_len2;
 3686 
 3687     snprintf(fname, sizeof(fname),
 3688         "/tmp/dhcp6.reply%d.raw", replyn++);
 3689     fd = open(fname, O_RDONLY, 0);
 3690     if (fd == -1) {
 3691         logerr("%s: open: %s", __func__, fname);
 3692         return;
 3693     }
 3694     tlen = read(fd, tbuf, sizeof(tbuf));
 3695     if (tlen == -1)
 3696         logerr("%s: read: %s", __func__, fname);
 3697     close(fd);
 3698 
 3699     /* Copy across ServerID so we can work with our own server. */
 3700     si1 = dhcp6_findmoption(r, len, D6_OPTION_SERVERID, &si_len1);
 3701     si2 = dhcp6_findmoption(tbuf, (size_t)tlen,
 3702         D6_OPTION_SERVERID, &si_len2);
 3703     if (si1 != NULL && si2 != NULL && si_len1 == si_len2)
 3704         memcpy(si2, si1, si_len2);
 3705     r = (struct dhcp6_message *)tbuf;
 3706     len = (size_t)tlen;
 3707 #endif
 3708 
 3709 recvif:
 3710     dhcp6_recvif(ifp, sfrom, r, len);
 3711 }
 3712 
 3713 static void
 3714 dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
 3715 {
 3716     struct sockaddr_in6 from;
 3717     union {
 3718         struct dhcp6_message dhcp6;
 3719         uint8_t buf[UDPLEN_MAX]; /* Maximum UDP message size */
 3720     } iovbuf;
 3721     struct iovec iov = {
 3722         .iov_base = iovbuf.buf, .iov_len = sizeof(iovbuf.buf),
 3723     };
 3724     union {
 3725         struct cmsghdr hdr;
 3726         uint8_t buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
 3727     } cmsgbuf = { .buf = { 0 } };
 3728     struct msghdr msg = {
 3729         .msg_name = &from, .msg_namelen = sizeof(from),
 3730         .msg_iov = &iov, .msg_iovlen = 1,
 3731         .msg_control = cmsgbuf.buf, .msg_controllen = sizeof(cmsgbuf.buf),
 3732     };
 3733     int s;
 3734     ssize_t bytes;
 3735 
 3736     s = ia != NULL ? ia->dhcp6_fd : ctx->dhcp6_rfd;
 3737     bytes = recvmsg(s, &msg, 0);
 3738     if (bytes == -1) {
 3739         logerr(__func__);
 3740         return;
 3741     }
 3742 
 3743     iov.iov_len = (size_t)bytes;
 3744     dhcp6_recvmsg(ctx, &msg, ia);
 3745 }
 3746 
 3747 static void
 3748 dhcp6_recvaddr(void *arg)
 3749 {
 3750     struct ipv6_addr *ia = arg;
 3751 
 3752     dhcp6_recv(ia->iface->ctx, ia);
 3753 }
 3754 
 3755 static void
 3756 dhcp6_recvctx(void *arg)
 3757 {
 3758     struct dhcpcd_ctx *ctx = arg;
 3759 
 3760     dhcp6_recv(ctx, NULL);
 3761 }
 3762 
 3763 int
 3764 dhcp6_openraw(void)
 3765 {
 3766     int fd, v;
 3767 
 3768     fd = socket(PF_INET6, SOCK_RAW | SOCK_CXNB, IPPROTO_UDP);
 3769     if (fd == -1)
 3770         return -1;
 3771 
 3772     v = 1;
 3773     if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &v, sizeof(v)) == -1)
 3774         goto errexit;
 3775 
 3776     v = offsetof(struct udphdr, uh_sum);
 3777     if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &v, sizeof(v)) == -1)
 3778         goto errexit;
 3779 
 3780     return fd;
 3781 
 3782 errexit:
 3783     close(fd);
 3784     return -1;
 3785 }
 3786 
 3787 int
 3788 dhcp6_openudp(unsigned int ifindex, struct in6_addr *ia)
 3789 {
 3790     struct sockaddr_in6 sa;
 3791     int n, s;
 3792 
 3793     s = xsocket(PF_INET6, SOCK_DGRAM | SOCK_CXNB, IPPROTO_UDP);
 3794     if (s == -1)
 3795         goto errexit;
 3796 
 3797     memset(&sa, 0, sizeof(sa));
 3798     sa.sin6_family = AF_INET6;
 3799     sa.sin6_port = htons(DHCP6_CLIENT_PORT);
 3800 #ifdef BSD
 3801     sa.sin6_len = sizeof(sa);
 3802 #endif
 3803 
 3804     if (ia != NULL) {
 3805         memcpy(&sa.sin6_addr, ia, sizeof(sa.sin6_addr));
 3806         ipv6_setscope(&sa, ifindex);
 3807     }
 3808 
 3809     if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) == -1)
 3810         goto errexit;
 3811 
 3812     n = 1;
 3813     if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &n, sizeof(n)) == -1)
 3814         goto errexit;
 3815 
 3816 #ifdef SO_RERROR
 3817     n = 1;
 3818     if (setsockopt(s, SOL_SOCKET, SO_RERROR, &n, sizeof(n)) == -1)
 3819         goto errexit;
 3820 #endif
 3821 
 3822     return s;
 3823 
 3824 errexit:
 3825     logerr(__func__);
 3826     if (s != -1)
 3827         close(s);
 3828     return -1;
 3829 }
 3830 
 3831 #ifndef SMALL
 3832 static void
 3833 dhcp6_activateinterfaces(struct interface *ifp)
 3834 {
 3835     struct interface *ifd;
 3836     size_t i, j;
 3837     struct if_ia *ia;
 3838     struct if_sla *sla;
 3839 
 3840     for (i = 0; i < ifp->options->ia_len; i++) {
 3841         ia = &ifp->options->ia[i];
 3842         if (ia->ia_type != D6_OPTION_IA_PD)
 3843             continue;
 3844         for (j = 0; j < ia->sla_len; j++) {
 3845             sla = &ia->sla[j];
 3846             ifd = if_find(ifp->ctx->ifaces, sla->ifname);
 3847             if (ifd == NULL) {
 3848                 logwarn("%s: cannot delegate to %s",
 3849                     ifp->name, sla->ifname);
 3850                 continue;
 3851             }
 3852             if (!ifd->active) {
 3853                 loginfox("%s: activating for delegation",
 3854                     sla->ifname);
 3855                 dhcpcd_activateinterface(ifd,
 3856                     DHCPCD_IPV6 | DHCPCD_DHCP6);
 3857             }
 3858         }
 3859     }
 3860 }
 3861 #endif
 3862 
 3863 static void
 3864 dhcp6_start1(void *arg)
 3865 {
 3866     struct interface *ifp = arg;
 3867     struct dhcpcd_ctx *ctx = ifp->ctx;
 3868     struct if_options *ifo = ifp->options;
 3869     struct dhcp6_state *state;
 3870     size_t i;
 3871     const struct dhcp_compat *dhc;
 3872 
 3873     if ((ctx->options & (DHCPCD_MANAGER|DHCPCD_PRIVSEP)) == DHCPCD_MANAGER &&
 3874         ctx->dhcp6_rfd == -1)
 3875     {
 3876         ctx->dhcp6_rfd = dhcp6_openudp(0, NULL);
 3877         if (ctx->dhcp6_rfd == -1) {
 3878             logerr(__func__);
 3879             return;
 3880         }
 3881         eloop_event_add(ctx->eloop, ctx->dhcp6_rfd, dhcp6_recvctx, ctx);
 3882     }
 3883 
 3884     if (!IN_PRIVSEP(ctx) && ctx->dhcp6_wfd == -1) {
 3885         ctx->dhcp6_wfd = dhcp6_openraw();
 3886         if (ctx->dhcp6_wfd == -1) {
 3887             logerr(__func__);
 3888             return;
 3889         }
 3890     }
 3891 
 3892     state = D6_STATE(ifp);
 3893     /* If no DHCPv6 options are configured,
 3894        match configured DHCPv4 options to DHCPv6 equivalents. */
 3895     for (i = 0; i < sizeof(ifo->requestmask6); i++) {
 3896         if (ifo->requestmask6[i] != '\0')
 3897             break;
 3898     }
 3899     if (i == sizeof(ifo->requestmask6)) {
 3900         for (dhc = dhcp_compats; dhc->dhcp_opt; dhc++) {
 3901             if (DHC_REQ(ifo->requestmask, ifo->nomask, dhc->dhcp_opt))
 3902                 add_option_mask(ifo->requestmask6,
 3903                     dhc->dhcp6_opt);
 3904         }
 3905         if (ifo->fqdn != FQDN_DISABLE || ifo->options & DHCPCD_HOSTNAME)
 3906             add_option_mask(ifo->requestmask6, D6_OPTION_FQDN);
 3907     }
 3908 
 3909 #ifndef SMALL
 3910     /* Rapid commit won't work with Prefix Delegation Exclusion */
 3911     if (dhcp6_findselfsla(ifp))
 3912         del_option_mask(ifo->requestmask6, D6_OPTION_RAPID_COMMIT);
 3913 #endif
 3914 
 3915     if (state->state == DH6S_INFORM) {
 3916         add_option_mask(ifo->requestmask6, D6_OPTION_INFO_REFRESH_TIME);
 3917         dhcp6_startinform(ifp);
 3918     } else {
 3919         del_option_mask(ifo->requestmask6, D6_OPTION_INFO_REFRESH_TIME);
 3920         dhcp6_startinit(ifp);
 3921     }
 3922 
 3923 #ifndef SMALL
 3924     dhcp6_activateinterfaces(ifp);
 3925 #endif
 3926 }
 3927 
 3928 int
 3929 dhcp6_start(struct interface *ifp, enum DH6S init_state)
 3930 {
 3931     struct dhcp6_state *state;
 3932 
 3933     state = D6_STATE(ifp);
 3934     if (state != NULL) {
 3935         switch (init_state) {
 3936         case DH6S_INIT:
 3937             goto gogogo;
 3938         case DH6S_INFORM:
 3939             if (state->state == DH6S_INIT ||
 3940                 state->state == DH6S_INFORMED ||
 3941                 (state->state == DH6S_DISCOVER &&
 3942                 !(ifp->options->options & DHCPCD_IA_FORCED) &&
 3943                 !ipv6nd_hasradhcp(ifp, true)))
 3944             {
 3945                 /* We don't want log spam when the RA
 3946                  * has just adjusted it's prefix times. */
 3947                 if (state->state != DH6S_INFORMED)
 3948                     state->new_start = true;
 3949                 dhcp6_startinform(ifp);
 3950             }
 3951             break;
 3952         case DH6S_REQUEST:
 3953             if (ifp->options->options & DHCPCD_DHCP6 &&
 3954                 (state->state == DH6S_INIT ||
 3955                  state->state == DH6S_INFORM ||
 3956                  state->state == DH6S_INFORMED ||
 3957                  state->state == DH6S_DELEGATED))
 3958             {
 3959                 /* Change from stateless to stateful */
 3960                 init_state = DH6S_INIT;
 3961                 goto gogogo;
 3962             }
 3963             break;
 3964         case DH6S_CONFIRM:
 3965             init_state = DH6S_INIT;
 3966             goto gogogo;
 3967         default:
 3968             /* Not possible, but sushes some compiler warnings. */
 3969             break;
 3970         }
 3971         return 0;
 3972     } else {
 3973         switch (init_state) {
 3974         case DH6S_CONFIRM:
 3975             /* No DHCPv6 config, no existing state
 3976              * so nothing to do. */
 3977             return 0;
 3978         case DH6S_INFORM:
 3979             break;
 3980         default:
 3981             init_state = DH6S_INIT;
 3982             break;
 3983         }
 3984     }
 3985 
 3986     if (!(ifp->options->options & DHCPCD_DHCP6))
 3987         return 0;
 3988 
 3989     ifp->if_data[IF_DATA_DHCP6] = calloc(1, sizeof(*state));
 3990     state = D6_STATE(ifp);
 3991     if (state == NULL)
 3992         return -1;
 3993 
 3994     state->sol_max_rt = SOL_MAX_RT;
 3995     state->inf_max_rt = INF_MAX_RT;
 3996     TAILQ_INIT(&state->addrs);
 3997 
 3998 gogogo:
 3999     state->new_start = true;
 4000     state->state = init_state;
 4001     state->lerror = 0;
 4002     state->failed = false;
 4003     dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
 4004         AF_INET6, ifp);
 4005     if (ipv6_linklocal(ifp) == NULL) {
 4006         logdebugx("%s: delaying DHCPv6 for LL address", ifp->name);
 4007         ipv6_addlinklocalcallback(ifp, dhcp6_start1, ifp);
 4008         return 0;
 4009     }
 4010 
 4011     dhcp6_start1(ifp);
 4012     return 0;
 4013 }
 4014 
 4015 void
 4016 dhcp6_reboot(struct interface *ifp)
 4017 {
 4018     struct dhcp6_state *state;
 4019 
 4020     state = D6_STATE(ifp);
 4021     if (state == NULL)
 4022         return;
 4023 
 4024     state->lerror = 0;
 4025     switch (state->state) {
 4026     case DH6S_BOUND:
 4027         dhcp6_startrebind(ifp);
 4028         break;
 4029     default:
 4030         dhcp6_startdiscoinform(ifp);
 4031         break;
 4032     }
 4033 }
 4034 
 4035 static void
 4036 dhcp6_freedrop(struct interface *ifp, int drop, const char *reason)
 4037 {
 4038     struct dhcp6_state *state;
 4039     struct dhcpcd_ctx *ctx;
 4040     unsigned long long options;
 4041 
 4042     if (ifp->options)
 4043         options = ifp->options->options;
 4044     else
 4045         options = ifp->ctx->options;
 4046 
 4047     if (ifp->ctx->eloop)
 4048         eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 4049 
 4050 #ifndef SMALL
 4051     /* If we're dropping the lease, drop delegated addresses.
 4052      * If, for whatever reason, we don't drop them in the future
 4053      * then they should at least be marked as deprecated (pltime 0). */
 4054     if (drop && (options & DHCPCD_NODROP) != DHCPCD_NODROP)
 4055         dhcp6_delete_delegates(ifp);
 4056 #endif
 4057 
 4058     state = D6_STATE(ifp);
 4059     if (state) {
 4060         /* Failure to send the release may cause this function to
 4061          * re-enter */
 4062         if (state->state == DH6S_RELEASE) {
 4063             dhcp6_finishrelease(ifp);
 4064             return;
 4065         }
 4066 
 4067         if (drop && options & DHCPCD_RELEASE &&
 4068             state->state != DH6S_DELEGATED)
 4069         {
 4070             if (if_is_link_up(ifp) &&
 4071                 state->state != DH6S_RELEASED &&
 4072                 state->state != DH6S_INFORMED)
 4073             {
 4074                 dhcp6_startrelease(ifp);
 4075                 return;
 4076             }
 4077             dhcp_unlink(ifp->ctx, state->leasefile);
 4078         }
 4079 #ifdef AUTH
 4080         else if (state->auth.reconf != NULL) {
 4081             /*
 4082              * Drop the lease as the token may only be present
 4083              * in the initial reply message and not subsequent
 4084              * renewals.
 4085              * If dhcpcd is restarted, the token is lost.
 4086              * XXX persist this in another file?
 4087              */
 4088             dhcp_unlink(ifp->ctx, state->leasefile);
 4089         }
 4090 #endif
 4091 
 4092         dhcp6_freedrop_addrs(ifp, drop, NULL);
 4093         free(state->old);
 4094         state->old = state->new;
 4095         state->old_len = state->new_len;
 4096         state->new = NULL;
 4097         state->new_len = 0;
 4098         if (drop && state->old &&
 4099             (options & DHCPCD_NODROP) != DHCPCD_NODROP)
 4100         {
 4101             if (reason == NULL)
 4102                 reason = "STOP6";
 4103             script_runreason(ifp, reason);
 4104         }
 4105         free(state->old);
 4106         free(state->send);
 4107         free(state->recv);
 4108         free(state);
 4109         ifp->if_data[IF_DATA_DHCP6] = NULL;
 4110     }
 4111 
 4112     /* If we don't have any more DHCP6 enabled interfaces,
 4113      * close the global socket and release resources */
 4114     ctx = ifp->ctx;
 4115     if (ctx->ifaces) {
 4116         TAILQ_FOREACH(ifp, ctx->ifaces, next) {
 4117             if (D6_STATE(ifp))
 4118                 break;
 4119         }
 4120     }
 4121     if (ifp == NULL && ctx->dhcp6_rfd != -1) {
 4122         eloop_event_delete(ctx->eloop, ctx->dhcp6_rfd);
 4123         close(ctx->dhcp6_rfd);
 4124         ctx->dhcp6_rfd = -1;
 4125     }
 4126 }
 4127 
 4128 void
 4129 dhcp6_drop(struct interface *ifp, const char *reason)
 4130 {
 4131 
 4132     dhcp6_freedrop(ifp, 1, reason);
 4133 }
 4134 
 4135 void
 4136 dhcp6_free(struct interface *ifp)
 4137 {
 4138 
 4139     dhcp6_freedrop(ifp, 0, NULL);
 4140 }
 4141 
 4142 void
 4143 dhcp6_abort(struct interface *ifp)
 4144 {
 4145     struct dhcp6_state *state;
 4146 #ifdef ND6_ADVERTISE
 4147     struct ipv6_addr *ia;
 4148 #endif
 4149 
 4150     eloop_timeout_delete(ifp->ctx->eloop, dhcp6_start1, ifp);
 4151     state = D6_STATE(ifp);
 4152     if (state == NULL)
 4153         return;
 4154 
 4155 #ifdef ND6_ADVERTISE
 4156     TAILQ_FOREACH(ia, &state->addrs, next) {
 4157         ipv6nd_advertise(ia);
 4158     }
 4159 #endif
 4160 
 4161     eloop_timeout_delete(ifp->ctx->eloop, dhcp6_startdiscover, ifp);
 4162     eloop_timeout_delete(ifp->ctx->eloop, dhcp6_senddiscover, ifp);
 4163     eloop_timeout_delete(ifp->ctx->eloop, dhcp6_startinform, ifp);
 4164     eloop_timeout_delete(ifp->ctx->eloop, dhcp6_sendinform, ifp);
 4165 
 4166     switch (state->state) {
 4167     case DH6S_DISCOVER: /* FALLTHROUGH */
 4168     case DH6S_REQUEST:  /* FALLTHROUGH */
 4169     case DH6S_INFORM:
 4170         state->state = DH6S_INIT;
 4171         break;
 4172     default:
 4173         break;
 4174     }
 4175 }
 4176 
 4177 void
 4178 dhcp6_handleifa(int cmd, struct ipv6_addr *ia, pid_t pid)
 4179 {
 4180     struct dhcp6_state *state;
 4181     struct interface *ifp = ia->iface;
 4182 
 4183     /* If not running in manager mode, listen to this address */
 4184     if (cmd == RTM_NEWADDR &&
 4185         !(ia->addr_flags & IN6_IFF_NOTUSEABLE) &&
 4186         ifp->active == IF_ACTIVE_USER &&
 4187         !(ifp->ctx->options & DHCPCD_MANAGER) &&
 4188         ifp->options->options & DHCPCD_DHCP6)
 4189     {
 4190 #ifdef PRIVSEP
 4191         if (IN_PRIVSEP_SE(ifp->ctx)) {
 4192             if (ps_inet_opendhcp6(ia) == -1)
 4193                 logerr(__func__);
 4194         } else
 4195 #endif
 4196         {
 4197             if (ia->dhcp6_fd == -1)
 4198                 ia->dhcp6_fd = dhcp6_openudp(ia->iface->index,
 4199                     &ia->addr);
 4200             if (ia->dhcp6_fd != -1)
 4201                 eloop_event_add(ia->iface->ctx->eloop,
 4202                 ia->dhcp6_fd, dhcp6_recvaddr, ia);
 4203         }
 4204     }
 4205 
 4206 
 4207     if ((state = D6_STATE(ifp)) != NULL)
 4208         ipv6_handleifa_addrs(cmd, &state->addrs, ia, pid);
 4209 }
 4210 
 4211 ssize_t
 4212 dhcp6_env(FILE *fp, const char *prefix, const struct interface *ifp,
 4213     const struct dhcp6_message *m, size_t len)
 4214 {
 4215     const struct if_options *ifo;
 4216     struct dhcp_opt *opt, *vo;
 4217     const uint8_t *p;
 4218     struct dhcp6_option o;
 4219     size_t i;
 4220     char *pfx;
 4221     uint32_t en;
 4222     const struct dhcpcd_ctx *ctx;
 4223 #ifndef SMALL
 4224     const struct dhcp6_state *state;
 4225     const struct ipv6_addr *ap;
 4226 #endif
 4227 
 4228     if (m == NULL)
 4229         goto delegated;
 4230 
 4231     if (len < sizeof(*m)) {
 4232         /* Should be impossible with guards at packet in
 4233          * and reading leases */
 4234         errno = EINVAL;
 4235         return -1;
 4236     }
 4237 
 4238     ifo = ifp->options;
 4239     ctx = ifp->ctx;
 4240 
 4241     /* Zero our indexes */
 4242     for (i = 0, opt = ctx->dhcp6_opts;
 4243         i < ctx->dhcp6_opts_len;
 4244         i++, opt++)
 4245         dhcp_zero_index(opt);
 4246     for (i = 0, opt = ifp->options->dhcp6_override;
 4247         i < ifp->options->dhcp6_override_len;
 4248         i++, opt++)
 4249         dhcp_zero_index(opt);
 4250     for (i = 0, opt = ctx->vivso;
 4251         i < ctx->vivso_len;
 4252         i++, opt++)
 4253         dhcp_zero_index(opt);
 4254     if (asprintf(&pfx, "%s_dhcp6", prefix) == -1)
 4255         return -1;
 4256 
 4257     /* Unlike DHCP, DHCPv6 options *may* occur more than once.
 4258      * There is also no provision for option concatenation unlike DHCP. */
 4259     p = (const uint8_t *)m + sizeof(*m);
 4260     len -= sizeof(*m);
 4261     for (; len != 0; p += o.len, len -= o.len) {
 4262         if (len < sizeof(o)) {
 4263             errno = EINVAL;
 4264             break;
 4265         }
 4266         memcpy(&o, p, sizeof(o));
 4267         p += sizeof(o);
 4268         len -= sizeof(o);
 4269         o.len = ntohs(o.len);
 4270         if (len < o.len) {
 4271             errno = EINVAL;
 4272             break;
 4273         }
 4274         o.code = ntohs(o.code);
 4275         if (has_option_mask(ifo->nomask6, o.code))
 4276             continue;
 4277         for (i = 0, opt = ifo->dhcp6_override;
 4278             i < ifo->dhcp6_override_len;
 4279             i++, opt++)
 4280             if (opt->option == o.code)
 4281                 break;
 4282         if (i == ifo->dhcp6_override_len &&
 4283             o.code == D6_OPTION_VENDOR_OPTS &&
 4284             o.len > sizeof(en))
 4285         {
 4286             memcpy(&en, p, sizeof(en));
 4287             en = ntohl(en);
 4288             vo = vivso_find(en, ifp);
 4289         } else
 4290             vo = NULL;
 4291         if (i == ifo->dhcp6_override_len) {
 4292             for (i = 0, opt = ctx->dhcp6_opts;
 4293                 i < ctx->dhcp6_opts_len;
 4294                 i++, opt++)
 4295                 if (opt->option == o.code)
 4296                     break;
 4297             if (i == ctx->dhcp6_opts_len)
 4298                 opt = NULL;
 4299         }
 4300         if (opt) {
 4301             dhcp_envoption(ifp->ctx,
 4302                 fp, pfx, ifp->name,
 4303                 opt, dhcp6_getoption, p, o.len);
 4304         }
 4305         if (vo) {
 4306             dhcp_envoption(ifp->ctx,
 4307                 fp, pfx, ifp->name,
 4308                 vo, dhcp6_getoption,
 4309                 p + sizeof(en),
 4310                 o.len - sizeof(en));
 4311         }
 4312     }
 4313     free(pfx);
 4314 
 4315 delegated:
 4316 #ifndef SMALL
 4317         /* Needed for Delegated Prefixes */
 4318     state = D6_CSTATE(ifp);
 4319     TAILQ_FOREACH(ap, &state->addrs, next) {
 4320         if (ap->delegating_prefix)
 4321             break;
 4322     }
 4323     if (ap == NULL)
 4324         return 1;
 4325     if (fprintf(fp, "%s_delegated_dhcp6_prefix=", prefix) == -1)
 4326         return -1;
 4327     TAILQ_FOREACH(ap, &state->addrs, next) {
 4328         if (ap->delegating_prefix == NULL)
 4329             continue;
 4330         if (ap != TAILQ_FIRST(&state->addrs)) {
 4331             if (fputc(' ', fp) == EOF)
 4332                 return -1;
 4333         }
 4334         if (fprintf(fp, "%s", ap->saddr) == -1)
 4335             return -1;
 4336         }
 4337     if (fputc('\0', fp) == EOF)
 4338         return -1;
 4339 #endif
 4340 
 4341     return 1;
 4342 }
 4343 #endif
 4344 
 4345 #ifndef SMALL
 4346 int
 4347 dhcp6_dump(struct interface *ifp)
 4348 {
 4349     struct dhcp6_state *state;
 4350 
 4351     ifp->if_data[IF_DATA_DHCP6] = state = calloc(1, sizeof(*state));
 4352     if (state == NULL) {
 4353         logerr(__func__);
 4354         return -1;
 4355     }
 4356     TAILQ_INIT(&state->addrs);
 4357     if (dhcp6_readlease(ifp, 0) == -1) {
 4358         logerr("dhcp6_readlease");
 4359         return -1;
 4360     }
 4361     state->reason = "DUMP6";
 4362     return script_runreason(ifp, state->reason);
 4363 }
 4364 #endif