]> git.decadent.org.uk Git - odhcp6c.git/blobdiff - src/dhcpv6.c
First hnet-based version.
[odhcp6c.git] / src / dhcpv6.c
index 561cf836778e1f62cfb5c05584774f97d33e60ca..013e215c6555d1a0f2ffa7cf794efb5f04799c73 100644 (file)
@@ -76,7 +76,7 @@ static struct dhcpv6_retx dhcpv6_retx[_DHCPV6_MSG_MAX] = {
 // Sockets
 static int sock = -1;
 static int ifindex = -1;
-static time_t t1 = 0, t2 = 0, t3 = 0;
+static int64_t t1 = 0, t2 = 0, t3 = 0;
 
 // IA states
 static int request_prefix = -1;
@@ -135,7 +135,8 @@ int init_dhcpv6(const char *ifname, int request_pd)
                        htons(DHCPV6_OPT_DNS_DOMAIN),
                        htons(DHCPV6_OPT_NTP_SERVER),
                        htons(DHCPV6_OPT_SIP_SERVER_A),
-                       htons(DHCPV6_OPT_SIP_SERVER_D)};
+                          htons(DHCPV6_OPT_PREFIX_CLASS)
+                         };
        odhcp6c_add_state(STATE_ORO, oro, sizeof(oro));
 
 
@@ -207,8 +208,8 @@ static void dhcpv6_send(enum dhcpv6_msg type, uint8_t trid[3], uint32_t ecs)
        for (size_t i = 0; i < ia_pd_entries; ++i) {
                p[i].type = htons(DHCPV6_OPT_IA_PREFIX);
                p[i].len = htons(sizeof(p[i]) - 4U);
-               p[i].preferred = htonl(e[i].preferred);
-               p[i].valid = htonl(e[i].valid);
+               p[i].preferred = 0;
+               p[i].valid = 0;
                p[i].prefix = e[i].length;
                p[i].addr = e[i].target;
        }
@@ -241,8 +242,8 @@ static void dhcpv6_send(enum dhcpv6_msg type, uint8_t trid[3], uint32_t ecs)
                pa[i].type = htons(DHCPV6_OPT_IA_ADDR);
                pa[i].len = htons(sizeof(pa[i]) - 4U);
                pa[i].addr = e[i].target;
-               pa[i].preferred = htonl(e[i].preferred);
-               pa[i].valid = htonl(e[i].valid);
+               pa[i].preferred = 0;
+               pa[i].valid = 0;
        }
 
        ia_na = pa;
@@ -520,7 +521,7 @@ static int dhcpv6_handle_advert(_unused enum dhcpv6_msg orig,
                        cand.preference -= 2000;
                } else if (otype == DHCPV6_OPT_PREF && olen >= 1 &&
                                cand.preference >= 0) {
-                       cand.preference = odata[1];
+                       cand.preference = odata[0];
                } else if (otype == DHCPV6_OPT_RECONF_ACCEPT) {
                        cand.wants_reconfigure = true;
                } else if (otype == DHCPV6_OPT_IA_PD && request_prefix) {
@@ -623,7 +624,7 @@ static int dhcpv6_handle_reply(enum dhcpv6_msg orig,
                if (t3 < 0)
                        t3 = 0;
        } else {
-               t1 = t2 = t3 = 86400;
+               t1 = t2 = t3 = UINT32_MAX;
        }
 
        if (opt) {
@@ -674,6 +675,12 @@ static int dhcpv6_handle_reply(enum dhcpv6_msg orig,
                        if (n < t3)
                                t3 = n;
 
+                       if (t2 >= t3)
+                               t2 = 8 * t3 / 10;
+
+                       if (t1 >= t2)
+                               t1 = 5 * t2 / 8;
+
                } else if (otype == DHCPV6_OPT_DNS_SERVERS) {
                        if (olen % 16 == 0)
                                odhcp6c_add_state(STATE_DNS, odata, olen);
@@ -719,11 +726,11 @@ static uint32_t dhcpv6_parse_ia(void *opt, void *end)
        uint16_t otype, olen;
        uint8_t *odata;
 
-       struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT,
-                       0, 0, IN6ADDR_ANY_INIT, 0, 0};
-
        // Update address IA
        dhcpv6_for_each_option(opt, end, otype, olen, odata) {
+          struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT,
+                                        0, 0, IN6ADDR_ANY_INIT, 0, 0, 0};
+
                if (otype == DHCPV6_OPT_IA_PREFIX) {
                        struct dhcpv6_ia_prefix *prefix = (void*)&odata[-4];
                        if (olen + 4U < sizeof(*prefix))
@@ -737,6 +744,14 @@ static uint32_t dhcpv6_parse_ia(void *opt, void *end)
 
                        entry.length = prefix->prefix;
                        entry.target = prefix->addr;
+                       uint16_t stype, slen;
+                       uint8_t *sdata;
+
+                        // Find prefix class, if any
+                       dhcpv6_for_each_option(odata, 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);
                } else if (otype == DHCPV6_OPT_IA_ADDR) {