Mercurial > hg > dhcpcd
changeset 2258:83f7b828306e draft
Implement support for RFC 3203, FORCERENEW message.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Fri, 31 Jan 2014 11:47:27 +0000 |
| parents | 5d6ccc5a3b11 |
| children | 7502a71beb0a |
| files | arp.c arp.h dhcp.c dhcp.h dhcpcd.8.in dhcpcd.c ipv4ll.c |
| diffstat | 7 files changed, 93 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/arp.c Thu Jan 30 14:20:24 2014 +0000 +++ b/arp.c Fri Jan 31 11:47:27 2014 +0000 @@ -106,7 +106,6 @@ unlink(state->leasefile); if (!state->lease.frominfo) dhcp_decline(ifp); - dhcp_close(ifp); eloop_timeout_delete(NULL, ifp); if (state->lease.frominfo) start_interface(ifp); @@ -336,3 +335,19 @@ state->arping_index = 0; arp_probe(ifp); } + +void +arp_close(struct interface *ifp) +{ + struct dhcp_state *state = D_STATE(ifp); + + if (state == NULL) + return; + + if (state->arp_fd != -1) { + eloop_event_delete(state->arp_fd); + close(state->arp_fd); + state->arp_fd = -1; + } +} +
--- a/arp.h Thu Jan 30 14:20:24 2014 +0000 +++ b/arp.h Fri Jan 31 11:47:27 2014 +0000 @@ -45,4 +45,5 @@ void arp_announce(void *); void arp_probe(void *); void arp_start(struct interface *); +void arp_close(struct interface *); #endif
--- a/dhcp.c Thu Jan 30 14:20:24 2014 +0000 +++ b/dhcp.c Fri Jan 31 11:47:27 2014 +0000 @@ -1718,9 +1718,8 @@ struct if_options *ifo = iface->options; struct dhcp_lease *lease = &state->lease; struct timeval tv; + uint8_t ipv4ll = 0; - /* We're binding an address now - ensure that sockets are closed */ - dhcp_close(iface); state->reason = NULL; if (clock_monotonic) get_monotonic(&lease->boundtime); @@ -1741,6 +1740,7 @@ iface->name, inet_ntoa(lease->addr)); lease->leasetime = ~0U; state->reason = "IPV4LL"; + ipv4ll = 1; } else if (ifo->options & DHCPCD_INFORM) { if (ifo->req_addr.s_addr != 0) lease->addr.s_addr = ifo->req_addr.s_addr; @@ -1822,6 +1822,8 @@ } ipv4_applyaddr(iface); daemonise(); + if (!ipv4ll) + arp_close(iface); state->state = DHS_BOUND; if (ifo->options & DHCPCD_ARP) { state->claims = 0; @@ -2011,6 +2013,8 @@ state = D_STATE(ifp); if (state == NULL) return; + dhcp_close(ifp); + arp_close(ifp); eloop_timeouts_delete(ifp, dhcp_expire, NULL); if (ifp->options->options & DHCPCD_RELEASE) { unlink(state->leasefile); @@ -2164,6 +2168,49 @@ log_dhcp1(LOG_WARNING, "no authentication", iface, dhcp, from, 0); + /* RFC 3203 */ + if (type == DHCP_FORCERENEW) { + if (from->s_addr == INADDR_ANY || + from->s_addr == INADDR_BROADCAST) + { + log_dhcp(LOG_ERR, "discarding Force Renew", + iface, dhcp, from); + return; + } + if (auth == NULL) { + log_dhcp(LOG_ERR, "unauthenticated Force Renew", + iface, dhcp, from); + return; + } + if (state->state != DHS_BOUND) { + log_dhcp(LOG_DEBUG, "not bound, ignoring Force Renew", + iface, dhcp, from); + return; + } + log_dhcp(LOG_ERR, "Force Renew from", iface, dhcp, from); + /* The rebind and expire timings are still the same, we just + * enter the renew state early */ + eloop_timeout_delete(dhcp_renew, iface); + dhcp_renew(iface); + return; + } + + if (state->state == DHS_BOUND) { + /* Before we supported FORCERENEW we closed off the raw + * port so we effectively ignored all messages. + * As such we'll not log by default here. */ + //log_dhcp(LOG_DEBUG, "bound, ignoring", iface, dhcp, from); + return; + } + + /* Ensure it's the right transaction */ + if (state->xid != ntohl(dhcp->xid)) { + syslog(LOG_DEBUG, + "%s: wrong xid 0x%x (expecting 0x%x) from %s", + iface->name, ntohl(dhcp->xid), state->xid, + inet_ntoa(*from)); + return; + } /* reset the message counter */ state->interval = 0; @@ -2175,13 +2222,14 @@ log_dhcp(LOG_WARNING, "reject NAK", iface, dhcp, from); return; } + /* We should restart on a NAK */ log_dhcp(LOG_WARNING, "NAK:", iface, dhcp, from); if (!(options & DHCPCD_TEST)) { dhcp_drop(iface, "NAK"); unlink(state->leasefile); } - dhcp_close(iface); + /* If we constantly get NAKS then we should slowly back off */ eloop_timeout_add_sec(state->nakoff, dhcp_discover, iface); if (state->nakoff == 0) @@ -2291,11 +2339,6 @@ lease->frominfo = 0; eloop_timeout_delete(NULL, iface); - /* We now have an offer, so close the DHCP sockets. - * This allows us to safely ARP when broken DHCP servers send an ACK - * follows by an invalid NAK. */ - dhcp_close(iface); - if (ifo->options & DHCPCD_ARP && state->addr.s_addr != state->offer->yiaddr) { @@ -2441,14 +2484,6 @@ iface->name, inet_ntoa(from)); continue; } - /* Ensure it's the right transaction */ - if (state->xid != ntohl(dhcp->xid)) { - syslog(LOG_DEBUG, - "%s: wrong xid 0x%x (expecting 0x%x) from %s", - iface->name, ntohl(dhcp->xid), state->xid, - inet_ntoa(from)); - continue; - } /* Ensure packet is for us */ if (iface->hwlen <= sizeof(dhcp->chaddr) && memcmp(dhcp->chaddr, iface->hwaddr, iface->hwlen)) @@ -2465,6 +2500,21 @@ free(dhcp); } +static void +dhcp_handleudp(void *arg) +{ + const struct interface *ifp; + const struct dhcp_state *state; + ssize_t bytes; + uint8_t buffer[sizeof(struct dhcp_message)]; + + ifp = arg; + state = D_CSTATE(ifp); + bytes = read(state->udp_fd, buffer, sizeof(buffer)); + /* Just read what's in the UDP fd and discard it as we always read + * from the raw fd */ +} + static int dhcp_open(struct interface *ifp) { @@ -2491,15 +2541,13 @@ eloop_event_add(state->raw_fd, dhcp_handlepacket, ifp); } if (state->udp_fd == -1 && - state->addr.s_addr != 0 && - state->new != NULL && - (state->new->cookie == htonl(MAGIC_COOKIE) || - ifp->options->options & DHCPCD_INFORM)) + ifp->options->options & DHCPCD_DHCP) { if (dhcp_openudp(ifp) == -1 && errno != EADDRINUSE) { syslog(LOG_ERR, "%s: dhcp_openudp: %m", ifp->name); return -1; } + eloop_event_add(state->udp_fd, dhcp_handleudp, ifp); } return 0; } @@ -2686,7 +2734,6 @@ syslog(LOG_WARNING, "%s: needs a clientid to configure", ifp->name); dhcp_drop(ifp, "FAIL"); - dhcp_close(ifp); eloop_timeout_delete(NULL, ifp); return; }
--- a/dhcp.h Thu Jan 30 14:20:24 2014 +0000 +++ b/dhcp.h Fri Jan 31 11:47:27 2014 +0000 @@ -57,6 +57,7 @@ #define DHCP_NAK 6 #define DHCP_RELEASE 7 #define DHCP_INFORM 8 +#define DHCP_FORCERENEW 9 /* Constants taken from RFC 2131. */ #define T1 0.5
--- a/dhcpcd.8.in Thu Jan 30 14:20:24 2014 +0000 +++ b/dhcpcd.8.in Fri Jan 31 11:47:27 2014 +0000 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 30, 2014 +.Dd January 31, 2014 .Dt DHCPCD 8 .Os .Sh NAME @@ -98,7 +98,8 @@ .Nm then daemonises and waits for the lease renewal time to lapse. It will then attempt to renew its lease and reconfigure if the new lease -changes. +changes when the lease beings to expire or the DHCP server sends message +to renew early. .Pp .Nm is also an implementation of the BOOTP client specified in @@ -652,10 +653,10 @@ .Xr resolvconf 8 .Sh STANDARDS RFC\ 951, RFC\ 1534, RFC\ 2104, RFC\ 2131, RFC\ 2132, RFC\ 2855, RFC\ 3004, -RFC\ 3118, RFC\ 3315, RFC\ 3361, RFC\ 3633, RFC\ 3396, RFC\ 3397, RFC\ 3442, -RFC\ 3495, RFC\ 3925, RFC\ 3927, RFC\ 4039, RFC\ 4075, RFC\ 4242, RFC\ 4361, -RFC\ 4390, RFC\ 4702, RFC\ 4074, RFC\ 4861, RFC\ 4833, RFC\ 5227, RFC\ 5942, -RFC\ 5969, RFC\ 6106. +RFC\ 3118, RFC\ 3203, RFC\ 3315, RFC\ 3361, RFC\ 3633, RFC\ 3396, RFC\ 3397, +RFC\ 3442, RFC\ 3495, RFC\ 3925, RFC\ 3927, RFC\ 4039, RFC\ 4075, RFC\ 4242, +RFC\ 4361, RFC\ 4390, RFC\ 4702, RFC\ 4074, RFC\ 4861, RFC\ 4833, RFC\ 5227, +RFC\ 5942, RFC\ 5969, RFC\ 6106. .Sh AUTHORS .An Roy Marples Aq Mt roy@marples.name .Sh BUGS
--- a/dhcpcd.c Thu Jan 30 14:20:24 2014 +0000 +++ b/dhcpcd.c Fri Jan 31 11:47:27 2014 +0000 @@ -328,7 +328,6 @@ dhcp6_drop(ifp, NULL); ipv6nd_drop(ifp); dhcp_drop(ifp, "STOP"); - dhcp_close(ifp); eloop_timeout_delete(NULL, ifp); if (ifp->options->options & DHCPCD_DEPARTED) script_runreason(ifp, "DEPARTED"); @@ -526,7 +525,6 @@ if (ifp->carrier == LINK_UP) syslog(LOG_INFO, "%s: carrier lost", ifp->name); ifp->carrier = LINK_DOWN; - dhcp_close(ifp); dhcp6_drop(ifp, "EXPIRE6"); ipv6nd_drop(ifp); /* Don't blindly delete our knowledge of LL addresses.
