net: ipv6: add socket option IPV6_ROUTER_ALERT_ISOLATE
authorFrancesco Ruggeri <fruggeri@arista.com>
Fri, 1 Mar 2019 23:31:03 +0000 (15:31 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 4 Mar 2019 05:05:10 +0000 (21:05 -0800)
By default IPv6 socket with IPV6_ROUTER_ALERT socket option set will
receive all IPv6 RA packets from all namespaces.
IPV6_ROUTER_ALERT_ISOLATE socket option restricts packets received by
the socket to be only from the socket's namespace.

Signed-off-by: Maxim Martynov <maxim@arista.com>
Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/ipv6.h
include/uapi/linux/in6.h
net/ipv6/ip6_output.c
net/ipv6/ipv6_sockglue.c

index 6d45ce784beaaf3ae5a3f29132c3b146221a6896..ea7c7906591ebeaf491bb1f2bba6fef3c0f409ec 100644 (file)
@@ -281,7 +281,8 @@ struct ipv6_pinfo {
                                dontfrag:1,
                                autoflowlabel:1,
                                autoflowlabel_set:1,
-                               mc_all:1;
+                               mc_all:1,
+                               rtalert_isolate:1;
        __u8                    min_hopcount;
        __u8                    tclass;
        __be32                  rcv_flowinfo;
index 71d82fe15b034db9ffc2127c1474cc8d0ef9c9d7..9f2273a0835642b243a7c10903ac24b79ecb9f99 100644 (file)
@@ -178,6 +178,7 @@ struct in6_flowlabel_req {
 #define IPV6_JOIN_ANYCAST      27
 #define IPV6_LEAVE_ANYCAST     28
 #define IPV6_MULTICAST_ALL     29
+#define IPV6_ROUTER_ALERT_ISOLATE      30
 
 /* IPV6_MTU_DISCOVER values */
 #define IPV6_PMTUDISC_DONT             0
index 5f9fa0302b5a97af835b6f9ff10f53f1b6e1c9be..edbd12067170bc77332d57a04c96812d9702520b 100644 (file)
@@ -300,6 +300,12 @@ static int ip6_call_ra_chain(struct sk_buff *skb, int sel)
                if (sk && ra->sel == sel &&
                    (!sk->sk_bound_dev_if ||
                     sk->sk_bound_dev_if == skb->dev->ifindex)) {
+                       struct ipv6_pinfo *np = inet6_sk(sk);
+
+                       if (np && np->rtalert_isolate &&
+                           !net_eq(sock_net(sk), dev_net(skb->dev))) {
+                               continue;
+                       }
                        if (last) {
                                struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
                                if (skb2)
index 973e215c3114a3f4b5af51dc44e593b0168e2ef3..40f21fef25ff459b0d2ec17c5679e29bf435297f 100644 (file)
@@ -787,6 +787,12 @@ done:
                        goto e_inval;
                retv = ip6_ra_control(sk, val);
                break;
+       case IPV6_ROUTER_ALERT_ISOLATE:
+               if (optlen < sizeof(int))
+                       goto e_inval;
+               np->rtalert_isolate = valbool;
+               retv = 0;
+               break;
        case IPV6_MTU_DISCOVER:
                if (optlen < sizeof(int))
                        goto e_inval;
@@ -1358,6 +1364,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                val = np->rxopt.bits.recvfragsize;
                break;
 
+       case IPV6_ROUTER_ALERT_ISOLATE:
+               val = np->rtalert_isolate;
+               break;
+
        default:
                return -ENOPROTOOPT;
        }