Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2762

kernel-2.6.18-238.el5.src.rpm

From: Thomas Graf <tgraf@redhat.com>
Date: Thu, 9 Sep 2010 12:05:54 -0400
Subject: [net] ipv6: add modes to do RA/RS when in forwarding mode
Message-id: <20100909120554.GA17134@lsx.localdomain>
Patchwork-id: 28186
O-Subject: [PATCH RHEL5.6] IPv6: Add special modes to accept RA/send RS while
	in forwarding mode (BZ614064)
Bugzilla: 614064
RH-Acked-by: Neil Horman <nhorman@redhat.com>
RH-Acked-by: David S. Miller <davem@redhat.com>

Current ipv6 behavior is to not accept RA and send RS while in
forwarding mode (cnf.fowarding > 0)

This does make sense since a router is typically configured
manually. However, there are exceptions for which we require
an overwrite.

This patchs adds a special mode to both cnf.accept_ra and
cnf.forwarding to overrule the existing behavior:

If cnf.accept_ra is set to 2: router advertisements will be
accepted even if forwarding is enabled.

If cnf.forwarding is set to 2: enables forwarding mode while
contienuing to send router solicitations if necessary.

Upstream commits (currently in net-next):
65e9b62d4503849b10bedfc29bff0473760cc597
ipv6: add special mode accept_ra=2 to accept RA while configured as router

c3bccac2fa76f1619dfe4fb7b9bee69de7f066d8
ipv6: add special mode forwarding=2 to send RS while configured as router

ae8abfa00efb8ec550f772cbd1e1854977d06212
ipv6: Update ip-sysctl.txt documentation for recent changes to accept_ra and forwarding

Brew:
http://brewweb.devel.redhat.com/brew/taskinfo?taskID=2747465

Resolves BZ614064

Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index edef9a3..d2bb93f 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -838,6 +838,12 @@ conf/interface/*:
 accept_ra - BOOLEAN
 	Accept Router Advertisements; autoconfigure using them.
 	
+	Possible values are:
+		0 Do not accept Router Advertisements.
+		1 Accept Router Advertisements if forwarding is disabled.
+		2 Overrule forwarding behaviour. Accept Router Advertisements
+		  even if forwarding is enabled.
+
 	Functional default: enabled if local forwarding is disabled.
 			    disabled if local forwarding is enabled.
 
@@ -891,7 +897,12 @@ forwarding - BOOLEAN
 	Note: It is recommended to have the same setting on all 
 	interfaces; mixed router/host scenarios are rather uncommon.
 
-	FALSE:
+	Possible values are:
+		0 Forwarding disabled
+		1 Forwarding enabled
+		2 Forwarding enabled (Hybrid Mode)
+
+	FALSE (0):
 
 	By default, Host behaviour is assumed.  This means:
 
@@ -901,18 +912,25 @@ forwarding - BOOLEAN
 	   Advertisements (and do autoconfiguration).
 	4. If accept_redirects is TRUE (default), accept Redirects.
 
-	TRUE:
+	TRUE (1):
 
 	If local forwarding is enabled, Router behaviour is assumed. 
 	This means exactly the reverse from the above:
 
 	1. IsRouter flag is set in Neighbour Advertisements.
 	2. Router Solicitations are not sent.
-	3. Router Advertisements are ignored.
+	3. Router Advertisements are ignored unless accept_ra is 2.
 	4. Redirects are ignored.
 
-	Default: FALSE if global forwarding is disabled (default),
-		 otherwise TRUE.
+	TRUE (2):
+
+	Hybrid mode. Same behaviour as TRUE, except for:
+
+	2. Router Solicitations are being sent when necessary.
+
+	Default: 0 (disabled) if global forwarding is disabled (default),
+		 otherwise 1 (enabled).
+
 
 hop_limit - INTEGER
 	Default Hop Limit to set.
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 4c2f6c3..1e877ae 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2744,7 +2744,8 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
 	   start sending router solicitations.
 	 */
 
-	if (ifp->idev->cnf.forwarding == 0 &&
+	if ((ifp->idev->cnf.forwarding == 0 ||
+	     ifp->idev->cnf.forwarding == 2) &&
 	    ifp->idev->cnf.rtr_solicits > 0 &&
 	    (dev->flags&IFF_LOOPBACK) == 0 &&
 	    (dev->flags & IFF_MULTICAST) &&
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 04e7f74..f37df88 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1193,6 +1193,18 @@ out:
 	in6_dev_put(idev);
 }
 
+static inline int accept_ra(struct inet6_dev *in6_dev)
+{
+	/*
+	 * If forwarding is enabled, RA are not accepted unless the special
+	 * hybrid mode (accept_ra=2) is enabled.
+	 */
+	if (in6_dev->cnf.forwarding && in6_dev->cnf.accept_ra < 2)
+		return 0;
+
+	return in6_dev->cnf.accept_ra;
+}
+
 static void ndisc_router_discovery(struct sk_buff *skb)
 {
         struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
@@ -1238,7 +1250,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
 		return;
 	}
 
-	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
+	if (!accept_ra(in6_dev))
 		goto skip_linkparms;
 
 	if (in6_dev->if_flags & IF_RS_SENT) {