Merge branch 'master' into hnet
authorMarkus Stenberg <markus.stenberg@iki.fi>
Mon, 24 Jun 2013 10:53:03 +0000 (13:53 +0300)
committerMarkus Stenberg <markus.stenberg@iki.fi>
Mon, 24 Jun 2013 10:53:38 +0000 (13:53 +0300)
Conflicts:
README
src/dhcpv6.c
src/odhcp6c.h

1  2 
README
src/dhcpv6.c
src/odhcp6c.c
src/odhcp6c.h
src/ra.c
src/script.c

diff --cc README
index 2a7ab633f4634ec09344f9b4f85b12769b602178,16ac904734bdae6e9ce166023e2be65543beb529..3f2087fe65f45cdc3cceec939ebf5795cec037b3
--- 1/README
--- 2/README
+++ b/README
@@@ -53,12 -66,12 +66,12 @@@ Environment
  * SNTP_FQDN           A space-separated list of SNTP server FQDNs
  * SIP_IP              A space-separated list of SIP servers
  * SIP_DOMAIN          A space-separated list of SIP domains
- * OPTION_<num>        Custom option received as base-16
+ * OPTION_<num>                Custom option received as base-16
  * PREFIXES            A space-separated list of prefixes currently assigned
-                               Format: <prefix>/<length>,preferred,valid[,cls]
 -                              Format: <prefix>/<length>,preferred,valid[,excluded=<excluded-prefix>/<length>]
++                              Format: <prefix>/<length>,preferred,valid[,excluded=<excluded-prefix>/<length>][,class=<prefix class #>]
  * ADDRESSES           A space-separated list of addresses currently assigned
                                Format: <address>/<length>,preferred,valid
- * RA_ADDRESSES        A space-separated list of addresses from RA-prefixes
+ * RA_ADDRESSES                A space-separated list of addresses from RA-prefixes
                                Format: <address>/<length>,preferred,valid
  * RA_ROUTES           A space-separated list of routes from the RA
                                Format: <address>/<length>,gateway,valid,metric
diff --cc src/dhcpv6.c
index 161f6287a546302db2288520461e8927f7d6ab6a,ed6b8f868a67accdad22418e34cfc369204f5347..7f2aa1a70ab91c22c2b18d0700c9e0c07ee2a639
@@@ -131,12 -136,15 +136,17 @@@ int init_dhcpv6(const char *ifname, in
        }
  
        // Create ORO
-       uint16_t oro[] = {htons(DHCPV6_OPT_DNS_SERVERS),
+       uint16_t oro[] = {
+                       htons(DHCPV6_OPT_SIP_SERVER_D),
+                       htons(DHCPV6_OPT_SIP_SERVER_A),
+                       htons(DHCPV6_OPT_DNS_SERVERS),
                        htons(DHCPV6_OPT_DNS_DOMAIN),
                        htons(DHCPV6_OPT_NTP_SERVER),
-                           htons(DHCPV6_OPT_PREFIX_CLASS)
-                          };
 +                      htons(DHCPV6_OPT_SIP_SERVER_A),
+                       htons(DHCPV6_OPT_AFTR_NAME),
+                       htons(DHCPV6_OPT_PD_EXCLUDE),
++                      htons(DHCPV6_OPT_PREFIX_CLASS),
+       };
        odhcp6c_add_state(STATE_ORO, oro, sizeof(oro));
  
  
@@@ -748,16 -818,51 +820,57 @@@ static uint32_t dhcpv6_parse_ia(void *o
  
                        entry.length = prefix->prefix;
                        entry.target = prefix->addr;
 +                      uint16_t stype, slen;
 +                      uint8_t *sdata;
 +
 +                        // Find prefix class, if any
 +                      dhcpv6_for_each_option(&prefix[1], odata + olen,
 +                                               stype, slen, sdata)
 +                          if (stype == DHCPV6_OPT_PREFIX_CLASS && slen == 2) 
 +                            entry.prefix_class = ntohs(*((uint16_t*)sdata));
  
-                       odhcp6c_update_entry(STATE_IA_PD, &entry);
+                       // Parse PD-exclude
+                       bool ok = true;
 -                      uint16_t stype, slen;
 -                      uint8_t *sdata;
+                       dhcpv6_for_each_option(odata + sizeof(*prefix) - 4U,
+                                       odata + olen, stype, slen, sdata) {
+                               if (stype != DHCPV6_OPT_PD_EXCLUDE || slen < 2)
+                                       continue;
+                               uint8_t elen = sdata[0];
+                               if (elen > 64)
+                                       elen = 64;
+                               if (elen <= 32 || elen <= entry.length) {
+                                       ok = false;
+                                       continue;
+                               }
+                               uint8_t bytes = ((elen - entry.length - 1) / 8) + 1;
+                               if (slen <= bytes) {
+                                       ok = false;
+                                       continue;
+                               }
+                               uint32_t exclude = 0;
+                               do {
+                                       exclude = exclude << 8 | sdata[bytes];
+                               } while (--bytes);
+                               exclude >>= 8 - ((elen - entry.length) % 8);
+                               exclude <<= 64 - elen;
+                               // Abusing router & priority fields for exclusion
+                               entry.router = entry.target;
+                               entry.router.s6_addr32[1] |= htonl(exclude);
+                               entry.priority = elen;
+                       }
+                       if (ok)
+                               odhcp6c_update_entry(STATE_IA_PD, &entry);
+                       entry.priority = 0;
+                       memset(&entry.router, 0, sizeof(entry.router));
                } else if (otype == DHCPV6_OPT_IA_ADDR) {
                        struct dhcpv6_ia_addr *addr = (void*)&odata[-4];
                        if (olen + 4U < sizeof(*addr))
diff --cc src/odhcp6c.c
Simple merge
diff --cc src/odhcp6c.h
index 1b46af01df98325b62913b06131bdcaff8cb4e6a,2e7107c5d582eb63748bb3018cfb27987b9c4e25..d8a9bffdf80e0040285182cc5de6ab3f0b3d6618
@@@ -51,9 -51,8 +51,10 @@@ enum dhcvp6_opt 
        DHCPV6_OPT_NTP_SERVER = 56,
        DHCPV6_OPT_SIP_SERVER_D = 21,
        DHCPV6_OPT_SIP_SERVER_A = 22,
+       DHCPV6_OPT_AFTR_NAME = 64,
+       DHCPV6_OPT_PD_EXCLUDE = 67,
 +        /* draft-bhandari-dhc-class-based-prefix */
 +      DHCPV6_OPT_PREFIX_CLASS = 200, /* NOT STANDARDIZED! */
  };
  
  enum dhcpv6_opt_npt {
diff --cc src/ra.c
index 580d4cdc3e9b185b3f685495379663c15647e74b,4690d419466975357a5a9bce667f469c633f87b2..9a579851524786704875d675100d8fded72ef6b7
+++ b/src/ra.c
@@@ -173,9 -202,8 +202,8 @@@ bool ra_process(void
        bool found = false;
        uint8_t buf[1500];
        struct nd_router_advert *adv = (struct nd_router_advert*)buf;
 -      struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT, 0, 0, IN6ADDR_ANY_INIT, 0, 0};
 +      struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT, 0, 0, IN6ADDR_ANY_INIT, 0, 0, 0};
        const struct in6_addr any = IN6ADDR_ANY_INIT;
-       odhcp6c_expire();
  
        while (true) {
                struct sockaddr_in6 from;
diff --cc src/script.c
index 7368080bc84c870a3db53647603d15f3fababa65,bda9749ec27eb66ba336b16414378c8669af2576..3cc7e2b47c663afacb4575acf3baa8147af69c32
@@@ -152,8 -186,14 +186,17 @@@ static void entry_to_env(const char *na
                                buf_len += snprintf(&buf[buf_len], 12, ",%u", e[i].priority);
                        } else {
                                buf_len += snprintf(&buf[buf_len], 24, ",%u,%u", e[i].preferred, e[i].valid);
-                                 if (e[i].prefix_class)
-                                   buf_len += snprintf(&buf[buf_len], 12, ",%u", e[i].prefix_class);
+                       }
++                        if (type == ENTRY_PREFIX && e[i].prefix_class) {
++                          buf_len += snprintf(&buf[buf_len], 12, ",class=%u", e[i].prefix_class);
++                        }
+                       if (type == ENTRY_PREFIX && e[i].priority) {
+                               // priority and router are abused for prefix exclusion
+                               buf_len += snprintf(&buf[buf_len], 12, ",excluded=");
+                               inet_ntop(AF_INET6, &e[i].router, &buf[buf_len], INET6_ADDRSTRLEN);
+                               buf_len += strlen(&buf[buf_len]);
+                               buf_len += snprintf(&buf[buf_len], 24, "/%u", e[i].priority);
                        }
                }
                buf[buf_len++] = ' ';