From: James Chapman <jchapman@katalix.com>
To: netdev@vger.kernel.org
Subject: [PATCH v3 11/12] l2tp: Add support for static unmanaged L2TPv3 tunnels
Date: Tue, 30 Mar 2010 17:18:24 +0100 [thread overview]
Message-ID: <20100330161824.9628.87415.stgit@bert.katalix.com> (raw)
In-Reply-To: <20100330161725.9628.69994.stgit@bert.katalix.com>
This patch adds support for static (unmanaged) L2TPv3 tunnels, where
the tunnel socket is created by the kernel rather than being created
by userspace. This means L2TP tunnels and sessions can be created
manually, without needing an L2TP control protocol implemented in
userspace. This might be useful where the user wants a simple ethernet
over IP tunnel.
A patch to iproute2 adds a new command set under "ip l2tp" to make use
of this feature. This will be submitted separately.
Signed-off-by: James Chapman <jchapman@katalix.com>
Reviewed-by: Randy Dunlap <randy.dunlap@oracle.com>
---
net/l2tp/l2tp_core.c | 115 +++++++++++++++++++++++++++++++++++++++++++----
net/l2tp/l2tp_core.h | 7 +++
net/l2tp/l2tp_netlink.c | 18 ++++++-
3 files changed, 126 insertions(+), 14 deletions(-)
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 1dd9dc7..994e1d2 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1256,6 +1256,82 @@ void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
}
EXPORT_SYMBOL_GPL(l2tp_tunnel_free);
+/* Create a socket for the tunnel, if one isn't set up by
+ * userspace. This is used for static tunnels where there is no
+ * managing L2TP daemon.
+ */
+static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct socket **sockp)
+{
+ int err = -EINVAL;
+ struct sockaddr_in udp_addr;
+ struct sockaddr_l2tpip ip_addr;
+ struct socket *sock;
+
+ switch (cfg->encap) {
+ case L2TP_ENCAPTYPE_UDP:
+ err = sock_create(AF_INET, SOCK_DGRAM, 0, sockp);
+ if (err < 0)
+ goto out;
+
+ sock = *sockp;
+
+ memset(&udp_addr, 0, sizeof(udp_addr));
+ udp_addr.sin_family = AF_INET;
+ udp_addr.sin_addr = cfg->local_ip;
+ udp_addr.sin_port = htons(cfg->local_udp_port);
+ err = kernel_bind(sock, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
+ if (err < 0)
+ goto out;
+
+ udp_addr.sin_family = AF_INET;
+ udp_addr.sin_addr = cfg->peer_ip;
+ udp_addr.sin_port = htons(cfg->peer_udp_port);
+ err = kernel_connect(sock, (struct sockaddr *) &udp_addr, sizeof(udp_addr), 0);
+ if (err < 0)
+ goto out;
+
+ if (!cfg->use_udp_checksums)
+ sock->sk->sk_no_check = UDP_CSUM_NOXMIT;
+
+ break;
+
+ case L2TP_ENCAPTYPE_IP:
+ err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, sockp);
+ if (err < 0)
+ goto out;
+
+ sock = *sockp;
+
+ memset(&ip_addr, 0, sizeof(ip_addr));
+ ip_addr.l2tp_family = AF_INET;
+ ip_addr.l2tp_addr = cfg->local_ip;
+ ip_addr.l2tp_conn_id = tunnel_id;
+ err = kernel_bind(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr));
+ if (err < 0)
+ goto out;
+
+ ip_addr.l2tp_family = AF_INET;
+ ip_addr.l2tp_addr = cfg->peer_ip;
+ ip_addr.l2tp_conn_id = peer_tunnel_id;
+ err = kernel_connect(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr), 0);
+ if (err < 0)
+ goto out;
+
+ break;
+
+ default:
+ goto out;
+ }
+
+out:
+ if ((err < 0) && sock) {
+ sock_release(sock);
+ *sockp = NULL;
+ }
+
+ return err;
+}
+
int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp)
{
struct l2tp_tunnel *tunnel = NULL;
@@ -1266,14 +1342,21 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP;
/* Get the tunnel socket from the fd, which was opened by
- * the userspace L2TP daemon.
+ * the userspace L2TP daemon. If not specified, create a
+ * kernel socket.
*/
- err = -EBADF;
- sock = sockfd_lookup(fd, &err);
- if (!sock) {
- printk(KERN_ERR "tunl %hu: sockfd_lookup(fd=%d) returned %d\n",
- tunnel_id, fd, err);
- goto err;
+ if (fd < 0) {
+ err = l2tp_tunnel_sock_create(tunnel_id, peer_tunnel_id, cfg, &sock);
+ if (err < 0)
+ goto err;
+ } else {
+ err = -EBADF;
+ sock = sockfd_lookup(fd, &err);
+ if (!sock) {
+ printk(KERN_ERR "tunl %hu: sockfd_lookup(fd=%d) returned %d\n",
+ tunnel_id, fd, err);
+ goto err;
+ }
}
sk = sock->sk;
@@ -1366,7 +1449,10 @@ err:
if (tunnelp)
*tunnelp = tunnel;
- if (sock)
+ /* If tunnel's socket was created by the kernel, it doesn't
+ * have a file.
+ */
+ if (sock && sock->file)
sockfd_put(sock);
return err;
@@ -1378,13 +1464,22 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
{
int err = 0;
+ struct socket *sock = tunnel->sock ? tunnel->sock->sk_socket : NULL;
/* Force the tunnel socket to close. This will eventually
* cause the tunnel to be deleted via the normal socket close
* mechanisms when userspace closes the tunnel socket.
*/
- if ((tunnel->sock != NULL) && (tunnel->sock->sk_socket != NULL))
- err = inet_shutdown(tunnel->sock->sk_socket, 2);
+ if (sock != NULL) {
+ err = inet_shutdown(sock, 2);
+
+ /* If the tunnel's socket was created by the kernel,
+ * close the socket here since the socket was not
+ * created by userspace.
+ */
+ if (sock->file == NULL)
+ err = inet_release(sock);
+ }
return err;
}
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index c5f2cc9..7e3387b 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -146,6 +146,13 @@ struct l2tp_tunnel_cfg {
int debug; /* bitmask of debug message
* categories */
enum l2tp_encap_type encap;
+
+ /* Used only for kernel-created sockets */
+ struct in_addr local_ip;
+ struct in_addr peer_ip;
+ u16 local_udp_port;
+ u16 peer_udp_port;
+ int use_udp_checksums:1;
};
struct l2tp_tunnel {
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index e051c13..115ea01 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -129,11 +129,21 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info
}
cfg.encap = nla_get_u16(info->attrs[L2TP_ATTR_ENCAP_TYPE]);
- if (!info->attrs[L2TP_ATTR_FD]) {
- ret = -EINVAL;
- goto out;
+ fd = -1;
+ if (info->attrs[L2TP_ATTR_FD]) {
+ fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]);
+ } else {
+ if (info->attrs[L2TP_ATTR_IP_SADDR])
+ cfg.local_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_SADDR]);
+ if (info->attrs[L2TP_ATTR_IP_DADDR])
+ cfg.peer_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_DADDR]);
+ if (info->attrs[L2TP_ATTR_UDP_SPORT])
+ cfg.local_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_SPORT]);
+ if (info->attrs[L2TP_ATTR_UDP_DPORT])
+ cfg.peer_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_DPORT]);
+ if (info->attrs[L2TP_ATTR_UDP_CSUM])
+ cfg.use_udp_checksums = nla_get_flag(info->attrs[L2TP_ATTR_UDP_CSUM]);
}
- fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]);
if (info->attrs[L2TP_ATTR_DEBUG])
cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);
next prev parent reply other threads:[~2010-03-30 16:18 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-03-30 16:17 [PATCH v3 00/12] l2tp: Introduce L2TPv3 support James Chapman
2010-03-30 16:17 ` [PATCH v3 01/12] l2tp: Relocate pppol2tp driver to new net/l2tp directory James Chapman
2010-03-30 16:17 ` [PATCH v3 02/12] l2tp: Split pppol2tp patch into separate l2tp and ppp parts James Chapman
2010-03-30 16:17 ` [PATCH v3 03/12] ppp: Add ppp_dev_name() exported function James Chapman
2010-03-30 16:17 ` [PATCH v3 04/12] l2tp: Add ppp device name to L2TP ppp session data James Chapman
2010-03-30 16:29 ` Stephen Hemminger
2010-03-31 7:43 ` James Chapman
2010-03-31 8:46 ` David Miller
2010-03-31 23:08 ` Stephen Hemminger
2010-04-01 7:19 ` James Chapman
2010-04-01 7:30 ` Eric Dumazet
2010-04-01 8:55 ` James Chapman
2010-04-01 7:34 ` David Miller
2010-04-01 8:59 ` James Chapman
2010-04-01 9:04 ` David Miller
2010-03-30 16:17 ` [PATCH v3 05/12] l2tp: Add L2TPv3 protocol support James Chapman
2010-03-30 16:17 ` [PATCH v3 06/12] l2tp: Update PPP-over-L2TP driver to work over L2TPv3 James Chapman
2010-03-30 16:18 ` [PATCH v3 07/12] l2tp: Add L2TPv3 IP encapsulation (no UDP) support James Chapman
2010-03-30 16:18 ` [PATCH v3 08/12] netlink: Export genl_lock() API for use by modules James Chapman
2010-03-30 16:18 ` [PATCH v3 09/12] l2tp: Add netlink control API for L2TP James Chapman
2010-03-31 8:59 ` Patrick McHardy
2010-03-30 16:18 ` [PATCH v3 10/12] l2tp: Add L2TP ethernet pseudowire support James Chapman
2010-03-30 16:30 ` Stephen Hemminger
2010-03-30 16:30 ` Stephen Hemminger
2010-03-30 16:32 ` Stephen Hemminger
2010-03-31 9:35 ` James Chapman
2010-03-31 17:38 ` Paul E. McKenney
2010-04-02 15:24 ` Paul E. McKenney
2010-04-02 15:58 ` Eric Dumazet
2010-04-02 16:21 ` Paul E. McKenney
2010-03-30 16:18 ` James Chapman [this message]
2010-03-30 16:18 ` [PATCH v3 12/12] l2tp: Update documentation James Chapman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100330161824.9628.87415.stgit@bert.katalix.com \
--to=jchapman@katalix.com \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).