Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv6: Send ICMPv6 RSes only when RAs are accepted

This patch improves the logic determining when to send ICMPv6 Router
Solicitations, so that they are 1) always sent when the kernel is
accepting Router Advertisements, and 2) never sent when the kernel is
not accepting RAs. In other words, the operational setting of the
"accept_ra" sysctl is used.

The change also makes the special "Hybrid Router" forwarding mode
("forwarding" sysctl set to 2) operate exactly the same as the standard
Router mode (forwarding=1). The only difference between the two was
that RSes was being sent in the Hybrid Router mode only. The sysctl
documentation describing the special Hybrid Router mode has therefore
been removed.

Rationale for the change:

Currently, the value of forwarding sysctl is the only thing determining
whether or not to send RSes. If it has the value 0 or 2, they are sent,
otherwise they are not. This leads to inconsistent behaviour in the
following cases:

* accept_ra=0, forwarding=0
* accept_ra=0, forwarding=2
* accept_ra=1, forwarding=2
* accept_ra=2, forwarding=1

In the first three cases, the kernel will send RSes, even though it will
not accept any RAs received in reply. In the last case, it will not send
any RSes, even though it will accept and process any RAs received. (Most
routers will send unsolicited RAs periodically, so suppressing RSes in
the last case will merely delay auto-configuration, not prevent it.)

Also, it is my opinion that having the forwarding sysctl control RS
sending behaviour (completely independent of whether RAs are being
accepted or not) is simply not what most users would intuitively expect
to be the case.

Signed-off-by: Tore Anderson <tore@fud.no>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Tore Anderson and committed by
David S. Miller
026359bc c1aabdf3

+12 -13
+8 -9
Documentation/networking/ip-sysctl.txt
··· 1045 1045 accept_ra - BOOLEAN 1046 1046 Accept Router Advertisements; autoconfigure using them. 1047 1047 1048 + It also determines whether or not to transmit Router 1049 + Solicitations. If and only if the functional setting is to 1050 + accept Router Advertisements, Router Solicitations will be 1051 + transmitted. 1052 + 1048 1053 Possible values are: 1049 1054 0 Do not accept Router Advertisements. 1050 1055 1 Accept Router Advertisements if forwarding is disabled. ··· 1120 1115 Possible values are: 1121 1116 0 Forwarding disabled 1122 1117 1 Forwarding enabled 1123 - 2 Forwarding enabled (Hybrid Mode) 1124 1118 1125 1119 FALSE (0): 1126 1120 1127 1121 By default, Host behaviour is assumed. This means: 1128 1122 1129 1123 1. IsRouter flag is not set in Neighbour Advertisements. 1130 - 2. Router Solicitations are being sent when necessary. 1124 + 2. If accept_ra is TRUE (default), transmit Router 1125 + Solicitations. 1131 1126 3. If accept_ra is TRUE (default), accept Router 1132 1127 Advertisements (and do autoconfiguration). 1133 1128 4. If accept_redirects is TRUE (default), accept Redirects. ··· 1138 1133 This means exactly the reverse from the above: 1139 1134 1140 1135 1. IsRouter flag is set in Neighbour Advertisements. 1141 - 2. Router Solicitations are not sent. 1136 + 2. Router Solicitations are not sent unless accept_ra is 2. 1142 1137 3. Router Advertisements are ignored unless accept_ra is 2. 1143 1138 4. Redirects are ignored. 1144 - 1145 - TRUE (2): 1146 - 1147 - Hybrid mode. Same behaviour as TRUE, except for: 1148 - 1149 - 2. Router Solicitations are being sent when necessary. 1150 1139 1151 1140 Default: 0 (disabled) if global forwarding is disabled (default), 1152 1141 otherwise 1 (enabled).
+4 -4
net/ipv6/addrconf.c
··· 2996 2996 2997 2997 ipv6_ifa_notify(RTM_NEWADDR, ifp); 2998 2998 2999 - /* If added prefix is link local and forwarding is off, 3000 - start sending router solicitations. 2999 + /* If added prefix is link local and we are prepared to process 3000 + router advertisements, start sending router solicitations. 3001 3001 */ 3002 3002 3003 - if ((ifp->idev->cnf.forwarding == 0 || 3004 - ifp->idev->cnf.forwarding == 2) && 3003 + if (((ifp->idev->cnf.accept_ra == 1 && !ifp->idev->cnf.forwarding) || 3004 + ifp->idev->cnf.accept_ra == 2) && 3005 3005 ifp->idev->cnf.rtr_solicits > 0 && 3006 3006 (dev->flags&IFF_LOOPBACK) == 0 && 3007 3007 (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {