diff options
-rw-r--r-- | src/config.c | 7 | ||||
-rw-r--r-- | src/dhcpv4.c | 30 | ||||
-rw-r--r-- | src/dhcpv6-ia.c | 20 | ||||
-rw-r--r-- | src/odhcpd.h | 2 |
4 files changed, 33 insertions, 26 deletions
diff --git a/src/config.c b/src/config.c index ef51112..44b049d 100644 --- a/src/config.c +++ b/src/config.c @@ -218,9 +218,10 @@ static void set_config(struct uci_section *s) } static double parse_leasetime(struct blob_attr *c) { - char *val = blobmsg_get_string(c), *endptr; - double time = strtod(val, &endptr); - if (time && endptr[0]) { + char *val = blobmsg_get_string(c), *endptr = NULL; + double time = strcmp(val, "infinite") ? strtod(val, &endptr) : UINT32_MAX; + + if (time && endptr && endptr[0]) { if (endptr[0] == 's') time *= 1; else if (endptr[0] == 'm') diff --git a/src/dhcpv4.c b/src/dhcpv4.c index f277a67..8469038 100644 --- a/src/dhcpv4.c +++ b/src/dhcpv4.c @@ -181,7 +181,8 @@ int setup_dhcpv4_interface(struct interface *iface, bool enable) a->addr = ntohl(lease->ipaddr.s_addr); memcpy(a->hwaddr, lease->mac.ether_addr_octet, sizeof(a->hwaddr)); memcpy(a->hostname, lease->hostname, hostlen); - a->valid_until = LONG_MAX; + /* Infinite valid */ + a->valid_until = 0; // Assign to all interfaces struct dhcpv4_assignment *c; @@ -246,8 +247,7 @@ static void dhcpv4_put(struct dhcpv4_message *msg, uint8_t **cookie, *cookie = c + len; } - -// Simple DHCPv6-server for information requests +// Handler for DHCPv4 messages static void handle_dhcpv4(void *addr, void *data, size_t len, struct interface *iface, _unused void *dest_addr) { @@ -396,11 +396,13 @@ static void handle_dhcpv4(void *addr, void *data, size_t len, val = htonl(leasetime); dhcpv4_put(&reply, &cookie, DHCPV4_OPT_LEASETIME, 4, &val); - val = htonl(500 * leasetime / 1000); - dhcpv4_put(&reply, &cookie, DHCPV4_OPT_RENEW, 4, &val); + if (leasetime != UINT32_MAX) { + val = htonl(500 * leasetime / 1000); + dhcpv4_put(&reply, &cookie, DHCPV4_OPT_RENEW, 4, &val); - val = htonl(875 * leasetime / 1000); - dhcpv4_put(&reply, &cookie, DHCPV4_OPT_REBIND, 4, &val); + val = htonl(875 * leasetime / 1000); + dhcpv4_put(&reply, &cookie, DHCPV4_OPT_REBIND, 4, &val); + } dhcpv4_put(&reply, &cookie, DHCPV4_OPT_NETMASK, 4, &ifnetmask.sin_addr); @@ -598,7 +600,7 @@ static struct dhcpv4_assignment* dhcpv4_lease(struct interface *iface, a = c; if (c->addr == raddr) break; - } else if (c->valid_until < now) { + } else if (!INFINITE_VALID(c->valid_until) && c->valid_until < now) { list_del(&c->head); free(c); } @@ -640,10 +642,10 @@ static struct dhcpv4_assignment* dhcpv4_lease(struct interface *iface, leasetime = iface->dhcpv4_leasetime; } - // Was only a solicitation: mark binding for removal + // Was only a discover; mark binding for removal if (assigned && a->valid_until < now) { - a->valid_until = (msg == DHCPV4_MSG_DISCOVER) ? 0 : - (now + leasetime); + a->valid_until = ((msg == DHCPV4_MSG_DISCOVER) ? now : ((leasetime == UINT32_MAX) ? + 0 : (time_t)(now + leasetime))); } else if (!assigned && a) { // Cleanup failed assignment free(a); a = NULL; @@ -652,9 +654,9 @@ static struct dhcpv4_assignment* dhcpv4_lease(struct interface *iface, if (assigned && a) lease = a; } else if (msg == DHCPV4_MSG_RELEASE) { - if (a && a->valid_until != LONG_MAX) - a->valid_until = 0; - } else if (msg == DHCPV4_MSG_DECLINE && a && a->valid_until != LONG_MAX) { + if (a && !INFINITE_VALID(a->valid_until)) + a->valid_until = now - 1; + } else if (msg == DHCPV4_MSG_DECLINE && a && !INFINITE_VALID(a->valid_until)) { memset(a->hwaddr, 0, sizeof(a->hwaddr)); a->valid_until = now + 3600; // Block address for 1h } diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index 4c321ac..597bc74 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -262,7 +262,7 @@ void dhcpv6_write_statefile(void) m = i; for (size_t i = 0; i < addrlen; ++i) { - if (addrs[i].prefix > 96 || c->valid_until <= now || + if (addrs[i].prefix > 96 || (!INFINITE_VALID(c->valid_until) && c->valid_until <= now) || (iface->managed < RELAYD_MANAGED_NO_AFLAG && i != m && addrs[i].prefix == 64)) continue; @@ -592,7 +592,8 @@ void dhcpv6_ia_postupdate(struct interface *iface, time_t now) struct list_head reassign = LIST_HEAD_INIT(reassign); struct dhcpv6_assignment *c, *d; list_for_each_entry_safe(c, d, &iface->ia_assignments, head) { - if (c->clid_len == 0 || c->valid_until < now || c->managed_size) + if (c->clid_len == 0 || (!INFINITE_VALID(c->valid_until) && c->valid_until < now) || + c->managed_size) continue; if (c->length < 128 && c->assigned >= border->assigned && c != border) @@ -637,7 +638,7 @@ static void reconf_timer(struct uloop_timeout *event) struct dhcpv6_assignment *a, *n; list_for_each_entry_safe(a, n, &iface->ia_assignments, head) { - if (a->valid_until < now) { + if (!INFINITE_VALID(a->valid_until) && a->valid_until < now) { if ((a->length < 128 && a->clid_len > 0) || (a->length == 128 && a->clid_len == 0)) { list_del(&a->head); @@ -768,9 +769,10 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, } } - a->valid_until = valid + now; - out.t1 = htonl(pref * 5 / 10); - out.t2 = htonl(pref * 8 / 10); + /* UINT32_MAX is considered as infinite leasetime */ + a->valid_until = (valid == UINT32_MAX) ? 0 : valid + now; + out.t1 = htonl((pref == UINT32_MAX) ? pref : pref * 5 / 10); + out.t2 = htonl((pref == UINT32_MAX) ? pref : pref * 8 / 10); if (!out.t1) out.t1 = htonl(1); @@ -1031,7 +1033,7 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, if (((c->clid_len == clid_len && !memcmp(c->clid_data, clid_data, clid_len)) || (c->clid_len >= clid_len && !c->clid_data[0] && !c->clid_data[1] && !memcmp(c->mac, mac, sizeof(mac)))) && - (c->iaid == ia->iaid || c->valid_until < now) && + (c->iaid == ia->iaid || (!INFINITE_VALID(c->valid_until) && c->valid_until < now)) && ((is_pd && c->length <= 64) || (is_na && c->length == 128))) { a = c; @@ -1114,7 +1116,7 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, // Was only a solicitation: mark binding for removal if (assigned && hdr->msg_type == DHCPV6_MSG_SOLICIT) { - a->valid_until = 0; + a->valid_until = now; } else if (assigned && hdr->msg_type == DHCPV6_MSG_REQUEST) { if (hostname_len > 0) { a->hostname = realloc(a->hostname, hostname_len + 1); @@ -1141,7 +1143,7 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, if (a) apply_lease(iface, a, true); } else if (hdr->msg_type == DHCPV6_MSG_RELEASE) { - a->valid_until = 0; + a->valid_until = now - 1; apply_lease(iface, a, false); } else if (hdr->msg_type == DHCPV6_MSG_DECLINE && a->length == 128) { a->clid_len = 0; diff --git a/src/odhcpd.h b/src/odhcpd.h index 3e8fc3e..e322ebd 100644 --- a/src/odhcpd.h +++ b/src/odhcpd.h @@ -44,6 +44,8 @@ #define RELAYD_BUFFER_SIZE 8192 #define RELAYD_MAX_PREFIXES 8 +#define INFINITE_VALID(x) ((x) == 0) + #define _unused __attribute__((unused)) #define _packed __attribute__((packed)) |