Add support for infinite leasetime value; this can be done by
specifying "infinite" as leasetime value which is similar to
dnsmasq infinite leasetime support.
Specifying "infinite" as leasetime is valid for both the host
and dhcp uci sections.
A DHCPv4/DHCPv6 assignment is now considered infinite if valid_unil
holds the value 0.
Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
}
static double parse_leasetime(struct blob_attr *c) {
}
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')
if (endptr[0] == 's')
time *= 1;
else if (endptr[0] == 'm')
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->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;
// Assign to all interfaces
struct dhcpv4_assignment *c;
-
-// 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)
{
static void handle_dhcpv4(void *addr, void *data, size_t len,
struct interface *iface, _unused void *dest_addr)
{
val = htonl(leasetime);
dhcpv4_put(&reply, &cookie, DHCPV4_OPT_LEASETIME, 4, &val);
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);
dhcpv4_put(&reply, &cookie, DHCPV4_OPT_NETMASK, 4, &ifnetmask.sin_addr);
a = c;
if (c->addr == raddr)
break;
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);
}
list_del(&c->head);
free(c);
}
leasetime = iface->dhcpv4_leasetime;
}
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) {
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;
} else if (!assigned && a) { // Cleanup failed assignment
free(a);
a = NULL;
if (assigned && a)
lease = a;
} else if (msg == DHCPV4_MSG_RELEASE) {
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
}
memset(a->hwaddr, 0, sizeof(a->hwaddr));
a->valid_until = now + 3600; // Block address for 1h
}
m = i;
for (size_t i = 0; i < addrlen; ++i) {
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;
(iface->managed < RELAYD_MANAGED_NO_AFLAG && i != m &&
addrs[i].prefix == 64))
continue;
struct list_head reassign = LIST_HEAD_INIT(reassign);
struct dhcpv6_assignment *c, *d;
list_for_each_entry_safe(c, d, &iface->ia_assignments, head) {
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)
continue;
if (c->length < 128 && c->assigned >= border->assigned && c != border)
struct dhcpv6_assignment *a, *n;
list_for_each_entry_safe(a, n, &iface->ia_assignments, head) {
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);
if ((a->length < 128 && a->clid_len > 0) ||
(a->length == 128 && a->clid_len == 0)) {
list_del(&a->head);
- 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);
if (!out.t1)
out.t1 = htonl(1);
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)))) &&
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;
((is_pd && c->length <= 64) || (is_na && c->length == 128))) {
a = c;
// Was only a solicitation: mark binding for removal
if (assigned && hdr->msg_type == DHCPV6_MSG_SOLICIT) {
// Was only a solicitation: mark binding for removal
if (assigned && hdr->msg_type == DHCPV6_MSG_SOLICIT) {
} else if (assigned && hdr->msg_type == DHCPV6_MSG_REQUEST) {
if (hostname_len > 0) {
a->hostname = realloc(a->hostname, hostname_len + 1);
} else if (assigned && hdr->msg_type == DHCPV6_MSG_REQUEST) {
if (hostname_len > 0) {
a->hostname = realloc(a->hostname, hostname_len + 1);
if (a)
apply_lease(iface, a, true);
} else if (hdr->msg_type == DHCPV6_MSG_RELEASE) {
if (a)
apply_lease(iface, a, true);
} else if (hdr->msg_type == DHCPV6_MSG_RELEASE) {
+ 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;
apply_lease(iface, a, false);
} else if (hdr->msg_type == DHCPV6_MSG_DECLINE && a->length == 128) {
a->clid_len = 0;
#define RELAYD_BUFFER_SIZE 8192
#define RELAYD_MAX_PREFIXES 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))
#define _unused __attribute__((unused))
#define _packed __attribute__((packed))