]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
inet6: Add support for reporting Mobile IPv6 RA's
authorRoy Marples <roy@marples.name>
Mon, 15 Jun 2020 21:43:39 +0000 (22:43 +0100)
committerRoy Marples <roy@marples.name>
Mon, 15 Jun 2020 21:43:39 +0000 (22:43 +0100)
This is RFC6275. dhcpcd is not a client suitable for this,
but it will at least decode the information properly.

src/dhcpcd-definitions-small.conf
src/dhcpcd-definitions.conf
src/ipv6.h
src/ipv6nd.c

index b58ab021c7b450528f9d5255a75d71472c2aa0d7..4b626f98c80c7febaa1eb939046a3d804f9f3396 100644 (file)
@@ -57,7 +57,7 @@ definend 2    binhex                  target_address
 
 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
index 5949be6785f835f0b9cbe0b487d35bf7760d1b3f..d0b643144940c1d429f0a047970abe9faf07979f 100644 (file)
@@ -341,7 +341,7 @@ definend 2  binhex                  target_address
 
 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 @@ definend 5 embed                   mtu
 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
index 5625d8510d160440e784823ea7c24b17793c604d..8eb4fd0050490ef212dac620f95b2db73c60b049 100644 (file)
@@ -226,8 +226,9 @@ struct ipv6_addr {
 #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 {
index 4e904292a7318090f31d00c35eb4c340ea2adc77..ecec7b6c8a918bd56fb38d296f33a41a47dc305d 100644 (file)
 /* 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 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
        uint32_t old_lifetime;
        int ifmtu;
        int loglevel;
+       unsigned int flags;
 #ifdef IPV6_MANAGETEMPADDR
        bool new_ia;
 #endif
@@ -1299,13 +1307,15 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
                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 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
                        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 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 #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 @@ ipv6nd_env(FILE *fp, const struct interface *ifp)
        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 @@ ipv6nd_env(FILE *fp, const struct interface *ifp)
                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;