ppp: implement x-netns support
authorGuillaume Nault <g.nault@alphalink.fr>
Mon, 24 Aug 2015 09:35:30 +0000 (11:35 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 25 Aug 2015 21:11:20 +0000 (14:11 -0700)
Let packets move from one netns to the other at PPP encapsulation and
decapsulation time.

PPP units and channels remain in the netns in which they were
originally created. Only the net_device may move to a different
namespace. Cross netns handling is thus transparent to lower PPP
layers (PPPoE, L2TP, etc.).

PPP devices are automatically unregistered when their netns gets
removed. So read() and poll() on the unit file descriptor will
respectively receive EOF and POLLHUP. Channels aren't affected.

Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ppp/ppp_generic.c

index fa8f5046afe90627242f6d2d523178da653c9427..0481daf9201a28eafbdde2798907bc0318a13ed1 100644 (file)
@@ -283,6 +283,8 @@ static int unit_set(struct idr *p, void *ptr, int n);
 static void unit_put(struct idr *p, int n);
 static void *unit_find(struct idr *p, int n);
 
+static const struct net_device_ops ppp_netdev_ops;
+
 static struct class *ppp_class;
 
 /* per net-namespace data */
@@ -919,13 +921,22 @@ static __net_init int ppp_init_net(struct net *net)
 static __net_exit void ppp_exit_net(struct net *net)
 {
        struct ppp_net *pn = net_generic(net, ppp_net_id);
+       struct net_device *dev;
+       struct net_device *aux;
        struct ppp *ppp;
        LIST_HEAD(list);
        int id;
 
        rtnl_lock();
+       for_each_netdev_safe(net, dev, aux) {
+               if (dev->netdev_ops == &ppp_netdev_ops)
+                       unregister_netdevice_queue(dev, &list);
+       }
+
        idr_for_each_entry(&pn->units_idr, ppp, id)
-               unregister_netdevice_queue(ppp->dev, &list);
+               /* Skip devices already unregistered by previous loop */
+               if (!net_eq(dev_net(ppp->dev), net))
+                       unregister_netdevice_queue(ppp->dev, &list);
 
        unregister_netdevice_many(&list);
        rtnl_unlock();
@@ -1017,6 +1028,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
        proto = npindex_to_proto[npi];
        put_unaligned_be16(proto, pp);
 
+       skb_scrub_packet(skb, !net_eq(ppp->ppp_net, dev_net(dev)));
        skb_queue_tail(&ppp->file.xq, skb);
        ppp_xmit_process(ppp);
        return NETDEV_TX_OK;
@@ -1137,7 +1149,6 @@ static void ppp_setup(struct net_device *dev)
        dev->tx_queue_len = 3;
        dev->type = ARPHRD_PPP;
        dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
-       dev->features |= NETIF_F_NETNS_LOCAL;
        netif_keep_dst(dev);
 }
 
@@ -1900,6 +1911,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
                        skb->dev = ppp->dev;
                        skb->protocol = htons(npindex_to_ethertype[npi]);
                        skb_reset_mac_header(skb);
+                       skb_scrub_packet(skb, !net_eq(ppp->ppp_net,
+                                                     dev_net(ppp->dev)));
                        netif_rx(skb);
                }
        }