Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 5 Jun 2011 11:20:19 +0000 (UTC)
From:      Hiroki Sato <hrs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r222710 - user/hrs/ipv6/usr.sbin/rtadvd
Message-ID:  <201106051120.p55BKJ62053566@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hrs
Date: Sun Jun  5 11:20:19 2011
New Revision: 222710
URL: http://svn.freebsd.org/changeset/base/222710

Log:
  Specify requirements for RA sending/receiving based on lifetime,
  IFF_ND6_ACCEPT_RTADV, and net.inet6.ip6.forwarding.
  
   ra_output:
    (lifetime == 0) = output
    (lifetime != 0 && (ACCEPT_RTADV || !ip6.forwarding) = no output
  
   ra_input:
    ACCEPT_RTADV = input
    !ACCEPT_RTADV = no input
  
  Note that the current implementation sends RAs with zero-lifetime even if
  ip6.forwarding == 0.  This behavior is derived from KAME and different from
  RFC 4861.

Modified:
  user/hrs/ipv6/usr.sbin/rtadvd/config.c
  user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c

Modified: user/hrs/ipv6/usr.sbin/rtadvd/config.c
==============================================================================
--- user/hrs/ipv6/usr.sbin/rtadvd/config.c	Sun Jun  5 10:07:12 2011	(r222709)
+++ user/hrs/ipv6/usr.sbin/rtadvd/config.c	Sun Jun  5 11:20:19 2011	(r222710)
@@ -34,7 +34,6 @@
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/time.h>
-#include <sys/sysctl.h>
 
 #include <net/if.h>
 #include <net/if_var.h>
@@ -76,7 +75,6 @@ static time_t prefix_timo = (60 * 120);	
 
 static struct rtadvd_timer *prefix_timeout(void *);
 static void makeentry(char *, size_t, int, const char *);
-static int getinet6sysctl(int);
 static size_t dname_labelenc(char *, const char *);
 
 /* Encode domain name label encoding in RFC 1035 Section 3.1 */
@@ -215,7 +213,6 @@ getconfig(int idx)
 	char *bp = buf;
 	char *addr, *flagstr;
 	char intface[IFNAMSIZ];
-	static int forwarding = -1;
 
 	if (if_indextoname(idx, intface) == NULL) {
 		syslog(LOG_ERR, "<%s> invalid index number (%d)",
@@ -247,11 +244,6 @@ getconfig(int idx)
 	TAILQ_INIT(&rai->rai_dnssl);
 	TAILQ_INIT(&rai->rai_soliciter);
 
-	/* check if we are allowed to forward packets (if not determined) */
-	if (forwarding < 0)
-		if ((forwarding = getinet6sysctl(IPV6CTL_FORWARDING)) < 0)
-			exit(1);
-
 	/* gather on-link prefixes from the network interfaces. */
 	if (agetflag("noifprefix"))
 		rai->rai_advifprefix = 0;
@@ -355,22 +347,6 @@ getconfig(int idx)
 		    MAXROUTERLIFETIME);
 		return (-1);
 	}
-	/*
-	 * Basically, hosts MUST NOT send Router Advertisement messages at any
-	 * time (RFC 4861, Section 6.2.3). However, it would sometimes be
-	 * useful to allow hosts to advertise some parameters such as prefix
-	 * information and link MTU. Thus, we allow hosts to invoke rtadvd
-	 * only when router lifetime (on every advertising interface) is
-	 * explicitly set zero. (see also the above section)
-	 */
-	if (val && forwarding == 0) {
-		syslog(LOG_ERR,
-		    "<%s> non zero router lifetime is specified for %s, "
-		    "which must not be allowed for hosts.  you must "
-		    "change router lifetime or enable IPv6 forwarding.",
-		    __func__, intface);
-		return (-1);
-	}
 	rai->rai_lifetime = val & 0xffff;
 
 	MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME);
@@ -1312,23 +1288,3 @@ make_packet(struct rainfo *rai)
 	}
 	return;
 }
-
-static int
-getinet6sysctl(int code)
-{
-	int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 };
-	int value;
-	size_t size;
-
-	mib[3] = code;
-	size = sizeof(value);
-	if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0)
-	    < 0) {
-		syslog(LOG_ERR, "<%s>: failed to get ip6 sysctl(%d): %s",
-		    __func__, code,
-		    strerror(errno));
-		return (-1);
-	}
-	else
-		return (value);
-}

Modified: user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c
==============================================================================
--- user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c	Sun Jun  5 10:07:12 2011	(r222709)
+++ user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c	Sun Jun  5 11:20:19 2011	(r222710)
@@ -31,10 +31,12 @@
  */
 
 #include <sys/param.h>
+#include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/uio.h>
 #include <sys/time.h>
 #include <sys/queue.h>
+#include <sys/sysctl.h>
 
 #include <net/if.h>
 #include <net/if_media.h>
@@ -47,6 +49,10 @@
 
 #include <arpa/inet.h>
 
+#include <net/if_var.h>
+#include <netinet/in_var.h>
+#include <netinet6/nd6.h>
+
 #include <time.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -174,6 +180,8 @@ static void	rtmsg_input(void);
 static void	rtadvd_set_dump_file(int);
 static void	set_short_delay(struct rainfo *);
 static int	ifl_lookup(char *, char **, int);
+static int	check_accept_rtadv(int);
+static int	getinet6sysctl(int);
 
 int
 main(int argc, char *argv[])
@@ -1030,6 +1038,61 @@ set_short_delay(struct rainfo *rai)
 	rtadvd_set_timer(&interval, rai->rai_timer);
 }
 
+static int
+check_accept_rtadv(int idx)
+{
+	struct in6_ndireq nd;
+	u_char ifname[IFNAMSIZ];
+	int s6;
+	int error;
+
+	if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+		syslog(LOG_ERR,
+		    "<%s> open socket failed for idx=%d.",
+		    __func__, idx);
+		return (0);
+	}
+	if ((if_indextoname(idx, ifname)) == NULL) {
+		syslog(LOG_ERR,
+		    "<%s> ifindex->ifname failed (idx=%d).",
+		    __func__, idx);
+		close(s6);
+		return (0);
+	}
+	memset(&nd, 0, sizeof(nd));
+	strncpy(nd.ifname, ifname, sizeof(nd.ifname));
+	error = ioctl(s6, SIOCGIFINFO_IN6, &nd);
+	if (error) {
+		syslog(LOG_ERR,
+		    "<%s> ioctl(SIOCGIFINFO_IN6) failed for idx=%d.",
+		    __func__, idx);
+		nd.ndi.flags = 0;
+	}
+	close(s6);
+
+	return (nd.ndi.flags & ND6_IFF_ACCEPT_RTADV);
+}
+
+static int
+getinet6sysctl(int code)
+{
+	int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 };
+	int value;
+	size_t size;
+
+	mib[3] = code;
+	size = sizeof(value);
+	if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0)
+	    < 0) {
+		syslog(LOG_ERR, "<%s>: failed to get ip6 sysctl(%d): %s",
+		    __func__, code,
+		    strerror(errno));
+		return (-1);
+	}
+	else
+		return (value);
+}
+
 static void
 ra_input(int len, struct nd_router_advert *nra,
 	 struct in6_pktinfo *pi, struct sockaddr_in6 *from)
@@ -1047,6 +1110,16 @@ ra_input(int len, struct nd_router_adver
 	    inet_ntop(AF_INET6, &from->sin6_addr, ntopbuf, sizeof(ntopbuf)),
 	    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
 
+	if (!check_accept_rtadv(pi->ipi6_ifindex)) {
+		syslog(LOG_INFO,
+		    "<%s> An RA from %s on %s ignored (no ACCEPT_RTADV flag).",
+		    __func__,
+		    inet_ntop(AF_INET6, &from->sin6_addr, ntopbuf,
+			sizeof(ntopbuf)), if_indextoname(pi->ipi6_ifindex,
+			ifnamebuf));
+		return;
+	}
+
 	/* ND option check */
 	memset(&ndopts, 0, sizeof(ndopts));
 	error = nd6_options((struct nd_opt_hdr *)(nra + 1),
@@ -1639,6 +1712,41 @@ ra_output(struct rainfo *rai)
 		return;
 	}
 
+	/*
+	 * Check lifetime, ACCEPT_RTADV flag, and ip6.forwarding.
+	 *
+	 * (lifetime == 0) = output
+	 * (lifetime != 0 && (ACCEPT_RTADV || !ip6.forwarding) = no output
+	 *
+	 * Basically, hosts MUST NOT send Router Advertisement
+	 * messages at any time (RFC 4861, Section 6.2.3). However, it
+	 * would sometimes be useful to allow hosts to advertise some
+	 * parameters such as prefix information and link MTU. Thus,
+	 * we allow hosts to invoke rtadvd only when router lifetime
+	 * (on every advertising interface) is explicitly set
+	 * zero. (see also the above section)
+	 */
+	syslog(LOG_DEBUG,
+	    "<%s> check lifetime=%d, ACCEPT_RTADV=%d, ip6.forwarding=%d on %s",
+	    __func__, rai->rai_lifetime, check_accept_rtadv(rai->rai_ifindex),
+	    getinet6sysctl(IPV6CTL_FORWARDING), rai->rai_ifname);
+	if (rai->rai_lifetime != 0) {
+		if (check_accept_rtadv(rai->rai_ifindex)) {
+			syslog(LOG_INFO,
+			    "<%s> non-zero lifetime RA "
+			    "on RA receiving interface %s."
+			    "  Ignored.", __func__, rai->rai_ifname);
+			return;
+		}
+		if (getinet6sysctl(IPV6CTL_FORWARDING) == 0) {
+			syslog(LOG_INFO,
+			    "<%s> non-zero lifetime RA "
+			    "but net.inet6.ip6.forwarding=0.  "
+			    "Ignored.", __func__);
+			return;
+		}
+	}
+
 	make_packet(rai);	/* XXX: inefficient */
 
 	sndmhdr.msg_name = (caddr_t)&sin6_linklocal_allnodes;



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