changeset 5362:17f0de2ed2aa draft

inet6: Add support for reporting Mobile IPv6 RA's This is RFC6275. dhcpcd is not a client suitable for this, but it will at least decode the information properly.
author Roy Marples <roy@marples.name>
date Mon, 15 Jun 2020 22:43:39 +0100
parents fabda5ae201c
children e161ef164608
files src/dhcpcd-definitions-small.conf src/dhcpcd-definitions.conf src/ipv6.h src/ipv6nd.c
diffstat 4 files changed, 60 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/dhcpcd-definitions-small.conf	Mon Jun 15 22:04:37 2020 +0100
+++ b/src/dhcpcd-definitions-small.conf	Mon Jun 15 22:43:39 2020 +0100
@@ -57,7 +57,7 @@
 
 definend 3	index embed		prefix_information
 embed		byte			length
-embed		bitflags=LA		flags
+embed		bitflags=LAH		flags
 embed		uint32			vltime
 embed		uint32			pltime
 embed		uint32			reserved
--- a/src/dhcpcd-definitions.conf	Mon Jun 15 22:04:37 2020 +0100
+++ b/src/dhcpcd-definitions.conf	Mon Jun 15 22:43:39 2020 +0100
@@ -341,7 +341,7 @@
 
 definend 3	index embed		prefix_information
 embed		byte			length
-embed		bitflags=LA		flags
+embed		bitflags=LAH		flags
 embed		uint32			vltime
 embed		uint32			pltime
 embed		uint32			reserved
@@ -353,6 +353,12 @@
 embed		uint16			reserved
 embed		uint32			mtu
 
+# ND6 Mobile IP, RFC6275
+definend 8	embed			homeagent_information
+embed		uint16			reserved
+embed		uint16			preference
+embed		uint16			lifetime
+
 # ND6 options, RFC6101
 definend 25	index embed		rdnss
 embed		uint16			reserved
--- a/src/ipv6.h	Mon Jun 15 22:04:37 2020 +0100
+++ b/src/ipv6.h	Mon Jun 15 22:43:39 2020 +0100
@@ -226,8 +226,9 @@
 #define	IPV6_AF_RAPFX		(1U << 12)
 #define	IPV6_AF_EXTENDED	(1U << 13)
 #define	IPV6_AF_REGEN		(1U << 14)
+#define	IPV6_AF_ROUTER		(1U << 15)
 #ifdef IPV6_MANAGETEMPADDR
-#define	IPV6_AF_TEMPORARY	(1U << 15)
+#define	IPV6_AF_TEMPORARY	(1U << 16)
 #endif
 
 struct ll_callback {
--- a/src/ipv6nd.c	Mon Jun 15 22:04:37 2020 +0100
+++ b/src/ipv6nd.c	Mon Jun 15 22:43:39 2020 +0100
@@ -61,6 +61,13 @@
 /* Debugging Router Solicitations is a lot of spam, so disable it */
 //#define DEBUG_RS
 
+#ifndef ND_RA_FLAG_HOME_AGENT
+#define	ND_RA_FLAG_HOME_AGENT	0x20	/* Home Agent flag in RA */
+#endif
+#ifndef ND_OPT_PI_FLAG_ROUTER
+#define	ND_OPT_PI_FLAG_ROUTER	0x20	/* Router flag in PI */
+#endif
+
 #ifndef ND_OPT_RDNSS
 #define ND_OPT_RDNSS			25
 struct nd_opt_rdnss {           /* RDNSS option RFC 6106 */
@@ -1096,6 +1103,7 @@
 	uint32_t old_lifetime;
 	int ifmtu;
 	int loglevel;
+	unsigned int flags;
 #ifdef IPV6_MANAGETEMPADDR
 	bool new_ia;
 #endif
@@ -1299,13 +1307,15 @@
 		case ND_OPT_PREFIX_INFORMATION:
 			loglevel = new_data ? LOG_ERR : LOG_DEBUG;
 			if (ndo.nd_opt_len != 4) {
-				logmessage(loglevel, "%s: invalid option len for prefix",
+				logmessage(loglevel,
+				    "%s: invalid option len for prefix",
 				    ifp->name);
 				continue;
 			}
 			memcpy(&pi, p, sizeof(pi));
 			if (pi.nd_opt_pi_prefix_len > 128) {
-				logmessage(loglevel, "%s: invalid prefix len", ifp->name);
+				logmessage(loglevel, "%s: invalid prefix len",
+				    ifp->name);
 				continue;
 			}
 			/* nd_opt_pi_prefix is not aligned. */
@@ -1314,29 +1324,41 @@
 			if (IN6_IS_ADDR_MULTICAST(&pi_prefix) ||
 			    IN6_IS_ADDR_LINKLOCAL(&pi_prefix))
 			{
-				logmessage(loglevel, "%s: invalid prefix in RA", ifp->name);
+				logmessage(loglevel, "%s: invalid prefix in RA",
+				    ifp->name);
 				continue;
 			}
 			if (ntohl(pi.nd_opt_pi_preferred_time) >
 			    ntohl(pi.nd_opt_pi_valid_time))
 			{
-				logmessage(loglevel, "%s: pltime > vltime", ifp->name);
+				logmessage(loglevel, "%s: pltime > vltime",
+				    ifp->name);
 				continue;
 			}
+
+			flags = 0;
+			if (pi.nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK)
+				flags |= IPV6_AF_ONLINK;
+			if (pi.nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO &&
+			    rap->iface->options->options &
+			    DHCPCD_IPV6RA_AUTOCONF)
+				flags |= IPV6_AF_AUTOCONF;
+			if (pi.nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ROUTER)
+				flags |= IPV6_AF_ROUTER;
+			if (flags == 0) {
+				logmessage(loglevel,
+				    "%s: prefix information option"
+				    " with unknown flags",
+				    ifp->name);
+				continue;
+			}
+
 			ia = ipv6nd_rapfindprefix(rap,
 			    &pi_prefix, pi.nd_opt_pi_prefix_len);
 			if (ia == NULL) {
-				unsigned int flags;
-
-				flags = IPV6_AF_RAPFX;
-				if (pi.nd_opt_pi_flags_reserved &
-				    ND_OPT_PI_FLAG_AUTO &&
-				    rap->iface->options->options &
-				    DHCPCD_IPV6RA_AUTOCONF)
-					flags |= IPV6_AF_AUTOCONF;
-
 				ia = ipv6_newaddr(rap->iface,
-				    &pi_prefix, pi.nd_opt_pi_prefix_len, flags);
+				    &pi_prefix, pi.nd_opt_pi_prefix_len,
+				    flags | IPV6_AF_RAPFX);
 				if (ia == NULL)
 					break;
 				ia->prefix = pi_prefix;
@@ -1363,12 +1385,10 @@
 #ifdef IPV6_MANAGETEMPADDR
 				new_ia = false;
 #endif
+				ia->flags |= flags;
 				ia->flags &= ~IPV6_AF_STALE;
 				ia->acquired = rap->acquired;
 			}
-			if (pi.nd_opt_pi_flags_reserved &
-			    ND_OPT_PI_FLAG_ONLINK)
-				ia->flags |= IPV6_AF_ONLINK;
 			ia->prefix_vltime =
 			    ntohl(pi.nd_opt_pi_valid_time);
 			ia->prefix_pltime =
@@ -1602,6 +1622,7 @@
 	struct nd_opt_hdr ndo;
 	struct ipv6_addr *ia;
 	struct timespec now;
+	int pref;
 
 	clock_gettime(CLOCK_MONOTONIC, &now);
 	i = n = 0;
@@ -1618,6 +1639,18 @@
 		if (efprintf(fp, "%s_now=%lld", ndprefix,
 		    (long long)now.tv_sec) == -1)
 			return -1;
+		if (efprintf(fp, "%s_hoplimit=%u", ndprefix, rap->hoplimit) == -1)
+			return -1;
+		pref = ipv6nd_rtpref(rap);
+		if (efprintf(fp, "%s_flags=%s%s%s%s", ndprefix,
+		    rap->flags & ND_RA_FLAG_MANAGED    ? "M" : "",
+		    rap->flags & ND_RA_FLAG_OTHER      ? "O" : "",
+		    rap->flags & ND_RA_FLAG_HOME_AGENT ? "H" : "",
+		    pref == RTPREF_HIGH ? "h" : pref == RTPREF_LOW ? "l" : ""
+		    ) == -1)
+			return -1;
+		if (efprintf(fp, "%s_lifetime=%u", ndprefix, rap->lifetime) == -1)
+			return -1;
 
 		/* Zero our indexes */
 		for (j = 0, opt = rap->iface->ctx->nd_opts;