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) {