]> git.decadent.org.uk Git - odhcp6c.git/blobdiff - src/dhcpv6.c
Check for unsupported PD exclusion configuration in dhcpv6_parse_ia
[odhcp6c.git] / src / dhcpv6.c
index cc286271519942bac3595d1edb11adf3cc27f02c..2d8124f288171f966e777720254c401d7d3b14ce 100644 (file)
@@ -272,17 +272,21 @@ static void dhcpv6_send(enum dhcpv6_msg type, uint8_t trid[3], uint32_t ecs)
                for (size_t i = 0; i < n_prefixes; i++) {
                        struct dhcpv6_ia_hdr hdr_ia_pd = {
                                htons(DHCPV6_OPT_IA_PD),
-                               htons(sizeof(hdr_ia_pd) - 4 + sizeof(struct dhcpv6_ia_prefix)),
+                               htons(sizeof(hdr_ia_pd) - 4 +
+                                     sizeof(struct dhcpv6_ia_prefix) * !!request_prefixes[i].length),
                                request_prefixes[i].iaid, 0, 0
                        };
                        struct dhcpv6_ia_prefix pref = {
                                .type = htons(DHCPV6_OPT_IA_PREFIX),
-                               .len = htons(25), .prefix = request_prefixes[i].length
+                               .len = htons(sizeof(pref) - 4),
+                               .prefix = request_prefixes[i].length
                        };
                        memcpy(ia_pd + ia_pd_len, &hdr_ia_pd, sizeof(hdr_ia_pd));
                        ia_pd_len += sizeof(hdr_ia_pd);
-                       memcpy(ia_pd + ia_pd_len, &pref, sizeof(pref));
-                       ia_pd_len += sizeof(pref);
+                       if (request_prefixes[i].length) {
+                               memcpy(ia_pd + ia_pd_len, &pref, sizeof(pref));
+                               ia_pd_len += sizeof(pref);
+                       }
                }
        } else {
                struct odhcp6c_entry *e = odhcp6c_get_state(STATE_IA_PD, &ia_pd_entries);
@@ -1181,7 +1185,7 @@ static int dhcpv6_parse_ia(void *opt, void *end)
                                if (elen > 64)
                                        elen = 64;
 
-                               if (elen <= 32 || elen <= entry.length) {
+                               if (entry.length < 32 || elen <= entry.length) {
                                        ok = false;
                                        continue;
                                }
@@ -1358,6 +1362,7 @@ static void dhcpv6_handle_ia_status_code(const enum dhcpv6_msg orig,
        }
 }
 
+// Note this always takes ownership of cand->ia_na and cand->ia_pd
 static void dhcpv6_add_server_cand(const struct dhcpv6_server_cand *cand)
 {
        size_t cand_len, i;
@@ -1380,7 +1385,10 @@ static void dhcpv6_add_server_cand(const struct dhcpv6_server_cand *cand)
                        break;
        }
 
-       odhcp6c_insert_state(STATE_SERVER_CAND, i * sizeof(*c), cand, sizeof(*cand));
+       if (odhcp6c_insert_state(STATE_SERVER_CAND, i * sizeof(*c), cand, sizeof(*cand))) {
+               free(cand->ia_na);
+               free(cand->ia_pd);
+       }
 }
 
 static void dhcpv6_clear_all_server_cand(void)