]> git.decadent.org.uk Git - odhcp6c.git/blobdiff - src/dhcpv6.c
Include IAs in Request to be more compatible with some servers
[odhcp6c.git] / src / dhcpv6.c
index 64c0cb44e90107b184590d6d265e03286c09c8c6..9742c39dd4316cf1c750246d19ef43319d6ec2b1 100644 (file)
@@ -559,12 +559,12 @@ static int dhcpv6_handle_reconfigure(_unused enum dhcpv6_msg orig,
 
 
 // Collect all advertised servers
-static int dhcpv6_handle_advert(_unused enum dhcpv6_msg orig,
+static int dhcpv6_handle_advert(enum dhcpv6_msg orig,
                const void *opt, const void *end)
 {
        uint16_t olen, otype;
        uint8_t *odata;
-       struct dhcpv6_server_cand cand = {false, false, 0, 0, {0}};
+       struct dhcpv6_server_cand cand = {false, false, 0, 0, {0}, NULL, NULL, 0, 0};
 
        dhcpv6_for_each_option(opt, end, otype, olen, odata) {
                if (otype == DHCPV6_OPT_SERVERID && olen <= 130) {
@@ -598,10 +598,25 @@ static int dhcpv6_handle_advert(_unused enum dhcpv6_msg orig,
                                        cand.preference -= 2000;
                        }
                }
+
+               if (orig == DHCPV6_MSG_SOLICIT &&
+                               (otype == DHCPV6_OPT_IA_PD || otype == DHCPV6_OPT_IA_NA) &&
+                               olen > sizeof(struct dhcpv6_ia_hdr)) {
+                       struct dhcpv6_ia_hdr *ia_hdr = (void*)(&odata[-4]);
+                       dhcpv6_parse_ia(&ia_hdr[1], odata + olen);
+               }
        }
 
-       if (cand.duid_len > 0)
+       if (cand.duid_len > 0) {
+               cand.ia_na = odhcp6c_move_state(STATE_IA_NA, &cand.ia_na_len);
+               cand.ia_pd = odhcp6c_move_state(STATE_IA_PD, &cand.ia_pd_len);
                odhcp6c_add_state(STATE_SERVER_CAND, &cand, sizeof(cand));
+       }
+
+       if (orig == DHCPV6_MSG_SOLICIT) {
+               odhcp6c_clear_state(STATE_IA_NA);
+               odhcp6c_clear_state(STATE_IA_PD);
+       }
 
        return -1;
 }
@@ -634,8 +649,14 @@ static int dhcpv6_commit_advert(void)
                odhcp6c_add_state(STATE_SERVER_ID, hdr, sizeof(hdr));
                odhcp6c_add_state(STATE_SERVER_ID, c->duid, c->duid_len);
                accept_reconfig = c->wants_reconfigure;
+               odhcp6c_add_state(STATE_IA_NA, c->ia_na, c->ia_na_len);
+               odhcp6c_add_state(STATE_IA_PD, c->ia_pd, c->ia_pd_len);
        }
 
+       for (size_t i = 0; i < cand_len / sizeof(*c); ++i) {
+               free(cand[i].ia_na);
+               free(cand[i].ia_pd);
+       }
        odhcp6c_clear_state(STATE_SERVER_CAND);
 
        if (!c)
@@ -691,6 +712,12 @@ static int dhcpv6_handle_reply(enum dhcpv6_msg orig,
                t1 = t2 = t3 = UINT32_MAX;
        }
 
+       if (orig == DHCPV6_MSG_REQUEST) {
+               // Delete NA and PD we have in the state from the Advert
+               odhcp6c_clear_state(STATE_IA_NA);
+               odhcp6c_clear_state(STATE_IA_PD);
+       }
+
        if (opt) {
                odhcp6c_clear_state(STATE_DNS);
                odhcp6c_clear_state(STATE_SEARCH);