From 405b2e82dfeb95e3b90d35f8970efad85388949c Mon Sep 17 00:00:00 2001 From: Hans Dedecker Date: Wed, 16 Apr 2014 11:53:32 +0200 Subject: [PATCH] Don't return a DHCPv6 reply in response to a confirm without address(es) RFC3315 Section 18.2.2 states no reply must returned by the server in case no address(es) are present : If the server is unable to perform this test (for example, the server does not have information about prefixes on the link to which the client is connected), or there were no addresses in any of the IAs sent by the client, the server MUST NOT send a reply to the client. --- src/dhcpv6-ia.c | 6 ++++-- src/dhcpv6.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index 844dfd3..5e34b5c 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -972,6 +972,7 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, dhcpv6_for_each_option(start, end, otype, olen, odata) { bool is_pd = (otype == DHCPV6_OPT_IA_PD); bool is_na = (otype == DHCPV6_OPT_IA_NA); + bool ia_addr_present = false; if (!is_pd && !is_na) continue; @@ -1024,6 +1025,7 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, if (stype != DHCPV6_OPT_IA_ADDR || slen < sizeof(struct dhcpv6_ia_addr) - 4) continue; + ia_addr_present = true; #ifdef DHCPV6_OPT_PREFIX_CLASS uint8_t *xdata; uint16_t xtype, xlen; @@ -1178,8 +1180,8 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, a->valid_until = now + 3600; // Block address for 1h update_state = true; } - } else if (hdr->msg_type == DHCPV6_MSG_CONFIRM) { - // Always send NOTONLINK for CONFIRM so that clients restart connection + } else if (hdr->msg_type == DHCPV6_MSG_CONFIRM && ia_addr_present) { + // Send NOTONLINK for CONFIRM with addr present so that clients restart connection status = DHCPV6_STATUS_NOTONLINK; ia_response_len = append_reply(buf, buflen, status, ia, a, iface, true); } diff --git a/src/dhcpv6.c b/src/dhcpv6.c index 62f30e2..55b9ea9 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -320,7 +320,7 @@ static void handle_client_request(void *addr, void *data, size_t len, if (opts[-4] != DHCPV6_MSG_INFORMATION_REQUEST) { ssize_t ialen = dhcpv6_handle_ia(pdbuf, sizeof(pdbuf), iface, addr, &opts[-4], opts_end); iov[6].iov_len = ialen; - if (ialen < 0 || (ialen == 0 && opts[-4] == DHCPV6_MSG_REBIND)) + if (ialen < 0 || (ialen == 0 && (opts[-4] == DHCPV6_MSG_REBIND || opts[-4] == DHCPV6_MSG_CONFIRM))) return; } -- 2.30.2