Skip to content

Commit 8013d1d

Browse files
liuhangbindavem330
authored andcommitted
net/ipv6: add sysctl option accept_ra_min_hop_limit
Commit 6fd9909 ("ipv6: Don't reduce hop limit for an interface") disabled accept hop limit from RA if it is smaller than the current hop limit for security stuff. But this behavior kind of break the RFC definition. RFC 4861, 6.3.4. Processing Received Router Advertisements A Router Advertisement field (e.g., Cur Hop Limit, Reachable Time, and Retrans Timer) may contain a value denoting that it is unspecified. In such cases, the parameter should be ignored and the host should continue using whatever value it is already using. If the received Cur Hop Limit value is non-zero, the host SHOULD set its CurHopLimit variable to the received value. So add sysctl option accept_ra_min_hop_limit to let user choose the minimum hop limit value they can accept from RA. And set default to 1 to meet RFC standards. Signed-off-by: Hangbin Liu <[email protected]> Acked-by: YOSHIFUJI Hideaki <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2f51a9b commit 8013d1d

File tree

5 files changed

+27
-9
lines changed

5 files changed

+27
-9
lines changed

Documentation/networking/ip-sysctl.txt

+8
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,14 @@ accept_ra_from_local - BOOLEAN
13401340
disabled if accept_ra_from_local is disabled
13411341
on a specific interface.
13421342

1343+
accept_ra_min_hop_limit - INTEGER
1344+
Minimum hop limit Information in Router Advertisement.
1345+
1346+
Hop limit Information in Router Advertisement less than this
1347+
variable shall be ignored.
1348+
1349+
Default: 1
1350+
13431351
accept_ra_pinfo - BOOLEAN
13441352
Learn Prefix Information in Router Advertisement.
13451353

include/linux/ipv6.h

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct ipv6_devconf {
2929
__s32 max_desync_factor;
3030
__s32 max_addresses;
3131
__s32 accept_ra_defrtr;
32+
__s32 accept_ra_min_hop_limit;
3233
__s32 accept_ra_pinfo;
3334
#ifdef CONFIG_IPV6_ROUTER_PREF
3435
__s32 accept_ra_rtr_pref;

include/uapi/linux/ipv6.h

+1
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ enum {
172172
DEVCONF_ACCEPT_RA_MTU,
173173
DEVCONF_STABLE_SECRET,
174174
DEVCONF_USE_OIF_ADDRS_ONLY,
175+
DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT,
175176
DEVCONF_MAX
176177
};
177178

net/ipv6/addrconf.c

+10
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
195195
.max_addresses = IPV6_MAX_ADDRESSES,
196196
.accept_ra_defrtr = 1,
197197
.accept_ra_from_local = 0,
198+
.accept_ra_min_hop_limit= 1,
198199
.accept_ra_pinfo = 1,
199200
#ifdef CONFIG_IPV6_ROUTER_PREF
200201
.accept_ra_rtr_pref = 1,
@@ -237,6 +238,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
237238
.max_addresses = IPV6_MAX_ADDRESSES,
238239
.accept_ra_defrtr = 1,
239240
.accept_ra_from_local = 0,
241+
.accept_ra_min_hop_limit= 1,
240242
.accept_ra_pinfo = 1,
241243
#ifdef CONFIG_IPV6_ROUTER_PREF
242244
.accept_ra_rtr_pref = 1,
@@ -4588,6 +4590,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
45884590
array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
45894591
array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
45904592
array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
4593+
array[DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT] = cnf->accept_ra_min_hop_limit;
45914594
array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
45924595
#ifdef CONFIG_IPV6_ROUTER_PREF
45934596
array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
@@ -5484,6 +5487,13 @@ static struct addrconf_sysctl_table
54845487
.mode = 0644,
54855488
.proc_handler = proc_dointvec,
54865489
},
5490+
{
5491+
.procname = "accept_ra_min_hop_limit",
5492+
.data = &ipv6_devconf.accept_ra_min_hop_limit,
5493+
.maxlen = sizeof(int),
5494+
.mode = 0644,
5495+
.proc_handler = proc_dointvec,
5496+
},
54875497
{
54885498
.procname = "accept_ra_pinfo",
54895499
.data = &ipv6_devconf.accept_ra_pinfo,

net/ipv6/ndisc.c

+7-9
Original file line numberDiff line numberDiff line change
@@ -1225,18 +1225,16 @@ static void ndisc_router_discovery(struct sk_buff *skb)
12251225

12261226
if (rt)
12271227
rt6_set_expires(rt, jiffies + (HZ * lifetime));
1228-
if (ra_msg->icmph.icmp6_hop_limit) {
1229-
/* Only set hop_limit on the interface if it is higher than
1230-
* the current hop_limit.
1231-
*/
1232-
if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) {
1228+
if (in6_dev->cnf.accept_ra_min_hop_limit < 256 &&
1229+
ra_msg->icmph.icmp6_hop_limit) {
1230+
if (in6_dev->cnf.accept_ra_min_hop_limit <= ra_msg->icmph.icmp6_hop_limit) {
12331231
in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
1232+
if (rt)
1233+
dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
1234+
ra_msg->icmph.icmp6_hop_limit);
12341235
} else {
1235-
ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n");
1236+
ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than minimum\n");
12361237
}
1237-
if (rt)
1238-
dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
1239-
ra_msg->icmph.icmp6_hop_limit);
12401238
}
12411239

12421240
skip_defrtr:

0 commit comments

Comments
 (0)