Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Dec 2013 00:01:45 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r259239 - user/ae/inet6/sys/net
Message-ID:  <201312120001.rBC01jM9017200@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Thu Dec 12 00:01:45 2013
New Revision: 259239
URL: http://svnweb.freebsd.org/changeset/base/259239

Log:
  We don't keep routes for link-local addresses in routing tables,
  thus we need to handle them specially in RTM_GET. This fixes some issues
  with ndp(8).
  
  If requested destination address has AF_INET6 family and it is from
  link-local scope, use sin6_scope_id to determine corresponding interface.
  Then do link layer address lookup. If address is in ND cache, return it,
  if not - return default AF_LINK ifaddr from this interface.

Modified:
  user/ae/inet6/sys/net/rtsock.c

Modified: user/ae/inet6/sys/net/rtsock.c
==============================================================================
--- user/ae/inet6/sys/net/rtsock.c	Wed Dec 11 23:28:31 2013	(r259238)
+++ user/ae/inet6/sys/net/rtsock.c	Thu Dec 12 00:01:45 2013	(r259239)
@@ -66,7 +66,7 @@
 #include <netinet/if_ether.h>
 #include <netinet/ip_carp.h>
 #ifdef INET6
-#include <netinet6/ip6_var.h>
+#include <netinet6/in6_var.h>
 #include <netinet6/scope6_var.h>
 #endif
 
@@ -558,6 +558,70 @@ rtm_get_jailed(struct rt_addrinfo *info,
 	return (0);
 }
 
+#ifdef INET6
+static int
+in6_rt_handle_lla(struct rt_msghdr **ortm, struct rt_addrinfo *info)
+{
+	struct sockaddr_dl sdl;
+	struct sockaddr_in6 *sin6;
+	struct rt_msghdr *rtm = *ortm;
+	struct llentry *lle;
+	struct ifnet *ifp;
+	int i;
+
+	if (rtm->rtm_type != RTM_GET)
+		return (EOPNOTSUPP);
+	sin6 = (struct sockaddr_in6 *)info->rti_info[RTAX_DST];
+	if (sin6->sin6_scope_id == 0)
+		return (EADDRNOTAVAIL);
+	ifp = in6_getlinkifnet(sin6->sin6_scope_id);
+	if (ifp == NULL)
+		return (ESRCH);
+	/* Clear all sockaddr pointers except DST */
+	for (i = RTAX_GATEWAY; i < RTAX_MAX; i++)
+		info->rti_info[i] = NULL;
+
+	IF_AFDATA_RLOCK(ifp);
+	lle = lla_lookup(LLTABLE6(ifp), 0, info->rti_info[RTAX_DST]);
+	IF_AFDATA_RUNLOCK(ifp);
+	if (lle != NULL) {
+		bzero(&sdl, sizeof(sdl));
+		info->rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sdl;
+		sdl.sdl_family = AF_LINK;
+		sdl.sdl_len = sizeof(sdl);
+		sdl.sdl_alen = ifp->if_addrlen;
+		sdl.sdl_index = ifp->if_index;
+		sdl.sdl_type = ifp->if_type;
+		bcopy(&lle->ll_addr, LLADDR(&sdl), ifp->if_addrlen);
+		if (lle->la_flags & LLE_PUB)
+			rtm->rtm_flags |= RTF_ANNOUNCE;
+		if (lle->la_flags & LLE_STATIC) {
+			rtm->rtm_flags |= RTF_STATIC;
+			rtm->rtm_rmx.rmx_expire = 0;
+		} else
+			rtm->rtm_rmx.rmx_expire = lle->la_expire;
+		LLE_RUNLOCK(lle);
+	} else
+		info->rti_info[RTAX_GATEWAY] = ifp->if_addr->ifa_addr;
+	rtm->rtm_flags |= RTF_UP | RTF_HOST;
+	rtm->rtm_index = ifp->if_index;
+	if (rtm->rtm_addrs & (RTA_IFA | RTA_IFP))
+		info->rti_info[RTAX_IFP] = ifp->if_addr->ifa_addr;
+	i = rt_msg2(rtm->rtm_type, info, NULL, NULL);
+	if (i > rtm->rtm_msglen) {
+		R_Malloc(rtm, struct rt_msghdr *, i);
+		if (rtm == NULL)
+			return (ENOBUFS);
+		bcopy(*ortm, rtm, i);
+		Free(*ortm);
+		*ortm = rtm;
+	}
+	rt_msg2(rtm->rtm_type, info, (caddr_t)rtm, NULL);
+	rtm->rtm_addrs = info->rti_addrs;
+	return (0);
+}
+#endif
+
 /*ARGSUSED*/
 static int
 route_output(struct mbuf *m, struct socket *so)
@@ -700,6 +764,17 @@ route_output(struct mbuf *m, struct sock
 	case RTM_GET:
 	case RTM_CHANGE:
 	case RTM_LOCK:
+#ifdef INET6
+		if (info.rti_info[RTAX_DST]->sa_family == AF_INET6) {
+			struct sockaddr_in6 *sin6;
+
+			sin6 = (struct sockaddr_in6 *)info.rti_info[RTAX_DST];
+			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+				error = in6_rt_handle_lla(&rtm, &info);
+				break;
+			}
+		}
+#endif
 		rnh = rt_tables_get_rnh(so->so_fibnum,
 		    info.rti_info[RTAX_DST]->sa_family);
 		if (rnh == NULL)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201312120001.rBC01jM9017200>