diff options
| author | Roy Marples <roy@marples.name> | 2020-06-15 22:43:39 +0100 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2020-06-15 22:43:39 +0100 |
| commit | 774505038c1dbcdd9c8de81a4c0c81b482b566e1 (patch) | |
| tree | a5c1de9c3caa2c1299e62fc430e8f0200a95b2de /src/ipv6nd.c | |
| parent | e28fb1bab09b0cfb230f6645d3f790793fb8b5f3 (diff) | |
| download | dhcpcd-774505038c1dbcdd9c8de81a4c0c81b482b566e1.tar.xz | |
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.
Diffstat (limited to 'src/ipv6nd.c')
| -rw-r--r-- | src/ipv6nd.c | 67 |
1 files changed, 50 insertions, 17 deletions
diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 4e904292..ecec7b6c 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -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 @@ 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; |
