Skip to content

Commit 309795f

Browse files
j-c-hdavem330
authored andcommitted
l2tp: Add netlink control API for L2TP
In L2TPv3, we need to create/delete/modify/query L2TP tunnel and session contexts. The number of parameters is significant. So let's use netlink. Userspace uses this API to control L2TP tunnel/session contexts in the kernel. The previous pppol2tp driver was managed using [gs]etsockopt(). This API is retained for backwards compatibility. Unlike L2TPv2 which carries only PPP frames, L2TPv3 can carry raw ethernet frames or other frame types and these do not always have an associated socket family. Therefore, we need a way to use L2TP sessions that doesn't require a socket type for each supported frame type. Hence netlink is used. Signed-off-by: James Chapman <jchapman@katalix.com> Reviewed-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent f408e0c commit 309795f

File tree

6 files changed

+1169
-44
lines changed

6 files changed

+1169
-44
lines changed

include/linux/l2tp.h

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#ifdef __KERNEL__
1212
#include <linux/socket.h>
1313
#include <linux/in.h>
14+
#else
15+
#include <netinet/in.h>
1416
#endif
1517

1618
#define IPPROTO_L2TP 115
@@ -21,6 +23,7 @@
2123
* @l2tp_addr: protocol specific address information
2224
* @l2tp_conn_id: connection id of tunnel
2325
*/
26+
#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
2427
struct sockaddr_l2tpip {
2528
/* The first fields must match struct sockaddr_in */
2629
sa_family_t l2tp_family; /* AF_INET */
@@ -35,4 +38,126 @@ struct sockaddr_l2tpip {
3538
sizeof(__u32)];
3639
};
3740

41+
/*****************************************************************************
42+
* NETLINK_GENERIC netlink family.
43+
*****************************************************************************/
44+
45+
/*
46+
* Commands.
47+
* Valid TLVs of each command are:-
48+
* TUNNEL_CREATE - CONN_ID, pw_type, netns, ifname, ipinfo, udpinfo, udpcsum, vlanid
49+
* TUNNEL_DELETE - CONN_ID
50+
* TUNNEL_MODIFY - CONN_ID, udpcsum
51+
* TUNNEL_GETSTATS - CONN_ID, (stats)
52+
* TUNNEL_GET - CONN_ID, (...)
53+
* SESSION_CREATE - SESSION_ID, PW_TYPE, offset, data_seq, cookie, peer_cookie, offset, l2spec
54+
* SESSION_DELETE - SESSION_ID
55+
* SESSION_MODIFY - SESSION_ID, data_seq
56+
* SESSION_GET - SESSION_ID, (...)
57+
* SESSION_GETSTATS - SESSION_ID, (stats)
58+
*
59+
*/
60+
enum {
61+
L2TP_CMD_NOOP,
62+
L2TP_CMD_TUNNEL_CREATE,
63+
L2TP_CMD_TUNNEL_DELETE,
64+
L2TP_CMD_TUNNEL_MODIFY,
65+
L2TP_CMD_TUNNEL_GET,
66+
L2TP_CMD_SESSION_CREATE,
67+
L2TP_CMD_SESSION_DELETE,
68+
L2TP_CMD_SESSION_MODIFY,
69+
L2TP_CMD_SESSION_GET,
70+
__L2TP_CMD_MAX,
71+
};
72+
73+
#define L2TP_CMD_MAX (__L2TP_CMD_MAX - 1)
74+
75+
/*
76+
* ATTR types defined for L2TP
77+
*/
78+
enum {
79+
L2TP_ATTR_NONE, /* no data */
80+
L2TP_ATTR_PW_TYPE, /* u16, enum l2tp_pwtype */
81+
L2TP_ATTR_ENCAP_TYPE, /* u16, enum l2tp_encap_type */
82+
L2TP_ATTR_OFFSET, /* u16 */
83+
L2TP_ATTR_DATA_SEQ, /* u16 */
84+
L2TP_ATTR_L2SPEC_TYPE, /* u8, enum l2tp_l2spec_type */
85+
L2TP_ATTR_L2SPEC_LEN, /* u8, enum l2tp_l2spec_type */
86+
L2TP_ATTR_PROTO_VERSION, /* u8 */
87+
L2TP_ATTR_IFNAME, /* string */
88+
L2TP_ATTR_CONN_ID, /* u32 */
89+
L2TP_ATTR_PEER_CONN_ID, /* u32 */
90+
L2TP_ATTR_SESSION_ID, /* u32 */
91+
L2TP_ATTR_PEER_SESSION_ID, /* u32 */
92+
L2TP_ATTR_UDP_CSUM, /* u8 */
93+
L2TP_ATTR_VLAN_ID, /* u16 */
94+
L2TP_ATTR_COOKIE, /* 0, 4 or 8 bytes */
95+
L2TP_ATTR_PEER_COOKIE, /* 0, 4 or 8 bytes */
96+
L2TP_ATTR_DEBUG, /* u32 */
97+
L2TP_ATTR_RECV_SEQ, /* u8 */
98+
L2TP_ATTR_SEND_SEQ, /* u8 */
99+
L2TP_ATTR_LNS_MODE, /* u8 */
100+
L2TP_ATTR_USING_IPSEC, /* u8 */
101+
L2TP_ATTR_RECV_TIMEOUT, /* msec */
102+
L2TP_ATTR_FD, /* int */
103+
L2TP_ATTR_IP_SADDR, /* u32 */
104+
L2TP_ATTR_IP_DADDR, /* u32 */
105+
L2TP_ATTR_UDP_SPORT, /* u16 */
106+
L2TP_ATTR_UDP_DPORT, /* u16 */
107+
L2TP_ATTR_MTU, /* u16 */
108+
L2TP_ATTR_MRU, /* u16 */
109+
L2TP_ATTR_STATS, /* nested */
110+
__L2TP_ATTR_MAX,
111+
};
112+
113+
#define L2TP_ATTR_MAX (__L2TP_ATTR_MAX - 1)
114+
115+
/* Nested in L2TP_ATTR_STATS */
116+
enum {
117+
L2TP_ATTR_STATS_NONE, /* no data */
118+
L2TP_ATTR_TX_PACKETS, /* u64 */
119+
L2TP_ATTR_TX_BYTES, /* u64 */
120+
L2TP_ATTR_TX_ERRORS, /* u64 */
121+
L2TP_ATTR_RX_PACKETS, /* u64 */
122+
L2TP_ATTR_RX_BYTES, /* u64 */
123+
L2TP_ATTR_RX_SEQ_DISCARDS, /* u64 */
124+
L2TP_ATTR_RX_OOS_PACKETS, /* u64 */
125+
L2TP_ATTR_RX_ERRORS, /* u64 */
126+
__L2TP_ATTR_STATS_MAX,
127+
};
128+
129+
#define L2TP_ATTR_STATS_MAX (__L2TP_ATTR_STATS_MAX - 1)
130+
131+
enum l2tp_pwtype {
132+
L2TP_PWTYPE_NONE = 0x0000,
133+
L2TP_PWTYPE_ETH_VLAN = 0x0004,
134+
L2TP_PWTYPE_ETH = 0x0005,
135+
L2TP_PWTYPE_PPP = 0x0007,
136+
L2TP_PWTYPE_PPP_AC = 0x0008,
137+
L2TP_PWTYPE_IP = 0x000b,
138+
__L2TP_PWTYPE_MAX
139+
};
140+
141+
enum l2tp_l2spec_type {
142+
L2TP_L2SPECTYPE_NONE,
143+
L2TP_L2SPECTYPE_DEFAULT,
144+
};
145+
146+
enum l2tp_encap_type {
147+
L2TP_ENCAPTYPE_UDP,
148+
L2TP_ENCAPTYPE_IP,
149+
};
150+
151+
enum l2tp_seqmode {
152+
L2TP_SEQ_NONE = 0,
153+
L2TP_SEQ_IP = 1,
154+
L2TP_SEQ_ALL = 2,
155+
};
156+
157+
/*
158+
* NETLINK_GENERIC related info
159+
*/
160+
#define L2TP_GENL_NAME "l2tp"
161+
#define L2TP_GENL_VERSION 0x1
162+
38163
#endif

net/l2tp/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ obj-$(CONFIG_L2TP) += l2tp_core.o
77
# Build l2tp as modules if L2TP is M
88
obj-$(subst y,$(CONFIG_L2TP),$(CONFIG_PPPOL2TP)) += l2tp_ppp.o
99
obj-$(subst y,$(CONFIG_L2TP),$(CONFIG_L2TP_IP)) += l2tp_ip.o
10+
obj-$(subst y,$(CONFIG_L2TP),$(CONFIG_L2TP_V3)) += l2tp_netlink.o

net/l2tp/l2tp_core.c

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include <net/dst.h>
5050
#include <net/ip.h>
5151
#include <net/udp.h>
52+
#include <net/inet_common.h>
5253
#include <net/xfrm.h>
5354
#include <net/protocol.h>
5455

@@ -214,6 +215,32 @@ struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth)
214215
}
215216
EXPORT_SYMBOL_GPL(l2tp_session_find_nth);
216217

218+
/* Lookup a session by interface name.
219+
* This is very inefficient but is only used by management interfaces.
220+
*/
221+
struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname)
222+
{
223+
struct l2tp_net *pn = l2tp_pernet(net);
224+
int hash;
225+
struct hlist_node *walk;
226+
struct l2tp_session *session;
227+
228+
read_lock_bh(&pn->l2tp_session_hlist_lock);
229+
for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) {
230+
hlist_for_each_entry(session, walk, &pn->l2tp_session_hlist[hash], global_hlist) {
231+
if (!strcmp(session->ifname, ifname)) {
232+
read_unlock_bh(&pn->l2tp_session_hlist_lock);
233+
return session;
234+
}
235+
}
236+
}
237+
238+
read_unlock_bh(&pn->l2tp_session_hlist_lock);
239+
240+
return NULL;
241+
}
242+
EXPORT_SYMBOL_GPL(l2tp_session_find_by_ifname);
243+
217244
/* Lookup a tunnel by id
218245
*/
219246
struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id)
@@ -758,7 +785,7 @@ int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
758785

759786
/* Find the session context */
760787
session = l2tp_session_find(tunnel->l2tp_net, tunnel, session_id);
761-
if (!session) {
788+
if (!session || !session->recv_skb) {
762789
/* Not found? Pass to userspace to deal with */
763790
PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO,
764791
"%s: no session found (%u/%u). Passing up.\n",
@@ -1305,6 +1332,23 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
13051332
}
13061333
EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
13071334

1335+
/* This function is used by the netlink TUNNEL_DELETE command.
1336+
*/
1337+
int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
1338+
{
1339+
int err = 0;
1340+
1341+
/* Force the tunnel socket to close. This will eventually
1342+
* cause the tunnel to be deleted via the normal socket close
1343+
* mechanisms when userspace closes the tunnel socket.
1344+
*/
1345+
if ((tunnel->sock != NULL) && (tunnel->sock->sk_socket != NULL))
1346+
err = inet_shutdown(tunnel->sock->sk_socket, 2);
1347+
1348+
return err;
1349+
}
1350+
EXPORT_SYMBOL_GPL(l2tp_tunnel_delete);
1351+
13081352
/* Really kill the session.
13091353
*/
13101354
void l2tp_session_free(struct l2tp_session *session)
@@ -1349,6 +1393,21 @@ void l2tp_session_free(struct l2tp_session *session)
13491393
}
13501394
EXPORT_SYMBOL_GPL(l2tp_session_free);
13511395

1396+
/* This function is used by the netlink SESSION_DELETE command and by
1397+
pseudowire modules.
1398+
*/
1399+
int l2tp_session_delete(struct l2tp_session *session)
1400+
{
1401+
if (session->session_close != NULL)
1402+
(*session->session_close)(session);
1403+
1404+
l2tp_session_dec_refcount(session);
1405+
1406+
return 0;
1407+
}
1408+
EXPORT_SYMBOL_GPL(l2tp_session_delete);
1409+
1410+
13521411
/* We come here whenever a session's send_seq, cookie_len or
13531412
* l2specific_len parameters are set.
13541413
*/

net/l2tp/l2tp_core.h

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,6 @@ enum {
3333
L2TP_MSG_DATA = (1 << 3), /* data packets */
3434
};
3535

36-
enum l2tp_pwtype {
37-
L2TP_PWTYPE_NONE = 0x0000,
38-
L2TP_PWTYPE_ETH_VLAN = 0x0004,
39-
L2TP_PWTYPE_ETH = 0x0005,
40-
L2TP_PWTYPE_PPP = 0x0007,
41-
L2TP_PWTYPE_PPP_AC = 0x0008,
42-
L2TP_PWTYPE_IP = 0x000b,
43-
__L2TP_PWTYPE_MAX
44-
};
45-
46-
enum l2tp_l2spec_type {
47-
L2TP_L2SPECTYPE_NONE,
48-
L2TP_L2SPECTYPE_DEFAULT,
49-
};
50-
51-
enum l2tp_encap_type {
52-
L2TP_ENCAPTYPE_UDP,
53-
L2TP_ENCAPTYPE_IP,
54-
};
55-
5636
struct sk_buff;
5737

5838
struct l2tp_stats {
@@ -87,6 +67,7 @@ struct l2tp_session_cfg {
8767
* control of LNS. */
8868
int debug; /* bitmask of debug message
8969
* categories */
70+
u16 vlan_id; /* VLAN pseudowire only */
9071
u16 offset; /* offset to payload */
9172
u16 l2specific_len; /* Layer 2 specific length */
9273
u16 l2specific_type; /* Layer 2 specific type */
@@ -98,6 +79,7 @@ struct l2tp_session_cfg {
9879
* (in jiffies) */
9980
int mtu;
10081
int mru;
82+
char *ifname;
10183
};
10284

10385
struct l2tp_session {
@@ -124,6 +106,7 @@ struct l2tp_session {
124106
atomic_t ref_count;
125107

126108
char name[32]; /* for logging */
109+
char ifname[IFNAMSIZ];
127110
unsigned data_seq:2; /* data sequencing level
128111
* 0 => none, 1 => IP only,
129112
* 2 => all
@@ -192,6 +175,11 @@ struct l2tp_tunnel {
192175
uint8_t priv[0]; /* private data */
193176
};
194177

178+
struct l2tp_nl_cmd_ops {
179+
int (*session_create)(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg);
180+
int (*session_delete)(struct l2tp_session *session);
181+
};
182+
195183
static inline void *l2tp_tunnel_priv(struct l2tp_tunnel *tunnel)
196184
{
197185
return &tunnel->priv[0];
@@ -224,11 +212,14 @@ static inline struct l2tp_tunnel *l2tp_sock_to_tunnel(struct sock *sk)
224212

225213
extern struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id);
226214
extern struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth);
215+
extern struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname);
227216
extern struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id);
228217
extern struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth);
229218

230219
extern 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);
220+
extern int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel);
231221
extern struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg);
222+
extern int l2tp_session_delete(struct l2tp_session *session);
232223
extern void l2tp_tunnel_free(struct l2tp_tunnel *tunnel);
233224
extern void l2tp_session_free(struct l2tp_session *session);
234225
extern void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, unsigned char *ptr, unsigned char *optr, u16 hdrflags, int length, int (*payload_hook)(struct sk_buff *skb));
@@ -241,6 +232,9 @@ extern void l2tp_tunnel_destruct(struct sock *sk);
241232
extern void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel);
242233
extern void l2tp_session_set_header_len(struct l2tp_session *session, int version);
243234

235+
extern int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops);
236+
extern void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type);
237+
244238
/* Tunnel reference counts. Incremented per session that is added to
245239
* the tunnel.
246240
*/

0 commit comments

Comments
 (0)