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 6d45ce7..ea7c790 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 71d82fe..9f2273a 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 5f9fa03..edbd120 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 973e215..40f21fe 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;
        }