X-Git-Url: https://git.decadent.org.uk/gitweb/?p=odhcp6c.git;a=blobdiff_plain;f=src%2Fdhcpv6.c;h=ca41db6b48e88dd90d05b73eb270f4d585fc5c55;hp=b7fccaca62e78e9a048b8da5151677523ef69dcd;hb=2015de99e2495e886a0e5c748a654d7d5b112cf9;hpb=0300fe7589a1701361735ac068e4b57bb1a1896f diff --git a/src/dhcpv6.c b/src/dhcpv6.c index b7fccac..ca41db6 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -551,10 +551,12 @@ int dhcpv6_request(enum dhcpv6_msg type) round_start = odhcp6c_get_milli_time()) { uint8_t buf[1536], cmsg_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; struct iovec iov = {buf, sizeof(buf)}; - struct msghdr msg = {NULL, 0, &iov, 1, + struct sockaddr_in6 addr; + struct msghdr msg = {&addr, sizeof(addr), &iov, 1, cmsg_buf, sizeof(cmsg_buf), 0}; struct in6_pktinfo *pktinfo = NULL; + // Check for pending signal if (odhcp6c_signal_process()) return -1; @@ -599,7 +601,7 @@ int dhcpv6_request(enum dhcpv6_msg type) "%llums", (unsigned long long)elapsed); if (retx->handler_reply) - len = retx->handler_reply(type, rc, opt, opt_end); + len = retx->handler_reply(type, rc, opt, opt_end, &addr); if (len > 0 && round_end - round_start > 1000) round_end = 1000 + round_start; @@ -691,7 +693,7 @@ static bool dhcpv6_response_is_valid(const void *buf, ssize_t len, rcmsg = odata[0]; } else if ((otype == DHCPV6_OPT_IA_PD || otype == DHCPV6_OPT_IA_NA)) { ia_present = true; - if (olen < sizeof(struct dhcpv6_ia_hdr)) + if (olen < -4 + sizeof(struct dhcpv6_ia_hdr)) options_valid = false; } else if ((otype == DHCPV6_OPT_IA_ADDR) || (otype == DHCPV6_OPT_IA_PREFIX) || @@ -729,7 +731,7 @@ int dhcpv6_poll_reconfigure(void) static int dhcpv6_handle_reconfigure(_unused enum dhcpv6_msg orig, const int rc, - const void *opt, const void *end) + const void *opt, const void *end, _unused const struct sockaddr_in6 *from) { uint16_t otype, olen; uint8_t *odata, msg = DHCPV6_MSG_RENEW; @@ -739,14 +741,14 @@ static int dhcpv6_handle_reconfigure(_unused enum dhcpv6_msg orig, const int rc, odata[0] == DHCPV6_MSG_INFO_REQ)) msg = odata[0]; - dhcpv6_handle_reply(DHCPV6_MSG_UNKNOWN, rc, NULL, NULL); + dhcpv6_handle_reply(DHCPV6_MSG_UNKNOWN, rc, NULL, NULL, NULL); return msg; } // Collect all advertised servers static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc, - const void *opt, const void *end) + const void *opt, const void *end, _unused const struct sockaddr_in6 *from) { uint16_t olen, otype; uint8_t *odata, pref = 0; @@ -759,7 +761,7 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc, dhcpv6_for_each_option(opt, end, otype, olen, odata) { if (orig == DHCPV6_MSG_SOLICIT && (otype == DHCPV6_OPT_IA_PD || otype == DHCPV6_OPT_IA_NA) && - olen > sizeof(struct dhcpv6_ia_hdr)) { + olen > -4 + sizeof(struct dhcpv6_ia_hdr)) { struct dhcpv6_ia_hdr *ia_hdr = (void*)(&odata[-4]); dhcpv6_parse_ia(ia_hdr, odata + olen + sizeof(*ia_hdr)); } @@ -798,8 +800,8 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc, 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) { - if (otype == DHCPV6_OPT_IA_PREFIX && (olen + 4) >= - (uint16_t)sizeof(struct dhcpv6_ia_prefix)) { + if (otype == DHCPV6_OPT_IA_PREFIX && + olen >= -4 + sizeof(struct dhcpv6_ia_prefix)) { struct dhcpv6_ia_prefix *p = (struct dhcpv6_ia_prefix*)&d[-4]; have_pd = p->prefix; } @@ -808,7 +810,8 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc, 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) - if (otype == DHCPV6_OPT_IA_ADDR) + if (otype == DHCPV6_OPT_IA_ADDR && + olen >= -4 + sizeof(struct dhcpv6_ia_addr)) have_na = true; } } @@ -854,18 +857,18 @@ static int dhcpv6_commit_advert(void) static int dhcpv6_handle_rebind_reply(enum dhcpv6_msg orig, const int rc, - const void *opt, const void *end) + const void *opt, const void *end, const struct sockaddr_in6 *from) { - dhcpv6_handle_advert(orig, rc, opt, end); + dhcpv6_handle_advert(orig, rc, opt, end, from); if (dhcpv6_commit_advert() < 0) return -1; - return dhcpv6_handle_reply(orig, rc, opt, end); + return dhcpv6_handle_reply(orig, rc, opt, end, from); } static int dhcpv6_handle_reply(enum dhcpv6_msg orig, _unused const int rc, - const void *opt, const void *end) + const void *opt, const void *end, const struct sockaddr_in6 *from) { uint8_t *odata; uint16_t otype, olen; @@ -928,7 +931,7 @@ static int dhcpv6_handle_reply(enum dhcpv6_msg orig, _unused const int rc, bool passthru = true; if ((otype == DHCPV6_OPT_IA_PD || otype == DHCPV6_OPT_IA_NA) - && olen > sizeof(struct dhcpv6_ia_hdr)) { + && olen > -4 + sizeof(struct dhcpv6_ia_hdr)) { struct dhcpv6_ia_hdr *ia_hdr = (void*)(&odata[-4]); // Test ID @@ -1090,6 +1093,11 @@ static int dhcpv6_handle_reply(enum dhcpv6_msg orig, _unused const int rc, default : break; } + + if (orig == DHCPV6_MSG_REBIND || orig == DHCPV6_MSG_REQUEST) { + odhcp6c_clear_state(STATE_SERVER_ADDR); + odhcp6c_add_state(STATE_SERVER_ADDR, &from->sin6_addr, 16); + } } } else if (ret > 0) {