changeset 4555:93b4eb29d297 draft

DHCP: Set address vltime and pltime to the length of the lease The only OS which supports this is Linux, but more importantly it will report the address as "dynamic" so that users can distinguish it from statically added addresses.
author Roy Marples <roy@marples.name>
date Mon, 22 Jul 2019 10:37:13 +0100
parents 8c493d779d03
children 0bf28a92cdde
files src/dhcp.c src/dhcp.h src/if-linux.c src/ipv4.c src/ipv4.h src/ipv4ll.c
diffstat 6 files changed, 74 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/src/dhcp.c	Tue Jul 16 10:53:35 2019 +0100
+++ b/src/dhcp.c	Mon Jul 22 10:37:13 2019 +0100
@@ -1443,7 +1443,7 @@
 	}
 	if (get_option_uint32(ctx, &lease->leasetime,
 	    bootp, len, DHO_LEASETIME) != 0)
-		lease->leasetime = ~0U; /* Default to infinite lease */
+		lease->leasetime = DHCP_INFINITE_LIFETIME;
 	if (get_option_uint32(ctx, &lease->renewaltime,
 	    bootp, len, DHO_RENEWALTIME) != 0)
 		lease->renewaltime = 0;
@@ -2135,17 +2135,17 @@
 		loginfox("%s: using static address %s/%d",
 		    ifp->name, inet_ntoa(lease->addr),
 		    inet_ntocidr(lease->mask));
-		lease->leasetime = ~0U;
+		lease->leasetime = DHCP_INFINITE_LIFETIME;
 		state->reason = "STATIC";
 	} else if (ifo->options & DHCPCD_INFORM) {
 		loginfox("%s: received approval for %s",
 		    ifp->name, inet_ntoa(lease->addr));
-		lease->leasetime = ~0U;
+		lease->leasetime = DHCP_INFINITE_LIFETIME;
 		state->reason = "INFORM";
 	} else {
 		if (lease->frominfo)
 			state->reason = "TIMEOUT";
-		if (lease->leasetime == ~0U) {
+		if (lease->leasetime == DHCP_INFINITE_LIFETIME) {
 			lease->renewaltime =
 			    lease->rebindtime =
 			    lease->leasetime;
@@ -2208,7 +2208,7 @@
 		else
 			state->reason = "BOUND";
 	}
-	if (lease->leasetime == ~0U)
+	if (lease->leasetime == DHCP_INFINITE_LIFETIME)
 		lease->renewaltime = lease->rebindtime = lease->leasetime;
 	else {
 		eloop_timeout_add_sec(ctx->eloop,
@@ -2346,7 +2346,8 @@
 
 			get_lease(ifp, &l, state->offer, state->offer_len);
 			/* Add the address now, let the kernel handle DAD. */
-			ipv4_addaddr(ifp, &l.addr, &l.mask, &l.brd);
+			ipv4_addaddr(ifp, &l.addr, &l.mask, &l.brd,
+			    l.leasetime, l.leastime);
 		} else
 			loginfox("%s: waiting for DAD on %s",
 			    ifp->name, inet_ntoa(addr));
@@ -3759,7 +3760,7 @@
 			state->offer = NULL;
 			state->offer_len = 0;
 		} else if (!(ifo->options & DHCPCD_LASTLEASE_EXTEND) &&
-		    state->lease.leasetime != ~0U &&
+		    state->lease.leasetime != DHCP_INFINITE_LIFETIME &&
 		    stat(state->leasefile, &st) == 0)
 		{
 			time_t now;
--- a/src/dhcp.h	Tue Jul 16 10:53:35 2019 +0100
+++ b/src/dhcp.h	Mon Jul 22 10:37:13 2019 +0100
@@ -183,6 +183,10 @@
 	uint32_t cookie;
 };
 
+#ifndef DHCP_INFINITE_LIFETIME
+#  define DHCP_INFINITE_LIFETIME	(~0U)
+#endif
+
 enum DHS {
 	DHS_NONE,
 	DHS_INIT,
--- a/src/if-linux.c	Tue Jul 16 10:53:35 2019 +0100
+++ b/src/if-linux.c	Mon Jul 22 10:37:13 2019 +0100
@@ -1466,13 +1466,12 @@
 }
 
 int
-if_address(unsigned char cmd, const struct ipv4_addr *addr)
+if_address(unsigned char cmd, const struct ipv4_addr *ia)
 {
 	struct nlma nlm;
+	struct ifa_cacheinfo cinfo;
 	int retval = 0;
-#if defined(IFA_F_NOPREFIXROUTE)
 	uint32_t flags = 0;
-#endif
 
 	memset(&nlm, 0, sizeof(nlm));
 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
@@ -1480,29 +1479,39 @@
 	nlm.hdr.nlmsg_type = cmd;
 	if (cmd == RTM_NEWADDR)
 		nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
-	nlm.ifa.ifa_index = addr->iface->index;
+	nlm.ifa.ifa_index = ia->iface->index;
 	nlm.ifa.ifa_family = AF_INET;
-	nlm.ifa.ifa_prefixlen = inet_ntocidr(addr->mask);
+
+	nlm.ifa.ifa_prefixlen = inet_ntocidr(ia->mask);
+
 #if 0
 	/* This creates the aliased interface */
 	add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LABEL,
-	    addr->iface->alias,
-	    (unsigned short)(strlen(addr->iface->alias) + 1));
-#endif
-	add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LOCAL,
-	    &addr->addr.s_addr, sizeof(addr->addr.s_addr));
-	if (cmd == RTM_NEWADDR)
-		add_attr_l(&nlm.hdr, sizeof(nlm), IFA_BROADCAST,
-		    &addr->brd.s_addr, sizeof(addr->brd.s_addr));
-
-#ifdef IFA_F_NOPREFIXROUTE
-	if (nlm.ifa.ifa_prefixlen < 32)
-		flags |= IFA_F_NOPREFIXROUTE;
-	if (flags)
-		add_attr_32(&nlm.hdr, sizeof(nlm), IFA_FLAGS, flags);
+	    ia->iface->alias,
+	    (unsigned short)(strlen(ia->iface->alias) + 1));
 #endif
 
-	if (send_netlink(addr->iface->ctx, NULL,
+	add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LOCAL,
+	    &ia->addr.s_addr, sizeof(ia->addr.s_addr));
+
+	if (cmd == RTM_NEWADDR) {
+#ifdef IFA_F_NOPREFIXROUTE
+		if (nlm.ifa.ifa_prefixlen < 32)
+			flags |= IFA_F_NOPREFIXROUTE;
+#endif
+		add_attr_32(&nlm.hdr, sizeof(nlm), IFA_FLAGS, flags);
+
+		add_attr_l(&nlm.hdr, sizeof(nlm), IFA_BROADCAST,
+		    &ia->brd.s_addr, sizeof(ia->brd.s_addr));
+
+		memset(&cinfo, 0, sizeof(cinfo));
+		cinfo.ifa_prefered = ia->pltime;
+		cinfo.ifa_valid = ia->vltime;
+		add_attr_l(&nlm.hdr, sizeof(nlm), IFA_CACHEINFO,
+		    &cinfo, sizeof(cinfo));
+	}
+
+	if (send_netlink(ia->iface->ctx, NULL,
 	    NETLINK_ROUTE, &nlm.hdr, NULL) == -1)
 		retval = -1;
 	return retval;
@@ -1524,11 +1533,7 @@
 {
 	struct nlma nlm;
 	struct ifa_cacheinfo cinfo;
-/* IFA_FLAGS is not a define, but is was added at the same time
- * IFA_F_NOPREFIXROUTE was do use that. */
-#if defined(IFA_F_NOPREFIXROUTE) || defined(IFA_F_MANAGETEMPADDR)
 	uint32_t flags = 0;
-#endif
 
 	memset(&nlm, 0, sizeof(nlm));
 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
@@ -1538,22 +1543,10 @@
 		nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
 	nlm.ifa.ifa_index = ia->iface->index;
 	nlm.ifa.ifa_family = AF_INET6;
-#ifdef IPV6_MANAGETEMPADDR
-	if (ia->flags & IPV6_AF_TEMPORARY) {
-		/* Currently the kernel filters out these flags */
-#ifdef IFA_F_NOPREFIXROUTE
-		flags |= IFA_F_TEMPORARY;
-#else
-		nlm.ifa.ifa_flags |= IFA_F_TEMPORARY;
-#endif
-	}
-#elif IFA_F_MANAGETEMPADDR
-	if (ia->flags & IPV6_AF_AUTOCONF)
-		flags |= IFA_F_MANAGETEMPADDR;
-#endif
 
 	/* Add as /128 if no IFA_F_NOPREFIXROUTE ? */
 	nlm.ifa.ifa_prefixlen = ia->prefix_len;
+
 #if 0
 	/* This creates the aliased interface */
 	add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LABEL,
@@ -1563,6 +1556,25 @@
 	    &ia->addr.s6_addr, sizeof(ia->addr.s6_addr));
 
 	if (cmd == RTM_NEWADDR) {
+#ifdef IPV6_MANAGETEMPADDR
+		if (ia->flags & IPV6_AF_TEMPORARY) {
+			/* Currently the kernel filters out these flags */
+#ifdef IFA_F_NOPREFIXROUTE
+			flags |= IFA_F_TEMPORARY;
+#else
+			nlm.ifa.ifa_flags |= IFA_F_TEMPORARY;
+#endif
+		}
+#elif IFA_F_MANAGETEMPADDR
+		if (ia->flags & IPV6_AF_AUTOCONF)
+			flags |= IFA_F_MANAGETEMPADDR;
+#endif
+#ifdef IFA_F_NOPREFIXROUTE
+		if (!IN6_IS_ADDR_LINKLOCAL(&ia->addr))
+			flags |= IFA_F_NOPREFIXROUTE;
+#endif
+		add_attr_32(&nlm.hdr, sizeof(nlm), IFA_FLAGS, flags);
+
 		memset(&cinfo, 0, sizeof(cinfo));
 		cinfo.ifa_prefered = ia->prefix_pltime;
 		cinfo.ifa_valid = ia->prefix_vltime;
@@ -1570,15 +1582,6 @@
 		    &cinfo, sizeof(cinfo));
 	}
 
-#ifdef IFA_F_NOPREFIXROUTE
-	if (!IN6_IS_ADDR_LINKLOCAL(&ia->addr))
-		flags |= IFA_F_NOPREFIXROUTE;
-#endif
-#if defined(IFA_F_NOPREFIXROUTE) || defined(IFA_F_MANAGETEMPADDR)
-	if (flags)
-		add_attr_32(&nlm.hdr, sizeof(nlm), IFA_FLAGS, flags);
-#endif
-
 	return send_netlink(ia->iface->ctx, NULL,
 	    NETLINK_ROUTE, &nlm.hdr, NULL);
 }
--- a/src/ipv4.c	Tue Jul 16 10:53:35 2019 +0100
+++ b/src/ipv4.c	Mon Jul 22 10:37:13 2019 +0100
@@ -599,7 +599,8 @@
 
 struct ipv4_addr *
 ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
-    const struct in_addr *mask, const struct in_addr *bcast)
+    const struct in_addr *mask, const struct in_addr *bcast,
+    uint32_t vltime, uint32_t pltime)
 {
 	struct ipv4_state *state;
 	struct ipv4_addr *ia;
@@ -639,6 +640,8 @@
 
 	ia->mask = *mask;
 	ia->brd = *bcast;
+	ia->vltime = vltime;
+	ia->pltime = pltime;
 	snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d",
 	    inet_ntoa(*addr), inet_ntocidr(*mask));
 
@@ -681,7 +684,8 @@
 	struct dhcp_state *state;
 	struct ipv4_addr *ia;
 
-	ia = ipv4_addaddr(ifp, &lease->addr, &lease->mask, &lease->brd);
+	ia = ipv4_addaddr(ifp, &lease->addr, &lease->mask, &lease->brd,
+	    lease->leasetime, lease->leasetime);
 	if (ia == NULL)
 		return -1;
 
--- a/src/ipv4.h	Tue Jul 16 10:53:35 2019 +0100
+++ b/src/ipv4.h	Mon Jul 22 10:37:13 2019 +0100
@@ -83,6 +83,8 @@
 	struct interface *iface;
 	int addr_flags;
 	unsigned int flags;
+	uint32_t vltime;
+	uint32_t pltime;
 	char saddr[INET_ADDRSTRLEN + 3];
 #ifdef ALIAS_ADDR
 	char alias[IF_NAMESIZE];
@@ -126,7 +128,8 @@
 
 int ipv4_deladdr(struct ipv4_addr *, int);
 struct ipv4_addr *ipv4_addaddr(struct interface *,
-    const struct in_addr *, const struct in_addr *, const struct in_addr *);
+    const struct in_addr *, const struct in_addr *, const struct in_addr *,
+    uint32_t, uint32_t);
 void ipv4_applyaddr(void *);
 
 struct ipv4_addr *ipv4_iffindaddr(struct interface *,
--- a/src/ipv4ll.c	Tue Jul 16 10:53:35 2019 +0100
+++ b/src/ipv4ll.c	Mon Jul 22 10:37:13 2019 +0100
@@ -40,6 +40,7 @@
 #include "config.h"
 #include "arp.h"
 #include "common.h"
+#include "dhcp.h"
 #include "eloop.h"
 #include "if.h"
 #include "if-options.h"
@@ -212,7 +213,8 @@
 		if (ifp->ctx->options & DHCPCD_TEST)
 			goto test;
 		ia = ipv4_addaddr(ifp, &state->pickedaddr,
-		    &inaddr_llmask, &inaddr_llbcast);
+		    &inaddr_llmask, &inaddr_llbcast,
+		    DHCP_INFINITE_LIFETIME, DHCP_INFINITE_LIFETIME);
 	}
 	if (ia == NULL)
 		return;