From 1cc00d8a7cba1e729af7a3efcec42d1e3f529fbb Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Wed, 17 Feb 2010 22:23:17 +0000 Subject: [PATCH] Allow IPv4LL address range to be configured by DHCP. We now check the message for a DHCP cookie instead of the address assigned to test for local link. --- arp.c | 4 ++-- bind.c | 2 +- dhcp.c | 16 +++++++--------- dhcp.h | 1 + dhcpcd.c | 22 +++++++++++----------- if-pref.c | 6 +++--- ipv4ll.c | 2 ++ 7 files changed, 27 insertions(+), 26 deletions(-) diff --git a/arp.c b/arp.c index 15d99825..e6a2928e 100644 --- a/arp.c +++ b/arp.c @@ -78,7 +78,7 @@ send_arp(const struct interface *iface, int op, in_addr_t sip, in_addr_t tip) static void handle_arp_failure(struct interface *iface) { - if (IN_LINKLOCAL(htonl(iface->state->fail.s_addr))) { + if (iface->state->offer->cookie != htonl(MAGIC_COOKIE)) { handle_ipv4ll_failure(iface); return; } @@ -216,7 +216,7 @@ send_arp_announce(void *arg) add_timeout_sec(ANNOUNCE_WAIT, send_arp_announce, iface); return; } - if (IN_LINKLOCAL(htonl(state->new->yiaddr))) { + if (state->new->cookie != htonl(MAGIC_COOKIE)) { /* We should pretend to be at the end * of the DHCP negotation cycle unless we rebooted */ if (state->interval != 0) diff --git a/bind.c b/bind.c index 40fc09e7..9e79ceaa 100644 --- a/bind.c +++ b/bind.c @@ -143,7 +143,7 @@ bind_interface(void *arg) lease->leasetime = ~0U; lease->net.s_addr = ifo->req_mask.s_addr; state->reason = "STATIC"; - } else if (IN_LINKLOCAL(htonl(state->new->yiaddr))) { + } else if (state->new->cookie != htonl(MAGIC_COOKIE)) { syslog(LOG_INFO, "%s: using IPv4LL address %s", iface->name, inet_ntoa(lease->addr)); lease->leasetime = ~0U; diff --git a/dhcp.c b/dhcp.c index 2c0c4a13..c036c00f 100644 --- a/dhcp.c +++ b/dhcp.c @@ -843,19 +843,16 @@ make_message(struct dhcp_message **message, m = (uint8_t *)dhcp; p = dhcp->options; - if ((type == DHCP_INFORM || - type == DHCP_RELEASE || - type == DHCP_REQUEST) && - !IN_LINKLOCAL(ntohl(iface->addr.s_addr))) + if ((type == DHCP_INFORM || type == DHCP_RELEASE || + (type == DHCP_REQUEST && + iface->net.s_addr == lease->net.s_addr && + (iface->state->new == NULL || + iface->state->new->cookie == htonl(MAGIC_COOKIE))))) { dhcp->ciaddr = iface->addr.s_addr; /* In-case we haven't actually configured the address yet */ if (type == DHCP_INFORM && iface->addr.s_addr == 0) dhcp->ciaddr = lease->addr.s_addr; - /* Zero the address if we're currently on a different subnet */ - if (type == DHCP_REQUEST && - iface->net.s_addr != lease->net.s_addr) - dhcp->ciaddr = 0; } dhcp->op = DHCP_BOOTREQUEST; @@ -893,7 +890,7 @@ make_message(struct dhcp_message **message, p += iface->clientid[0] + 1; } - if (lease->addr.s_addr && !IN_LINKLOCAL(htonl(lease->addr.s_addr))) { + if (lease->addr.s_addr && lease->cookie == htonl(MAGIC_COOKIE)) { if (type == DHCP_DECLINE || type == DHCP_DISCOVER || (type == DHCP_REQUEST && @@ -1374,6 +1371,7 @@ get_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp) { struct timeval now; + lease->cookie = dhcp->cookie; /* BOOTP does not set yiaddr for replies when ciaddr is set. */ if (dhcp->yiaddr) lease->addr.s_addr = dhcp->yiaddr; diff --git a/dhcp.h b/dhcp.h index 3562a5a0..cb42275f 100644 --- a/dhcp.h +++ b/dhcp.h @@ -165,6 +165,7 @@ struct dhcp_lease { time_t leasedfrom; struct timeval boundtime; uint8_t frominfo; + uint32_t cookie; }; #include "dhcpcd.h" diff --git a/dhcpcd.c b/dhcpcd.c index f37c8017..bcfb7b00 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -540,6 +540,7 @@ handle_dhcp(struct interface *iface, struct dhcp_message **dhcpp) { lease->frominfo = 0; lease->addr.s_addr = dhcp->yiaddr; + lease->cookie = dhcp->cookie; if (type == 0 || get_option_addr(&lease->server, dhcp, DHO_SERVERID) != 0) lease->server.s_addr = INADDR_ANY; @@ -728,8 +729,8 @@ send_release(struct interface *iface) { struct timespec ts; - if (iface->state->lease.addr.s_addr && - !IN_LINKLOCAL(htonl(iface->state->lease.addr.s_addr))) + if (iface->state->new != NULL && + iface->state->new->cookie == htonl(MAGIC_COOKIE)) { syslog(LOG_INFO, "%s: releasing lease of %s", iface->name, inet_ntoa(iface->state->lease.addr)); @@ -1064,21 +1065,20 @@ start_reboot(struct interface *iface) start_static(iface); return; } - if (ifo->reboot == 0) { + if (ifo->reboot == 0 || iface->state->offer == NULL) { start_discover(iface); return; } - if (IN_LINKLOCAL(htonl(iface->state->lease.addr.s_addr))) { + if (ifo->options & DHCPCD_INFORM) { + syslog(LOG_INFO, "%s: informing address of %s", + iface->name, inet_ntoa(iface->state->lease.addr)); + } else if (iface->state->offer->cookie == 0) { if (ifo->options & DHCPCD_IPV4LL) { iface->state->claims = 0; send_arp_announce(iface); } else start_discover(iface); return; - } - if (ifo->options & DHCPCD_INFORM) { - syslog(LOG_INFO, "%s: informing address of %s", - iface->name, inet_ntoa(iface->state->lease.addr)); } else { syslog(LOG_INFO, "%s: rebinding lease of %s", iface->name, inet_ntoa(iface->state->lease.addr)); @@ -1161,7 +1161,7 @@ start_interface(void *arg) if (iface->state->offer) { get_lease(&iface->state->lease, iface->state->offer); iface->state->lease.frominfo = 1; - if (IN_LINKLOCAL(htonl(iface->state->offer->yiaddr))) { + if (iface->state->offer->cookie == 0) { if (iface->state->offer->yiaddr == iface->addr.s_addr) { @@ -1189,9 +1189,9 @@ start_interface(void *arg) } } } - if (!iface->state->offer) + if (iface->state->offer == NULL) start_discover(iface); - else if (IN_LINKLOCAL(htonl(iface->state->lease.addr.s_addr)) && + else if (iface->state->offer->cookie == 0 && iface->state->options->options & DHCPCD_IPV4LL) start_ipv4ll(iface); else diff --git a/if-pref.c b/if-pref.c index d8741d16..d6eee3ae 100644 --- a/if-pref.c +++ b/if-pref.c @@ -51,9 +51,9 @@ ifcmp(struct interface *si, struct interface *ti) return 1; /* If we are either, they neither have a lease, or they both have. * We need to check for IPv4LL and make it non-preferred. */ - if (si->state->new) { - sill = IN_LINKLOCAL(htonl(si->state->new->yiaddr)); - till = IN_LINKLOCAL(htonl(ti->state->new->yiaddr)); + if (si->state->new && ti->state->new) { + sill = (si->state->new->cookie == htonl(MAGIC_COOKIE)); + till = (ti->state->new->cookie == htonl(MAGIC_COOKIE)); if (!sill && till) return -1; if (sill && !till) diff --git a/ipv4ll.c b/ipv4ll.c index a91a2f32..13f163a9 100644 --- a/ipv4ll.c +++ b/ipv4ll.c @@ -99,6 +99,8 @@ start_ipv4ll(void *arg) iface->state->offer = make_ipv4ll_lease(0); iface->state->lease.frominfo = 0; } + /* Ensure we don't have a cookie */ + iface->state->offer->cookie = 0; send_arp_probe(iface); }