+ if (type == DHCPV6_MSG_SOLICIT) {
+ odhcp6c_clear_state(STATE_IA_PD);
+ size_t n_prefixes;
+ struct odhcp6c_request_prefix *request_prefixes = odhcp6c_get_state(STATE_IA_PD_INIT, &n_prefixes);
+ n_prefixes /= sizeof(struct odhcp6c_request_prefix);
+
+ ia_pd = alloca(n_prefixes * (sizeof(struct dhcpv6_ia_hdr) + sizeof(struct dhcpv6_ia_prefix)));
+
+ 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)),
+ 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
+ };
+ 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);
+ }
+ } else {
+ struct odhcp6c_entry *e = odhcp6c_get_state(STATE_IA_PD, &ia_pd_entries);
+ ia_pd_entries /= sizeof(*e);
+
+ // we're too lazy to count our distinct IAIDs,
+ // so just allocate maximally needed space
+ ia_pd = alloca(ia_pd_entries * (sizeof(struct dhcpv6_ia_prefix) + 10 +
+ sizeof(struct dhcpv6_ia_hdr)));
+
+ for (size_t i = 0; i < ia_pd_entries; ++i) {
+ uint32_t iaid = e[i].iaid;
+
+ // check if this is an unprocessed IAID and skip if not.
+ int new_iaid = 1;
+ for (int j = i-1; j >= 0; j--) {
+ if (e[j].iaid == iaid) {
+ new_iaid = 0;
+ break;
+ }
+ }