svn commit: r204798 - in user/hrs/ipv6: sbin/ifconfig sys/netinet6
Hiroki Sato
hrs at FreeBSD.org
Sat Mar 6 16:27:43 UTC 2010
Author: hrs
Date: Sat Mar 6 16:27:43 2010
New Revision: 204798
URL: http://svn.freebsd.org/changeset/base/204798
Log:
Summary:
- Accept Router Advertisement messages even when
net.inet6.ip6.forwarding=1.
- A new per-interface knob: IPV6CTL_DEFROUTE_RTADV. This controls
if accepting a route in an RA message as the default route.
- A new sysctl: net.inet6.ip6.disable_isrouter_rtadvif. This
controls if setting R-bit in NA on RA accepting interfaces. The
default is 0 (R-bit is set based on net.inet6.ip6.forwarding).
Background:
IPv6 host/router model suggests a router sends an RA and a host
accepts it for router discovery. Because of that, KAME
implementation does not allow accepting RAs when
net.inet6.ip6.forwarding=1. Accepting RAs on a router can make the
routing table confused since it can change the default router
unintentionally.
However, in practice there are cases where we cannot distinguish a
host from a router clearly. For example, a customer edge router
often works as a host against the ISP, and as a router against the
LAN at the same time. Another example is a complex network
configurations like an L2TP tunnel for IPv6 connection to Internet
over an Ethernet link with another native IPv6 subnet. In this case,
the physical interface for the native IPv6 subnet works as a host,
and the pseudo-interface for L2TP works as the default IP forwarding
route.
Problems:
When processing RA messages is limited when
net.inet6.ip6.forwarding=1, the following issues are typical:
- A router cannot perform SLAAC. It becomes a problem if a box has
multiple interfaces and you want to use SLAAC on some of them, for
example. A customer edge router for IPv6 Internet access service
using an IPv6-over-IPv6 tunnel sometimes needs SLAAC on the
physical interface for administration purpose; updating firmware
and so on (link-local addresses can be used there, but GUAs by
SLAAC are often used for scalability).
- When a box has multiple IPv6 interfaces and it receives multiple
RAs on them, controlling the default route is difficult. Router
preferences defined in RFC 4191 works only when the routers are
under your control.
Details of Implementation Changes:
Router Advertisement messages will be accepted even when
net.inet6.ip6.forwarding=1. More precisely, the conditions are as
follow:
(ACCEPT_RTADV && DEFROUTE_RTADV)
=> Normal RA processing (as IPv6 host)
(ACCEPT_RTADV && !DEFROUTE_RTADV)
=> Accept RA but add the router to the defroute list with
rtlifetime=0 unconditionally. This effectively prevents
from setting the received router address as the box's
default route.
(!ACCEPT_RTADV && DEFROUTE_RTADV)
=> No RA processing
ACCEPT_RTADV and DEFROUTE_RTADV are per-interface knob.
R-bit in NA on the RA accepting interfaces is set based on
net.inet6.ip6.forwarding. While an on-going discussion on
draft-ietf-v6ops-ipv6-cpe-router suggests R-bit can be disabled
completely even when net.inet6.ip6.forwarding=1, I believe there is
no technical reason with disabling it. This behavior can be set by a
new sysctl net.inet6.ip6.disable_isrouter_rtadvif (the default is 0).
Usage:
# ifconfig fxp0 inet6 accept_rtadv
=> accept RA on fxp0
# ifconfig fxp0 inet6 accept_rtadv -defroute_rtadv
=> accept RA but ignore default route information on fxp0.
The default value of defroute_rtadv flag can be set by
net.inet6.ip6.defroute_rtadv (the default is 1).
# sysctl net.inet6.ip6.disable_isrouter_rtadvif=1
=> R-bit in NAs on RA accepting interfaces will always be set as 0.
Reviewed by: bz
Modified:
user/hrs/ipv6/sbin/ifconfig/af_inet6.c
user/hrs/ipv6/sbin/ifconfig/af_nd6.c
user/hrs/ipv6/sys/netinet6/in6.h
user/hrs/ipv6/sys/netinet6/in6_proto.c
user/hrs/ipv6/sys/netinet6/ip6_input.c
user/hrs/ipv6/sys/netinet6/ip6_var.h
user/hrs/ipv6/sys/netinet6/nd6.c
user/hrs/ipv6/sys/netinet6/nd6.h
user/hrs/ipv6/sys/netinet6/nd6_nbr.c
user/hrs/ipv6/sys/netinet6/nd6_rtr.c
Modified: user/hrs/ipv6/sbin/ifconfig/af_inet6.c
==============================================================================
--- user/hrs/ipv6/sbin/ifconfig/af_inet6.c Sat Mar 6 12:47:50 2010 (r204797)
+++ user/hrs/ipv6/sbin/ifconfig/af_inet6.c Sat Mar 6 16:27:43 2010 (r204798)
@@ -498,6 +498,8 @@ static struct cmd inet6_cmds[] = {
DEF_CMD("-autoconf", -IN6_IFF_AUTOCONF, setip6flags),
DEF_CMD("accept_rtadv", ND6_IFF_ACCEPT_RTADV, setnd6flags),
DEF_CMD("-accept_rtadv",-ND6_IFF_ACCEPT_RTADV, setnd6flags),
+ DEF_CMD("defroute_rtadv",ND6_IFF_DEFROUTE_RTADV,setnd6flags),
+ DEF_CMD("-defroute_rtadv",-ND6_IFF_DEFROUTE_RTADV,setnd6flags),
DEF_CMD("defaultif", 1, setnd6defif),
DEF_CMD("-defaultif", -1, setnd6defif),
DEF_CMD("ifdisabled", ND6_IFF_IFDISABLED, setnd6flags),
Modified: user/hrs/ipv6/sbin/ifconfig/af_nd6.c
==============================================================================
--- user/hrs/ipv6/sbin/ifconfig/af_nd6.c Sat Mar 6 12:47:50 2010 (r204797)
+++ user/hrs/ipv6/sbin/ifconfig/af_nd6.c Sat Mar 6 16:27:43 2010 (r204798)
@@ -58,7 +58,7 @@ static const char rcsid[] =
#define MAX_SYSCTL_TRY 5
#define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
"\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \
- "\020DEFAULTIF"
+ "\007DEFROUTE_RTADV\020DEFAULTIF"
static int isnd6defif(int);
void setnd6flags(const char *, int, int, const struct afswtch *);
Modified: user/hrs/ipv6/sys/netinet6/in6.h
==============================================================================
--- user/hrs/ipv6/sys/netinet6/in6.h Sat Mar 6 12:47:50 2010 (r204797)
+++ user/hrs/ipv6/sys/netinet6/in6.h Sat Mar 6 16:27:43 2010 (r204798)
@@ -611,7 +611,10 @@ struct ip6_mtuinfo {
#define IPV6CTL_STEALTH 45
#define ICMPV6CTL_ND6_ONLINKNSRFC4861 47
-#define IPV6CTL_MAXID 48
+#define IPV6CTL_DEFROUTE_RTADV 48 /* Add a route in RA to defroute list.*/
+#define IPV6CTL_DISABLE_ISROUTER_RTADVIF 49 /* Disable R-bit in NA on RA
+ * receiving IF. */
+#define IPV6CTL_MAXID 50
#endif /* __BSD_VISIBLE */
/*
Modified: user/hrs/ipv6/sys/netinet6/in6_proto.c
==============================================================================
--- user/hrs/ipv6/sys/netinet6/in6_proto.c Sat Mar 6 12:47:50 2010 (r204797)
+++ user/hrs/ipv6/sys/netinet6/in6_proto.c Sat Mar 6 16:27:43 2010 (r204798)
@@ -383,6 +383,8 @@ VNET_DEFINE(int, ip6_sendredirects);
VNET_DEFINE(int, ip6_defhlim);
VNET_DEFINE(int, ip6_defmcasthlim);
VNET_DEFINE(int, ip6_accept_rtadv);
+VNET_DEFINE(int, ip6_defroute_rtadv);
+VNET_DEFINE(int, ip6_disable_isrouter_rtadvif);
VNET_DEFINE(int, ip6_maxfragpackets);
VNET_DEFINE(int, ip6_maxfrags);
VNET_DEFINE(int, ip6_log_interval);
@@ -499,6 +501,16 @@ SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_
CTLFLAG_RW, &VNET_NAME(ip6_accept_rtadv), 0,
"Default value of per-interface flag for accepting ICMPv6 Router"
"Advertisement messages");
+SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_DEFROUTE_RTADV, defroute_rtadv,
+ CTLFLAG_RW, &VNET_NAME(ip6_defroute_rtadv), 0,
+ "Default value of per-interface flag to control whether routers "
+ "sending ICMPv6 RA messages on that interface are added into the "
+ "default router list.");
+SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_DISABLE_ISROUTER_RTADVIF,
+ disable_isrouter_rtadvif, CTLFLAG_RW,
+ &VNET_NAME(ip6_disable_isrouter_rtadvif), 0,
+ "Always set 0 to R flag in ICMPv6 NA messages when accepting RA"
+ " on the interface.");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_KEEPFAITH, keepfaith, CTLFLAG_RW,
&VNET_NAME(ip6_keepfaith), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_LOG_INTERVAL, log_interval,
Modified: user/hrs/ipv6/sys/netinet6/ip6_input.c
==============================================================================
--- user/hrs/ipv6/sys/netinet6/ip6_input.c Sat Mar 6 12:47:50 2010 (r204797)
+++ user/hrs/ipv6/sys/netinet6/ip6_input.c Sat Mar 6 16:27:43 2010 (r204798)
@@ -197,6 +197,8 @@ ip6_init(void)
V_ip6_defhlim = IPV6_DEFHLIM;
V_ip6_defmcasthlim = IPV6_DEFAULT_MULTICAST_HOPS;
V_ip6_accept_rtadv = 0;
+ V_ip6_defroute_rtadv = 1;
+ V_ip6_disable_isrouter_rtadvif = 0;
V_ip6_log_interval = 5;
V_ip6_hdrnestlimit = 15; /* How many header options will we process? */
V_ip6_dad_count = 1; /* DupAddrDetectionTransmits */
Modified: user/hrs/ipv6/sys/netinet6/ip6_var.h
==============================================================================
--- user/hrs/ipv6/sys/netinet6/ip6_var.h Sat Mar 6 12:47:50 2010 (r204797)
+++ user/hrs/ipv6/sys/netinet6/ip6_var.h Sat Mar 6 16:27:43 2010 (r204798)
@@ -308,6 +308,9 @@ VNET_DECLARE(int, ip6_maxfragpackets); /
VNET_DECLARE(int, ip6_maxfrags); /* Maximum fragments in reassembly
* queue */
VNET_DECLARE(int, ip6_accept_rtadv); /* Acts as a host not a router */
+VNET_DECLARE(int, ip6_defroute_rtadv); /* Add a route in RA to defroute list.*/
+VNET_DECLARE(int, ip6_disable_isrouter_rtadvif); /* Disable R-bit in NA on RA
+ * receiving IF. */
VNET_DECLARE(int, ip6_keepfaith); /* Firewall Aided Internet Translator */
VNET_DECLARE(int, ip6_log_interval);
VNET_DECLARE(time_t, ip6_log_time);
@@ -344,6 +347,8 @@ VNET_DECLARE(int, ip6_use_defzone); /* W
#define V_ip6_maxfragpackets VNET(ip6_maxfragpackets)
#define V_ip6_maxfrags VNET(ip6_maxfrags)
#define V_ip6_accept_rtadv VNET(ip6_accept_rtadv)
+#define V_ip6_defroute_rtadv VNET(ip6_defroute_rtadv)
+#define V_ip6_disable_isrouter_rtadvif VNET(ip6_disable_isrouter_rtadvif)
#define V_ip6_keepfaith VNET(ip6_keepfaith)
#define V_ip6_log_interval VNET(ip6_log_interval)
#define V_ip6_log_time VNET(ip6_log_time)
Modified: user/hrs/ipv6/sys/netinet6/nd6.c
==============================================================================
--- user/hrs/ipv6/sys/netinet6/nd6.c Sat Mar 6 12:47:50 2010 (r204797)
+++ user/hrs/ipv6/sys/netinet6/nd6.c Sat Mar 6 16:27:43 2010 (r204798)
@@ -223,6 +223,8 @@ nd6_ifattach(struct ifnet *ifp)
/* A loopback interface does not need to accept RTADV. */
if (V_ip6_accept_rtadv && !(ifp->if_flags & IFF_LOOPBACK))
nd->flags |= ND6_IFF_ACCEPT_RTADV;
+ if (V_ip6_defroute_rtadv && !(ifp->if_flags & IFF_LOOPBACK))
+ nd->flags |= ND6_IFF_DEFROUTE_RTADV;
/* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */
nd6_setmtu0(ifp, nd);
@@ -848,7 +850,7 @@ nd6_purge(struct ifnet *ifp)
if (V_nd6_defifindex == ifp->if_index)
nd6_setdefaultiface(0);
- if (!V_ip6_forwarding && ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
+ if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
/* Refresh default router list. */
defrouter_select();
}
@@ -982,10 +984,9 @@ nd6_is_new_addr_neighbor(struct sockaddr
/*
* If the default router list is empty, all addresses are regarded
* as on-link, and thus, as a neighbor.
- * XXX: we restrict the condition to hosts, because routers usually do
- * not have the "default router list".
*/
- if (!V_ip6_forwarding && TAILQ_FIRST(&V_nd_defrouter) == NULL &&
+ if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV &&
+ TAILQ_FIRST(&V_nd_defrouter) == NULL &&
V_nd6_defifindex == ifp->if_index) {
return (1);
}
@@ -1042,7 +1043,7 @@ nd6_free(struct llentry *ln, int gc)
/* cancel timer */
nd6_llinfo_settimer(ln, -1);
- if (!V_ip6_forwarding) {
+ if (ND_IFINFO(ln->lle_tbl->llt_ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
int s;
s = splnet();
dr = defrouter_lookup(&L3_ADDR_SIN6(ln)->sin6_addr, ln->lle_tbl->llt_ifp);
@@ -1720,7 +1721,7 @@ nd6_cache_lladdr(struct ifnet *ifp, stru
* for those are not autoconfigured hosts, we explicitly avoid such
* cases for safety.
*/
- if (do_update && router && !V_ip6_forwarding &&
+ if (do_update && router &&
ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
/*
* guaranteed recursion
Modified: user/hrs/ipv6/sys/netinet6/nd6.h
==============================================================================
--- user/hrs/ipv6/sys/netinet6/nd6.h Sat Mar 6 12:47:50 2010 (r204797)
+++ user/hrs/ipv6/sys/netinet6/nd6.h Sat Mar 6 16:27:43 2010 (r204798)
@@ -85,6 +85,7 @@ struct nd_ifinfo {
*/
#define ND6_IFF_DONT_SET_IFROUTE 0x10
#define ND6_IFF_AUTO_LINKLOCAL 0x20
+#define ND6_IFF_DEFROUTE_RTADV 0x40
#define ND6_CREATE LLE_CREATE
#define ND6_EXCLUSIVE LLE_EXCLUSIVE
Modified: user/hrs/ipv6/sys/netinet6/nd6_nbr.c
==============================================================================
--- user/hrs/ipv6/sys/netinet6/nd6_nbr.c Sat Mar 6 12:47:50 2010 (r204797)
+++ user/hrs/ipv6/sys/netinet6/nd6_nbr.c Sat Mar 6 16:27:43 2010 (r204798)
@@ -116,10 +116,15 @@ nd6_ns_input(struct mbuf *m, int off, in
int lladdrlen = 0;
int anycast = 0, proxy = 0, tentative = 0;
int tlladdr;
+ int rflag;
union nd_opts ndopts;
struct sockaddr_dl *proxydl = NULL;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
+ rflag = (V_ip6_forwarding) ? ND_NA_FLAG_ROUTER : 0;
+ if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV &&
+ V_ip6_disable_isrouter_rtadvif)
+ rflag = 0;
#ifndef PULLDOWN_TEST
IP6_EXTHDR_CHECK(m, off, icmp6len,);
nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
@@ -340,8 +345,7 @@ nd6_ns_input(struct mbuf *m, int off, in
goto bad;
nd6_na_output(ifp, &in6_all, &taddr6,
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
- (V_ip6_forwarding ? ND_NA_FLAG_ROUTER : 0),
- tlladdr, (struct sockaddr *)proxydl);
+ rflag, tlladdr, (struct sockaddr *)proxydl);
goto freeit;
}
@@ -350,8 +354,7 @@ nd6_ns_input(struct mbuf *m, int off, in
nd6_na_output(ifp, &saddr6, &taddr6,
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
- (V_ip6_forwarding ? ND_NA_FLAG_ROUTER : 0) | ND_NA_FLAG_SOLICITED,
- tlladdr, (struct sockaddr *)proxydl);
+ rflag | ND_NA_FLAG_SOLICITED, tlladdr, (struct sockaddr *)proxydl);
freeit:
if (ifa != NULL)
ifa_free(ifa);
@@ -848,7 +851,8 @@ nd6_na_input(struct mbuf *m, int off, in
dr = defrouter_lookup(in6, ln->lle_tbl->llt_ifp);
if (dr)
defrtrlist_del(dr);
- else if (!V_ip6_forwarding) {
+ else if (ND_IFINFO(ln->lle_tbl->llt_ifp)->flags &
+ ND6_IFF_ACCEPT_RTADV) {
/*
* Even if the neighbor is not in the default
* router list, the neighbor may be used
Modified: user/hrs/ipv6/sys/netinet6/nd6_rtr.c
==============================================================================
--- user/hrs/ipv6/sys/netinet6/nd6_rtr.c Sat Mar 6 12:47:50 2010 (r204797)
+++ user/hrs/ipv6/sys/netinet6/nd6_rtr.c Sat Mar 6 16:27:43 2010 (r204798)
@@ -125,8 +125,11 @@ nd6_rs_input(struct mbuf *m, int off, in
union nd_opts ndopts;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
- /* If I'm not a router, ignore it. */
- if (!V_ip6_forwarding)
+ /*
+ * Accept RS only when V_ip6_forwarding=1 and the interface has
+ * no ND6_IFF_ACCEPT_RTADV.
+ */
+ if (!V_ip6_forwarding || ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV)
goto freeit;
/* Sanity checks */
@@ -211,11 +214,10 @@ nd6_ra_input(struct mbuf *m, int off, in
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
/*
- * We only accept RAs only when
- * the node is not a router and
- * per-interface variable allows RAs on the receiving interface.
+ * We only accept RAs only when the per-interface flag
+ * ND6_IFF_ACCEPT_RTADV is on the receiving interface.
*/
- if (V_ip6_forwarding || !(ndi->flags & ND6_IFF_ACCEPT_RTADV))
+ if (!(ndi->flags & ND6_IFF_ACCEPT_RTADV))
goto freeit;
if (ip6->ip6_hlim != 255) {
@@ -264,7 +266,14 @@ nd6_ra_input(struct mbuf *m, int off, in
bzero(&dr0, sizeof(dr0));
dr0.rtaddr = saddr6;
dr0.flags = nd_ra->nd_ra_flags_reserved;
- dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
+ /*
+ * Effectively-disable the route in the RA packet
+ * when !ND6_IFF_DEFROUTE_RTADV on the receiving interface.
+ */
+ if (ndi->flags & ND6_IFF_DEFROUTE_RTADV)
+ dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
+ else
+ dr0.rtlifetime = 0;
dr0.expire = time_second + dr0.rtlifetime;
dr0.ifp = ifp;
/* unspecified or not? (RFC 2461 6.3.4) */
@@ -555,7 +564,7 @@ defrtrlist_del(struct nd_defrouter *dr)
* Flush all the routing table entries that use the router
* as a next hop.
*/
- if (!V_ip6_forwarding)
+ if (ND_IFINFO(dr->ifp)->flags & ND6_IFF_ACCEPT_RTADV)
rt6_flush(&dr->rtaddr, dr->ifp);
if (dr->installed) {
@@ -614,20 +623,6 @@ defrouter_select(void)
struct llentry *ln = NULL;
/*
- * This function should be called only when acting as an autoconfigured
- * host. Although the remaining part of this function is not effective
- * if the node is not an autoconfigured host, we explicitly exclude
- * such cases here for safety.
- */
- if (V_ip6_forwarding) {
- nd6log((LOG_WARNING,
- "defrouter_select: called unexpectedly (forwarding=%d)\n",
- V_ip6_forwarding));
- splx(s);
- return;
- }
-
- /*
* Let's handle easy case (3) first:
* If default router list is empty, there's nothing to be done.
*/
More information about the svn-src-user
mailing list