[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20170124152848.6120-18-aschultz@tpip.net>
Date: Tue, 24 Jan 2017 16:28:47 +0100
From: Andreas Schultz <aschultz@...p.net>
To: Pablo Neira <pablo@...filter.org>
Cc: netdev@...r.kernel.org,
Lionel Gauthier <Lionel.Gauthier@...ecom.fr>,
openbsc@...ts.osmocom.org, Harald Welte <laforge@...monks.org>
Subject: [PATCH v2 17/18] gtp: add support to select a GTP socket during PDP context creation
Signed-off-by: Andreas Schultz <aschultz@...p.net>
---
drivers/net/gtp.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 65 insertions(+), 3 deletions(-)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index c6c1f0d..4637ce7 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -1023,6 +1023,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
struct net_device *dev;
struct net *net;
struct socket *sock;
+ int err;
if (!info->attrs[GTPA_VERSION] ||
!info->attrs[GTPA_LINK] ||
@@ -1060,11 +1061,19 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
}
put_net(net);
- sock = gtp_genl_new_pdp_select_socket(version, dev);
- if (!sock)
+ if (info->attrs[GTPA_FD])
+ sock = sockfd_lookup(nla_get_u32(info->attrs[GTPA_FD]), &err);
+ else
+ sock = gtp_genl_new_pdp_select_socket(version, dev);
+ if (!sock || !sock->sk)
return -ENODEV;
- return ipv4_pdp_add(dev, sock->sk, info);
+ err = ipv4_pdp_add(dev, sock->sk, info);
+
+ if (info->attrs[GTPA_FD])
+ sockfd_put(sock);
+
+ return err;
}
static struct pdp_ctx *gtp_genl_find_pdp_by_link(struct sk_buff *skb,
@@ -1096,11 +1105,64 @@ static struct pdp_ctx *gtp_genl_find_pdp_by_link(struct sk_buff *skb,
return ipv4_pdp_find(gtp, ms_addr);
}
+static struct pdp_ctx *gtp_genl_find_pdp_by_socket(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct socket *sock;
+ struct gtp_sock *gsk;
+ struct pdp_ctx *pctx;
+ int fd, err = 0;
+
+ if (!info->attrs[GTPA_FD])
+ return ERR_PTR(-EINVAL);
+
+ fd = nla_get_u32(info->attrs[GTPA_FD]);
+ sock = sockfd_lookup(fd, &err);
+ if (!sock) {
+ pr_debug("gtp socket fd=%d not found\n", fd);
+ return ERR_PTR(-EBADF);
+ }
+
+ gsk = rcu_dereference_sk_user_data(sock->sk);
+ if (!gsk) {
+ pctx = ERR_PTR(-EINVAL);
+ goto out_sock;
+ }
+
+ switch (nla_get_u32(info->attrs[GTPA_VERSION])) {
+ case GTP_V0:
+ if (!info->attrs[GTPA_TID]) {
+ pctx = ERR_PTR(-EINVAL);
+ break;
+ }
+ pctx = gtp0_pdp_find(gsk, nla_get_u64(info->attrs[GTPA_TID]));
+ break;
+
+ case GTP_V1:
+ if (!info->attrs[GTPA_I_TEI]) {
+ pctx = ERR_PTR(-EINVAL);
+ break;
+ }
+ pctx = gtp1_pdp_find(gsk, nla_get_u64(info->attrs[GTPA_I_TEI]));
+ break;
+
+ default:
+ pctx = ERR_PTR(-EINVAL);
+ break;
+ }
+
+out_sock:
+ sockfd_put(sock);
+ return pctx;
+}
+
static struct pdp_ctx *gtp_genl_find_pdp(struct sk_buff *skb,
struct genl_info *info)
{
if (info->attrs[GTPA_LINK])
return gtp_genl_find_pdp_by_link(skb, info);
+ else if (info->attrs[GTPA_FD])
+ return gtp_genl_find_pdp_by_socket(skb, info);
else
return ERR_PTR(-EINVAL);
}
--
2.10.2
Powered by blists - more mailing lists