Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144994779
D55267.id171844.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D55267.id171844.diff
View Options
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -79,7 +79,7 @@
static struct nd_defrouter *defrtrlist_update(struct nd_defrouter *);
static int prelist_update(struct nd_prefixctl *, struct nd_defrouter *,
- struct mbuf *, int);
+ bool, int);
static int nd6_prefix_onlink(struct nd_prefix *);
static int in6_get_tmp_ifid(struct in6_aliasreq *);
@@ -180,7 +180,7 @@
if (!V_ip6_forwarding || ifp->if_inet6->nd_flags & ND6_IFF_ACCEPT_RTADV)
goto freeit;
- /* RFC 6980: Nodes MUST silently ignore fragments */
+ /* RFC 6980: Nodes MUST silently ignore fragments */
if(m->m_flags & M_FRAGMENTED)
goto freeit;
@@ -355,6 +355,127 @@
#endif
}
+static void
+nd6_ra_opt_pi(struct nd_opt_hdr *pt, struct ifnet *ifp,
+ struct nd_router_advert *nd_ra, struct nd_defrouter *dr,
+ bool auth, bool mcast)
+{
+ struct nd_opt_prefix_info *pi = NULL;
+ struct nd_prefixctl pr;
+ char ip6bufs[INET6_ADDRSTRLEN];
+
+ if (pt->nd_opt_type != ND_OPT_PREFIX_INFORMATION)
+ return;
+
+ pi = (struct nd_opt_prefix_info *)pt;
+ if (pi->nd_opt_pi_len != 4) {
+ nd6log((LOG_INFO,
+ "%s: invalid option len %d for prefix "
+ "information option, ignored\n", __func__,
+ pi->nd_opt_pi_len));
+ return;
+ }
+
+ if (pi->nd_opt_pi_prefix_len > 128) {
+ nd6log((LOG_INFO,
+ "%s: invalid prefix len %d for prefix "
+ "information option, ignored\n", __func__,
+ pi->nd_opt_pi_prefix_len));
+ return;
+ }
+
+ if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix)
+ || IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
+ nd6log((LOG_INFO,
+ "%s: invalid prefix %s, ignored\n",
+ __func__, ip6_sprintf(ip6bufs,
+ &pi->nd_opt_pi_prefix)));
+ return;
+ }
+
+ bzero(&pr, sizeof(pr));
+ pr.ndpr_prefix.sin6_family = AF_INET6;
+ pr.ndpr_prefix.sin6_len = sizeof(pr.ndpr_prefix);
+ pr.ndpr_prefix.sin6_addr = pi->nd_opt_pi_prefix;
+ pr.ndpr_ifp = ifp;
+
+ pr.ndpr_raf_onlink = (pi->nd_opt_pi_flags_reserved &
+ ND_OPT_PI_FLAG_ONLINK) ? 1 : 0;
+ pr.ndpr_raf_auto = (pi->nd_opt_pi_flags_reserved &
+ ND_OPT_PI_FLAG_AUTO) ? 1 : 0;
+ pr.ndpr_plen = pi->nd_opt_pi_prefix_len;
+ pr.ndpr_vltime = ntohl(pi->nd_opt_pi_valid_time);
+ pr.ndpr_pltime = ntohl(pi->nd_opt_pi_preferred_time);
+ (void)prelist_update(&pr, dr, auth, mcast);
+}
+
+static void
+nd6_ra_opt_mtu(struct nd_opt_mtu *optmtu, struct ifnet *ifp,
+ struct in6_addr saddr6)
+{
+ struct in6_ifextra *ndi;
+ char ip6bufs[INET6_ADDRSTRLEN];
+ uint32_t mtu, maxmtu;
+
+ ndi = ifp->if_inet6;
+
+ if (optmtu->nd_opt_mtu_len != 1)
+ return;
+ mtu = (uint32_t)ntohl(optmtu->nd_opt_mtu_mtu);
+ /* lower bound */
+ if (mtu < IPV6_MMTU) {
+ nd6log((LOG_INFO, "%s: bogus mtu option mtu=%u sent from %s, "
+ "ignoring\n", __func__, mtu, ip6_sprintf(ip6bufs, &saddr6)));
+ return;
+ }
+
+ /* upper bound */
+ maxmtu = (ndi->nd_maxmtu && ndi->nd_maxmtu < ifp->if_mtu)
+ ? ndi->nd_maxmtu : ifp->if_mtu;
+ if (mtu <= maxmtu) {
+ if (ndi->nd_linkmtu != mtu) {
+ ndi->nd_linkmtu = mtu;
+ rt_updatemtu(ifp);
+ }
+ } else {
+ nd6log((LOG_INFO, "%s: bogus mtu=%u sent from %s; "
+ "exceeds maxmtu %u, ignoring\n", __func__,
+ mtu, ip6_sprintf(ip6bufs, &saddr6), maxmtu));
+ }
+}
+
+static int
+nd6_ra_opt_src_lladdr(struct nd_opt_hdr *opthdr, struct ifnet *ifp,
+ struct in6_addr saddr6)
+{
+ char ip6bufs[INET6_ADDRSTRLEN];
+ char *lladdr = NULL;
+ int lladdrlen = 0;
+
+ if (opthdr != NULL) {
+ lladdr = (char *)(opthdr + 1);
+ lladdrlen = opthdr->nd_opt_len << 3;
+ }
+
+ if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
+ nd6log((LOG_INFO,
+ "%s: lladdrlen mismatch for %s (if %d, RA packet %d)\n",
+ __func__, ip6_sprintf(ip6bufs, &saddr6),
+ ifp->if_addrlen, lladdrlen - 2));
+ return (-1);
+ }
+
+ nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_ADVERT, 0);
+
+ /*
+ * Installing a link-layer address might change the state of the
+ * router's neighbor cache, which might also affect our on-link
+ * detection of adveritsed prefixes.
+ */
+ pfxlist_onlink_check();
+ return (0);
+}
+
/*
* Receive Router Advertisement Message.
*
@@ -369,11 +490,13 @@
struct in6_ifextra *ndi;
struct ip6_hdr *ip6;
struct nd_router_advert *nd_ra;
+ struct nd_opt_hdr *pt;
struct in6_addr saddr6;
- struct nd_defrouter *dr;
+ struct nd_defrouter dr0, *dr;
union nd_opts ndopts;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
- int mcast;
+ uint32_t advreachable;
+ bool mcast, auth;
/*
* We only accept RAs only when the per-interface flag
@@ -425,15 +548,11 @@
goto freeit;
}
- mcast = 0;
dr = NULL;
- {
- struct nd_defrouter dr0;
- u_int32_t advreachable = nd_ra->nd_ra_reachable;
-
+ mcast = false;
/* remember if this is a multicasted advertisement */
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
- mcast = 1;
+ mcast = true;
bzero(&dr0, sizeof(dr0));
dr0.rtaddr = saddr6;
@@ -443,17 +562,16 @@
* ND6_IFF_NO_RADR enabled on the receiving interface or
* (ip6.forwarding == 1 && ip6.rfc6204w3 != 1).
*/
- if (ndi->nd_flags & ND6_IFF_NO_RADR)
- dr0.rtlifetime = 0;
- else if (V_ip6_forwarding && !V_ip6_rfc6204w3)
+ if ((ndi->nd_flags & ND6_IFF_NO_RADR) ||
+ (V_ip6_forwarding && !V_ip6_rfc6204w3))
dr0.rtlifetime = 0;
else
dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
dr0.expire = time_uptime + dr0.rtlifetime;
dr0.ifp = ifp;
/* unspecified or not? (RFC 2461 6.3.4) */
- if (advreachable) {
- advreachable = ntohl(advreachable);
+ if (nd_ra->nd_ra_reachable) {
+ advreachable = ntohl(nd_ra->nd_ra_reachable);
if (advreachable <= MAX_REACHABLE_TIME &&
ndi->nd_basereachable != advreachable) {
ndi->nd_basereachable = advreachable;
@@ -479,63 +597,18 @@
#ifdef EXPERIMENTAL
defrtr_ipv6_only_ifp(ifp);
#endif
- }
-
- /*
- * prefix
- */
- if (ndopts.nd_opts_pi) {
- struct nd_opt_hdr *pt;
- struct nd_opt_prefix_info *pi = NULL;
- struct nd_prefixctl pr;
-
+ /* Prefix Information */
+ if (ndopts.nd_opts_pi != NULL) {
+ /*
+ * Authenticity for NA consists authentication for
+ * both IP header and IP datagrams, doesn't it ?
+ */
+ auth = ((m->m_flags & M_AUTHIPHDR) && (m->m_flags & M_AUTHIPDGM));
for (pt = (struct nd_opt_hdr *)ndopts.nd_opts_pi;
pt <= (struct nd_opt_hdr *)ndopts.nd_opts_pi_end;
pt = (struct nd_opt_hdr *)((caddr_t)pt +
(pt->nd_opt_len << 3))) {
- if (pt->nd_opt_type != ND_OPT_PREFIX_INFORMATION)
- continue;
- pi = (struct nd_opt_prefix_info *)pt;
-
- if (pi->nd_opt_pi_len != 4) {
- nd6log((LOG_INFO,
- "%s: invalid option len %d for prefix "
- "information option, ignored\n", __func__,
- pi->nd_opt_pi_len));
- continue;
- }
-
- if (128 < pi->nd_opt_pi_prefix_len) {
- nd6log((LOG_INFO,
- "%s: invalid prefix len %d for prefix "
- "information option, ignored\n", __func__,
- pi->nd_opt_pi_prefix_len));
- continue;
- }
-
- if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix)
- || IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
- nd6log((LOG_INFO,
- "%s: invalid prefix %s, ignored\n",
- __func__, ip6_sprintf(ip6bufs,
- &pi->nd_opt_pi_prefix)));
- continue;
- }
-
- bzero(&pr, sizeof(pr));
- pr.ndpr_prefix.sin6_family = AF_INET6;
- pr.ndpr_prefix.sin6_len = sizeof(pr.ndpr_prefix);
- pr.ndpr_prefix.sin6_addr = pi->nd_opt_pi_prefix;
- pr.ndpr_ifp = (struct ifnet *)m->m_pkthdr.rcvif;
-
- pr.ndpr_raf_onlink = (pi->nd_opt_pi_flags_reserved &
- ND_OPT_PI_FLAG_ONLINK) ? 1 : 0;
- pr.ndpr_raf_auto = (pi->nd_opt_pi_flags_reserved &
- ND_OPT_PI_FLAG_AUTO) ? 1 : 0;
- pr.ndpr_plen = pi->nd_opt_pi_prefix_len;
- pr.ndpr_vltime = ntohl(pi->nd_opt_pi_valid_time);
- pr.ndpr_pltime = ntohl(pi->nd_opt_pi_preferred_time);
- (void)prelist_update(&pr, dr, m, mcast);
+ nd6_ra_opt_pi(pt, ifp, nd_ra, dr, auth, mcast);
}
}
if (dr != NULL) {
@@ -543,70 +616,13 @@
dr = NULL;
}
- /*
- * MTU
- */
- if (ndopts.nd_opts_mtu && ndopts.nd_opts_mtu->nd_opt_mtu_len == 1) {
- u_long mtu;
- u_long maxmtu;
-
- mtu = (u_long)ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
-
- /* lower bound */
- if (mtu < IPV6_MMTU) {
- nd6log((LOG_INFO, "%s: bogus mtu option mtu=%lu sent "
- "from %s, ignoring\n", __func__,
- mtu, ip6_sprintf(ip6bufs, &ip6->ip6_src)));
- goto skip;
- }
-
- /* upper bound */
- maxmtu = (ndi->nd_maxmtu && ndi->nd_maxmtu < ifp->if_mtu)
- ? ndi->nd_maxmtu : ifp->if_mtu;
- if (mtu <= maxmtu) {
- if (ndi->nd_linkmtu != mtu) {
- ndi->nd_linkmtu = mtu;
- rt_updatemtu(ifp);
- }
- } else {
- nd6log((LOG_INFO, "%s: bogus mtu=%lu sent from %s; "
- "exceeds maxmtu %lu, ignoring\n", __func__,
- mtu, ip6_sprintf(ip6bufs, &ip6->ip6_src), maxmtu));
- }
- }
-
- skip:
-
- /*
- * Source link layer address
- */
- {
- char *lladdr = NULL;
- int lladdrlen = 0;
+ /* MTU */
+ if (ndopts.nd_opts_mtu != NULL)
+ nd6_ra_opt_mtu(ndopts.nd_opts_mtu, ifp, saddr6);
- if (ndopts.nd_opts_src_lladdr) {
- lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
- lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
- }
-
- if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
- nd6log((LOG_INFO,
- "%s: lladdrlen mismatch for %s (if %d, RA packet %d)\n",
- __func__, ip6_sprintf(ip6bufs, &saddr6),
- ifp->if_addrlen, lladdrlen - 2));
+ /* Source link layer address */
+ if (nd6_ra_opt_src_lladdr(ndopts.nd_opts_src_lladdr, ifp, saddr6) != 0)
goto bad;
- }
-
- nd6_cache_lladdr(ifp, &saddr6, lladdr,
- lladdrlen, ND_ROUTER_ADVERT, 0);
-
- /*
- * Installing a link-layer address might change the state of the
- * router's neighbor cache, which might also affect our on-link
- * detection of adveritsed prefixes.
- */
- pfxlist_onlink_check();
- }
freeit:
m_freem(m);
@@ -1478,32 +1494,19 @@
static int
prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
- struct mbuf *m, int mcast)
+ bool auth, int mcast)
{
struct in6_ifaddr *ia6 = NULL, *ia6_match = NULL;
struct ifaddr *ifa;
struct ifnet *ifp = new->ndpr_ifp;
struct nd_prefix *pr;
int error = 0;
- int auth;
struct in6_addrlifetime lt6_tmp;
char ip6buf[INET6_ADDRSTRLEN];
bool has_temporary = false;
NET_EPOCH_ASSERT();
- auth = 0;
- if (m) {
- /*
- * Authenticity for NA consists authentication for
- * both IP header and IP datagrams, doesn't it ?
- */
-#if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)
- auth = ((m->m_flags & M_AUTHIPHDR) &&
- (m->m_flags & M_AUTHIPDGM));
-#endif
- }
-
if ((pr = nd6_prefix_lookup(new)) != NULL) {
/*
* nd6_prefix_lookup() ensures that pr and new have the same
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 15, 8:45 PM (12 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28682594
Default Alt Text
D55267.id171844.diff (10 KB)
Attached To
Mode
D55267: ndp: Simplify and breakdown nd6_ra_input()
Attached
Detach File
Event Timeline
Log In to Comment