X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fdhcpv4.c;h=b8d64ceaf7358c60bba1a6e3feaef6df90ecbfb3;hp=b5eeb6e971df48f65971a9767a5fc30609358482;hb=4267915aef64aae345972c77148b11759a172b14;hpb=69ca34df0145dd204dceeacc7caf978e4055d679;ds=sidebyside diff --git a/src/dhcpv4.c b/src/dhcpv4.c index b5eeb6e..b8d64ce 100644 --- a/src/dhcpv4.c +++ b/src/dhcpv4.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -155,17 +156,22 @@ 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; // Assign to all interfaces struct dhcpv4_assignment *c; list_for_each_entry(c, &iface->dhcpv4_assignments, head) { if (c->addr > a->addr) { list_add_tail(&a->head, &c->head); + break; } else if (c->addr == a->addr) { // Already an assignment with that number break; } } + if (&c->head == &iface->dhcpv4_assignments) { + list_add(&a->head, &iface->dhcpv4_assignments); + } if (!a->head.next) free(a); @@ -175,7 +181,7 @@ int setup_dhcpv4_interface(struct interface *iface, bool enable) struct dhcpv4_assignment *a, *n; list_for_each_entry_safe(a, n, &iface->dhcpv4_assignments, head) { if ((htonl(a->addr) & smask->sin_addr.s_addr) != - (saddr->sin_addr.s_addr & smask->sin_addr.s_addr)) { + (iface->dhcpv4_start.s_addr & smask->sin_addr.s_addr)) { list_del(&a->head); free(a); } @@ -325,6 +331,10 @@ static void handle_dhcpv4(void *addr, void *data, size_t len, return; } else if (reqmsg == DHCPV4_MSG_DISCOVER) { msg = DHCPV4_MSG_OFFER; + } else if (reqmsg == DHCPV4_MSG_REQUEST && reqaddr.s_addr && + reqaddr.s_addr != htonl(lease->addr)) { + msg = DHCPV4_MSG_NAK; + lease = NULL; } if (reqmsg == DHCPV4_MSG_DECLINE || reqmsg == DHCPV4_MSG_RELEASE) @@ -395,7 +405,7 @@ static void handle_dhcpv4(void *addr, void *data, size_t len, dest.sin_addr = req->ciaddr; dest.sin_port = htons(DHCPV4_CLIENT_PORT); } else if ((ntohs(req->flags) & DHCPV4_FLAG_BROADCAST) || - req->hlen != reply.hlen) { + req->hlen != reply.hlen || !reply.yiaddr.s_addr) { dest.sin_addr.s_addr = INADDR_BROADCAST; dest.sin_port = htons(DHCPV4_CLIENT_PORT); } else { @@ -471,9 +481,10 @@ static struct dhcpv4_assignment* dhcpv4_lease(struct interface *iface, struct dhcpv4_assignment *c, *n, *a = NULL; list_for_each_entry_safe(c, n, &iface->dhcpv4_assignments, head) { - if (c->addr == raddr && !memcmp(c->hwaddr, mac, 6)) { + if (!memcmp(c->hwaddr, mac, 6)) { a = c; - break; + if (c->addr == raddr) + break; } else if (c->valid_until < now) { list_del(&c->head); free(c); @@ -517,10 +528,11 @@ static struct dhcpv4_assignment* dhcpv4_lease(struct interface *iface, } else if (!assigned && a) { // Cleanup failed assignment free(a); a = NULL; - } else { - update_state = true; } + if (a) + update_state = true; + if (assigned && a) lease = a; } else if (msg == DHCPV4_MSG_RELEASE) {