From b65ff293a96924f9b19dff8855232bfb9054b976 Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Sat, 18 Oct 2025 22:22:41 +0200 Subject: [PATCH] dhcpv6: Check status code for IA_ADDR operations MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Check for error status code in the IA Address option in replies to RENEW messages. Signed-off-by: Paul Donald Link: https://github.com/openwrt/odhcp6c/pull/103 Signed-off-by: Álvaro Fernández Rojas --- src/dhcpv6.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/dhcpv6.c b/src/dhcpv6.c index e8dd2ae..fa0c2a1 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -1425,8 +1425,8 @@ static unsigned int dhcpv6_parse_ia(void *opt, void *end, int *ret) The status of any operations involving this IA Prefix option is indicated in a Status Code option (see Section 21.13) in the IAprefix-options field. */ - uint8_t *status_msg = (slen > 2) ? &sdata[2] : NULL; - uint16_t msg_len = (slen > 2) ? slen - 2 : 0; + uint8_t *status_msg = &sdata[2]; + uint16_t msg_len = slen - 2; uint16_t code = ((int)sdata[0]) << 8 | ((int)sdata[1]); if (code == DHCPV6_Success) @@ -1497,13 +1497,38 @@ static unsigned int dhcpv6_parse_ia(void *opt, void *end, int *ret) entry.length = 128; entry.target = addr->addr; + uint16_t stype, slen; + uint8_t *sdata; + + bool update_state = true; + dhcpv6_for_each_option(odata + sizeof(*addr) - 4U, + odata + olen, stype, slen, sdata) { + if (stype == DHCPV6_OPT_STATUS && slen > 2) { + /* RFC 8415 §21.6 + The status of any operations involving this IA Address is indicated + in a Status Code option in the IAaddr-options field, as specified in + Section 21.13. */ + uint8_t *status_msg = &sdata[2]; + uint16_t msg_len = slen - 2; + uint16_t code = ((int)sdata[0]) << 8 | ((int)sdata[1]); + + if (code == DHCPV6_Success) + continue; - if (odhcp6c_update_entry(STATE_IA_NA, &entry, 0, 0)) - updated_IAs++; + dhcpv6_log_status_code(code, "IA_ADDR", status_msg, msg_len); + if (ret) *ret = 0; // renewal failed + update_state = false; + } + } - syslog(LOG_INFO, "%s preferred %d valid %d", - inet_ntop(AF_INET6, &entry.target, buf, sizeof(buf)), - entry.preferred , entry.valid); + if (update_state) { + if (odhcp6c_update_entry(STATE_IA_NA, &entry, 0, 0)) + updated_IAs++; + + syslog(LOG_INFO, "%s preferred %d valid %d", + inet_ntop(AF_INET6, &entry.target, buf, sizeof(buf)), + entry.preferred , entry.valid); + } break; } default: -- 2.30.2