Skip to content

Commit

Permalink
net: add sysctl accept_ra_min_rtr_lft
Browse files Browse the repository at this point in the history
commit 1671bcf upstream.

This change adds a new sysctl accept_ra_min_rtr_lft to specify the
minimum acceptable router lifetime in an RA. If the received RA router
lifetime is less than the configured value (and not 0), the RA is
ignored.
This is useful for mobile devices, whose battery life can be impacted
by networks that configure RAs with a short lifetime. On such networks,
the device should never gain IPv6 provisioning and should attempt to
drop RAs via hardware offload, if available.

Signed-off-by: Patrick Rohr <prohr@google.com>
Cc: Maciej Żenczykowski <maze@google.com>
Cc: Lorenzo Colitti <lorenzo@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Patrick Rohr authored and gregkh committed Oct 10, 2023
1 parent 9d91134 commit ec4162b
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 2 deletions.
8 changes: 8 additions & 0 deletions Documentation/networking/ip-sysctl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2148,6 +2148,14 @@ accept_ra_min_hop_limit - INTEGER

Default: 1

accept_ra_min_rtr_lft - INTEGER
Minimum acceptable router lifetime in Router Advertisement.

RAs with a router lifetime less than this value shall be
ignored. RAs with a router lifetime of 0 are unaffected.

Default: 0

accept_ra_pinfo - BOOLEAN
Learn Prefix Information in Router Advertisement.

Expand Down
1 change: 1 addition & 0 deletions include/linux/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct ipv6_devconf {
__s32 accept_ra_defrtr;
__u32 ra_defrtr_metric;
__s32 accept_ra_min_hop_limit;
__s32 accept_ra_min_rtr_lft;
__s32 accept_ra_pinfo;
__s32 ignore_routes_with_linkdown;
#ifdef CONFIG_IPV6_ROUTER_PREF
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ enum {
DEVCONF_IOAM6_ID_WIDE,
DEVCONF_NDISC_EVICT_NOCARRIER,
DEVCONF_ACCEPT_UNTRACKED_NA,
DEVCONF_ACCEPT_RA_MIN_RTR_LFT,
DEVCONF_MAX
};

Expand Down
10 changes: 10 additions & 0 deletions net/ipv6/addrconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
.ra_defrtr_metric = IP6_RT_PRIO_USER,
.accept_ra_from_local = 0,
.accept_ra_min_hop_limit= 1,
.accept_ra_min_rtr_lft = 0,
.accept_ra_pinfo = 1,
#ifdef CONFIG_IPV6_ROUTER_PREF
.accept_ra_rtr_pref = 1,
Expand Down Expand Up @@ -262,6 +263,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
.ra_defrtr_metric = IP6_RT_PRIO_USER,
.accept_ra_from_local = 0,
.accept_ra_min_hop_limit= 1,
.accept_ra_min_rtr_lft = 0,
.accept_ra_pinfo = 1,
#ifdef CONFIG_IPV6_ROUTER_PREF
.accept_ra_rtr_pref = 1,
Expand Down Expand Up @@ -5601,6 +5603,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
array[DEVCONF_IOAM6_ID_WIDE] = cnf->ioam6_id_wide;
array[DEVCONF_NDISC_EVICT_NOCARRIER] = cnf->ndisc_evict_nocarrier;
array[DEVCONF_ACCEPT_UNTRACKED_NA] = cnf->accept_untracked_na;
array[DEVCONF_ACCEPT_RA_MIN_RTR_LFT] = cnf->accept_ra_min_rtr_lft;
}

static inline size_t inet6_ifla6_size(void)
Expand Down Expand Up @@ -6794,6 +6797,13 @@ static const struct ctl_table addrconf_sysctl[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "accept_ra_min_rtr_lft",
.data = &ipv6_devconf.accept_ra_min_rtr_lft,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "accept_ra_pinfo",
.data = &ipv6_devconf.accept_ra_pinfo,
Expand Down
18 changes: 16 additions & 2 deletions net/ipv6/ndisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1284,13 +1284,22 @@ static void ndisc_router_discovery(struct sk_buff *skb)
return;
}

lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);

if (!ipv6_accept_ra(in6_dev)) {
ND_PRINTK(2, info,
"RA: %s, did not accept ra for dev: %s\n",
__func__, skb->dev->name);
goto skip_linkparms;
}

if (lifetime != 0 && lifetime < in6_dev->cnf.accept_ra_min_rtr_lft) {
ND_PRINTK(2, info,
"RA: router lifetime (%ds) is too short: %s\n",
lifetime, skb->dev->name);
goto skip_linkparms;
}

#ifdef CONFIG_IPV6_NDISC_NODETYPE
/* skip link-specific parameters from interior routers */
if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) {
Expand Down Expand Up @@ -1343,8 +1352,6 @@ static void ndisc_router_discovery(struct sk_buff *skb)
goto skip_defrtr;
}

lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);

#ifdef CONFIG_IPV6_ROUTER_PREF
pref = ra_msg->icmph.icmp6_router_pref;
/* 10b is handled as if it were 00b (medium) */
Expand Down Expand Up @@ -1495,6 +1502,13 @@ static void ndisc_router_discovery(struct sk_buff *skb)
goto out;
}

if (lifetime != 0 && lifetime < in6_dev->cnf.accept_ra_min_rtr_lft) {
ND_PRINTK(2, info,
"RA: router lifetime (%ds) is too short: %s\n",
lifetime, skb->dev->name);
goto out;
}

#ifdef CONFIG_IPV6_ROUTE_INFO
if (!in6_dev->cnf.accept_ra_from_local &&
ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
Expand Down

0 comments on commit ec4162b

Please sign in to comment.