X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fdhcpv4.c;h=618475ff341655afce591e4660dd1e68f80f04d2;hp=647cdc0f53d49476fe81b06108c5c6789b9c652d;hb=44ca70ae6f0fb649cef47d9160ec1ee13e7844f1;hpb=a06dd6481cd046e4856774ac32cdc11f4bc721e2 diff --git a/src/dhcpv4.c b/src/dhcpv4.c index 647cdc0..618475f 100644 --- a/src/dhcpv4.c +++ b/src/dhcpv4.c @@ -176,10 +176,13 @@ int setup_dhcpv4_interface(struct interface *iface, bool enable) iface->ifname); return -1; } + if (lease->dhcpv4_leasetime >= 60) + a->leasetime = lease->dhcpv4_leasetime; 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; @@ -222,7 +225,6 @@ int setup_dhcpv4_interface(struct interface *iface, bool enable) struct dhcpv4_assignment *a = list_first_entry(&iface->dhcpv4_assignments, struct dhcpv4_assignment, head); list_del(&a->head); - free(a->hostname); free(a); } @@ -245,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) { @@ -383,14 +384,25 @@ static void handle_dhcpv4(void *addr, void *data, size_t len, if (lease) { reply.yiaddr.s_addr = htonl(lease->addr); - uint32_t val = htonl(iface->dhcpv4_leasetime); + uint32_t val; + uint32_t leasetime; + + if (lease->leasetime >= 60) { + leasetime = lease->leasetime; + } else { + leasetime = iface->dhcpv4_leasetime; + } + + val = htonl(leasetime); dhcpv4_put(&reply, &cookie, DHCPV4_OPT_LEASETIME, 4, &val); - val = htonl(500 * iface->dhcpv4_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 * iface->dhcpv4_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); @@ -588,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); } @@ -606,6 +618,8 @@ static struct dhcpv4_assignment* dhcpv4_lease(struct interface *iface, } memcpy(a->hwaddr, mac, sizeof(a->hwaddr)); memcpy(a->hostname, hostname, hostlen); + // Don't consider new assignment as infinite + a->valid_until = now; assigned = dhcpv4_assign(iface, a, raddr); } @@ -623,10 +637,18 @@ static struct dhcpv4_assignment* dhcpv4_lease(struct interface *iface, a->head.prev->next = &a->head; } - // Was only a solicitation: mark binding for removal - if (assigned && a->valid_until < now) { - a->valid_until = (msg == DHCPV4_MSG_DISCOVER) ? 0 : - (now + iface->dhcpv4_leasetime); + uint32_t leasetime; + if (a->leasetime) { + leasetime = a->leasetime; + } else { + leasetime = iface->dhcpv4_leasetime; + } + + if (assigned) { + if (!INFINITE_VALID(a->valid_until)) + // Was only a discover; mark binding for removal + 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; @@ -635,9 +657,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 }