X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=src%2Fdhcpv6.c;h=e27d8995a40102a5446816334fb3e3843819e311;hb=8a8005f7ca8973702b36e711993bfff89ca9600c;hp=cc286271519942bac3595d1edb11adf3cc27f02c;hpb=523431acff2f8afc2309c2e17b3add83d03125dc;p=odhcp6c.git diff --git a/src/dhcpv6.c b/src/dhcpv6.c index cc28627..e27d899 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -272,17 +273,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); @@ -808,7 +813,8 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc, if (inf_max_rt >= DHCPV6_INF_MAX_RT_MIN && inf_max_rt <= DHCPV6_INF_MAX_RT_MAX) cand.inf_max_rt = inf_max_rt; - } else if (otype == DHCPV6_OPT_IA_PD && request_prefix) { + } else if (otype == DHCPV6_OPT_IA_PD && request_prefix && + olen >= -4 + sizeof(struct dhcpv6_ia_hdr)) { struct dhcpv6_ia_hdr *h = (struct dhcpv6_ia_hdr*)&odata[-4]; uint8_t *oend = odata + olen, *d; dhcpv6_for_each_option(&h[1], oend, otype, olen, d) { @@ -818,7 +824,8 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc, have_pd = p->prefix; } } - } else if (otype == DHCPV6_OPT_IA_NA) { + } else if (otype == DHCPV6_OPT_IA_NA && + olen >= -4 + sizeof(struct dhcpv6_ia_hdr)) { struct dhcpv6_ia_hdr *h = (struct dhcpv6_ia_hdr*)&odata[-4]; uint8_t *oend = odata + olen, *d; dhcpv6_for_each_option(&h[1], oend, otype, olen, d) @@ -1181,7 +1188,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; } @@ -1286,16 +1293,22 @@ static int dhcpv6_calc_refresh_timers(void) static void dhcpv6_log_status_code(const uint16_t code, const char *scope, - const void *status_msg, const int len) + const void *status_msg, int len) { - uint8_t buf[len + 3]; + const char *src = status_msg; + char buf[len + 3]; + char *dst = buf; - memset(buf, 0, sizeof(buf)); if (len) { - buf[0] = '('; - memcpy(&buf[1], status_msg, len); - buf[len + 1] = ')'; + *dst++ = '('; + while (len--) { + *dst = isprint((unsigned char)*src) ? *src : '?'; + src++; + dst++; + } + *dst++ = ')'; } + *dst = 0; syslog(LOG_WARNING, "Server returned %s status %i %s", scope, code, buf); @@ -1358,6 +1371,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 +1394,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)