X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fdhcpv6-ia.c;h=c655d93c1911235c187615523997ea59a3bcb141;hp=c8473a7cdd6c6bb6949076ffc11c1a79496994db;hb=749997650804f107ebb2f5ed6c91ed95b620b4dd;hpb=eaff6fa14161d58af63bda2e5d56bed2593ad0d0 diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index c8473a7..c655d93 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -279,7 +280,7 @@ void dhcpv6_write_statefile(void) md5_hash(c->hostname, strlen(c->hostname), &md5); } - l += snprintf(leasebuf + l, sizeof(leasebuf) - l, "%s/%hhu ", ipbuf, + l += snprintf(leasebuf + l, sizeof(leasebuf) - l, "%s/%d ", ipbuf, (c->managed_size) ? addrs[i].prefix : c->length); } leasebuf[l - 1] = '\n'; @@ -428,6 +429,8 @@ static void managed_handle_pd_data(struct ustream *s, _unused int bytes_new) if (first && c->managed_size == 0) free_dhcpv6_assignment(c); + else if (first) + c->valid_until = now + 150; } @@ -462,6 +465,14 @@ static bool assign_pd(struct interface *iface, struct dhcpv6_assignment *assign) assign->managed_size = -1; assign->valid_until = odhcpd_time() + 15; list_add(&assign->head, &iface->ia_assignments); + + // Wait initial period of up to 250ms for immediate assignment + struct pollfd pfd = { .fd = fd, .events = POLLIN }; + poll(&pfd, 1, 250); + managed_handle_pd_data(&assign->managed_sock.stream, 0); + + if (fcntl(fd, F_GETFL) >= 0 && assign->managed_size > 0) + return true; } return false; @@ -961,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; @@ -1013,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; @@ -1167,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); } @@ -1178,7 +1191,8 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, response_len += ia_response_len; } - if (hdr->msg_type == DHCPV6_MSG_RELEASE && response_len + 6 < buflen) { + if ((hdr->msg_type == DHCPV6_MSG_RELEASE || hdr->msg_type == DHCPV6_MSG_DECLINE) && + response_len + 6 < buflen) { buf[0] = 0; buf[1] = DHCPV6_OPT_STATUS; buf[2] = 0;