pts rule name              description
 ---- ---------------------- --------------------------------------------------
  2.7 DNS_FROM_AHBL_RHSBL    RBL: Envelope sender listed in dnsbl.ahbl.org
 -0.0 SPF_PASS               SPF: sender matches SPF record
 -1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%
                             [score: 0.0000]
Status: O
X-Status: F
Content-Length: 4391

This permits a split namespace setup where the GTP transport
sockets are in one namespace the gtp tunnel interface is in
another namespace.

The target namespece is selected by the new GTPA_NET_NS_FD NL
attributes. It fall back to the netns of the GTP-U sockets if
the NL attr is not present.

Signed-off-by: Andreas Schultz <[email protected]>
---
 gtp.c    | 35 +++++++++++++++++++++++++++++++----
 gtp_nl.h |  1 +
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/gtp.c b/gtp.c
index cbe2da1..cd41aea 100644
--- a/gtp.c
+++ b/gtp.c
@@ -740,7 +740,7 @@ static int gtp_encap_enable(struct net_device *dev, struct 
gtp_instance *gti,
 static int gtp_newlink(struct net *src_net, struct net_device *dev,
                        struct nlattr *tb[], struct nlattr *data[])
 {
-       struct gtp_net *gn = net_generic(src_net, gtp_net_id);
+       struct gtp_net *gn;
        struct net_device *real_dev;
        struct gtp_instance *gti;
        int hashsize, err, fd0, fd1;
@@ -780,6 +780,7 @@ static int gtp_newlink(struct net *src_net, struct 
net_device *dev,
        if (err < 0)
                goto err1;

+       gn = net_generic(dev_net(dev), gtp_net_id);
        list_add_rcu(&gti->list, &gn->gtp_instance_list);

        netdev_dbg(dev, "registered new interface\n");
@@ -847,6 +848,19 @@ static struct rtnl_link_ops gtp_link_ops __read_mostly = {
        .fill_info      = gtp_fill_info,
 };

+static struct net *gtp_genl_get_net(struct net *src_net, struct nlattr *tb[])
+{
+       struct net *net;
+       /* Examine the link attributes and figure out which
+        * network namespace we are talking about.
+        */
+       if (tb[GTPA_NET_NS_FD])
+               net = get_net_ns_by_fd(nla_get_u32(tb[GTPA_NET_NS_FD]));
+       else
+               net = get_net(src_net);
+       return net;
+}
+
 static int gtp_hashtable_new(struct gtp_instance *gti, int hsize)
 {
        int i;
@@ -1065,7 +1079,7 @@ static int ipv4_pdp_add(struct net_device *dev, struct 
genl_info *info)

 static int gtp_genl_tunnel_new(struct sk_buff *skb, struct genl_info *info)
 {
-       struct net *net = sock_net(skb->sk);
+       struct net *net;
        struct net_device *dev;

        if (!info->attrs[GTPA_VERSION] ||
@@ -1075,6 +1089,10 @@ static int gtp_genl_tunnel_new(struct sk_buff *skb, 
struct genl_info *info)
            !info->attrs[GTPA_TID])
                return -EINVAL;

+       net = gtp_genl_get_net(sock_net(skb->sk), info->attrs);
+       if (IS_ERR(net))
+               return PTR_ERR(net);
+
        /* Check if there's an existing gtpX device to configure */
        dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK]));
        if (dev == NULL)
@@ -1085,7 +1103,7 @@ static int gtp_genl_tunnel_new(struct sk_buff *skb, 
struct genl_info *info)

 static int gtp_genl_tunnel_delete(struct sk_buff *skb, struct genl_info *info)
 {
-       struct net *net = sock_net(skb->sk);
+       struct net *net;
        struct gtp_instance *gti;
        struct net_device *dev;
        struct pdp_ctx *pctx;
@@ -1113,6 +1131,10 @@ static int gtp_genl_tunnel_delete(struct sk_buff *skb, 
struct genl_info *info)
        if (gtp_version == GTP_V1 && tid > UINT_MAX)
                return -EINVAL;

+       net = gtp_genl_get_net(sock_net(skb->sk), info->attrs);
+       if (IS_ERR(net))
+               return PTR_ERR(net);
+
        /* Check if there's an existing gtpX device to configure */
        dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK]));
        if (dev == NULL)
@@ -1181,7 +1203,7 @@ nla_put_failure:

 static int gtp_genl_tunnel_get(struct sk_buff *skb, struct genl_info *info)
 {
-       struct net *net = sock_net(skb->sk);
+       struct net *net;
        struct net_device *dev;
        struct gtp_instance *gti;
        struct pdp_ctx *pctx = NULL;
@@ -1202,6 +1224,10 @@ static int gtp_genl_tunnel_get(struct sk_buff *skb, 
struct genl_info *info)
                return -EINVAL;
        }

+       net = gtp_genl_get_net(sock_net(skb->sk), info->attrs);
+       if (IS_ERR(net))
+               return PTR_ERR(net);
+
        /* Check if there's an existing gtpX device to configure */
        dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK]));
        if (dev == NULL)
@@ -1310,6 +1336,7 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = {
        [GTPA_SGSN_ADDRESS]     = { .type = NLA_NESTED, },
        [GTPA_MS_ADDRESS]       = { .type = NLA_NESTED, },
        [GTPA_FLOW]             = { .type = NLA_U16, },
+       [GTPA_NET_NS_FD]        = { .type = NLA_U32, },
 };

 static const struct genl_ops gtp_genl_ops[] = {
diff --git a/gtp_nl.h b/gtp_nl.h
index 7bdd2f5..c20666d 100644
--- a/gtp_nl.h
+++ b/gtp_nl.h
@@ -40,6 +40,7 @@ enum gtp_attrs {
        GTPA_SGSN_ADDRESS,
        GTPA_MS_ADDRESS,
        GTPA_FLOW,
+       GTPA_NET_NS_FD,
        __GTPA_MAX,
 };
 #define GTPA_MAX (__GTPA_MAX + 1)
-- 
2.7.4

Reply via email to