diff options
Diffstat (limited to 'src/dhcpv6.c')
-rw-r--r-- | src/dhcpv6.c | 48 |
1 files changed, 30 insertions, 18 deletions
diff --git a/src/dhcpv6.c b/src/dhcpv6.c index a40c353..f2080c8 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -163,6 +163,7 @@ enum { IOV_DEST, IOV_MAXRT, #define IOV_STAT IOV_MAXRT + IOV_RAPID_COMMIT, IOV_DNS, IOV_DNS_ADDR, IOV_SEARCH, @@ -237,6 +238,8 @@ static void handle_client_request(void *addr, void *data, size_t len, struct interface *iface, void *dest_addr) { struct dhcpv6_client_header *hdr = data; + uint8_t *opts = (uint8_t *)&hdr[1], *opts_end = (uint8_t *)data + len; + bool o_rapid_commit = false; if (len < sizeof(*hdr)) return; @@ -276,6 +279,11 @@ static void handle_client_request(void *addr, void *data, size_t len, struct __attribute__((packed)) { uint16_t type; uint16_t len; + } rapid_commit = {htons(DHCPV6_OPT_RAPID_COMMIT), 0}; + + struct __attribute__((packed)) { + uint16_t type; + uint16_t len; uint16_t value; } stat = {htons(DHCPV6_OPT_STATUS), htons(sizeof(stat) - 4), htons(DHCPV6_STATUS_USEMULTICAST)}; @@ -336,6 +344,7 @@ static void handle_client_request(void *addr, void *data, size_t len, [IOV_NESTED] = {NULL, 0}, [IOV_DEST] = {&dest, (uint8_t*)&dest.clientid_type - (uint8_t*)&dest}, [IOV_MAXRT] = {&maxrt, sizeof(maxrt)}, + [IOV_RAPID_COMMIT] = {&rapid_commit, 0}, [IOV_DNS] = {&dns, (dns_cnt) ? sizeof(dns) : 0}, [IOV_DNS_ADDR] = {dns_addr_ptr, dns_cnt * sizeof(*dns_addr_ptr)}, [IOV_SEARCH] = {&search, (search_len) ? sizeof(search) : 0}, @@ -346,30 +355,19 @@ static void handle_client_request(void *addr, void *data, size_t len, [IOV_RELAY_MSG] = {NULL, 0} }; - uint8_t *opts = (uint8_t*)&hdr[1], *opts_end = (uint8_t*)data + len; if (hdr->msg_type == DHCPV6_MSG_RELAY_FORW) handle_nested_message(data, len, &hdr, &opts, &opts_end, iov); - memcpy(dest.tr_id, hdr->transaction_id, sizeof(dest.tr_id)); - if (hdr->msg_type == DHCPV6_MSG_ADVERTISE || hdr->msg_type == DHCPV6_MSG_REPLY || hdr->msg_type == DHCPV6_MSG_RELAY_REPL) return; if (!IN6_IS_ADDR_MULTICAST((struct in6_addr *)dest_addr) && iov[IOV_NESTED].iov_len == 0 && - (hdr->msg_type == DHCPV6_MSG_SOLICIT || hdr->msg_type == DHCPV6_MSG_CONFIRM || - hdr->msg_type == DHCPV6_MSG_REBIND || hdr->msg_type == DHCPV6_MSG_INFORMATION_REQUEST)) + (hdr->msg_type == DHCPV6_MSG_SOLICIT || hdr->msg_type == DHCPV6_MSG_CONFIRM || + hdr->msg_type == DHCPV6_MSG_REBIND || hdr->msg_type == DHCPV6_MSG_INFORMATION_REQUEST)) return; - if (hdr->msg_type == DHCPV6_MSG_SOLICIT) { - dest.msg_type = DHCPV6_MSG_ADVERTISE; - } else if (hdr->msg_type == DHCPV6_MSG_INFORMATION_REQUEST) { - iov[IOV_REFRESH].iov_base = &refresh; - iov[IOV_REFRESH].iov_len = sizeof(refresh); - - /* Return inf max rt option in reply to information request */ - maxrt.type = htons(DHCPV6_OPT_INF_MAX_RT); - } + memcpy(dest.tr_id, hdr->transaction_id, sizeof(dest.tr_id)); /* Go through options and find what we need */ uint16_t otype, olen; @@ -406,6 +404,9 @@ static void handle_client_request(void *addr, void *data, size_t len, free(addrs); } #endif + } else if (otype == DHCPV6_OPT_RAPID_COMMIT && hdr->msg_type == DHCPV6_MSG_SOLICIT) { + iov[IOV_RAPID_COMMIT].iov_len = sizeof(rapid_commit); + o_rapid_commit = true; } } @@ -422,6 +423,16 @@ static void handle_client_request(void *addr, void *data, size_t len, return; } + if (hdr->msg_type == DHCPV6_MSG_SOLICIT && !o_rapid_commit) { + dest.msg_type = DHCPV6_MSG_ADVERTISE; + } else if (hdr->msg_type == DHCPV6_MSG_INFORMATION_REQUEST) { + iov[IOV_REFRESH].iov_base = &refresh; + iov[IOV_REFRESH].iov_len = sizeof(refresh); + + /* Return inf max rt option in reply to information request */ + maxrt.type = htons(DHCPV6_OPT_INF_MAX_RT); + } + if (hdr->msg_type != DHCPV6_MSG_INFORMATION_REQUEST) { ssize_t ialen = dhcpv6_ia_handle_IAs(pdbuf, sizeof(pdbuf), iface, addr, (const void *)hdr, opts_end); @@ -433,10 +444,11 @@ static void handle_client_request(void *addr, void *data, size_t len, if (iov[IOV_NESTED].iov_len > 0) /* Update length */ update_nested_message(data, len, iov[IOV_DEST].iov_len + iov[IOV_MAXRT].iov_len + - iov[IOV_DNS].iov_len + iov[IOV_DNS_ADDR].iov_len + - iov[IOV_SEARCH].iov_len + iov[IOV_SEARCH_DOMAIN].iov_len + - iov[IOV_PDBUF].iov_len + iov[IOV_CERID].iov_len + - iov[IOV_DHCPV6_RAW].iov_len - (4 + opts_end - opts)); + iov[IOV_RAPID_COMMIT].iov_len + iov[IOV_DNS].iov_len + + iov[IOV_DNS_ADDR].iov_len + iov[IOV_SEARCH].iov_len + + iov[IOV_SEARCH_DOMAIN].iov_len + iov[IOV_PDBUF].iov_len + + iov[IOV_CERID].iov_len + iov[IOV_DHCPV6_RAW].iov_len - + (4 + opts_end - opts)); odhcpd_send(iface->dhcpv6_event.uloop.fd, addr, iov, ARRAY_SIZE(iov), iface); } |