]> git.pld-linux.org Git - packages/dhcpcd.git/commitdiff
- correct patch auto/th/dhcpcd-8.1.1-2
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Wed, 6 Nov 2019 13:56:48 +0000 (14:56 +0100)
committerArkadiusz Miśkiewicz <arekm@maven.pl>
Wed, 6 Nov 2019 13:56:48 +0000 (14:56 +0100)
cpuhog.patch [new file with mode: 0644]
dhcpcd-git.patch [deleted file]

diff --git a/cpuhog.patch b/cpuhog.patch
new file mode 100644 (file)
index 0000000..58863ae
--- /dev/null
@@ -0,0 +1,52 @@
+From 73ac184333f77b38a8b4c4202c2928278e2237ca Mon Sep 17 00:00:00 2001
+From: Roy Marples <roy@marples.name>
+Date: Tue, 5 Nov 2019 15:52:57 +0000
+Subject: INET: Fix corruption of IPv4 address flags when renewing
+
+What a mistaka to maka!
+---
+ src/ipv4.c | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+(limited to 'src')
+
+diff --git a/src/ipv4.c b/src/ipv4.c
+index fd2a15d7..53550696 100644
+--- a/src/ipv4.c
++++ b/src/ipv4.c
+@@ -654,7 +654,7 @@ ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
+ #endif
+               ia->flags = IPV4_AF_NEW;
+       } else
+-              ia->flags |= ~IPV4_AF_NEW;
++              ia->flags &= ~IPV4_AF_NEW;
+       ia->mask = *mask;
+       ia->brd = *bcast;
+@@ -952,15 +952,13 @@ ipv4_free(struct interface *ifp)
+       struct ipv4_state *state;
+       struct ipv4_addr *ia;
+-      if (ifp) {
+-              state = IPV4_STATE(ifp);
+-              if (state) {
+-                      while ((ia = TAILQ_FIRST(&state->addrs))) {
+-                              TAILQ_REMOVE(&state->addrs, ia, next);
+-                              free(ia);
+-                      }
+-                      free(state->buffer);
+-                      free(state);
+-              }
++      if (ifp == NULL || (state = IPV4_STATE(ifp)) == NULL)
++              return;
++
++      while ((ia = TAILQ_FIRST(&state->addrs))) {
++              TAILQ_REMOVE(&state->addrs, ia, next);
++              free(ia);
+       }
++      free(state->buffer);
++      free(state);
+ }
+-- 
+cgit v1.2.1
+
diff --git a/dhcpcd-git.patch b/dhcpcd-git.patch
deleted file mode 100644 (file)
index 9a77b9c..0000000
+++ /dev/null
@@ -1,3014 +0,0 @@
-diff -urN dhcpcd-6.4.0.org/configure dhcpcd-6.4.0/configure
---- dhcpcd-6.4.0.org/configure 2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/configure     2014-07-05 21:47:22.000000000 +0200
-@@ -272,8 +272,18 @@
- fi
- echo "Using compiler .. $CC"
--if ! type "$CC" >/dev/null 2>&1; then
--      echo "$CC is not an executable"
-+cat <<EOF >_test.c
-+int main(void) {
-+      return 0;
-+}
-+EOF
-+_CC=false
-+if $CC _test.c -o _test >/dev/null 2>&1; then
-+      [ -x _test ] && _CC=true
-+fi
-+rm -f _test.c _test
-+if ! $_CC; then
-+      echo "$CC does not create executables"
-       exit 1
- fi
- [ "$CC" != cc ] && echo "CC=  $CC" >>$CONFIG_MK
-@@ -422,7 +432,7 @@
- EOF
- if $XCC _getifaddrs.c -o _getifaddrs 2>/dev/null; then
-       echo "yes"
--elif $XCC _getifaddrs.c -o _getifaddrs -lsocket >/dev/null; then
-+elif $XCC _getifaddrs.c -o _getifaddrs -lsocket 2>/dev/null; then
-       echo "yes (-lsocket)"
-       echo "LDADD+=           -lsocket" >>$CONFIG_MK
- else
-diff -urN dhcpcd-6.4.0.org/control.c dhcpcd-6.4.0/control.c
---- dhcpcd-6.4.0.org/control.c 2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/control.c     2014-07-05 21:47:22.000000000 +0200
-@@ -52,8 +52,9 @@
- control_handle_data(void *arg)
- {
-       struct fd_list *l = arg, *lp, *last;
--      char buffer[1024], *e, *p, *argvp[255], **ap;
-+      char buffer[1024], *e, *p, *argvp[255], **ap, *a;
-       ssize_t bytes;
-+      size_t len;
-       int argc;
-       bytes = read(l->fd, buffer, sizeof(buffer) - 1);
-@@ -79,14 +80,28 @@
-       buffer[bytes] = '\0';
-       p = buffer;
-       e = buffer + bytes;
--      argc = 0;
--      ap = argvp;
--      while (p < e && (size_t)argc < sizeof(argvp)) {
--              argc++;
--              *ap++ = p;
--              p += strlen(p) + 1;
-+
-+      /* Each command is \n terminated
-+       * Each argument is NULL separated */
-+      while (p < e) {
-+              argc = 0;
-+              ap = argvp;
-+              while (p < e) {
-+                      argc++;
-+                      if ((size_t)argc > sizeof(argvp)) {
-+                              errno = ENOBUFS;
-+                              return;
-+                      }
-+                      a = *ap++ = p;
-+                      len = strlen(p);
-+                      p += len + 1;
-+                      if (a[len - 1] == '\n') {
-+                              a[len - 1] = '\0';
-+                              break;
-+                      }
-+              }
-+              dhcpcd_handleargs(l->ctx, l, argc, argvp);
-       }
--      dhcpcd_handleargs(l->ctx, l, argc, argvp);
- }
- static void
-diff -urN dhcpcd-6.4.0.org/defs.h dhcpcd-6.4.0/defs.h
---- dhcpcd-6.4.0.org/defs.h    2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/defs.h        2014-07-05 21:47:22.000000000 +0200
-@@ -49,7 +49,7 @@
- # define LEASEFILE            DBDIR "/" PACKAGE "-%s.lease"
- #endif
- #ifndef LEASEFILE6
--# define LEASEFILE6           DBDIR "/" PACKAGE "-%s.lease6"
-+# define LEASEFILE6           DBDIR "/" PACKAGE "-%s%s.lease6"
- #endif
- #ifndef PIDFILE
- # define PIDFILE              RUNDIR "/" PACKAGE "%s%s%s.pid"
-diff -urN dhcpcd-6.4.0.org/dhcp6.c dhcpcd-6.4.0/dhcp6.c
---- dhcpcd-6.4.0.org/dhcp6.c   2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp6.c       2014-07-05 21:47:22.000000000 +0200
-@@ -121,13 +121,22 @@
- };
- void
--dhcp6_printoptions(const struct dhcpcd_ctx *ctx)
-+dhcp6_printoptions(const struct dhcpcd_ctx *ctx,
-+    const struct dhcp_opt *opts, size_t opts_len)
- {
--      size_t i;
--      const struct dhcp_opt *opt;
-+      size_t i, j;
-+      const struct dhcp_opt *opt, *opt2;
-       for (i = 0, opt = ctx->dhcp6_opts;
-           i < ctx->dhcp6_opts_len; i++, opt++)
-+      {
-+              for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
-+                      if (opt2->option == opt->option)
-+                              break;
-+              if (j == opts_len)
-+                      printf("%05d %s\n", opt->option, opt->var);
-+      }
-+      for (i = 0, opt = opts; i < opts_len; i++, opt++)
-               printf("%05d %s\n", opt->option, opt->var);
- }
-@@ -304,24 +313,112 @@
-       m->xid[2] = xid & 0xff;
- }
-+static const struct if_sla *
-+dhcp6_findselfsla(struct interface *ifp, const uint8_t *iaid)
-+{
-+      size_t i, j;
-+
-+      for (i = 0; i < ifp->options->ia_len; i++) {
-+              if (iaid == NULL ||
-+                  memcmp(&ifp->options->ia[i].iaid, iaid,
-+                  sizeof(ifp->options->ia[i].iaid)) == 0)
-+              {
-+                      for (j = 0; j < ifp->options->ia[i].sla_len; j++) {
-+                              if (strcmp(ifp->options->ia[i].sla[j].ifname,
-+                                  ifp->name) == 0)
-+                                      return &ifp->options->ia[i].sla[j];
-+                      }
-+              }
-+      }
-+      return NULL;
-+}
-+
-+static int
-+dhcp6_delegateaddr(struct in6_addr *addr, struct interface *ifp,
-+    const struct ipv6_addr *prefix, const struct if_sla *sla)
-+{
-+      struct dhcp6_state *state;
-+      struct if_sla asla;
-+      char iabuf[INET6_ADDRSTRLEN];
-+      const char *ia;
-+
-+      state = D6_STATE(ifp);
-+      if (state == NULL) {
-+              ifp->if_data[IF_DATA_DHCP6] = calloc(1, sizeof(*state));
-+              state = D6_STATE(ifp);
-+              if (state == NULL) {
-+                      syslog(LOG_ERR, "%s: %m", __func__);
-+                      return -1;
-+              }
-+
-+              TAILQ_INIT(&state->addrs);
-+              state->state = DH6S_DELEGATED;
-+              state->reason = "DELEGATED6";
-+      }
-+
-+      if (sla == NULL || sla->sla_set == 0) {
-+              struct interface *ifi;
-+              unsigned int idx;
-+              int bits;
-+
-+              asla.sla = ifp->index;
-+              /* Work out our largest index delegating to. */
-+              idx = 0;
-+              TAILQ_FOREACH(ifi, ifp->ctx->ifaces, next) {
-+                      if (ifi != ifp && ifi->index > idx)
-+                              idx = ifi->index;
-+              }
-+              bits = ffs((int)idx);
-+              if (prefix->prefix_len + bits > UINT8_MAX)
-+                      asla.prefix_len = UINT8_MAX;
-+              else {
-+                      asla.prefix_len = prefix->prefix_len + (uint8_t)bits;
-+
-+                      /* Make a 64 prefix by default, as this maks SLAAC
-+                       * possible. Otherwise round up to the nearest octet. */
-+                      if (asla.prefix_len <= 64)
-+                              asla.prefix_len = 64;
-+                      else
-+                              asla.prefix_len = ROUNDUP8(asla.prefix_len);
-+
-+              }
-+              sla = &asla;
-+      }
-+
-+      if (ipv6_userprefix(&prefix->prefix, prefix->prefix_len,
-+              sla->sla, addr, sla->prefix_len) == -1)
-+      {
-+              ia = inet_ntop(AF_INET6, &prefix->prefix.s6_addr,
-+                  iabuf, sizeof(iabuf));
-+              syslog(LOG_ERR, "%s: invalid prefix %s/%d + %d/%d: %m",
-+                      ifp->name, ia, prefix->prefix_len,
-+                      sla->sla, sla->prefix_len);
-+              return -1;
-+      }
-+
-+      return 0;
-+}
-+
- static int
- dhcp6_makemessage(struct interface *ifp)
- {
-       struct dhcp6_state *state;
-       struct dhcp6_message *m;
--      struct dhcp6_option *o, *so;
-+      struct dhcp6_option *o, *so, *eo;
-       const struct dhcp6_option *si, *unicast;
--      size_t l, len, ml, auth_len;
-+      size_t l, n, len, ml, auth_len;
-       uint8_t u8, type;
-       uint16_t *u16, n_options;
-       struct if_options *ifo;
--      const struct dhcp_opt *opt;
-+      const struct dhcp_opt *opt, *opt2;
-       uint8_t IA, *p;
-       uint32_t u32;
-       const struct ipv6_addr *ap;
-       char hbuf[HOSTNAME_MAX_LEN + 1];
-       const char *hostname;
-       int fqdn;
-+      const struct if_sla *sla;
-+      struct in6_addr addr;
-       state = D6_STATE(ifp);
-       if (state->send) {
-@@ -356,6 +453,15 @@
-                   l < ifp->ctx->dhcp6_opts_len;
-                   l++, opt++)
-               {
-+                      for (n = 0, opt2 = ifo->dhcp6_override;
-+                          n < ifo->dhcp6_override_len;
-+                          n++, opt2++)
-+                      {
-+                              if (opt->option == opt2->option)
-+                                      break;
-+                      }
-+                      if (n < ifo->dhcp6_override_len)
-+                          continue;
-                       if (!(opt->type & NOREQ) &&
-                           (opt->type & REQUEST ||
-                           has_option_mask(ifo->requestmask6, opt->option)))
-@@ -364,6 +470,22 @@
-                               len += sizeof(*u16);
-                       }
-               }
-+              for (l = 0, opt = ifo->dhcp6_override;
-+                  l < ifo->dhcp6_override_len;
-+                  l++, opt++)
-+              {
-+                      if (!(opt->type & NOREQ) &&
-+                          (opt->type & REQUEST ||
-+                          has_option_mask(ifo->requestmask6, opt->option)))
-+                      {
-+                              n_options++;
-+                              len += sizeof(*u16);
-+                      }
-+              }
-+              if (dhcp6_findselfsla(ifp, NULL)) {
-+                      n_options++;
-+                      len += sizeof(*u16);
-+              }
-               if (len)
-                       len += sizeof(*o);
-@@ -405,25 +527,43 @@
-       case DH6S_REBIND:
-               /* FALLTHROUGH */
-       case DH6S_CONFIRM:
-+              /* FALLTHROUGH */
-+      case DH6S_DISCOVER:
-               if (m == NULL) {
-                       m = state->new;
-                       ml = state->new_len;
-               }
-               TAILQ_FOREACH(ap, &state->addrs, next) {
--                      if (ap->prefix_vltime == 0)
-+                      if (ap->prefix_vltime == 0 &&
-+                          !(ap->flags & IPV6_AF_REQUEST))
-                               continue;
--                      if (ifo->ia_type == D6_OPTION_IA_PD)
--                              len += sizeof(*o) + sizeof(u8) +
--                                  sizeof(u32) + sizeof(u32) +
--                                  sizeof(ap->prefix.s6_addr);
--                      else
-+                      if (ap->ia_type == D6_OPTION_IA_PD) {
-+                              if (!(ifo->options & DHCPCD_NOPFXDLG)) {
-+                                      len += sizeof(*o) + sizeof(u8) +
-+                                          sizeof(u32) + sizeof(u32) +
-+                                          sizeof(ap->prefix.s6_addr);
-+                                      sla = dhcp6_findselfsla(ifp, ap->iaid);
-+                                      if (sla)
-+                                              len += sizeof(*o) + 1 +
-+                                                  ((sla->prefix_len -
-+                                                  ap->prefix_len - 1) / NBBY)
-+                                                  + 1;
-+
-+                              }
-+                      } else if (!(ifo->options & DHCPCD_PFXDLGONLY))
-                               len += sizeof(*o) + sizeof(ap->addr.s6_addr) +
-                                   sizeof(u32) + sizeof(u32);
-               }
-               /* FALLTHROUGH */
--      case DH6S_INIT: /* FALLTHROUGH */
--      case DH6S_DISCOVER:
--              len += ifo->ia_len * (sizeof(*o) + (sizeof(u32) * 3));
-+      case DH6S_INIT:
-+              for (l = 0; l < ifo->ia_len; l++) {
-+                      if (ifo->ia[l].ia_type == D6_OPTION_IA_PD) {
-+                              if (ifo->options & DHCPCD_NOPFXDLG)
-+                                      continue;
-+                      } else if (ifo->options & DHCPCD_PFXDLGONLY)
-+                              continue;
-+                      len += sizeof(*o) + (sizeof(u32) * 3);
-+              }
-               IA = 1;
-               break;
-       default:
-@@ -528,20 +668,26 @@
-       }
-       for (l = 0; IA && l < ifo->ia_len; l++) {
-+              if (ifo->ia[l].ia_type == D6_OPTION_IA_PD) {
-+                      if (ifo->options & DHCPCD_NOPFXDLG)
-+                              continue;
-+              } else if (ifo->options & DHCPCD_PFXDLGONLY)
-+                      continue;
-               o = D6_NEXT_OPTION(o);
--              o->code = htons(ifo->ia_type);
-+              o->code = htons(ifo->ia[l].ia_type);
-               o->len = htons(sizeof(u32) + sizeof(u32) + sizeof(u32));
-               p = D6_OPTION_DATA(o);
-               memcpy(p, ifo->ia[l].iaid, sizeof(u32));
-               p += sizeof(u32);
-               memset(p, 0, sizeof(u32) + sizeof(u32));
-               TAILQ_FOREACH(ap, &state->addrs, next) {
--                      if (ap->prefix_vltime == 0)
-+                      if (ap->prefix_vltime == 0 &&
-+                          !(ap->flags & IPV6_AF_REQUEST))
-                               continue;
-                       if (memcmp(ifo->ia[l].iaid, ap->iaid, sizeof(u32)))
-                               continue;
-                       so = D6_NEXT_OPTION(o);
--                      if (ifo->ia_type == D6_OPTION_IA_PD) {
-+                      if (ap->ia_type == D6_OPTION_IA_PD) {
-                               so->code = htons(D6_OPTION_IAPREFIX);
-                               so->len = htons(sizeof(ap->prefix.s6_addr) +
-                                   sizeof(u32) + sizeof(u32) + sizeof(u8));
-@@ -557,16 +703,45 @@
-                               p += sizeof(u8);
-                               memcpy(p, &ap->prefix.s6_addr,
-                                   sizeof(ap->prefix.s6_addr));
--                              /* Avoid a shadowed declaration warning by
--                               * moving our addition outside of the htons
--                               * macro */
-+
-+                              /* RFC6603 Sectio 4.2 */
-+                              sla = dhcp6_findselfsla(ifp, ap->iaid);
-+                              if (sla &&
-+                                  dhcp6_delegateaddr(&addr, ifp, ap, sla) ==0)
-+                              {
-+                                      uint16_t el;
-+                                      uint8_t *pp;
-+
-+                                      el = ((sla->prefix_len -
-+                                          ap->prefix_len - 1) / NBBY) + 1;
-+                                      eo = D6_NEXT_OPTION(so);
-+                                      eo->code = htons(D6_OPTION_PD_EXCLUDE);
-+                                      eo->len = el + 1;
-+                                      p = D6_OPTION_DATA(eo);
-+                                      *p++ = (uint8_t)sla->prefix_len;
-+                                      pp = addr.s6_addr;
-+                                      pp += (ap->prefix_len - 1) / NBBY;
-+                                      u8 = ap->prefix_len % NBBY;
-+                                      if (u8 % NBBY == 0)
-+                                              pp++;
-+                                      else {
-+                                              *p = (uint8_t)(*pp++ << u8);
-+                                              el--;
-+                                      }
-+                                      memcpy(p, pp, el);
-+                                      u32 = ntohs(so->len) +
-+                                          sizeof(*eo) + eo->len;
-+                                      so->len = htons(u32);
-+                                      eo->len = htons(eo->len);
-+                              }
-+
-                               u32 = ntohs(o->len) + sizeof(*so)
-                                   + ntohs(so->len);
-                               o->len = htons(u32);
-                       } else {
-                               so->code = htons(D6_OPTION_IA_ADDR);
--                              so->len = htons(sizeof(ap->addr.s6_addr) +
--                                  sizeof(u32) + sizeof(u32));
-+                              so->len = sizeof(ap->addr.s6_addr) +
-+                                  sizeof(u32) + sizeof(u32);
-                               p = D6_OPTION_DATA(so);
-                               memcpy(p, &ap->addr.s6_addr,
-                                   sizeof(ap->addr.s6_addr));
-@@ -576,11 +751,9 @@
-                               p += sizeof(u32);
-                               u32 = htonl(ap->prefix_vltime);
-                               memcpy(p, &u32, sizeof(u32));
--                              /* Avoid a shadowed declaration warning by
--                               * moving our addition outside of the htons
--                               * macro */
-                               u32 = ntohs(o->len) + sizeof(*so)
--                                  + ntohs(so->len);
-+                                  + so->len;
-+                              so->len = htons(so->len);
-                               o->len = htons(u32);
-                       }
-               }
-@@ -625,6 +798,28 @@
-                           l < ifp->ctx->dhcp6_opts_len;
-                           l++, opt++)
-                       {
-+                              for (n = 0, opt2 = ifo->dhcp6_override;
-+                                  n < ifo->dhcp6_override_len;
-+                                  n++, opt2++)
-+                              {
-+                                      if (opt->option == opt2->option)
-+                                              break;
-+                              }
-+                              if (n < ifo->dhcp6_override_len)
-+                                  continue;
-+                              if (!(opt->type & NOREQ) &&
-+                                  (opt->type & REQUEST ||
-+                                  has_option_mask(ifo->requestmask6,
-+                                      opt->option)))
-+                              {
-+                                      *u16++ = htons(opt->option);
-+                                      o->len += sizeof(*u16);
-+                              }
-+                      }
-+                      for (l = 0, opt = ifo->dhcp6_override;
-+                          l < ifo->dhcp6_override_len;
-+                          l++, opt++)
-+                      {
-                               if (!(opt->type & NOREQ) &&
-                                   (opt->type & REQUEST ||
-                                   has_option_mask(ifo->requestmask6,
-@@ -634,6 +829,10 @@
-                                       o->len += sizeof(*u16);
-                               }
-                       }
-+                      if (dhcp6_findselfsla(ifp, NULL)) {
-+                              *u16++ = htons(D6_OPTION_PD_EXCLUDE);
-+                              o->len += sizeof(*u16);
-+                      }
-                       o->len = htons(o->len);
-               }
-       }
-@@ -949,6 +1148,99 @@
- }
- static void
-+dhcp6_dadcallback(void *arg)
-+{
-+      struct ipv6_addr *ap = arg;
-+      struct interface *ifp;
-+      struct dhcp6_state *state;
-+      int wascompleted;
-+
-+      wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED);
-+      ap->flags |= IPV6_AF_DADCOMPLETED;
-+      if (ap->flags & IPV6_AF_DUPLICATED)
-+              /* XXX FIXME
-+               * We should decline the address */
-+              syslog(LOG_WARNING, "%s: DAD detected %s",
-+                  ap->iface->name, ap->saddr);
-+
-+      if (!wascompleted) {
-+              ifp = ap->iface;
-+              state = D6_STATE(ifp);
-+              if (state->state == DH6S_BOUND ||
-+                  state->state == DH6S_DELEGATED)
-+              {
-+                      TAILQ_FOREACH(ap, &state->addrs, next) {
-+                              if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
-+                                      wascompleted = 1;
-+                                      break;
-+                              }
-+                      }
-+                      if (!wascompleted) {
-+                              syslog(LOG_DEBUG, "%s: DHCPv6 DAD completed",
-+                                  ifp->name);
-+                              script_runreason(ifp, state->reason);
-+                              dhcpcd_daemonise(ifp->ctx);
-+                      }
-+              }
-+      }
-+}
-+
-+static void
-+dhcp6_addrequestedaddrs(struct interface *ifp)
-+{
-+      struct dhcp6_state *state;
-+      size_t i;
-+      struct if_ia *ia;
-+      struct ipv6_addr *a;
-+      char iabuf[INET6_ADDRSTRLEN];
-+      const char *iap;
-+
-+      state = D6_STATE(ifp);
-+      /* Add any requested prefixes / addresses */
-+      for (i = 0; i < ifp->options->ia_len; i++) {
-+              ia = &ifp->options->ia[i];
-+              if (!((ia->ia_type == D6_OPTION_IA_PD && ia->prefix_len) ||
-+                  !IN6_IS_ADDR_UNSPECIFIED(&ia->addr)))
-+                      continue;
-+              a = calloc(1, sizeof(*a));
-+              if (a == NULL) {
-+                      syslog(LOG_ERR, "%s: %m", __func__);
-+                      return;
-+              }
-+              a->flags = IPV6_AF_REQUEST;
-+              a->iface = ifp;
-+              a->dadcallback = dhcp6_dadcallback;
-+              memcpy(&a->iaid, &ia->iaid, sizeof(a->iaid));
-+              a->ia_type = ia->ia_type;
-+              //a->prefix_pltime = 0;
-+              //a->prefix_vltime = 0;
-+
-+              if (ia->ia_type == D6_OPTION_IA_PD) {
-+                      memcpy(&a->prefix, &ia->addr, sizeof(a->addr));
-+                      a->prefix_len = ia->prefix_len;
-+                      iap = inet_ntop(AF_INET6, &a->prefix.s6_addr,
-+                          iabuf, sizeof(iabuf));
-+              } else {
-+                      memcpy(&a->addr, &ia->addr, sizeof(a->addr));
-+                      /*
-+                       * RFC 5942 Section 5
-+                       * We cannot assume any prefix length, nor tie the
-+                       * address to an existing one as it could expire
-+                       * before the address.
-+                       * As such we just give it a 128 prefix.
-+                       */
-+                      a->prefix_len = 128;
-+                      ipv6_makeprefix(&a->prefix, &a->addr, a->prefix_len);
-+                      iap = inet_ntop(AF_INET6, &a->addr.s6_addr,
-+                          iabuf, sizeof(iabuf));
-+              }
-+              snprintf(a->saddr, sizeof(a->saddr),
-+                  "%s/%d", iap, a->prefix_len);
-+              TAILQ_INSERT_TAIL(&state->addrs, a, next);
-+      }
-+}
-+
-+static void
- dhcp6_startdiscover(void *arg)
- {
-       struct interface *ifp;
-@@ -974,6 +1266,8 @@
-       dhcp6_freedrop_addrs(ifp, 0, NULL);
-       unlink(state->leasefile);
-+      dhcp6_addrequestedaddrs(ifp);
-+
-       if (dhcp6_makemessage(ifp) == -1)
-               syslog(LOG_ERR, "%s: dhcp6_makemessage: %m", ifp->name);
-       else
-@@ -1021,11 +1315,25 @@
-       dhcp6_startdiscover(ifp);
- }
-+
-+static int
-+dhcp6_hasprefixdelegation(struct interface *ifp)
-+{
-+      size_t i;
-+
-+      for (i = 0; i < ifp->options->ia_len; i++) {
-+              if (ifp->options->ia[i].ia_type == D6_OPTION_IA_PD)
-+                      return 1;
-+      }
-+      return 0;
-+}
-+
- static void
- dhcp6_startrebind(void *arg)
- {
-       struct interface *ifp;
-       struct dhcp6_state *state;
-+      int pd;
-       ifp = arg;
-       eloop_timeout_delete(ifp->ctx->eloop, dhcp6_sendrenew, ifp);
-@@ -1033,13 +1341,16 @@
-       if (state->state == DH6S_RENEW)
-               syslog(LOG_WARNING, "%s: failed to renew DHCPv6, rebinding",
-                   ifp->name);
-+      else
-+              syslog(LOG_INFO, "%s: rebinding prior DHCPc6 lease",
-+                  ifp->name);
-       state->state = DH6S_REBIND;
-       state->RTC = 0;
-       state->MRC = 0;
-       /* RFC 3633 section 12.1 */
--      if (ifp->options->ia_type == D6_OPTION_IA_PD) {
--              syslog(LOG_INFO, "%s: confirming Prefix Delegation", ifp->name);
-+      pd = dhcp6_hasprefixdelegation(ifp);
-+      if (pd) {
-               state->IMD = CNF_MAX_DELAY;
-               state->IRT = CNF_TIMEOUT;
-               state->MRT = CNF_MAX_RT;
-@@ -1054,7 +1365,7 @@
-               dhcp6_sendrebind(ifp);
-       /* RFC 3633 section 12.1 */
--      if (ifp->options->ia_type == D6_OPTION_IA_PD)
-+      if (pd)
-               eloop_timeout_add_sec(ifp->ctx->eloop,
-                   CNF_MAX_RD, dhcp6_failrebind, ifp);
- }
-@@ -1264,46 +1575,8 @@
-       return 0;
- }
--static void
--dhcp6_dadcallback(void *arg)
--{
--      struct ipv6_addr *ap = arg;
--      struct interface *ifp;
--      struct dhcp6_state *state;
--      int wascompleted;
--
--      wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED);
--      ap->flags |= IPV6_AF_DADCOMPLETED;
--      if (ap->flags & IPV6_AF_DUPLICATED)
--              /* XXX FIXME
--               * We should decline the address */
--              syslog(LOG_WARNING, "%s: DAD detected %s",
--                  ap->iface->name, ap->saddr);
--
--      if (!wascompleted) {
--              ifp = ap->iface;
--              state = D6_STATE(ifp);
--              if (state->state == DH6S_BOUND ||
--                  state->state == DH6S_DELEGATED)
--              {
--                      TAILQ_FOREACH(ap, &state->addrs, next) {
--                              if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
--                                      wascompleted = 1;
--                                      break;
--                              }
--                      }
--                      if (!wascompleted) {
--                              syslog(LOG_DEBUG, "%s: DHCPv6 DAD completed",
--                                  ifp->name);
--                              script_runreason(ifp, state->reason);
--                              dhcpcd_daemonise(ifp->ctx);
--                      }
--              }
--      }
--}
--
- static int
--dhcp6_findna(struct interface *ifp, const uint8_t *iaid,
-+dhcp6_findna(struct interface *ifp, uint16_t ot, const uint8_t *iaid,
-     const uint8_t *d, size_t l)
- {
-       struct dhcp6_state *state;
-@@ -1345,6 +1618,7 @@
-                       a->iface = ifp;
-                       a->flags = IPV6_AF_NEW | IPV6_AF_ONLINK;
-                       a->dadcallback = dhcp6_dadcallback;
-+                      a->ia_type = ot;
-                       memcpy(a->iaid, iaid, sizeof(a->iaid));
-                       memcpy(&a->addr.s6_addr, &in6.s6_addr,
-                           sizeof(in6.s6_addr));
-@@ -1357,20 +1631,18 @@
-                        * As such we just give it a 128 prefix.
-                        */
-                       a->prefix_len = 128;
--                      if (ipv6_makeprefix(&a->prefix, &a->addr,
--                          a->prefix_len) == -1)
--                      {
--                              syslog(LOG_ERR, "%s: %m", __func__);
--                              free(a);
--                              continue;
--                      }
-+                      ipv6_makeprefix(&a->prefix, &a->addr, a->prefix_len);
-                       ia = inet_ntop(AF_INET6, &a->addr.s6_addr,
-                           iabuf, sizeof(iabuf));
-                       snprintf(a->saddr, sizeof(a->saddr),
-                           "%s/%d", ia, a->prefix_len);
-+
-                       TAILQ_INSERT_TAIL(&state->addrs, a, next);
--              } else
-+              } else {
-+                      if (!(a->flags & IPV6_AF_ONLINK))
-+                              a->flags |= IPV6_AF_ONLINK | IPV6_AF_NEW;
-                       a->flags &= ~IPV6_AF_STALE;
-+              }
-               memcpy(&u32, p, sizeof(u32));
-               a->prefix_pltime = ntohl(u32);
-               p += sizeof(u32);
-@@ -1394,8 +1666,8 @@
-     const uint8_t *d, size_t l)
- {
-       struct dhcp6_state *state;
--      const struct dhcp6_option *o;
--      const uint8_t *p;
-+      const struct dhcp6_option *o, *ex;
-+      const uint8_t *p, *ps, *pe, *op;
-       struct ipv6_addr *a;
-       char iabuf[INET6_ADDRSTRLEN];
-       const char *ia;
-@@ -1420,7 +1692,8 @@
-                           ifp->name);
-                       continue;
-               }
--              p = D6_COPTION_DATA(o);
-+              ps = p = D6_COPTION_DATA(o);
-+              pe = ps + u32;
-               memcpy(&u32, p, sizeof(u32));
-               pltime = ntohl(u32);
-               p += sizeof(u32);
-@@ -1431,6 +1704,7 @@
-               p += sizeof(u8);
-               len = u8;
-               memcpy(&prefix.s6_addr, p, sizeof(prefix.s6_addr));
-+              p += sizeof(prefix.s6_addr);
-               TAILQ_FOREACH(a, &state->addrs, next) {
-                       if (IN6_ARE_ADDR_EQUAL(&a->prefix, &prefix))
-@@ -1445,6 +1719,7 @@
-                       a->iface = ifp;
-                       a->flags = IPV6_AF_NEW | IPV6_AF_DELEGATEDPFX;
-                       a->dadcallback = dhcp6_dadcallback;
-+                      a->ia_type = D6_OPTION_IA_PD;
-                       memcpy(a->iaid, iaid, sizeof(a->iaid));
-                       memcpy(&a->prefix.s6_addr,
-                           &prefix.s6_addr, sizeof(a->prefix.s6_addr));
-@@ -1455,24 +1730,58 @@
-                           "%s/%d", ia, a->prefix_len);
-                       TAILQ_INSERT_TAIL(&state->addrs, a, next);
-               } else {
--                      a->flags &= ~IPV6_AF_STALE;
-+                      if (!(a->flags & IPV6_AF_DELEGATEDPFX))
-+                              a->flags |= IPV6_AF_NEW | IPV6_AF_DELEGATEDPFX;
-+                      a->flags &= ~(IPV6_AF_STALE | IPV6_AF_REQUEST);
-                       if (a->prefix_vltime != vltime)
-                               a->flags |= IPV6_AF_NEW;
-               }
-               a->prefix_pltime = pltime;
-               a->prefix_vltime = vltime;
-+
-               if (a->prefix_pltime && a->prefix_pltime < state->lowpl)
-                       state->lowpl = a->prefix_pltime;
-               if (a->prefix_vltime && a->prefix_vltime > state->expire)
-                       state->expire = a->prefix_vltime;
-               i++;
-+
-+              off = (size_t)(pe - p);
-+              ex = dhcp6_findoption(D6_OPTION_PD_EXCLUDE, p, off);
-+
-+              if (ex) {
-+                      off = ntohs(ex->len);
-+                      if (off < 2) {
-+                              syslog(LOG_ERR, "%s: truncated PD Exclude",
-+                                  ifp->name);
-+                              ex = NULL;
-+                      }
-+              }
-+              if (ex) {
-+                      int bytelen, bitlen;
-+
-+                      op = D6_COPTION_DATA(ex);
-+                      a->prefix_exclude_len = *op++;
-+                      memcpy(&a->prefix_exclude, &a->prefix,
-+                          sizeof(a->prefix_exclude));
-+                      bytelen = a->prefix_len / NBBY;
-+                      bitlen = a->prefix_len % NBBY;
-+                      if (bitlen != 0)
-+                              a->prefix_exclude.s6_addr[bytelen] |=
-+                                  *op++ >> bitlen;
-+                      memcpy(a->prefix_exclude.s6_addr + bytelen + 1,
-+                          op, off - 2);
-+              } else {
-+                      a->prefix_exclude_len = 0;
-+                      memset(&a->prefix_exclude, 0,
-+                          sizeof(a->prefix_exclude));
-+              }
-       }
-       return i;
- }
- static int
--dhcp6_findia(struct interface *ifp, const uint8_t *d, size_t l,
-+dhcp6_findia(struct interface *ifp, const struct dhcp6_message *m, size_t l,
-     const char *sfrom)
- {
-       struct dhcp6_state *state;
-@@ -1480,25 +1789,47 @@
-       const struct dhcp6_option *o;
-       const uint8_t *p;
-       int i, e;
-+      size_t j;
-       uint32_t u32, renew, rebind;
-+      uint16_t code, ol;
-       uint8_t iaid[4];
--      size_t ol;
-+      char buf[sizeof(iaid) * 3];
-       struct ipv6_addr *ap, *nap;
-+      if (l < sizeof(*m)) {
-+              syslog(LOG_ERR, "%s: message truncated", ifp->name);
-+              errno = EINVAL;
-+              return -1;
-+      }
-+
-       ifo = ifp->options;
-       i = e = 0;
-       state = D6_STATE(ifp);
-       TAILQ_FOREACH(ap, &state->addrs, next) {
-               ap->flags |= IPV6_AF_STALE;
-       }
--      while ((o = dhcp6_findoption(ifo->ia_type, d, l))) {
--              ol = (size_t)((const uint8_t *)o - d);
--              l -= ol;
--              d += ol;
-+      l -= sizeof(*m);
-+      for (o = D6_FIRST_OPTION(m); l > sizeof(*o); o = D6_NEXT_OPTION(o)) {
-               ol = ntohs(o->len);
-+              if (sizeof(*o) + ol > l) {
-+                      errno = EINVAL;
-+                      syslog(LOG_ERR, "%s: option overflow", ifp->name);
-+                      break;
-+              }
-               l -= sizeof(*o) + ol;
--              d += sizeof(*o) + ol;
--              u32 = ifo->ia_type == D6_OPTION_IA_TA ? 4 : 12;
-+
-+              code = ntohs(o->code);
-+              switch(code) {
-+              case D6_OPTION_IA_TA:
-+                      u32 = 4;
-+                      break;
-+              case D6_OPTION_IA_NA:
-+              case D6_OPTION_IA_PD:
-+                      u32 = 12;
-+                      break;
-+              default:
-+                      continue;
-+              }
-               if (ol < u32) {
-                       errno = EINVAL;
-                       syslog(LOG_ERR, "%s: IA option truncated", ifp->name);
-@@ -1509,7 +1840,25 @@
-               memcpy(iaid, p, sizeof(iaid));
-               p += sizeof(iaid);
-               ol -= sizeof(iaid);
--              if (ifo->ia_type != D6_OPTION_IA_TA) {
-+
-+              for (j = 0; j < ifo->ia_len; j++) {
-+                      if (memcmp(&ifo->ia[j].iaid, iaid, sizeof(iaid)) == 0)
-+                              break;
-+              }
-+              if (j == ifo->ia_len) {
-+                      syslog(LOG_DEBUG, "%s: ignoring unrequested IAID %s",
-+                          ifp->name,
-+                          hwaddr_ntoa(iaid, sizeof(iaid), buf, sizeof(buf)));
-+                      continue;
-+              }
-+              if (ifo->ia[j].ia_type != code) {
-+                      syslog(LOG_ERR, "%s: IAID %s: option type mismatch",
-+                          ifp->name,
-+                          hwaddr_ntoa(iaid, sizeof(iaid), buf, sizeof(buf)));
-+                      continue;
-+              }
-+
-+              if (code != D6_OPTION_IA_TA) {
-                       memcpy(&u32, p, sizeof(u32));
-                       renew = ntohl(u32);
-                       p += sizeof(u32);
-@@ -1524,22 +1873,24 @@
-                       e = 1;
-                       continue;
-               }
--              if (ifo->ia_type == D6_OPTION_IA_PD) {
--                      if (dhcp6_findpd(ifp, iaid, p, ol) == 0) {
-+              if (code == D6_OPTION_IA_PD) {
-+                      if (!(ifo->options & DHCPCD_NOPFXDLG) &&
-+                          dhcp6_findpd(ifp, iaid, p, ol) == 0)
-+                      {
-                               syslog(LOG_WARNING,
-                                   "%s: %s: DHCPv6 REPLY missing Prefix",
-                                   ifp->name, sfrom);
-                               continue;
-                       }
--              } else {
--                      if (dhcp6_findna(ifp, iaid, p, ol) == 0) {
-+              } else if (!(ifo->options & DHCPCD_PFXDLGONLY)) {
-+                      if (dhcp6_findna(ifp, code, iaid, p, ol) == 0) {
-                               syslog(LOG_WARNING,
-                                   "%s: %s: DHCPv6 REPLY missing IA Address",
-                                   ifp->name, sfrom);
-                               continue;
-                       }
-               }
--              if (ifo->ia_type != D6_OPTION_IA_TA) {
-+              if (code != D6_OPTION_IA_TA) {
-                       if (renew > rebind && rebind > 0) {
-                               if (sfrom)
-                                   syslog(LOG_WARNING,
-@@ -1559,11 +1910,15 @@
-       }
-       TAILQ_FOREACH_SAFE(ap, &state->addrs, next, nap) {
-               if (ap->flags & IPV6_AF_STALE) {
--                      TAILQ_REMOVE(&state->addrs, ap, next);
-                       if (ap->dadcallback)
-                               eloop_q_timeout_delete(ap->iface->ctx->eloop,
-                                   0, NULL, ap);
--                      free(ap);
-+                      if (ap->flags & IPV6_AF_REQUEST) {
-+                              ap->prefix_vltime = ap->prefix_pltime = 0;
-+                      } else {
-+                              TAILQ_REMOVE(&state->addrs, ap, next);
-+                              free(ap);
-+                      }
-               }
-       }
-       if (i == 0 && e)
-@@ -1577,25 +1932,14 @@
-     const char *sfrom)
- {
-       struct dhcp6_state *state;
--      const struct dhcp6_option *o;
-       state = D6_STATE(ifp);
--      o = dhcp6_getmoption(ifp->options->ia_type, m, len);
--      if (o == NULL) {
--              if (sfrom &&
--                  dhcp6_checkstatusok(ifp, m, NULL, len) != -1)
--                      syslog(LOG_ERR, "%s: no IA in REPLY from %s",
--                          ifp->name, sfrom);
--              return -1;
--      }
--
-       if (dhcp6_checkstatusok(ifp, m, NULL, len) == -1)
-               return -1;
-       state->renew = state->rebind = state->expire = 0;
-       state->lowpl = ND6_INFINITE_LIFETIME;
--      len -= (size_t)((const char *)o - (const char *)m);
--      return dhcp6_findia(ifp, (const uint8_t *)o, len, sfrom);
-+      return dhcp6_findia(ifp, m, len, sfrom);
- }
- static ssize_t
-@@ -1633,6 +1977,7 @@
-       if (stat(state->leasefile, &st) == -1) {
-               if (errno == ENOENT)
-                       return 0;
-+              syslog(LOG_ERR, "%s: %s: %m", ifp->name, __func__);
-               return -1;
-       }
-       syslog(LOG_DEBUG, "%s: reading lease `%s'",
-@@ -1642,12 +1987,17 @@
-               return -1;
-       }
-       state->new = malloc((size_t)st.st_size);
--      if (state->new == NULL)
-+      if (state->new == NULL) {
-+              syslog(LOG_ERR, "%s: %m", __func__);
-               return -1;
-+      }
-       state->new_len = (size_t)st.st_size;
-       fd = open(state->leasefile, O_RDONLY);
--      if (fd == -1)
-+      if (fd == -1) {
-+              syslog(LOG_ERR, "%s: %s: %s: %m", ifp->name, __func__,
-+                  state->leasefile);
-               return -1;
-+      }
-       bytes = read(fd, state->new, state->new_len);
-       close(fd);
-       if (bytes < (ssize_t)state->new_len) {
-@@ -1660,7 +2010,7 @@
-       if (fd == -1)
-               goto ex;
-       if (fd == 0) {
--              syslog(LOG_INFO, "%s: lease was for different IA type",
-+              syslog(LOG_INFO, "%s: no useable IA found in lease",
-                   ifp->name);
-               goto ex;
-       }
-@@ -1705,22 +2055,39 @@
-       free(state->new);
-       state->new = NULL;
-       state->new_len = 0;
--      unlink(state->leasefile);
-+      if (!(ifp->ctx->options & DHCPCD_DUMPLEASE))
-+              unlink(state->leasefile);
-       return 0;
- }
-+
- static void
- dhcp6_startinit(struct interface *ifp)
- {
-       struct dhcp6_state *state;
-       int r;
-+      uint8_t has_ta, has_non_ta;
-+      size_t i;
-       state = D6_STATE(ifp);
-       state->state = DH6S_INIT;
-       state->expire = ND6_INFINITE_LIFETIME;
-       state->lowpl = ND6_INFINITE_LIFETIME;
-+
-+      dhcp6_addrequestedaddrs(ifp);
-+      has_ta = has_non_ta = 0;
-+      for (i = 0; i < ifp->options->ia_len; i++) {
-+              switch (ifp->options->ia[i].ia_type) {
-+              case D6_OPTION_IA_TA:
-+                      has_ta = 1;
-+                      break;
-+              default:
-+                      has_non_ta = 1;
-+              }
-+      }
-+
-       if (!(ifp->ctx->options & DHCPCD_TEST) &&
--          ifp->options->ia_type != D6_OPTION_IA_TA &&
-+          !(has_ta && !has_non_ta) &&
-           ifp->options->reboot != 0)
-       {
-               r = dhcp6_readlease(ifp);
-@@ -1729,7 +2096,7 @@
-                                       ifp->name, state->leasefile);
-               else if (r != 0) {
-                       /* RFC 3633 section 12.1 */
--                      if (ifp->options->ia_type == D6_OPTION_IA_PD)
-+                      if (dhcp6_hasprefixdelegation(ifp))
-                               dhcp6_startrebind(ifp);
-                       else
-                               dhcp6_startconfirm(ifp);
-@@ -1740,69 +2107,28 @@
- }
- static struct ipv6_addr *
--dhcp6_delegate_addr(struct interface *ifp, struct ipv6_addr *prefix,
-+dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix,
-     const struct if_sla *sla, struct interface *ifs)
- {
-       struct dhcp6_state *state;
--      struct if_sla asla;
-       struct in6_addr addr;
-       struct ipv6_addr *a, *ap, *apn;
-       char iabuf[INET6_ADDRSTRLEN];
-       const char *ia;
--      state = D6_STATE(ifp);
--      if (state == NULL) {
--              ifp->if_data[IF_DATA_DHCP6] = calloc(1, sizeof(*state));
--              state = D6_STATE(ifp);
--              if (state == NULL) {
--                      syslog(LOG_ERR, "%s: %m", __func__);
-+      /* RFC6603 Section 4.2 */
-+      if (ifp == ifs) {
-+              if (prefix->prefix_exclude_len == 0) {
-+                      syslog(LOG_WARNING,
-+                          "%s: DHCPv6 server does not support "
-+                          "OPTION_PD_EXCLUDE",
-+                          ifp->name);
-                       return NULL;
-               }
--
--              TAILQ_INIT(&state->addrs);
--              state->state = DH6S_DELEGATED;
--              state->reason = "DELEGATED6";
--      }
--
--      if (sla == NULL || sla->sla_set == 0) {
--              struct interface *ifi;
--              unsigned int idx;
--              int bits;
--
--              asla.sla = ifp->index;
--              /* Work out our largest index delegating to. */
--              idx = 0;
--              TAILQ_FOREACH(ifi, ifp->ctx->ifaces, next) {
--                      if (ifi != ifp && ifi->index > idx)
--                              idx = ifi->index;
--              }
--              bits = ffs((int)idx);
--              if (prefix->prefix_len + bits > UINT8_MAX)
--                      asla.prefix_len = UINT8_MAX;
--              else {
--                      asla.prefix_len = prefix->prefix_len + (uint8_t)bits;
--
--                      /* Make a 64 prefix by default, as this maks SLAAC
--                       * possible. Otherwise round up to the nearest octet. */
--                      if (asla.prefix_len <= 64)
--                              asla.prefix_len = 64;
--                      else
--                              asla.prefix_len = ROUNDUP8(asla.prefix_len);
--
--              }
--              sla = &asla;
--      }
--
--      if (ipv6_userprefix(&prefix->prefix, prefix->prefix_len,
--              sla->sla, &addr, sla->prefix_len) == -1)
--      {
--              ia = inet_ntop(AF_INET6, &prefix->prefix.s6_addr,
--                  iabuf, sizeof(iabuf));
--              syslog(LOG_ERR, "%s: invalid prefix %s/%d + %d/%d: %m",
--                      ifp->name, ia, prefix->prefix_len,
--                      sla->sla, sla->prefix_len);
-+              memcpy(&addr, &prefix->prefix_exclude, sizeof(addr));
-+      } else if (dhcp6_delegateaddr(&addr, ifp, prefix, sla) == -1)
-               return NULL;
--      }
-+
-       a = calloc(1, sizeof(*a));
-       if (a == NULL) {
-@@ -1824,6 +2150,7 @@
-       memcpy(&a->addr.s6_addr, &a->prefix.s6_addr, sizeof(a->addr.s6_addr));
-       a->addr.s6_addr[sizeof(a->addr.s6_addr) - 1] += 1;
-+      state = D6_STATE(ifp);
-       /* Remove any exiting address */
-       TAILQ_FOREACH_SAFE(ap, &state->addrs, next, apn) {
-               if (IN6_ARE_ADDR_EQUAL(&ap->addr, &a->addr)) {
-@@ -1916,7 +2243,7 @@
-                                                   abrt = 1;
-                                               break;
-                                       }
--                                      if (dhcp6_delegate_addr(ifd, ap,
-+                                      if (dhcp6_ifdelegateaddr(ifd, ap,
-                                           NULL, ifp))
-                                               k++;
-                               }
-@@ -1935,7 +2262,7 @@
-                                               carrier_warned = 1;
-                                               break;
-                                       }
--                                      if (dhcp6_delegate_addr(ifd, ap,
-+                                      if (dhcp6_ifdelegateaddr(ifd, ap,
-                                           sla, ifp))
-                                               k++;
-                               }
-@@ -1998,7 +2325,7 @@
-                                                   dhcp6_find_delegates1, ifp);
-                                               return 1;
-                                       }
--                                      if (dhcp6_delegate_addr(ifp, ap,
-+                                      if (dhcp6_ifdelegateaddr(ifp, ap,
-                                           sla, ifd))
-                                           k++;
-                               }
-@@ -2225,7 +2552,7 @@
-                               /* PD doesn't use CONFIRM, so REBIND could
-                                * throw up an invalid prefix if we
-                                * changed link */
--                              if (ifp->options->ia_type == D6_OPTION_IA_PD)
-+                              if (dhcp6_hasprefixdelegation(ifp))
-                                       dhcp6_startdiscover(ifp);
-                               return;
-                       }
-@@ -2437,10 +2764,10 @@
-               if (state->expire && state->expire != ND6_INFINITE_LIFETIME)
-                       eloop_timeout_add_sec(ifp->ctx->eloop,
-                           (time_t)state->expire, dhcp6_startexpire, ifp);
--              if (ifp->options->ia_type == D6_OPTION_IA_PD)
--                      dhcp6_delegate_prefix(ifp);
-               ipv6_addaddrs(&state->addrs);
-+              dhcp6_delegate_prefix(ifp);
-+
-               if (state->state == DH6S_INFORMED)
-                       syslog(has_new ? LOG_INFO : LOG_DEBUG,
-                           "%s: refresh in %"PRIu32" seconds",
-@@ -2584,6 +2911,10 @@
-                       add_option_mask(ifo->requestmask6, D6_OPTION_FQDN);
-       }
-+      /* Rapid commit won't wor with Prefix Delegation Exclusion */
-+      if (dhcp6_findselfsla(ifp, NULL))
-+              del_option_mask(ifo->requestmask6, D6_OPTION_RAPID_COMMIT);
-+
-       if (state->state == DH6S_INFORM) {
-               add_option_mask(ifo->requestmask6, D6_OPTION_INFO_REFRESH_TIME);
-               dhcp6_startinform(ifp);
-@@ -2635,7 +2966,8 @@
-       state->state = init_state;
-       snprintf(state->leasefile, sizeof(state->leasefile),
--          LEASEFILE6, ifp->name);
-+          LEASEFILE6, ifp->name,
-+          ifp->options->options & DHCPCD_PFXDLGONLY ? ".pd" : "");
-       if (ipv6_linklocal(ifp) == NULL) {
-               syslog(LOG_DEBUG,
-@@ -2790,18 +3122,21 @@
- dhcp6_env(char **env, const char *prefix, const struct interface *ifp,
-     const struct dhcp6_message *m, size_t len)
- {
--      const struct dhcp6_state *state;
-       const struct if_options *ifo;
-       struct dhcp_opt *opt, *vo;
-       const struct dhcp6_option *o;
--      size_t i, l, n;
-+      size_t i, n;
-       uint16_t ol, oc;
--      char *v, *val, *pfx;
--      const struct ipv6_addr *ap;
-+      char *pfx;
-       uint32_t en;
-       const struct dhcpcd_ctx *ctx;
--      state = D6_CSTATE(ifp);
-+      if (len < sizeof(*m)) {
-+              syslog(LOG_ERR, "%s: message truncated", ifp->name);
-+              errno = EINVAL;
-+              return -1;
-+      }
-+
-       n = 0;
-       ifo = ifp->options;
-       ctx = ifp->ctx;
-@@ -2885,64 +3220,38 @@
-       }
-       free(pfx);
--      /* It is tempting to remove this section.
--       * However, we need it at least for Delegated Prefixes
--       * (they don't have a DHCPv6 message to parse to get the addressses)
--       * and it's easier for shell scripts to see which addresses have
--       * been added */
--      if (TAILQ_FIRST(&state->addrs)) {
--              if (env) {
--                      if (ifo->ia_type == D6_OPTION_IA_PD) {
--                              l = strlen(prefix) +
--                                  strlen("_dhcp6_prefix=");
--                              TAILQ_FOREACH(ap, &state->addrs, next) {
--                                      l += strlen(ap->saddr) + 1;
--                              }
--                              v = val = env[n] = malloc(l);
--                              if (v == NULL) {
--                                      syslog(LOG_ERR, "%s: %m", __func__);
--                                      return -1;
--                              }
--                              i = (size_t)snprintf(v, l, "%s_dhcp6_prefix=",
--                                  prefix);
--                              v += i;
--                              l -= i;
--                              TAILQ_FOREACH(ap, &state->addrs, next) {
--                                      i = strlen(ap->saddr);
--                                      strlcpy(v, ap->saddr, l);
--                                      v += i;
--                                      l -= i;
--                                      *v++ = ' ';
--                              }
--                              *--v = '\0';
--                      } else {
--                              l = strlen(prefix) +
--                                  strlen("_dhcp6_ip_address=");
--                              TAILQ_FOREACH(ap, &state->addrs, next) {
--                                      l += strlen(ap->saddr) + 1;
--                              }
--                              v = val = env[n] = malloc(l);
--                              if (v == NULL) {
--                                      syslog(LOG_ERR, "%s: %m", __func__);
--                                      return -1;
--                              }
--                              i = (size_t)snprintf(v, l,
--                                  "%s_dhcp6_ip_address=",
--                                  prefix);
--                              v += i;
--                              l -= i;
--                              TAILQ_FOREACH(ap, &state->addrs, next) {
--                                      i = strlen(ap->saddr);
--                                      strlcpy(v, ap->saddr, l);
--                                      v += i;
--                                      l -= i;
--                                      *v++ = ' ';
--                              }
--                              *--v = '\0';
--                      }
--              }
--              n++;
-+      return (ssize_t)n;
-+}
-+
-+int
-+dhcp6_dump(struct interface *ifp)
-+{
-+      struct dhcp6_state *state;
-+      int r;
-+
-+      ifp->if_data[IF_DATA_DHCP6] = state = calloc(1, sizeof(*state));
-+      if (state == NULL)
-+              goto eexit;
-+      TAILQ_INIT(&state->addrs);
-+      snprintf(state->leasefile, sizeof(state->leasefile),
-+          LEASEFILE6, ifp->name,
-+          ifp->options->options & DHCPCD_PFXDLGONLY ? ".pd" : "");
-+      r = dhcp6_readlease(ifp);
-+      if (r == -1 && errno == ENOENT) {
-+              strlcpy(state->leasefile, ifp->name, sizeof(state->leasefile));
-+              r = dhcp6_readlease(ifp);
-       }
-+      if (r == -1) {
-+              if (errno == ENOENT)
-+                      syslog(LOG_ERR, "%s: no lease to dump", ifp->name);
-+              else
-+                      syslog(LOG_ERR, "%s: dhcp6_readlease: %m", ifp->name);
-+              return -1;
-+      }
-+      state->reason = "DUMP6";
-+      return script_runreason(ifp, state->reason);
--      return (ssize_t)n;
-+eexit:
-+      syslog(LOG_ERR, "%s: %m", __func__);
-+      return -1;
- }
-diff -urN dhcpcd-6.4.0.org/dhcp6.h dhcpcd-6.4.0/dhcp6.h
---- dhcpcd-6.4.0.org/dhcp6.h   2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp6.h       2014-07-05 21:47:22.000000000 +0200
-@@ -89,6 +89,7 @@
- #define D6_OPTION_FQDN                        39
- #define D6_OPTION_POSIX_TIMEZONE      41
- #define D6_OPTION_TZDB_TIMEZONE               42
-+#define D6_OPTION_PD_EXCLUDE          67
- #define D6_OPTION_SOL_MAX_RT          82
- #define D6_OPTION_INF_MAX_RT          83
-@@ -225,7 +226,8 @@
-     ((const uint8_t *)(o) + sizeof(struct dhcp6_option))
- #ifdef INET6
--void dhcp6_printoptions(const struct dhcpcd_ctx *);
-+void dhcp6_printoptions(const struct dhcpcd_ctx *,
-+    const struct dhcp_opt *, size_t);
- int dhcp6_addrexists(struct dhcpcd_ctx *, const struct ipv6_addr *);
- size_t dhcp6_find_delegates(struct interface *);
- int dhcp6_start(struct interface *, enum DH6S);
-@@ -236,15 +238,16 @@
- void dhcp6_handleifa(struct dhcpcd_ctx *, int, const char *,
-     const struct in6_addr *addr, int);
- void dhcp6_drop(struct interface *, const char *);
-+int dhcp6_dump(struct interface *);
- #else
--#define dhcp6_printoptions()
- #define dhcp6_addrexists(a, b) (0)
--#define dhcp6_find_delegates(a) (0)
-+#define dhcp6_find_delegates(a)
- #define dhcp6_start(a, b) (0)
- #define dhcp6_reboot(a)
- #define dhcp6_env(a, b, c, d, e)
- #define dhcp6_free(a)
- #define dhcp6_drop(a, b)
-+#define dhcp6_dump(a) -1
- #endif
- #endif
-diff -urN dhcpcd-6.4.0.org/dhcp.c dhcpcd-6.4.0/dhcp.c
---- dhcpcd-6.4.0.org/dhcp.c    2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp.c        2014-07-05 21:47:22.000000000 +0200
-@@ -125,16 +125,24 @@
- static int dhcp_open(struct interface *);
- void
--dhcp_printoptions(const struct dhcpcd_ctx *ctx)
-+dhcp_printoptions(const struct dhcpcd_ctx *ctx,
-+    const struct dhcp_opt *opts, size_t opts_len)
- {
-       const char * const *p;
--      size_t i;
--      const struct dhcp_opt *opt;
-+      size_t i, j;
-+      const struct dhcp_opt *opt, *opt2;
-       for (p = dhcp_params; *p; p++)
-               printf("    %s\n", *p);
--      for (i = 0, opt = ctx->dhcp_opts; i < ctx->dhcp_opts_len; i++, opt++)
-+      for (i = 0, opt = ctx->dhcp_opts; i < ctx->dhcp_opts_len; i++, opt++) {
-+              for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
-+                      if (opt->option == opt2->option)
-+                              break;
-+              if (j == opts_len)
-+                      printf("%03d %s\n", opt->option, opt->var);
-+      }
-+      for (i = 0, opt = opts; i < opts_len; i++, opt++)
-               printf("%03d %s\n", opt->option, opt->var);
- }
-@@ -286,7 +294,7 @@
-                       errno = EINVAL;
-                       return -1;
-               }
--              ocets = (cidr + 7) / 8;
-+              ocets = (cidr + 7) / NBBY;
-               if (!out) {
-                       p += 4 + ocets;
-                       bytes += ((4 * 4) * 2) + 4;
-@@ -357,7 +365,7 @@
-               }
-               TAILQ_INSERT_TAIL(routes, rt, next);
--              ocets = (cidr + 7) / 8;
-+              ocets = (cidr + 7) / NBBY;
-               /* If we have ocets then we have a destination and netmask */
-               if (ocets > 0) {
-                       memcpy(&rt->dest.s_addr, p, ocets);
-@@ -943,6 +951,30 @@
-                               goto toobig;
-                       *p++ = (uint8_t)opt->option;
-               }
-+              for (i = 0, opt = ifo->dhcp_override;
-+                  i < ifo->dhcp_override_len;
-+                  i++, opt++)
-+              {
-+                      /* Check if added above */
-+                      for (lp = n_params + 1; lp < p; lp++)
-+                              if (*lp == (uint8_t)opt->option)
-+                                      break;
-+                      if (lp < p)
-+                              continue;
-+                      if (!(opt->type & REQUEST ||
-+                              has_option_mask(ifo->requestmask, opt->option)))
-+                              continue;
-+                      if (opt->type & NOREQ)
-+                              continue;
-+                      if (type == DHCP_INFORM &&
-+                          (opt->option == DHO_RENEWALTIME ||
-+                              opt->option == DHO_REBINDTIME))
-+                              continue;
-+                      len = (size_t)((p - m) + 2);
-+                      if (len > sizeof(*dhcp))
-+                              goto toobig;
-+                      *p++ = (uint8_t)opt->option;
-+              }
-               *n_params = (uint8_t)(p - n_params - 1);
-       }
-@@ -2733,40 +2765,23 @@
- }
- int
--dhcp_dump(struct dhcpcd_ctx *ctx, const char *ifname)
-+dhcp_dump(struct interface *ifp)
- {
--      struct interface *ifp;
-       struct dhcp_state *state;
--      if (ctx->ifaces == NULL) {
--              ctx->ifaces = malloc(sizeof(*ctx->ifaces));
--              if (ctx->ifaces == NULL)
--                      return -1;
--              TAILQ_INIT(ctx->ifaces);
--      }
--      state = NULL;
--      ifp = calloc(1, sizeof(*ifp));
--      if (ifp == NULL)
--              goto eexit;
--      ifp->ctx = ctx;
--      TAILQ_INSERT_HEAD(ctx->ifaces, ifp, next);
-       ifp->if_data[IF_DATA_DHCP] = state = calloc(1, sizeof(*state));
-       if (state == NULL)
-               goto eexit;
--      ifp->options = calloc(1, sizeof(*ifp->options));
--      if (ifp->options == NULL)
--              goto eexit;
--      strlcpy(ifp->name, ifname, sizeof(ifp->name));
-       snprintf(state->leasefile, sizeof(state->leasefile),
-           LEASEFILE, ifp->name);
-       state->new = read_lease(ifp);
-       if (state->new == NULL && errno == ENOENT) {
--              strlcpy(state->leasefile, ifname, sizeof(state->leasefile));
-+              strlcpy(state->leasefile, ifp->name, sizeof(state->leasefile));
-               state->new = read_lease(ifp);
-       }
-       if (state->new == NULL) {
-               if (errno == ENOENT)
--                      syslog(LOG_ERR, "%s: no lease to dump", ifname);
-+                      syslog(LOG_ERR, "%s: no lease to dump", ifp->name);
-               return -1;
-       }
-       state->reason = "DUMP";
-@@ -3015,13 +3030,22 @@
-       if (!(ifp->options->options & DHCPCD_IPV4))
-               return;
--      tv.tv_sec = DHCP_MIN_DELAY;
--      tv.tv_usec = (suseconds_t)arc4random_uniform(
--          (DHCP_MAX_DELAY - DHCP_MIN_DELAY) * 1000000);
--      timernorm(&tv);
--      syslog(LOG_DEBUG,
--          "%s: delaying DHCP for %0.1f seconds",
--          ifp->name, timeval_to_double(&tv));
-+      /* No point in delaying a static configuration */
-+      if (ifp->options->options & DHCPCD_STATIC &&
-+          !(ifp->options->options & DHCPCD_INFORM))
-+      {
-+              tv.tv_sec = 0;
-+              tv.tv_usec = 0;
-+      } else {
-+              tv.tv_sec = DHCP_MIN_DELAY;
-+              tv.tv_usec = (suseconds_t)arc4random_uniform(
-+                  (DHCP_MAX_DELAY - DHCP_MIN_DELAY) * 1000000);
-+              timernorm(&tv);
-+              syslog(LOG_DEBUG,
-+                  "%s: delaying DHCP for %0.1f seconds",
-+                  ifp->name, timeval_to_double(&tv));
-+      }
-+
-       eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcp_start1, ifp);
- }
-diff -urN dhcpcd-6.4.0.org/dhcpcd.8.in dhcpcd-6.4.0/dhcpcd.8.in
---- dhcpcd-6.4.0.org/dhcpcd.8.in       2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd.8.in   2014-07-05 21:47:22.000000000 +0200
-@@ -22,7 +22,7 @@
- .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- .\" SUCH DAMAGE.
- .\"
--.Dd June 2, 2014
-+.Dd July 4, 2014
- .Dt DHCPCD 8
- .Os
- .Sh NAME
-@@ -68,6 +68,10 @@
- .Fl U, Fl Fl dumplease
- .Ar interface
- .Nm
-+.Fl Fl pfxdlgonly
-+.Nm
-+.Fl Fl nopfxdlg
-+.Nm
- .Fl Fl version
- .Nm
- .Fl x , Fl Fl exit
-@@ -75,7 +79,7 @@
- .Sh DESCRIPTION
- .Nm
- is an implementation of the DHCP client specified in
--.%R RFC 2131 .
-+.Li RFC 2131 .
- .Nm
- gets the host information
- .Po
-@@ -103,17 +107,17 @@
- .Pp
- .Nm
- is also an implementation of the BOOTP client specified in
--.%R RFC 951 .
-+.Li RFC 951 .
- .Pp
- .Nm
- is also an implementation of the IPv6 Router Solicitor as specified in
--.%R RFC 4861
-+.Li RFC 4861
- and
--.%R RFC 6106 .
-+.Li RFC 6106 .
- .Pp
- .Nm
- is also an implemenation of the DHCPv6 client as specified in
--.%R RFC 3315 .
-+.Li RFC 3315 .
- By default,
- .Nm
- only starts DHCPv6 when instructed to do so by an IPV6 Router Advertisement.
-@@ -211,7 +215,7 @@
- .Pa @SCRIPT@ .
- .It Fl D , Fl Fl duid
- Generate an
--.%R RFC 4361
-+.Li RFC 4361
- compliant clientid.
- This requires persistent storage and not all DHCP servers work with it so it
- is not enabled by default.
-@@ -259,7 +263,7 @@
- itself never does any DNS updates.
- .Nm
- encodes the FQDN hostname as specified in
--.%R RFC1035 .
-+.Li RFC1035 .
- .It Fl f , Fl Fl config Ar file
- Specify a config to load instead of
- .Pa @SYSCONFDIR@/dhcpcd.conf .
-@@ -614,6 +618,30 @@
- so that
- .Nm
- knows which process to signal.
-+.Pp
-+.Li RFC3633
-+DHCPv6 Prefix Delegation does not work in the same state or session as
-+Normal or Temporary Addresses.
-+.Nm
-+is designed for a single state per protocol and as such
-+.Li draft-ietf-dhc-dhcpv6-stateful-issues-06
-+is supported by default, but that is not a published RFC yet.
-+To allow RFC conformance,
-+.Nm
-+supports the
-+.Fl Fl pfxdlgonly
-+and
-+.Fl Fl nopfxdlg
-+options which allow the spawning of two
-+.Nm
-+instances to separate the Prefix Delegation state from the others.
-+You may wish to disable
-+.Xr dhcpcd-run-hooks 8
-+on the
-+.Fl Fl pfxdlgonly
-+instance using the
-+.Fl Fl script \"\"
-+option.
- .Sh FILES
- .Bl -ohang
- .It Pa @SYSCONFDIR@/dhcpcd.conf
-@@ -671,7 +699,8 @@
- RFC\ 3004, RFC\ 3118, RFC\ 3203, RFC\ 3315, RFC\ 3361, RFC\ 3633, RFC\ 3396,
- RFC\ 3397, RFC\ 3442, RFC\ 3495, RFC\ 3925, RFC\ 3927, RFC\ 4039, RFC\ 4075,
- RFC\ 4242, RFC\ 4361, RFC\ 4390, RFC\ 4702, RFC\ 4074, RFC\ 4861, RFC\ 4833,
--RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6704, RFC\ 7217.
-+RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6603, RFC\ 6704,
-+RFC\ 7217.
- .Sh AUTHORS
- .An Roy Marples Aq Mt roy@marples.name
- .Sh BUGS
-diff -urN dhcpcd-6.4.0.org/dhcpcd.c dhcpcd-6.4.0/dhcpcd.c
---- dhcpcd-6.4.0.org/dhcpcd.c  2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd.c      2014-07-05 21:47:22.000000000 +0200
-@@ -139,14 +139,14 @@
-       struct dhcp_opt *opt;
-       if (ctx->ifac) {
--              for (ctx->ifac--; ctx->ifac >= 0; ctx->ifac--)
--                      free(ctx->ifav[ctx->ifac]);
-+              for (; ctx->ifac > 0; ctx->ifac--)
-+                      free(ctx->ifav[ctx->ifac - 1]);
-               free(ctx->ifav);
-               ctx->ifav = NULL;
-       }
-       if (ctx->ifdc) {
--              for (ctx->ifdc--; ctx->ifdc >= 0; ctx->ifdc--)
--                      free(ctx->ifdv[ctx->ifdc]);
-+              for (; ctx->ifdc > 0; ctx->ifdc--)
-+                      free(ctx->ifdv[ctx->ifdc - 1]);
-               free(ctx->ifdv);
-               ctx->ifdv = NULL;
-       }
-@@ -323,6 +323,9 @@
- {
-       struct if_options *ifo = ifp->options;
-       int ra_global, ra_iface;
-+#ifdef INET6
-+      size_t i;
-+#endif
-       /* Do any platform specific configuration */
-       if_conf(ifp);
-@@ -339,7 +342,7 @@
-               ifo->options &= ~(DHCPCD_ARP | DHCPCD_IPV4LL);
-       if (!(ifp->flags & (IFF_POINTOPOINT | IFF_LOOPBACK | IFF_MULTICAST)))
-               ifo->options &= ~DHCPCD_IPV6RS;
--      if (ifo->options & DHCPCD_LINK && if_carrier(ifp) == LINK_UNKNOWN)
-+      if (ifo->options & DHCPCD_LINK && ifp->carrier == LINK_UNKNOWN)
-               ifo->options &= ~DHCPCD_LINK;
-       if (ifo->metric != -1)
-@@ -431,17 +434,27 @@
-       }
- #ifdef INET6
--      if (ifo->ia == NULL && ifo->options & DHCPCD_IPV6) {
--              ifo->ia = malloc(sizeof(*ifo->ia));
--              if (ifo->ia == NULL)
--                      syslog(LOG_ERR, "%s: %m", __func__);
--              else {
--                      if (ifo->ia_type == 0)
--                              ifo->ia_type = D6_OPTION_IA_NA;
--                      memcpy(ifo->ia->iaid, ifo->iaid, sizeof(ifo->iaid));
--                      ifo->ia_len = 1;
--                      ifo->ia->sla = NULL;
--                      ifo->ia->sla_len = 0;
-+      if (ifo->options & DHCPCD_IPV6) {
-+              if (ifo->ia == NULL) {
-+                      ifo->ia = malloc(sizeof(*ifo->ia));
-+                      if (ifo->ia == NULL)
-+                              syslog(LOG_ERR, "%s: %m", __func__);
-+                      else {
-+                              ifo->ia_len = 1;
-+                              ifo->ia->ia_type = D6_OPTION_IA_NA;
-+                              memcpy(ifo->ia->iaid, ifo->iaid,
-+                                  sizeof(ifo->iaid));
-+                              memset(&ifo->ia->addr, 0,
-+                                  sizeof(ifo->ia->addr));
-+                              ifo->ia->sla = NULL;
-+                              ifo->ia->sla_len = 0;
-+                      }
-+              } else {
-+                      for (i = 0; i < ifo->ia_len; i++) {
-+                              if (!ifo->ia[i].iaid_set)
-+                                      memcpy(ifo->ia->iaid, ifo->iaid,
-+                                          sizeof(ifo->iaid));
-+                      }
-               }
-       }
- #endif
-@@ -493,10 +506,23 @@
-       if (ifp == NULL || !(ifp->options->options & DHCPCD_LINK))
-               return;
--      if (carrier == LINK_UNKNOWN)
-+      switch(carrier) {
-+      case LINK_UNKNOWN:
-               carrier = if_carrier(ifp); /* will set ifp->flags */
--      else
-+              break;
-+      case LINK_UP:
-+              /* we have a carrier! however, we need to ignore the flags
-+               * set in the kernel message as sometimes this message is
-+               * reported before IFF_UP is set by the kernel even though
-+               * dhcpcd has already set it.
-+               *
-+               * So we check the flags now. If IFF_UP is still not set
-+               * then we should expect an accompanying link_down message */
-+              if_setflag(ifp, 0); /* will set ifp->flags */
-+              break;
-+      default:
-               ifp->flags = flags;
-+      }
-       if (carrier == LINK_UNKNOWN)
-               syslog(LOG_ERR, "%s: carrier_status: %m", ifname);
-@@ -561,32 +587,33 @@
-                   ifp->name, ifn->name);
- }
--void
--dhcpcd_startinterface(void *arg)
-+static void
-+pre_start(struct interface *ifp)
- {
--      struct interface *ifp = arg;
--      struct if_options *ifo = ifp->options;
--      size_t i;
--      char buf[DUID_LEN * 3];
-       /* Add our link-local address before upping the interface
-        * so our RFC7217 address beats the hwaddr based one.
-        * This is also a safety check incase it was ripped out
-        * from under us. */
--      if (ifo->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) {
-+      if (ifp->options->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) {
-               syslog(LOG_ERR, "%s: ipv6_start: %m", ifp->name);
--              ifo->options &= DHCPCD_IPV6;
-+              ifp->options->options &= DHCPCD_IPV6;
-       }
-+}
--      if (!(ifp->flags & IFF_UP) && if_carrier(ifp) != LINK_UNKNOWN) {
--              if (if_up(ifp) == -1)
--                      syslog(LOG_ERR, "%s: if_up: %m",
--                          ifp->name);
--      }
-+void
-+dhcpcd_startinterface(void *arg)
-+{
-+      struct interface *ifp = arg;
-+      struct if_options *ifo = ifp->options;
-+      size_t i;
-+      char buf[DUID_LEN * 3];
--      if (ifp->carrier == LINK_UNKNOWN)
--              dhcpcd_handlecarrier(ifp->ctx, LINK_UNKNOWN, 0, ifp->name);
--      if (ifp->carrier == LINK_DOWN) {
-+      pre_start(ifp);
-+      if (if_up(ifp) == -1)
-+              syslog(LOG_ERR, "%s: if_up: %m", ifp->name);
-+
-+      if (ifp->carrier == LINK_DOWN && ifo->options & DHCPCD_LINK) {
-               syslog(LOG_INFO, "%s: waiting for carrier", ifp->name);
-               return;
-       }
-@@ -621,10 +648,12 @@
-       if (ifo->options & DHCPCD_IPV6) {
-               if (ifo->options & DHCPCD_IPV6RS &&
--                  !(ifo->options & DHCPCD_INFORM))
-+                  !(ifo->options & (DHCPCD_INFORM | DHCPCD_PFXDLGONLY)))
-                       ipv6nd_startrs(ifp);
--              if (!(ifo->options & DHCPCD_IPV6RS)) {
-+              if (!(ifo->options & DHCPCD_IPV6RS) ||
-+                  ifo->options & DHCPCD_IA_FORCED)
-+              {
-                       ssize_t nolease;
-                       if (ifo->options & DHCPCD_IA_FORCED)
-@@ -651,6 +680,8 @@
-                                   "%s: dhcp6_start: %m", ifp->name);
-               }
-       }
-+      if (ifo->options & DHCPCD_PFXDLGONLY)
-+              return;
-       if (ifo->options & DHCPCD_IPV4)
-               dhcp_start(ifp);
-@@ -700,31 +731,17 @@
- static void
- run_preinit(struct interface *ifp)
- {
--      const char *reason;
--      reason = NULL; /* appease gcc */
--      if (ifp->options->options & DHCPCD_LINK) {
--              switch (if_carrier(ifp)) {
--              case LINK_DOWN:
--                      ifp->carrier = LINK_DOWN;
--                      reason = "NOCARRIER";
--                      break;
--              case LINK_UP:
--                      ifp->carrier = LINK_UP;
--                      reason = "CARRIER";
--                      break;
--              default:
--                      ifp->carrier = LINK_UNKNOWN;
--                      return;
--              }
--      } else
--              ifp->carrier = LINK_UNKNOWN;
-+      pre_start(ifp);
-+      if (ifp->ctx->options & DHCPCD_TEST)
-+              return;
--      if (!(ifp->ctx->options & DHCPCD_TEST))
--              script_runreason(ifp, "PREINIT");
-+      script_runreason(ifp, "PREINIT");
--      if (ifp->carrier != LINK_UNKNOWN && !(ifp->ctx->options & DHCPCD_TEST))
--              script_runreason(ifp, reason);
-+      if (ifp->carrier != LINK_UNKNOWN &&
-+          ifp->options->options & DHCPCD_LINK)
-+              script_runreason(ifp,
-+                  ifp->carrier == LINK_UP ? "CARRIER" : "NOCARRIER");
- }
- int
-@@ -732,7 +749,7 @@
- {
-       struct dhcpcd_ctx *ctx;
-       struct if_head *ifs;
--      struct interface *ifp, *ifn, *ifl = NULL;
-+      struct interface *ifp, *iff, *ifn;
-       const char * const argv[] = { ifname };
-       int i;
-@@ -743,6 +760,7 @@
-                       errno = ESRCH;
-                       return -1;
-               }
-+              syslog(LOG_DEBUG, "%s: interface departed", ifp->name);
-               ifp->options->options |= DHCPCD_DEPARTED;
-               stop_interface(ifp);
-               return 0;
-@@ -764,22 +782,24 @@
-                       continue;
-               i = 0;
-               /* Check if we already have the interface */
--              ifl = if_find(ctx, ifp->name);
--              if (ifl) {
-+              iff = if_find(ctx, ifp->name);
-+              if (iff) {
-+                      syslog(LOG_DEBUG, "%s: interface updated", iff->name);
-                       /* The flags and hwaddr could have changed */
--                      ifl->flags = ifp->flags;
--                      ifl->hwlen = ifp->hwlen;
-+                      iff->flags = ifp->flags;
-+                      iff->hwlen = ifp->hwlen;
-                       if (ifp->hwlen != 0)
--                              memcpy(ifl->hwaddr, ifp->hwaddr, ifl->hwlen);
-+                              memcpy(iff->hwaddr, ifp->hwaddr, iff->hwlen);
-               } else {
-+                      syslog(LOG_DEBUG, "%s: interface added", ifp->name);
-                       TAILQ_REMOVE(ifs, ifp, next);
-                       TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
--              }
--              if (action > 0) {
-                       init_state(ifp, ctx->argc, ctx->argv);
-                       run_preinit(ifp);
--                      dhcpcd_startinterface(ifp);
-+                      iff = ifp;
-               }
-+              if (action > 0)
-+                      dhcpcd_startinterface(iff);
-       }
-       /* Free our discovered list */
-@@ -1264,6 +1284,8 @@
-       ctx.ifv = argv + optind;
-       ifo = read_config(&ctx, NULL, NULL, NULL);
-+      if (ifo == NULL)
-+              goto exit_failure;
-       opt = add_options(&ctx, NULL, ifo, argc, argv);
-       if (opt != 1) {
-               if (opt == 0)
-@@ -1272,17 +1294,26 @@
-       }
-       if (i == 3) {
-               printf("Interface options:\n");
-+              if (optind == argc - 1) {
-+                      free_options(ifo);
-+                      ifo = read_config(&ctx, argv[optind], NULL, NULL);
-+                      if (ifo == NULL)
-+                              goto exit_failure;
-+                      add_options(&ctx, NULL, ifo, argc, argv);
-+              }
-               if_printoptions();
- #ifdef INET
-               if (family == 0 || family == AF_INET) {
-                       printf("\nDHCPv4 options:\n");
--                      dhcp_printoptions(&ctx);
-+                      dhcp_printoptions(&ctx,
-+                          ifo->dhcp_override, ifo->dhcp_override_len);
-               }
- #endif
- #ifdef INET6
-               if (family == 0 || family == AF_INET6) {
-                       printf("\nDHCPv6 options:\n");
--                      dhcp6_printoptions(&ctx);
-+                      dhcp6_printoptions(&ctx,
-+                          ifo->dhcp6_override, ifo->dhcp6_override_len);
-               }
- #endif
-               goto exit_success;
-@@ -1341,9 +1372,10 @@
-                       }
-                       snprintf(pidfile, sizeof(pidfile),
-                           PIDFILE, "-", argv[optind], per);
--              }
--              else {
--                      snprintf(pidfile, sizeof(pidfile), PIDFILE, "", "", "");
-+              } else {
-+                      snprintf(pidfile, sizeof(pidfile), PIDFILE,
-+                          ctx.options & DHCPCD_PFXDLGONLY ? ".pd" : "",
-+                          "", "");
-                       ctx.options |= DHCPCD_MASTER;
-               }
-       }
-@@ -1351,18 +1383,52 @@
-       if (chdir("/") == -1)
-               syslog(LOG_ERR, "chdir `/': %m");
-+      /* Freeing allocated addresses from dumping leases can trigger
-+       * eloop removals as well, so init here. */
-+      ctx.eloop = eloop_init();
-+      if (ctx.eloop == NULL) {
-+              syslog(LOG_ERR, "%s: %m", __func__);
-+              goto exit_failure;
-+      }
-+
-       if (ctx.options & DHCPCD_DUMPLEASE) {
-               if (optind != argc - 1) {
-                       syslog(LOG_ERR, "dumplease requires an interface");
-                       goto exit_failure;
-               }
--              if (dhcp_dump(&ctx, argv[optind]) == -1)
-+              i = 0;
-+              /* We need to try and find the interface so we can
-+               * load the hardware address to compare automated IAID */
-+              ctx.ifaces = if_discover(&ctx, 1, argv + optind);
-+              if (ctx.ifaces == NULL)
-+                      goto exit_failure;
-+              ifp = TAILQ_FIRST(ctx.ifaces);
-+              if (ifp == NULL) {
-+                      ifp = calloc(1, sizeof(*ifp));
-+                      if (ifp == NULL) {
-+                              syslog(LOG_ERR, "%s: %m", __func__);
-+                              goto exit_failure;
-+                      }
-+                      strlcpy(ifp->name, argv[optind], sizeof(ifp->name));
-+                      ifp->ctx = &ctx;
-+                      TAILQ_INSERT_HEAD(ctx.ifaces, ifp, next);
-+              }
-+              configure_interface(ifp, ctx.argc, ctx.argv);
-+              if (family == 0 || family == AF_INET) {
-+                      if (dhcp_dump(ifp) == -1)
-+                              i = 1;
-+              }
-+              if (family == 0 || family == AF_INET6) {
-+                      if (dhcp6_dump(ifp) == -1)
-+                              i = 1;
-+              }
-+              if (i == -1)
-                       goto exit_failure;
-               goto exit_success;
-       }
- #ifdef USE_SIGNALS
--      if (!(ctx.options & DHCPCD_TEST) &&
-+      if (!(ctx.options & (DHCPCD_TEST | DHCPCD_PFXDLGONLY)) &&
-           (sig == 0 || ctx.ifc != 0))
-       {
- #endif
-@@ -1396,12 +1462,6 @@
-               syslog(LOG_WARNING,
-                   PACKAGE " will not work correctly unless run as root");
--      ctx.eloop = eloop_init();
--      if (ctx.eloop == NULL) {
--              syslog(LOG_ERR, "%s: %m", __func__);
--              goto exit_failure;
--      }
--
- #ifdef USE_SIGNALS
-       if (sig != 0) {
-               pid = read_pid(pidfile);
-@@ -1484,7 +1544,7 @@
-       }
--      if (ctx.options & DHCPCD_MASTER) {
-+      if (ctx.options & DHCPCD_MASTER && !(ctx.options & DHCPCD_PFXDLGONLY)) {
-               if (control_start(&ctx, NULL) == -1)
-                       syslog(LOG_ERR, "control_start: %m");
-       }
-@@ -1622,7 +1682,6 @@
-       free_options(ifo);
-       free_globals(&ctx);
--      if_rarestore(&ctx);
-       ipv4_ctxfree(&ctx);
-       ipv6_ctxfree(&ctx);
-       dev_stop(&ctx, !(ctx.options & DHCPCD_FORKED));
-diff -urN dhcpcd-6.4.0.org/dhcpcd.conf.5.in dhcpcd-6.4.0/dhcpcd.conf.5.in
---- dhcpcd-6.4.0.org/dhcpcd.conf.5.in  2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd.conf.5.in      2014-07-05 21:47:22.000000000 +0200
-@@ -22,7 +22,7 @@
- .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- .\" SUCH DAMAGE.
- .\"
--.Dd June 6, 2014
-+.Dd July 4, 2014
- .Dt DHCPCD.CONF 5
- .Os
- .Sh NAME
-@@ -214,7 +214,7 @@
- Also, see the
- .Ic env
- option above to control how the hostname is set on the host.
--.It Ic ia_na Op Ar iaid
-+.It Ic ia_na Op Ar iaid Op / address
- Request a DHCPv6 Normal Address for
- .Ar iaid .
- .Ar iaid
-@@ -230,7 +230,7 @@
- You can request more than one ia_ta by specifying a unique
- .Ar iaid
- for each one.
--.It Ic ia_pd Op Ar iaid Op Ar interface Op / Ar sla_id Op / Ar prefix_len
-+.It Ic ia_pd Op Ar iaid Oo / Ar prefix / Ar prefix_len Oc Op Ar interface Op / Ar sla_id Op / Ar prefix_len
- Request a DHCPv6 Delegated Prefix for
- .Ar iaid .
- This option must be used in an
-@@ -250,7 +250,10 @@
- and
- .Ar sla_id .
- Each assigned address will have a suffix of 1.
--You cannot assign a prefix to the requesting interface.
-+You cannot assign a prefix to the requesting interface unless the
-+DHCPv6 server supports
-+.Li RFC6603
-+Prefix Exclude Option.
- .Nm dhcpcd
- has to be running for all the interfaces it is delegating to.
- A default
-@@ -290,6 +293,12 @@
- .D1 interface eth1
- .D1 ipv4
- .D1 ipv6rs
-+.Pp
-+Using this option with other IA options in the same interface block is not
-+currently RFC conformant.
-+Please see the
-+.Li BUGS
-+section below.
- .It Ic ipv4only
- Only configure IPv4.
- .It Ic ipv6only
-@@ -457,6 +466,9 @@
- .Ar ssid .
- .It Ic slaac Op Ar hwaddr | Ar private
- Selects the interface identifier used for SLAAC generated IPv6 addresses.
-+If
-+.Ar private
-+is used, a RFC7217 address is generated.
- .It Ic static Ar value
- Configures a static
- .Ar value .
-@@ -739,11 +751,21 @@
- .Sh AUTHORS
- .An Roy Marples Aq Mt roy@marples.name
- .Sh BUGS
--When configuring DHCPv6 you can only select one IA type.
--I can't think of a use case where you would want different types,
--so if you have one then please bring it up for discussion on the
--.Aq Mt  dhcpcd-discuss@marples.name
--mailing list.
-+Combining different DHCPv6 IA options in the same interface block is not
-+currently RFC conformant.
-+See
-+.Lk http://datatracker.ietf.org/doc/draft-ietf-dhc-dhcpv6-stateful-issues
-+for details.
-+.Nm dhcpcd
-+strives to comply with this document and will be updated when finally published.
-+To enable RFC conformance, spawn separate
-+.Nm dhcpcd
-+instances using the
-+.Fl Fl pfxdlgonly
-+and
-+.Fl Fl nopfxdlg
-+options as described in
-+.Xr dhcpcd 8 .
- .Pp
- Please report them to
- .Lk http://roy.marples.name/projects/dhcpcd
-diff -urN dhcpcd-6.4.0.org/dhcpcd-definitions.conf dhcpcd-6.4.0/dhcpcd-definitions.conf
---- dhcpcd-6.4.0.org/dhcpcd-definitions.conf   2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd-definitions.conf       2014-07-05 21:47:22.000000000 +0200
-@@ -360,6 +360,7 @@
- embed         uint32                  vltime
- embed         ip6address              prefix
- encap 13      option
-+encap 67      option
- # DHCPv6 Network Information Service Options, RFC3898
- define6 27    array ip6address        nis_servers
-@@ -463,6 +464,11 @@
- # DHCPv6 AFTR-Name, RFC6334
- define6 64    domain                  aftr_name
-+# DHCPv6 Prefix Exclude Option, RFC6603
-+define6 67    embed                   pd_exclude
-+embed         byte                    prefix_len
-+embed         binhex                  subnetID
-+
- # DHCPv6 Home Info Discovery in MIPv6, RFC6610
- define6 69    encap                   mip6_idinf
- encap 71      option
-diff -urN dhcpcd-6.4.0.org/dhcpcd.h dhcpcd-6.4.0/dhcpcd.h
---- dhcpcd-6.4.0.org/dhcpcd.h  2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd.h      2014-07-05 21:47:22.000000000 +0200
-@@ -123,11 +123,8 @@
-       struct dhcp_opt *dhcp6_opts;
-       size_t dhcp6_opts_len;
-       struct ipv6_ctx *ipv6;
--      char **ra_restore;
--      size_t ra_restore_len;
- #ifndef __linux__
-       int ra_global;
--      int ra_kernel_set;
- #endif
- #endif /* INET6 */
-diff -urN dhcpcd-6.4.0.org/dhcpcd-hooks/02-dump dhcpcd-6.4.0/dhcpcd-hooks/02-dump
---- dhcpcd-6.4.0.org/dhcpcd-hooks/02-dump      2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd-hooks/02-dump  2014-07-05 21:47:22.000000000 +0200
-@@ -1,6 +1,8 @@
- # Just echo our DHCP options we have
--if [ "$reason" = "DUMP" ]; then
-+case "$reason" in
-+DUMP|DUMP6)
-       set | sed -ne 's/^new_//p' | sort
-       exit 0
--fi
-+      ;;
-+esac
-diff -urN dhcpcd-6.4.0.org/dhcpcd-hooks/20-resolv.conf dhcpcd-6.4.0/dhcpcd-hooks/20-resolv.conf
---- dhcpcd-6.4.0.org/dhcpcd-hooks/20-resolv.conf       2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd-hooks/20-resolv.conf   2014-07-05 21:47:22.000000000 +0200
-@@ -70,7 +70,7 @@
- add_resolv_conf()
- {
--      local x= conf="$signature$NL" i=${ra_count:-0} ra=
-+      local x= conf="$signature$NL" i=${ra_count:-0} ra= warn=true
-       while [ $i -ne 0 ]; do
-               eval ra=\$ra${i}_rdnss
-@@ -101,24 +101,23 @@
-       if [ -n "$new_domain_name" ]; then
-               set -- $new_domain_name
--              new_domain_name="$1"
--              if valid_domainname "$new_domain_name"; then
--                      conf="${conf}domain $new_domain_name$NL"
-+              if valid_domainname "$1"; then
-+                      conf="${conf}domain $1$NL"
-               else
--                      syslog err "Invalid domain name: $new_domain_name"
-+                      syslog err "Invalid domain name: $1"
-               fi
--              # Support RFC violating search in domain
--              if [ -z "$new_domain_search" -a -n "$2" ]; then
--                      new_domain_search="$*"
-+              # If there is no search this, make this one
-+              if [ -z "$new_domain_search" ]; then
-+                      new_domain_search="$new_domain_name"
-+                      [ "$new_domain_name" = "$1" ] && warn=true
-               fi
-       fi
--      if [ -n "$new_domain_search" -a \
--          "$new_domain_search" != "$new_domain_name" ]
--      then
-+      if [ -n "$new_domain_search" ]; then
-               if valid_domainname_list $new_domain_search; then
-                       conf="${conf}search $new_domain_search$NL"
--              else
--                      syslog err "Invalid domain name in list: $new_domain_search"
-+              elif ! $warn; then
-+                      syslog err "Invalid domain name in list:" \
-+                          "$new_domain_search"
-               fi
-       fi
-       for x in ${new_domain_name_servers}; do
-diff -urN dhcpcd-6.4.0.org/dhcpcd-hooks/Makefile dhcpcd-6.4.0/dhcpcd-hooks/Makefile
---- dhcpcd-6.4.0.org/dhcpcd-hooks/Makefile     2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd-hooks/Makefile 2014-07-05 21:47:22.000000000 +0200
-@@ -25,7 +25,7 @@
- install: proginstall
--import:
-+import: ${HOOKSCRIPTS}
-       ${INSTALL} -d /tmp/${DISTPREFIX}/dhcpcd-hooks
-       for x in ${SCRIPTS}; do \
-               t="/tmp/${DISTPREFIX}/dhcpcd-hooks/$$x"; \
-diff -urN dhcpcd-6.4.0.org/dhcp-common.c dhcpcd-6.4.0/dhcp-common.c
---- dhcpcd-6.4.0.org/dhcp-common.c     2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp-common.c 2014-07-05 21:47:22.000000000 +0200
-@@ -86,6 +86,7 @@
- int
- make_option_mask(const struct dhcp_opt *dopts, size_t dopts_len,
-+    const struct dhcp_opt *odopts, size_t odopts_len,
-     uint8_t *mask, const char *opts, int add)
- {
-       char *token, *o, *p, *t;
-@@ -94,14 +95,14 @@
-       unsigned int n;
-       size_t i;
--      o = p = strdup(opts);
-       if (opts == NULL)
-               return -1;
-+      o = p = strdup(opts);
-       while ((token = strsep(&p, ", "))) {
-               if (*token == '\0')
-                       continue;
--              for (i = 0, opt = dopts; i < dopts_len; i++, opt++) {
--                      match = 0;
-+              match = 0;
-+              for (i = 0, opt = odopts; i < odopts_len; i++, opt++) {
-                       if (strcmp(opt->var, token) == 0)
-                               match = 1;
-                       else {
-@@ -111,26 +112,40 @@
-                                       if (opt->option == n)
-                                               match = 1;
-                       }
--                      if (match) {
--                              if (add == 2 && !(opt->type & ADDRIPV4)) {
--                                      free(o);
--                                      errno = EINVAL;
--                                      return -1;
--                              }
--                              if (add == 1 || add == 2)
--                                      add_option_mask(mask,
--                                          opt->option);
--                              else
--                                      del_option_mask(mask,
--                                          opt->option);
-+                      if (match)
-                               break;
-+              }
-+              if (match == 0) {
-+                      for (i = 0, opt = dopts; i < dopts_len; i++, opt++) {
-+                              if (strcmp(opt->var, token) == 0)
-+                                      match = 1;
-+                              else {
-+                                      errno = 0;
-+                                      n = (unsigned int)strtol(token, &t, 0);
-+                                      if (errno == 0 && !*t)
-+                                              if (opt->option == n)
-+                                                      match = 1;
-+                              }
-+                              if (match)
-+                                      break;
-                       }
-               }
--              if (!opt->option) {
-+              if (!match || !opt->option) {
-                       free(o);
-                       errno = ENOENT;
-                       return -1;
-               }
-+              if (add == 2 && !(opt->type & ADDRIPV4)) {
-+                      free(o);
-+                      errno = EINVAL;
-+                      return -1;
-+              }
-+              if (add == 1 || add == 2)
-+                      add_option_mask(mask,
-+                          opt->option);
-+              else
-+                      del_option_mask(mask,
-+                          opt->option);
-       }
-       free(o);
-       return 0;
-diff -urN dhcpcd-6.4.0.org/dhcp-common.h dhcpcd-6.4.0/dhcp-common.h
---- dhcpcd-6.4.0.org/dhcp-common.h     2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp-common.h 2014-07-05 21:47:22.000000000 +0200
-@@ -88,6 +88,7 @@
- #define del_option_mask(var, val) (var[val >> 3] &= ~(1 << (val & 7)))
- #define has_option_mask(var, val) (var[val >>3] & (1 << (val & 7)))
- int make_option_mask(const struct dhcp_opt *, size_t,
-+    const struct dhcp_opt *, size_t,
-     uint8_t *, const char *, int);
- size_t encode_rfc1035(const char *src, uint8_t *dst);
-diff -urN dhcpcd-6.4.0.org/dhcp.h dhcpcd-6.4.0/dhcp.h
---- dhcpcd-6.4.0.org/dhcp.h    2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp.h        2014-07-05 21:47:22.000000000 +0200
-@@ -250,7 +250,8 @@
- ssize_t decode_rfc3442(char *, size_t, const uint8_t *p, size_t);
- ssize_t decode_rfc5969(char *, size_t, const uint8_t *p, size_t);
--void dhcp_printoptions(const struct dhcpcd_ctx *);
-+void dhcp_printoptions(const struct dhcpcd_ctx *,
-+    const struct dhcp_opt *, size_t);
- int get_option_addr(struct dhcpcd_ctx *,struct in_addr *,
-     const struct dhcp_message *, uint8_t);
- #define is_bootp(i, m) ((m) &&                                                \
-@@ -285,16 +286,15 @@
- void dhcp_reboot_newopts(struct interface *, unsigned long long);
- void dhcp_close(struct interface *);
- void dhcp_free(struct interface *);
--int dhcp_dump(struct dhcpcd_ctx *, const char *);
-+int dhcp_dump(struct interface *);
- #else
--#define dhcp_printoptions
- #define dhcp_drop(a, b)
- #define dhcp_start(a) {}
- #define dhcp_reboot(a, b) b = b
- #define dhcp_reboot_newopts(a, b)
- #define dhcp_close(a)
- #define dhcp_free(a)
--#define dhcp_dump(a, b) -1
-+#define dhcp_dump(a) -1
- #endif
- #endif
-diff -urN dhcpcd-6.4.0.org/if-bsd.c dhcpcd-6.4.0/if-bsd.c
---- dhcpcd-6.4.0.org/if-bsd.c  2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if-bsd.c      2014-07-05 21:47:22.000000000 +0200
-@@ -1019,45 +1019,6 @@
-       return flags;
- }
--void
--if_rarestore(struct dhcpcd_ctx *ctx)
--{
--
--      if (ctx->options & DHCPCD_FORKED)
--              return;
--
--      for (; ctx->ra_restore_len > 0; ctx->ra_restore_len--) {
--#ifdef ND6_IFF_ACCEPT_RTADV
--              if (!(ctx->options & DHCPCD_FORKED)) {
--                      syslog(LOG_DEBUG,
--                          "%s: restoring kernel IPv6 RA support",
--                          ctx->ra_restore[ctx->ra_restore_len - 1]);
--                      if (set_if_nd6_flag(
--                          ctx->ra_restore[ctx->ra_restore_len -1],
--                          ND6_IFF_ACCEPT_RTADV) == -1)
--                              syslog(LOG_ERR, "%s: set_if_nd6_flag: %m",
--                                  ctx->ra_restore[ctx->ra_restore_len - 1]);
--#ifdef ND6_IFF_OVERRIDE_RTADV
--                      if (ctx->ra_kernel_set == 0 && del_if_nd6_flag(
--                          ctx->ra_restore[ctx->ra_restore_len -1],
--                          ND6_IFF_OVERRIDE_RTADV) == -1)
--                              syslog(LOG_ERR, "%s: del_if_nd6_flag: %m",
--                                  ctx->ra_restore[ctx->ra_restore_len - 1]);
--#endif
--              }
--#endif
--              free(ctx->ra_restore[ctx->ra_restore_len - 1]);
--      }
--      free(ctx->ra_restore);
--      ctx->ra_restore = NULL;
--
--      if (ctx->ra_kernel_set) {
--              syslog(LOG_DEBUG, "restoring kernel IPv6 RA support");
--              if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 1) == -1)
--                      syslog(LOG_ERR, "IPV6CTL_ACCEPT_RTADV: %m");
--      }
--}
--
- static int
- if_raflush(void)
- {
-@@ -1085,10 +1046,6 @@
- #ifdef ND6_IFF_OVERRIDE_RTADV
-               int override;
- #endif
--#ifdef ND6_IFF_ACCEPT_RTADV
--              size_t i;
--              char *p, **nrest;
--#endif
- #ifdef ND6_IFF_IFDISABLED
-               if (del_if_nd6_flag(ifname, ND6_IFF_IFDISABLED) == -1) {
-@@ -1166,7 +1123,7 @@
-                               return ra;
-                       }
- #ifdef ND6_IFF_OVERRIDE_RTADV
--                      if (override == 0 && ctx->ra_kernel_set == 0 &&
-+                      if (override == 0 &&
-                           set_if_nd6_flag(ifname, ND6_IFF_OVERRIDE_RTADV)
-                           == -1)
-                       {
-@@ -1177,25 +1134,6 @@
-                               return ra;
-                       }
- #endif
--                      for (i = 0; i < ctx->ra_restore_len; i++)
--                              if (strcmp(ctx->ra_restore[i], ifname) == 0)
--                                      break;
--                      if (i == ctx->ra_restore_len) {
--                              p = strdup(ifname);
--                              if (p == NULL) {
--                                      syslog(LOG_ERR, "%s: %m", __func__);
--                                      return 0;
--                              }
--                              nrest = realloc(ctx->ra_restore,
--                                  (ctx->ra_restore_len + 1) * sizeof(char *));
--                              if (nrest == NULL) {
--                                      syslog(LOG_ERR, "%s: %m", __func__);
--                                      free(p);
--                                      return 0;
--                              }
--                              ctx->ra_restore = nrest;
--                              ctx->ra_restore[ctx->ra_restore_len++] = p;
--                      }
-                       return 0;
-               }
-               return ra;
-@@ -1217,7 +1155,6 @@
-                       return ra;
-               }
-               ra = 0;
--              ctx->ra_kernel_set = 1;
-               /* Flush the kernel knowledge of advertised routers
-                * and prefixes so the kernel does not expire prefixes
-diff -urN dhcpcd-6.4.0.org/if.c dhcpcd-6.4.0/if.c
---- dhcpcd-6.4.0.org/if.c      2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if.c  2014-07-05 21:47:22.000000000 +0200
-@@ -133,7 +133,7 @@
- }
- int
--if_up(struct interface *ifp)
-+if_setflag(struct interface *ifp, short flag)
- {
-       struct ifreq ifr;
-       int s, r;
-@@ -152,10 +152,10 @@
- #endif
-       r = -1;
-       if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) {
--              if ((ifr.ifr_flags & IFF_UP))
-+              if (flag == 0 || ifr.ifr_flags & flag)
-                       r = 0;
-               else {
--                      ifr.ifr_flags |= IFF_UP;
-+                      ifr.ifr_flags |= flag;
-                       if (ioctl(s, SIOCSIFFLAGS, &ifr) == 0)
-                               r = 0;
-               }
-@@ -295,6 +295,7 @@
-               ifp->ctx = ctx;
-               strlcpy(ifp->name, p, sizeof(ifp->name));
-               ifp->flags = ifa->ifa_flags;
-+              ifp->carrier = if_carrier(ifp);
-               sdl_type = 0;
-               /* Don't allow loopback unless explicit */
-diff -urN dhcpcd-6.4.0.org/if.h dhcpcd-6.4.0/if.h
---- dhcpcd-6.4.0.org/if.h      2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if.h  2014-07-05 21:47:22.000000000 +0200
-@@ -90,7 +90,8 @@
- #define RAW_EOF                       1 << 0
- #define RAW_PARTIALCSUM               2 << 0
--int if_up(struct interface *ifp);
-+int if_setflag(struct interface *ifp, short flag);
-+#define if_up(ifp) if_setflag((ifp), IFF_UP)
- struct if_head *if_discover(struct dhcpcd_ctx *, int, char * const *);
- struct interface *if_find(struct dhcpcd_ctx *, const char *);
- void if_free(struct interface *);
-@@ -131,7 +132,6 @@
- #ifdef INET6
- int if_checkipv6(struct dhcpcd_ctx *ctx, const char *, int);
--void if_rarestore(struct dhcpcd_ctx *);
- int if_nd6reachable(const char *ifname, struct in6_addr *addr);
- int if_address6(const struct ipv6_addr *, int);
-@@ -145,7 +145,6 @@
- #define if_delroute6(rt) if_route6(rt, -1)
- #else
- #define if_checkipv6(a, b, c) (-1)
--#define if_rarestore(a)
- #endif
- int if_machinearch(char *, size_t);
-diff -urN dhcpcd-6.4.0.org/if-linux.c dhcpcd-6.4.0/if-linux.c
---- dhcpcd-6.4.0.org/if-linux.c        2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if-linux.c    2014-07-05 21:47:22.000000000 +0200
-@@ -1223,33 +1223,11 @@
- static const char *prefix = "/proc/sys/net/ipv6/conf";
--void
--if_rarestore(struct dhcpcd_ctx *ctx)
--{
--      char path[256];
--
--      for (; ctx->ra_restore_len > 0; ctx->ra_restore_len--) {
--              if (!(ctx->options & DHCPCD_FORKED)) {
--                      syslog(LOG_DEBUG,
--                          "%s: restoring kernel IPv6 RA support",
--                          ctx->ra_restore[ctx->ra_restore_len - 1]);
--                      snprintf(path, sizeof(path), "%s/%s/accept_ra",
--                          prefix, ctx->ra_restore[ctx->ra_restore_len - 1]);
--                      if (write_path(path, "1") == -1 && errno != ENOENT)
--                          syslog(LOG_ERR, "write_path: %s: %m", path);
--              }
--              free(ctx->ra_restore[ctx->ra_restore_len - 1]);
--      }
--      free(ctx->ra_restore);
--      ctx->ra_restore = NULL;
--}
--
- int
--if_checkipv6(struct dhcpcd_ctx *ctx, const char *ifname, int own)
-+if_checkipv6(__unused struct dhcpcd_ctx *ctx, const char *ifname, int own)
- {
-       int ra;
--      size_t i;
--      char path[256], *p, **nrest;
-+      char path[256];
-       if (ifname == NULL)
-               ifname = "all";
-@@ -1283,25 +1261,6 @@
-                       syslog(LOG_ERR, "write_path: %s: %m", path);
-                       return ra;
-               }
--              for (i = 0; i < ctx->ra_restore_len; i++)
--                      if (strcmp(ctx->ra_restore[i], ifname) == 0)
--                              break;
--              if (i == ctx->ra_restore_len) {
--                      p = strdup(ifname);
--                      if (p == NULL) {
--                              syslog(LOG_ERR, "%s: %m", __func__);
--                              return 0;
--                      }
--                      nrest = realloc(ctx->ra_restore,
--                          (ctx->ra_restore_len + 1) * sizeof(char *));
--                      if (nrest == NULL) {
--                              syslog(LOG_ERR, "%s: %m", __func__);
--                              free(p);
--                              return 0;
--                      }
--                      ctx->ra_restore = nrest;
--                      ctx->ra_restore[ctx->ra_restore_len++] = p;
--              }
-               return 0;
-       }
-diff -urN dhcpcd-6.4.0.org/if-options.c dhcpcd-6.4.0/if-options.c
---- dhcpcd-6.4.0.org/if-options.c      2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if-options.c  2014-07-05 21:47:22.000000000 +0200
-@@ -93,6 +93,8 @@
- #define O_CONTROLGRP          O_BASE + 34
- #define O_SLAAC                       O_BASE + 35
- #define O_GATEWAY             O_BASE + 36
-+#define O_NOPFXDLG            O_BASE + 37
-+#define O_PFXDLGONLY          O_BASE + 38
- const struct option cf_options[] = {
-       {"background",      no_argument,       NULL, 'b'},
-@@ -179,6 +181,8 @@
-       {"controlgroup",    required_argument, NULL, O_CONTROLGRP},
-       {"slaac",           required_argument, NULL, O_SLAAC},
-       {"gateway",         no_argument,       NULL, O_GATEWAY},
-+      {"nopfxdlg",        no_argument,       NULL, O_NOPFXDLG},
-+      {"pfxdlgonly",      no_argument,       NULL, O_PFXDLGONLY},
-       {NULL,              0,                 NULL, '\0'}
- };
-@@ -518,7 +522,9 @@
- static const char *
- set_option_space(struct dhcpcd_ctx *ctx,
--    const char *arg, const struct dhcp_opt **d, size_t *dl,
-+    const char *arg,
-+    const struct dhcp_opt **d, size_t *dl,
-+    const struct dhcp_opt **od, size_t *odl,
-     struct if_options *ifo,
-     uint8_t *request[], uint8_t *require[], uint8_t *no[])
- {
-@@ -527,6 +533,8 @@
-       if (strncmp(arg, "dhcp6_", strlen("dhcp6_")) == 0) {
-               *d = ctx->dhcp6_opts;
-               *dl = ctx->dhcp6_opts_len;
-+              *od = ifo->dhcp6_override;
-+              *odl = ifo->dhcp6_override_len;
-               *request = ifo->requestmask6;
-               *require = ifo->requiremask6;
-               *no = ifo->nomask6;
-@@ -537,9 +545,13 @@
- #ifdef INET
-       *d = ctx->dhcp_opts;
-       *dl = ctx->dhcp_opts_len;
-+      *od = ifo->dhcp_override;
-+      *odl = ifo->dhcp_override_len;
- #else
-       *d = NULL;
-       *dl = 0;
-+      *od = NULL;
-+      *odl = 0;
- #endif
-       *request = ifo->requestmask;
-       *require = ifo->requiremask;
-@@ -630,10 +642,10 @@
-       struct in_addr addr, addr2;
-       in_addr_t *naddr;
-       struct rt *rt;
--      const struct dhcp_opt *d;
-+      const struct dhcp_opt *d, *od;
-       uint8_t *request, *require, *no;
-       struct dhcp_opt **dop, *ndop;
--      size_t *dop_len, dl;
-+      size_t *dop_len, dl, odl;
-       struct vivco *vivco;
-       struct token *token;
-       struct group *grp;
-@@ -733,10 +745,10 @@
-               }
-               break;
-       case 'o':
--              arg = set_option_space(ctx, arg, &d, &dl, ifo,
-+              arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
-                   &request, &require, &no);
--              if (make_option_mask(d, dl, request, arg, 1) != 0 ||
--                  make_option_mask(d, dl, no, arg, -1) != 0)
-+              if (make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
-+                  make_option_mask(d, dl, od, odl, no, arg, -1) != 0)
-               {
-                       syslog(LOG_ERR, "unknown option `%s'", arg);
-                       return -1;
-@@ -952,22 +964,22 @@
-               ifo->options |= DHCPCD_MASTER;
-               break;
-       case 'O':
--              arg = set_option_space(ctx, arg, &d, &dl, ifo,
-+              arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
-                   &request, &require, &no);
--              if (make_option_mask(d, dl, request, arg, -1) != 0 ||
--                  make_option_mask(d, dl, require, arg, -1) != 0 ||
--                  make_option_mask(d, dl, no, arg, 1) != 0)
-+              if (make_option_mask(d, dl, od, odl, request, arg, -1) != 0 ||
-+                  make_option_mask(d, dl, od, odl, require, arg, -1) != 0 ||
-+                  make_option_mask(d, dl, od, odl, no, arg, 1) != 0)
-               {
-                       syslog(LOG_ERR, "unknown option `%s'", arg);
-                       return -1;
-               }
-               break;
-       case 'Q':
--              arg = set_option_space(ctx, arg, &d, &dl, ifo,
-+              arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
-                   &request, &require, &no);
--              if (make_option_mask(d, dl, require, arg, 1) != 0 ||
--                  make_option_mask(d, dl, request, arg, 1) != 0 ||
--                  make_option_mask(d, dl, no, arg, -1) != 0)
-+              if (make_option_mask(d, dl, od, odl, require, arg, 1) != 0 ||
-+                  make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
-+                  make_option_mask(d, dl, od, odl, no, arg, -1) != 0)
-               {
-                       syslog(LOG_ERR, "unknown option `%s'", arg);
-                       return -1;
-@@ -1156,8 +1168,11 @@
-               }
-               break;
-       case O_DESTINATION:
--              if (make_option_mask(ctx->dhcp_opts, ctx->dhcp_opts_len,
--                  ifo->dstmask, arg, 2) != 0) {
-+              arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
-+                  &request, &require, &no);
-+              if (make_option_mask(d, dl, od, odl,
-+                  ifo->dstmask, arg, 2) != 0)
-+              {
-                       if (errno == EINVAL)
-                               syslog(LOG_ERR, "option `%s' does not take"
-                                   " an IPv4 address", arg);
-@@ -1220,35 +1235,40 @@
-                       }
-                       i = D6_OPTION_IA_PD;
-               }
--              if (arg != NULL && ifname == NULL) {
-+              if (ifname == NULL && arg) {
-                       syslog(LOG_ERR,
-                           "IA with IAID must belong in an interface block");
-                       return -1;
-               }
-               ifo->options |= DHCPCD_IA_FORCED;
--              if (ifo->ia_type != 0 && ifo->ia_type != i) {
--                      syslog(LOG_ERR, "cannot specify a different IA type");
--                      return -1;
--              }
--              ifo->ia_type = (uint16_t)i;
--              if (arg == NULL)
--                      break;
-               fp = strwhite(arg);
--              if (fp)
-+              if (fp) {
-                       *fp++ = '\0';
--              if (parse_iaid(iaid, arg, sizeof(iaid)) == -1)
--                      return -1;
-+                      fp = strskipwhite(fp);
-+              }
-+              if (arg) {
-+                      p = strchr(arg, '/');
-+                      if (p)
-+                              *p++ = '\0';
-+                      if (parse_iaid(iaid, arg, sizeof(iaid)) == -1)
-+                              return -1;
-+              }
-               ia = NULL;
-               for (sl = 0; sl < ifo->ia_len; sl++) {
--                      if (ifo->ia[sl].iaid[0] == iaid[0] &&
-+                      if ((arg == NULL && !ifo->ia[sl].iaid_set) ||
-+                          (ifo->ia[sl].iaid[0] == iaid[0] &&
-                           ifo->ia[sl].iaid[1] == iaid[1] &&
-                           ifo->ia[sl].iaid[2] == iaid[2] &&
--                          ifo->ia[sl].iaid[3] == iaid[3])
-+                          ifo->ia[sl].iaid[3] == iaid[3]))
-                       {
-                               ia = &ifo->ia[sl];
-                               break;
-                       }
-               }
-+              if (ia && ia->ia_type != (uint16_t)i) {
-+                      syslog(LOG_ERR, "Cannot mix IA for the same IAID");
-+                      break;
-+              }
-               if (ia == NULL) {
-                       ia = realloc(ifo->ia,
-                           sizeof(*ifo->ia) * (ifo->ia_len + 1));
-@@ -1258,14 +1278,47 @@
-                       }
-                       ifo->ia = ia;
-                       ia = &ifo->ia[ifo->ia_len++];
--                      ia->iaid[0] = iaid[0];
--                      ia->iaid[1] = iaid[1];
--                      ia->iaid[2] = iaid[2];
--                      ia->iaid[3] = iaid[3];
--                      ia->sla = NULL;
-+                      ia->ia_type = (uint16_t)i;
-+                      if (arg) {
-+                              ia->iaid[0] = iaid[0];
-+                              ia->iaid[1] = iaid[1];
-+                              ia->iaid[2] = iaid[2];
-+                              ia->iaid[3] = iaid[3];
-+                              ia->iaid_set = 1;
-+                      } else
-+                              ia->iaid_set = 0;
-+                      if (!ia->iaid_set ||
-+                          p == NULL ||
-+                          ia->ia_type == D6_OPTION_IA_TA)
-+                      {
-+                              memset(&ia->addr, 0, sizeof(ia->addr));
-+                              ia->prefix_len = 0;
-+                      } else {
-+                              arg = p;
-+                              p = strchr(arg, '/');
-+                              if (p)
-+                                      *p++ = '\0';
-+                              if (inet_pton(AF_INET6, arg, &ia->addr) == -1) {
-+                                      syslog(LOG_ERR, "%s: %m", arg);
-+                                      memset(&ia->addr, 0, sizeof(ia->addr));
-+                              }
-+                              if (p && ia->ia_type == D6_OPTION_IA_PD) {
-+                                      i = atoint(p);
-+                                      if (i != -1 && (i < 8 || i > 120)) {
-+                                              errno = EINVAL;
-+                                              i = -1;
-+                                      }
-+                                      if (i == -1) {
-+                                              syslog(LOG_ERR, "%s: %m", p);
-+                                              ia->prefix_len = 0;
-+                                      } else
-+                                              ia->prefix_len = (uint8_t)i;
-+                              }
-+                      }
-                       ia->sla_len = 0;
-+                      ia->sla = NULL;
-               }
--              if (ifo->ia_type != D6_OPTION_IA_PD)
-+              if (ia->ia_type != D6_OPTION_IA_PD)
-                       break;
-               for (p = fp; p; p = fp) {
-                       fp = strwhite(p);
-@@ -1284,12 +1337,6 @@
-                       np = strchr(p, '/');
-                       if (np)
-                               *np++ = '\0';
--                      if (strcmp(ifname, p) == 0) {
--                              syslog(LOG_ERR,
--                                  "%s: cannot assign IA_PD to itself",
--                                  ifname);
--                              goto err_sla;
--                      }
-                       if (strlcpy(sla->ifname, p,
-                           sizeof(sla->ifname)) >= sizeof(sla->ifname))
-                       {
-@@ -1853,6 +1900,12 @@
-               else
-                       ifo->options &= ~DHCPCD_SLAACPRIVATE;
-               break;
-+      case O_NOPFXDLG:
-+              ifo->options |= DHCPCD_NOPFXDLG;
-+              break;
-+      case O_PFXDLGONLY:
-+              ifo->options |= DHCPCD_PFXDLGONLY;
-+              break;
-       default:
-               return 0;
-       }
-@@ -2124,6 +2177,10 @@
-                               skip = 1;
-                       continue;
-               }
-+              /* Skip arping if we have selected a profile but not parsing
-+               * one. */
-+              if (profile && !have_profile && strcmp(option, "arping") == 0)
-+                      continue;
-               if (skip)
-                       continue;
-               parse_config_line(ctx, ifname, ifo, option, line, &ldop, &edop);
-diff -urN dhcpcd-6.4.0.org/if-options.h dhcpcd-6.4.0/if-options.h
---- dhcpcd-6.4.0.org/if-options.h      2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if-options.h  2014-07-05 21:47:22.000000000 +0200
-@@ -28,6 +28,7 @@
- #ifndef IF_OPTIONS_H
- #define IF_OPTIONS_H
-+#include <sys/param.h>
- #include <sys/socket.h>
- #include <net/if.h>
- #include <netinet/in.h>
-@@ -102,6 +103,8 @@
- #define DHCPCD_IAID                   (1ULL << 48)
- #define DHCPCD_DHCP                   (1ULL << 49)
- #define DHCPCD_DHCP6                  (1ULL << 50)
-+#define DHCPCD_NOPFXDLG                       (1ULL << 51)
-+#define DHCPCD_PFXDLGONLY             (1ULL << 52)
- extern const struct option cf_options[];
-@@ -115,6 +118,10 @@
- struct if_ia {
-       uint8_t iaid[4];
- #ifdef INET6
-+      uint16_t ia_type;
-+      uint8_t iaid_set;
-+      struct in6_addr addr;
-+      uint8_t prefix_len;
-       size_t sla_len;
-       struct if_sla *sla;
- #endif
-@@ -128,13 +135,13 @@
- struct if_options {
-       uint8_t iaid[4];
-       int metric;
--      uint8_t requestmask[256 / 8];
--      uint8_t requiremask[256 / 8];
--      uint8_t nomask[256 / 8];
--      uint8_t requestmask6[(UINT16_MAX + 1) / 8];
--      uint8_t requiremask6[(UINT16_MAX + 1) / 8];
--      uint8_t nomask6[(UINT16_MAX + 1) / 8];
--      uint8_t dstmask[256 / 8];
-+      uint8_t requestmask[256 / NBBY];
-+      uint8_t requiremask[256 / NBBY];
-+      uint8_t nomask[256 / NBBY];
-+      uint8_t requestmask6[(UINT16_MAX + 1) / NBBY];
-+      uint8_t requiremask6[(UINT16_MAX + 1) / NBBY];
-+      uint8_t nomask6[(UINT16_MAX + 1) / NBBY];
-+      uint8_t dstmask[256 / NBBY];
-       uint32_t leasetime;
-       time_t timeout;
-       time_t reboot;
-@@ -163,7 +170,6 @@
-       in_addr_t *arping;
-       char *fallback;
--      uint16_t ia_type;
-       struct if_ia *ia;
-       size_t ia_len;
-diff -urN dhcpcd-6.4.0.org/ipv4.c dhcpcd-6.4.0/ipv4.c
---- dhcpcd-6.4.0.org/ipv4.c    2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/ipv4.c        2014-07-05 21:47:22.000000000 +0200
-@@ -82,13 +82,13 @@
-               errno = EINVAL;
-               return -1;
-       }
--      ocets = (cidr + 7) / 8;
-+      ocets = (cidr + 7) / NBBY;
-       addr->s_addr = 0;
-       if (ocets > 0) {
-               memset(&addr->s_addr, 255, (size_t)ocets - 1);
-               memset((unsigned char *)&addr->s_addr + (ocets - 1),
--                  (256 - (1 << (32 - cidr) % 8)), 1);
-+                  (256 - (1 << (32 - cidr) % NBBY)), 1);
-       }
-       return 0;
-diff -urN dhcpcd-6.4.0.org/ipv6.c dhcpcd-6.4.0/ipv6.c
---- dhcpcd-6.4.0.org/ipv6.c    2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/ipv6.c        2014-07-05 21:47:22.000000000 +0200
-@@ -652,7 +652,6 @@
-       i = 0;
-       TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
-               if (ap->prefix_vltime == 0) {
--                      TAILQ_REMOVE(addrs, ap, next);
-                       if (ap->flags & IPV6_AF_ADDED) {
-                               syslog(LOG_INFO, "%s: deleting address %s",
-                                   ap->iface->name, ap->saddr);
-@@ -664,7 +663,12 @@
-                       }
-                       eloop_q_timeout_delete(ap->iface->ctx->eloop,
-                           0, NULL, ap);
--                      free(ap);
-+                      if (ap->flags & IPV6_AF_REQUEST) {
-+                              ap->flags &= ~IPV6_AF_ADDED;
-+                      } else {
-+                              TAILQ_REMOVE(addrs, ap, next);
-+                              free(ap);
-+                      }
-               } else if (!IN6_IS_ADDR_UNSPECIFIED(&ap->addr)) {
-                       if (ap->flags & IPV6_AF_NEW)
-                               i++;
-diff -urN dhcpcd-6.4.0.org/ipv6.h dhcpcd-6.4.0/ipv6.h
---- dhcpcd-6.4.0.org/ipv6.h    2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/ipv6.h        2014-07-05 21:47:22.000000000 +0200
-@@ -90,7 +90,10 @@
-       short flags;
-       char saddr[INET6_ADDRSTRLEN];
-       uint8_t iaid[4];
-+      uint16_t ia_type;
-       struct interface *delegating_iface;
-+      uint8_t prefix_exclude_len;
-+      struct in6_addr prefix_exclude;
-       void (*dadcallback)(void *);
-       int dadcounter;
-@@ -109,7 +112,8 @@
- #define IPV6_AF_DADCOMPLETED  0x0040
- #define IPV6_AF_DELEGATED     0x0080
- #define IPV6_AF_DELEGATEDPFX  0x0100
--#define IPV6_AF_DELEGATEDZERO 0X0200
-+#define IPV6_AF_DELEGATEDZERO 0x0200
-+#define IPV6_AF_REQUEST               0x0400
- struct rt6 {
-       TAILQ_ENTRY(rt6) next;
This page took 0.175925 seconds and 4 git commands to generate.