xref: /openbmc/linux/net/l2tp/l2tp_core.c (revision 4781a75d)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
220dcb110STom Parkin /* L2TP core.
3fd558d18SJames Chapman  *
4fd558d18SJames Chapman  * Copyright (c) 2008,2009,2010 Katalix Systems Ltd
5fd558d18SJames Chapman  *
6fd558d18SJames Chapman  * This file contains some code of the original L2TPv2 pppol2tp
7fd558d18SJames Chapman  * driver, which has the following copyright:
8fd558d18SJames Chapman  *
9fd558d18SJames Chapman  * Authors:	Martijn van Oosterhout <kleptog@svana.org>
10fd558d18SJames Chapman  *		James Chapman (jchapman@katalix.com)
11fd558d18SJames Chapman  * Contributors:
12fd558d18SJames Chapman  *		Michal Ostrowski <mostrows@speakeasy.net>
13fd558d18SJames Chapman  *		Arnaldo Carvalho de Melo <acme@xconectiva.com.br>
14fd558d18SJames Chapman  *		David S. Miller (davem@redhat.com)
15fd558d18SJames Chapman  */
16fd558d18SJames Chapman 
17a4ca44faSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18a4ca44faSJoe Perches 
19fd558d18SJames Chapman #include <linux/module.h>
20fd558d18SJames Chapman #include <linux/string.h>
21fd558d18SJames Chapman #include <linux/list.h>
22e02d494dSJames Chapman #include <linux/rculist.h>
23fd558d18SJames Chapman #include <linux/uaccess.h>
24fd558d18SJames Chapman 
25fd558d18SJames Chapman #include <linux/kernel.h>
26fd558d18SJames Chapman #include <linux/spinlock.h>
27fd558d18SJames Chapman #include <linux/kthread.h>
28fd558d18SJames Chapman #include <linux/sched.h>
29fd558d18SJames Chapman #include <linux/slab.h>
30fd558d18SJames Chapman #include <linux/errno.h>
31fd558d18SJames Chapman #include <linux/jiffies.h>
32fd558d18SJames Chapman 
33fd558d18SJames Chapman #include <linux/netdevice.h>
34fd558d18SJames Chapman #include <linux/net.h>
35fd558d18SJames Chapman #include <linux/inetdevice.h>
36fd558d18SJames Chapman #include <linux/skbuff.h>
37fd558d18SJames Chapman #include <linux/init.h>
380d76751fSJames Chapman #include <linux/in.h>
39fd558d18SJames Chapman #include <linux/ip.h>
40fd558d18SJames Chapman #include <linux/udp.h>
410d76751fSJames Chapman #include <linux/l2tp.h>
42fd558d18SJames Chapman #include <linux/hash.h>
43fd558d18SJames Chapman #include <linux/sort.h>
44fd558d18SJames Chapman #include <linux/file.h>
45fd558d18SJames Chapman #include <linux/nsproxy.h>
46fd558d18SJames Chapman #include <net/net_namespace.h>
47fd558d18SJames Chapman #include <net/netns/generic.h>
48fd558d18SJames Chapman #include <net/dst.h>
49fd558d18SJames Chapman #include <net/ip.h>
50fd558d18SJames Chapman #include <net/udp.h>
5185644b4dSTom Herbert #include <net/udp_tunnel.h>
52309795f4SJames Chapman #include <net/inet_common.h>
53fd558d18SJames Chapman #include <net/xfrm.h>
540d76751fSJames Chapman #include <net/protocol.h>
55d2cf3361SBenjamin LaHaise #include <net/inet6_connection_sock.h>
56d2cf3361SBenjamin LaHaise #include <net/inet_ecn.h>
57d2cf3361SBenjamin LaHaise #include <net/ip6_route.h>
58d499bd2eSDavid S. Miller #include <net/ip6_checksum.h>
59fd558d18SJames Chapman 
60fd558d18SJames Chapman #include <asm/byteorder.h>
6160063497SArun Sharma #include <linux/atomic.h>
62fd558d18SJames Chapman 
63fd558d18SJames Chapman #include "l2tp_core.h"
646b7bdcd7STom Parkin #include "trace.h"
65fd558d18SJames Chapman 
663f117d6fSTom Parkin #define CREATE_TRACE_POINTS
673f117d6fSTom Parkin #include "trace.h"
683f117d6fSTom Parkin 
69fd558d18SJames Chapman #define L2TP_DRV_VERSION	"V2.0"
70fd558d18SJames Chapman 
71fd558d18SJames Chapman /* L2TP header constants */
72fd558d18SJames Chapman #define L2TP_HDRFLAG_T	   0x8000
73fd558d18SJames Chapman #define L2TP_HDRFLAG_L	   0x4000
74fd558d18SJames Chapman #define L2TP_HDRFLAG_S	   0x0800
75fd558d18SJames Chapman #define L2TP_HDRFLAG_O	   0x0200
76fd558d18SJames Chapman #define L2TP_HDRFLAG_P	   0x0100
77fd558d18SJames Chapman 
78fd558d18SJames Chapman #define L2TP_HDR_VER_MASK  0x000F
79fd558d18SJames Chapman #define L2TP_HDR_VER_2	   0x0002
80f7faffa3SJames Chapman #define L2TP_HDR_VER_3	   0x0003
81fd558d18SJames Chapman 
82fd558d18SJames Chapman /* L2TPv3 default L2-specific sublayer */
83fd558d18SJames Chapman #define L2TP_SLFLAG_S	   0x40000000
84fd558d18SJames Chapman #define L2TP_SL_SEQ_MASK   0x00ffffff
85fd558d18SJames Chapman 
8691c52470SJacob Wen #define L2TP_HDR_SIZE_MAX		14
87fd558d18SJames Chapman 
88fd558d18SJames Chapman /* Default trace flags */
89fd558d18SJames Chapman #define L2TP_DEFAULT_DEBUG_FLAGS	0
90fd558d18SJames Chapman 
91fd558d18SJames Chapman /* Private data stored for received packets in the skb.
92fd558d18SJames Chapman  */
93fd558d18SJames Chapman struct l2tp_skb_cb {
94f7faffa3SJames Chapman 	u32			ns;
95fd558d18SJames Chapman 	u16			has_seq;
96fd558d18SJames Chapman 	u16			length;
97fd558d18SJames Chapman 	unsigned long		expires;
98fd558d18SJames Chapman };
99fd558d18SJames Chapman 
100efcd8c85STom Parkin #define L2TP_SKB_CB(skb)	((struct l2tp_skb_cb *)&(skb)->cb[sizeof(struct inet_skb_parm)])
101fd558d18SJames Chapman 
102f8ccac0eSTom Parkin static struct workqueue_struct *l2tp_wq;
103fd558d18SJames Chapman 
104fd558d18SJames Chapman /* per-net private data for this module */
105fd558d18SJames Chapman static unsigned int l2tp_net_id;
106fd558d18SJames Chapman struct l2tp_net {
107c4d48a58SCong Wang 	/* Lock for write access to l2tp_tunnel_idr */
108c4d48a58SCong Wang 	spinlock_t l2tp_tunnel_idr_lock;
109c4d48a58SCong Wang 	struct idr l2tp_tunnel_idr;
110f7faffa3SJames Chapman 	struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2];
11120dcb110STom Parkin 	/* Lock for write access to l2tp_session_hlist */
112e02d494dSJames Chapman 	spinlock_t l2tp_session_hlist_lock;
113fd558d18SJames Chapman };
114fd558d18SJames Chapman 
115b954f940SPaolo Abeni #if IS_ENABLED(CONFIG_IPV6)
l2tp_sk_is_v6(struct sock * sk)116b954f940SPaolo Abeni static bool l2tp_sk_is_v6(struct sock *sk)
117b954f940SPaolo Abeni {
118b954f940SPaolo Abeni 	return sk->sk_family == PF_INET6 &&
119b954f940SPaolo Abeni 	       !ipv6_addr_v4mapped(&sk->sk_v6_daddr);
120b954f940SPaolo Abeni }
121b954f940SPaolo Abeni #endif
122fc130840Sstephen hemminger 
l2tp_pernet(const struct net * net)1239aaef50cSGuillaume Nault static inline struct l2tp_net *l2tp_pernet(const struct net *net)
124fd558d18SJames Chapman {
125fd558d18SJames Chapman 	return net_generic(net, l2tp_net_id);
126fd558d18SJames Chapman }
127fd558d18SJames Chapman 
128f7faffa3SJames Chapman /* Session hash global list for L2TPv3.
129f7faffa3SJames Chapman  * The session_id SHOULD be random according to RFC3931, but several
130f7faffa3SJames Chapman  * L2TP implementations use incrementing session_ids.  So we do a real
131f7faffa3SJames Chapman  * hash on the session_id, rather than a simple bitmask.
132f7faffa3SJames Chapman  */
133f7faffa3SJames Chapman static inline struct hlist_head *
l2tp_session_id_hash_2(struct l2tp_net * pn,u32 session_id)134f7faffa3SJames Chapman l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id)
135f7faffa3SJames Chapman {
136f7faffa3SJames Chapman 	return &pn->l2tp_session_hlist[hash_32(session_id, L2TP_HASH_BITS_2)];
137f7faffa3SJames Chapman }
138f7faffa3SJames Chapman 
139fd558d18SJames Chapman /* Session hash list.
140fd558d18SJames Chapman  * The session_id SHOULD be random according to RFC2661, but several
141fd558d18SJames Chapman  * L2TP implementations (Cisco and Microsoft) use incrementing
142fd558d18SJames Chapman  * session_ids.  So we do a real hash on the session_id, rather than a
143fd558d18SJames Chapman  * simple bitmask.
144fd558d18SJames Chapman  */
145fd558d18SJames Chapman static inline struct hlist_head *
l2tp_session_id_hash(struct l2tp_tunnel * tunnel,u32 session_id)146fd558d18SJames Chapman l2tp_session_id_hash(struct l2tp_tunnel *tunnel, u32 session_id)
147fd558d18SJames Chapman {
148fd558d18SJames Chapman 	return &tunnel->session_hlist[hash_32(session_id, L2TP_HASH_BITS)];
149fd558d18SJames Chapman }
150fd558d18SJames Chapman 
l2tp_tunnel_free(struct l2tp_tunnel * tunnel)15152016e25STom Parkin static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
152d00fa9adSJames Chapman {
1536b7bdcd7STom Parkin 	trace_free_tunnel(tunnel);
154d00fa9adSJames Chapman 	sock_put(tunnel->sock);
155d00fa9adSJames Chapman 	/* the tunnel is freed in the socket destructor */
156d00fa9adSJames Chapman }
15752016e25STom Parkin 
l2tp_session_free(struct l2tp_session * session)15852016e25STom Parkin static void l2tp_session_free(struct l2tp_session *session)
15952016e25STom Parkin {
1606b7bdcd7STom Parkin 	trace_free_session(session);
16145faeff1STom Parkin 	if (session->tunnel)
16245faeff1STom Parkin 		l2tp_tunnel_dec_refcount(session->tunnel);
16352016e25STom Parkin 	kfree(session);
16452016e25STom Parkin }
16552016e25STom Parkin 
l2tp_sk_to_tunnel(struct sock * sk)16645faeff1STom Parkin struct l2tp_tunnel *l2tp_sk_to_tunnel(struct sock *sk)
16745faeff1STom Parkin {
16845faeff1STom Parkin 	struct l2tp_tunnel *tunnel = sk->sk_user_data;
16945faeff1STom Parkin 
17045faeff1STom Parkin 	if (tunnel)
17145faeff1STom Parkin 		if (WARN_ON(tunnel->magic != L2TP_TUNNEL_MAGIC))
17245faeff1STom Parkin 			return NULL;
17345faeff1STom Parkin 
17445faeff1STom Parkin 	return tunnel;
17545faeff1STom Parkin }
17645faeff1STom Parkin EXPORT_SYMBOL_GPL(l2tp_sk_to_tunnel);
17745faeff1STom Parkin 
l2tp_tunnel_inc_refcount(struct l2tp_tunnel * tunnel)17852016e25STom Parkin void l2tp_tunnel_inc_refcount(struct l2tp_tunnel *tunnel)
17952016e25STom Parkin {
18052016e25STom Parkin 	refcount_inc(&tunnel->ref_count);
18152016e25STom Parkin }
18252016e25STom Parkin EXPORT_SYMBOL_GPL(l2tp_tunnel_inc_refcount);
18352016e25STom Parkin 
l2tp_tunnel_dec_refcount(struct l2tp_tunnel * tunnel)18452016e25STom Parkin void l2tp_tunnel_dec_refcount(struct l2tp_tunnel *tunnel)
18552016e25STom Parkin {
18652016e25STom Parkin 	if (refcount_dec_and_test(&tunnel->ref_count))
18752016e25STom Parkin 		l2tp_tunnel_free(tunnel);
18852016e25STom Parkin }
18952016e25STom Parkin EXPORT_SYMBOL_GPL(l2tp_tunnel_dec_refcount);
19052016e25STom Parkin 
l2tp_session_inc_refcount(struct l2tp_session * session)19152016e25STom Parkin void l2tp_session_inc_refcount(struct l2tp_session *session)
19252016e25STom Parkin {
19352016e25STom Parkin 	refcount_inc(&session->ref_count);
19452016e25STom Parkin }
19552016e25STom Parkin EXPORT_SYMBOL_GPL(l2tp_session_inc_refcount);
19652016e25STom Parkin 
l2tp_session_dec_refcount(struct l2tp_session * session)19752016e25STom Parkin void l2tp_session_dec_refcount(struct l2tp_session *session)
19852016e25STom Parkin {
19952016e25STom Parkin 	if (refcount_dec_and_test(&session->ref_count))
20052016e25STom Parkin 		l2tp_session_free(session);
20152016e25STom Parkin }
20252016e25STom Parkin EXPORT_SYMBOL_GPL(l2tp_session_dec_refcount);
203d00fa9adSJames Chapman 
20454652eb1SGuillaume Nault /* Lookup a tunnel. A new reference is held on the returned tunnel. */
l2tp_tunnel_get(const struct net * net,u32 tunnel_id)20554652eb1SGuillaume Nault struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, u32 tunnel_id)
20654652eb1SGuillaume Nault {
20754652eb1SGuillaume Nault 	const struct l2tp_net *pn = l2tp_pernet(net);
20854652eb1SGuillaume Nault 	struct l2tp_tunnel *tunnel;
20954652eb1SGuillaume Nault 
21054652eb1SGuillaume Nault 	rcu_read_lock_bh();
211c4d48a58SCong Wang 	tunnel = idr_find(&pn->l2tp_tunnel_idr, tunnel_id);
212c4d48a58SCong Wang 	if (tunnel && refcount_inc_not_zero(&tunnel->ref_count)) {
21354652eb1SGuillaume Nault 		rcu_read_unlock_bh();
21454652eb1SGuillaume Nault 		return tunnel;
21554652eb1SGuillaume Nault 	}
21654652eb1SGuillaume Nault 	rcu_read_unlock_bh();
21754652eb1SGuillaume Nault 
21854652eb1SGuillaume Nault 	return NULL;
21954652eb1SGuillaume Nault }
22054652eb1SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_tunnel_get);
22154652eb1SGuillaume Nault 
l2tp_tunnel_get_nth(const struct net * net,int nth)2225846c131SGuillaume Nault struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth)
2235846c131SGuillaume Nault {
224c4d48a58SCong Wang 	struct l2tp_net *pn = l2tp_pernet(net);
225c4d48a58SCong Wang 	unsigned long tunnel_id, tmp;
2265846c131SGuillaume Nault 	struct l2tp_tunnel *tunnel;
2275846c131SGuillaume Nault 	int count = 0;
2285846c131SGuillaume Nault 
2295846c131SGuillaume Nault 	rcu_read_lock_bh();
230c4d48a58SCong Wang 	idr_for_each_entry_ul(&pn->l2tp_tunnel_idr, tunnel, tmp, tunnel_id) {
231c4d48a58SCong Wang 		if (tunnel && ++count > nth &&
232a622b400SEric Dumazet 		    refcount_inc_not_zero(&tunnel->ref_count)) {
2335846c131SGuillaume Nault 			rcu_read_unlock_bh();
2345846c131SGuillaume Nault 			return tunnel;
2355846c131SGuillaume Nault 		}
2365846c131SGuillaume Nault 	}
2375846c131SGuillaume Nault 	rcu_read_unlock_bh();
2385846c131SGuillaume Nault 
2395846c131SGuillaume Nault 	return NULL;
2405846c131SGuillaume Nault }
2415846c131SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_tunnel_get_nth);
2425846c131SGuillaume Nault 
l2tp_tunnel_get_session(struct l2tp_tunnel * tunnel,u32 session_id)24301e28b92SGuillaume Nault struct l2tp_session *l2tp_tunnel_get_session(struct l2tp_tunnel *tunnel,
244a4346210SGuillaume Nault 					     u32 session_id)
24561b9a047SGuillaume Nault {
24661b9a047SGuillaume Nault 	struct hlist_head *session_list;
24761b9a047SGuillaume Nault 	struct l2tp_session *session;
24861b9a047SGuillaume Nault 
24901e28b92SGuillaume Nault 	session_list = l2tp_session_id_hash(tunnel, session_id);
25061b9a047SGuillaume Nault 
25107b8ca37STom Parkin 	rcu_read_lock_bh();
25207b8ca37STom Parkin 	hlist_for_each_entry_rcu(session, session_list, hlist)
25361b9a047SGuillaume Nault 		if (session->session_id == session_id) {
25461b9a047SGuillaume Nault 			l2tp_session_inc_refcount(session);
25507b8ca37STom Parkin 			rcu_read_unlock_bh();
25661b9a047SGuillaume Nault 
25761b9a047SGuillaume Nault 			return session;
25861b9a047SGuillaume Nault 		}
25907b8ca37STom Parkin 	rcu_read_unlock_bh();
26061b9a047SGuillaume Nault 
26161b9a047SGuillaume Nault 	return NULL;
26261b9a047SGuillaume Nault }
26301e28b92SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_tunnel_get_session);
26461b9a047SGuillaume Nault 
l2tp_session_get(const struct net * net,u32 session_id)26501e28b92SGuillaume Nault struct l2tp_session *l2tp_session_get(const struct net *net, u32 session_id)
26601e28b92SGuillaume Nault {
26701e28b92SGuillaume Nault 	struct hlist_head *session_list;
26801e28b92SGuillaume Nault 	struct l2tp_session *session;
26901e28b92SGuillaume Nault 
27001e28b92SGuillaume Nault 	session_list = l2tp_session_id_hash_2(l2tp_pernet(net), session_id);
27101e28b92SGuillaume Nault 
27201e28b92SGuillaume Nault 	rcu_read_lock_bh();
27301e28b92SGuillaume Nault 	hlist_for_each_entry_rcu(session, session_list, global_hlist)
27461b9a047SGuillaume Nault 		if (session->session_id == session_id) {
27561b9a047SGuillaume Nault 			l2tp_session_inc_refcount(session);
27601e28b92SGuillaume Nault 			rcu_read_unlock_bh();
27761b9a047SGuillaume Nault 
27861b9a047SGuillaume Nault 			return session;
27961b9a047SGuillaume Nault 		}
28001e28b92SGuillaume Nault 	rcu_read_unlock_bh();
28161b9a047SGuillaume Nault 
28261b9a047SGuillaume Nault 	return NULL;
28361b9a047SGuillaume Nault }
28461b9a047SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_get);
28561b9a047SGuillaume Nault 
l2tp_session_get_nth(struct l2tp_tunnel * tunnel,int nth)286a4346210SGuillaume Nault struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth)
287fd558d18SJames Chapman {
288fd558d18SJames Chapman 	int hash;
289fd558d18SJames Chapman 	struct l2tp_session *session;
290fd558d18SJames Chapman 	int count = 0;
291fd558d18SJames Chapman 
29207b8ca37STom Parkin 	rcu_read_lock_bh();
293fd558d18SJames Chapman 	for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
29407b8ca37STom Parkin 		hlist_for_each_entry_rcu(session, &tunnel->session_hlist[hash], hlist) {
295fd558d18SJames Chapman 			if (++count > nth) {
296e08293a4SGuillaume Nault 				l2tp_session_inc_refcount(session);
29707b8ca37STom Parkin 				rcu_read_unlock_bh();
298fd558d18SJames Chapman 				return session;
299fd558d18SJames Chapman 			}
300fd558d18SJames Chapman 		}
301fd558d18SJames Chapman 	}
302fd558d18SJames Chapman 
30307b8ca37STom Parkin 	rcu_read_unlock_bh();
304fd558d18SJames Chapman 
305fd558d18SJames Chapman 	return NULL;
306fd558d18SJames Chapman }
307e08293a4SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_get_nth);
308fd558d18SJames Chapman 
309309795f4SJames Chapman /* Lookup a session by interface name.
310309795f4SJames Chapman  * This is very inefficient but is only used by management interfaces.
311309795f4SJames Chapman  */
l2tp_session_get_by_ifname(const struct net * net,const char * ifname)3129aaef50cSGuillaume Nault struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net,
313a4346210SGuillaume Nault 						const char *ifname)
314309795f4SJames Chapman {
315309795f4SJames Chapman 	struct l2tp_net *pn = l2tp_pernet(net);
316309795f4SJames Chapman 	int hash;
317309795f4SJames Chapman 	struct l2tp_session *session;
318309795f4SJames Chapman 
319e02d494dSJames Chapman 	rcu_read_lock_bh();
320309795f4SJames Chapman 	for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) {
321b67bfe0dSSasha Levin 		hlist_for_each_entry_rcu(session, &pn->l2tp_session_hlist[hash], global_hlist) {
322309795f4SJames Chapman 			if (!strcmp(session->ifname, ifname)) {
3232777e2abSGuillaume Nault 				l2tp_session_inc_refcount(session);
324e02d494dSJames Chapman 				rcu_read_unlock_bh();
3252777e2abSGuillaume Nault 
326309795f4SJames Chapman 				return session;
327309795f4SJames Chapman 			}
328309795f4SJames Chapman 		}
329309795f4SJames Chapman 	}
330309795f4SJames Chapman 
331e02d494dSJames Chapman 	rcu_read_unlock_bh();
332309795f4SJames Chapman 
333309795f4SJames Chapman 	return NULL;
334309795f4SJames Chapman }
3352777e2abSGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_get_by_ifname);
336309795f4SJames Chapman 
l2tp_session_register(struct l2tp_session * session,struct l2tp_tunnel * tunnel)3373953ae7bSGuillaume Nault int l2tp_session_register(struct l2tp_session *session,
3383953ae7bSGuillaume Nault 			  struct l2tp_tunnel *tunnel)
339dbdbc73bSGuillaume Nault {
340dbdbc73bSGuillaume Nault 	struct l2tp_session *session_walk;
341dbdbc73bSGuillaume Nault 	struct hlist_head *g_head;
342dbdbc73bSGuillaume Nault 	struct hlist_head *head;
343dbdbc73bSGuillaume Nault 	struct l2tp_net *pn;
344f3c66d4eSGuillaume Nault 	int err;
345dbdbc73bSGuillaume Nault 
346dbdbc73bSGuillaume Nault 	head = l2tp_session_id_hash(tunnel, session->session_id);
347dbdbc73bSGuillaume Nault 
34807b8ca37STom Parkin 	spin_lock_bh(&tunnel->hlist_lock);
349f3c66d4eSGuillaume Nault 	if (!tunnel->acpt_newsess) {
350f3c66d4eSGuillaume Nault 		err = -ENODEV;
351f3c66d4eSGuillaume Nault 		goto err_tlock;
352f3c66d4eSGuillaume Nault 	}
353f3c66d4eSGuillaume Nault 
354dbdbc73bSGuillaume Nault 	hlist_for_each_entry(session_walk, head, hlist)
355f3c66d4eSGuillaume Nault 		if (session_walk->session_id == session->session_id) {
356f3c66d4eSGuillaume Nault 			err = -EEXIST;
357f3c66d4eSGuillaume Nault 			goto err_tlock;
358f3c66d4eSGuillaume Nault 		}
359dbdbc73bSGuillaume Nault 
360dbdbc73bSGuillaume Nault 	if (tunnel->version == L2TP_HDR_VER_3) {
361dbdbc73bSGuillaume Nault 		pn = l2tp_pernet(tunnel->l2tp_net);
362363a341dSGuillaume Nault 		g_head = l2tp_session_id_hash_2(pn, session->session_id);
363dbdbc73bSGuillaume Nault 
364dbdbc73bSGuillaume Nault 		spin_lock_bh(&pn->l2tp_session_hlist_lock);
365dbdbc73bSGuillaume Nault 
3660d0d9a38SRidge Kennedy 		/* IP encap expects session IDs to be globally unique, while
3670d0d9a38SRidge Kennedy 		 * UDP encap doesn't.
3680d0d9a38SRidge Kennedy 		 */
369f3c66d4eSGuillaume Nault 		hlist_for_each_entry(session_walk, g_head, global_hlist)
3700d0d9a38SRidge Kennedy 			if (session_walk->session_id == session->session_id &&
3710d0d9a38SRidge Kennedy 			    (session_walk->tunnel->encap == L2TP_ENCAPTYPE_IP ||
3720d0d9a38SRidge Kennedy 			     tunnel->encap == L2TP_ENCAPTYPE_IP)) {
373f3c66d4eSGuillaume Nault 				err = -EEXIST;
374f3c66d4eSGuillaume Nault 				goto err_tlock_pnlock;
375f3c66d4eSGuillaume Nault 			}
376f3c66d4eSGuillaume Nault 
377f3c66d4eSGuillaume Nault 		l2tp_tunnel_inc_refcount(tunnel);
378dbdbc73bSGuillaume Nault 		hlist_add_head_rcu(&session->global_hlist, g_head);
379f3c66d4eSGuillaume Nault 
380dbdbc73bSGuillaume Nault 		spin_unlock_bh(&pn->l2tp_session_hlist_lock);
381f3c66d4eSGuillaume Nault 	} else {
382f3c66d4eSGuillaume Nault 		l2tp_tunnel_inc_refcount(tunnel);
383dbdbc73bSGuillaume Nault 	}
384dbdbc73bSGuillaume Nault 
38507b8ca37STom Parkin 	hlist_add_head_rcu(&session->hlist, head);
38607b8ca37STom Parkin 	spin_unlock_bh(&tunnel->hlist_lock);
387dbdbc73bSGuillaume Nault 
3886b7bdcd7STom Parkin 	trace_register_session(session);
3896b7bdcd7STom Parkin 
390dbdbc73bSGuillaume Nault 	return 0;
391dbdbc73bSGuillaume Nault 
392f3c66d4eSGuillaume Nault err_tlock_pnlock:
393dbdbc73bSGuillaume Nault 	spin_unlock_bh(&pn->l2tp_session_hlist_lock);
394f3c66d4eSGuillaume Nault err_tlock:
39507b8ca37STom Parkin 	spin_unlock_bh(&tunnel->hlist_lock);
396dbdbc73bSGuillaume Nault 
397f3c66d4eSGuillaume Nault 	return err;
398dbdbc73bSGuillaume Nault }
3993953ae7bSGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_register);
400dbdbc73bSGuillaume Nault 
401fd558d18SJames Chapman /*****************************************************************************
402fd558d18SJames Chapman  * Receive data handling
403fd558d18SJames Chapman  *****************************************************************************/
404fd558d18SJames Chapman 
405fd558d18SJames Chapman /* Queue a skb in order. We come here only if the skb has an L2TP sequence
406fd558d18SJames Chapman  * number.
407fd558d18SJames Chapman  */
l2tp_recv_queue_skb(struct l2tp_session * session,struct sk_buff * skb)408fd558d18SJames Chapman static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *skb)
409fd558d18SJames Chapman {
410fd558d18SJames Chapman 	struct sk_buff *skbp;
411fd558d18SJames Chapman 	struct sk_buff *tmp;
412f7faffa3SJames Chapman 	u32 ns = L2TP_SKB_CB(skb)->ns;
413fd558d18SJames Chapman 
414fd558d18SJames Chapman 	spin_lock_bh(&session->reorder_q.lock);
415fd558d18SJames Chapman 	skb_queue_walk_safe(&session->reorder_q, skbp, tmp) {
416fd558d18SJames Chapman 		if (L2TP_SKB_CB(skbp)->ns > ns) {
417fd558d18SJames Chapman 			__skb_queue_before(&session->reorder_q, skbp, skb);
4187b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_oos_packets);
419fd558d18SJames Chapman 			goto out;
420fd558d18SJames Chapman 		}
421fd558d18SJames Chapman 	}
422fd558d18SJames Chapman 
423fd558d18SJames Chapman 	__skb_queue_tail(&session->reorder_q, skb);
424fd558d18SJames Chapman 
425fd558d18SJames Chapman out:
426fd558d18SJames Chapman 	spin_unlock_bh(&session->reorder_q.lock);
427fd558d18SJames Chapman }
428fd558d18SJames Chapman 
429fd558d18SJames Chapman /* Dequeue a single skb.
430fd558d18SJames Chapman  */
l2tp_recv_dequeue_skb(struct l2tp_session * session,struct sk_buff * skb)431fd558d18SJames Chapman static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff *skb)
432fd558d18SJames Chapman {
433fd558d18SJames Chapman 	struct l2tp_tunnel *tunnel = session->tunnel;
434fd558d18SJames Chapman 	int length = L2TP_SKB_CB(skb)->length;
435fd558d18SJames Chapman 
436fd558d18SJames Chapman 	/* We're about to requeue the skb, so return resources
437fd558d18SJames Chapman 	 * to its current owner (a socket receive buffer).
438fd558d18SJames Chapman 	 */
439fd558d18SJames Chapman 	skb_orphan(skb);
440fd558d18SJames Chapman 
4417b7c0719STom Parkin 	atomic_long_inc(&tunnel->stats.rx_packets);
4427b7c0719STom Parkin 	atomic_long_add(length, &tunnel->stats.rx_bytes);
4437b7c0719STom Parkin 	atomic_long_inc(&session->stats.rx_packets);
4447b7c0719STom Parkin 	atomic_long_add(length, &session->stats.rx_bytes);
445fd558d18SJames Chapman 
446fd558d18SJames Chapman 	if (L2TP_SKB_CB(skb)->has_seq) {
447fd558d18SJames Chapman 		/* Bump our Nr */
448fd558d18SJames Chapman 		session->nr++;
4498a1631d5SJames Chapman 		session->nr &= session->nr_max;
4506b7bdcd7STom Parkin 		trace_session_seqnum_update(session);
451fd558d18SJames Chapman 	}
452fd558d18SJames Chapman 
453fd558d18SJames Chapman 	/* call private receive handler */
4540febc7b3STom Parkin 	if (session->recv_skb)
455fd558d18SJames Chapman 		(*session->recv_skb)(session, skb, L2TP_SKB_CB(skb)->length);
456fd558d18SJames Chapman 	else
457fd558d18SJames Chapman 		kfree_skb(skb);
458fd558d18SJames Chapman }
459fd558d18SJames Chapman 
460fd558d18SJames Chapman /* Dequeue skbs from the session's reorder_q, subject to packet order.
461fd558d18SJames Chapman  * Skbs that have been in the queue for too long are simply discarded.
462fd558d18SJames Chapman  */
l2tp_recv_dequeue(struct l2tp_session * session)463fd558d18SJames Chapman static void l2tp_recv_dequeue(struct l2tp_session *session)
464fd558d18SJames Chapman {
465fd558d18SJames Chapman 	struct sk_buff *skb;
466fd558d18SJames Chapman 	struct sk_buff *tmp;
467fd558d18SJames Chapman 
468fd558d18SJames Chapman 	/* If the pkt at the head of the queue has the nr that we
469fd558d18SJames Chapman 	 * expect to send up next, dequeue it and any other
470fd558d18SJames Chapman 	 * in-sequence packets behind it.
471fd558d18SJames Chapman 	 */
472e2e210c0SEric Dumazet start:
473fd558d18SJames Chapman 	spin_lock_bh(&session->reorder_q.lock);
474fd558d18SJames Chapman 	skb_queue_walk_safe(&session->reorder_q, skb, tmp) {
4756b7bdcd7STom Parkin 		struct l2tp_skb_cb *cb = L2TP_SKB_CB(skb);
4766b7bdcd7STom Parkin 
4776b7bdcd7STom Parkin 		/* If the packet has been pending on the queue for too long, discard it */
4786b7bdcd7STom Parkin 		if (time_after(jiffies, cb->expires)) {
4797b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_seq_discards);
4807b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_errors);
4816b7bdcd7STom Parkin 			trace_session_pkt_expired(session, cb->ns);
48238d40b3fSJames Chapman 			session->reorder_skip = 1;
483fd558d18SJames Chapman 			__skb_unlink(skb, &session->reorder_q);
484fd558d18SJames Chapman 			kfree_skb(skb);
485fd558d18SJames Chapman 			continue;
486fd558d18SJames Chapman 		}
487fd558d18SJames Chapman 
4886b7bdcd7STom Parkin 		if (cb->has_seq) {
48938d40b3fSJames Chapman 			if (session->reorder_skip) {
49038d40b3fSJames Chapman 				session->reorder_skip = 0;
4916b7bdcd7STom Parkin 				session->nr = cb->ns;
4926b7bdcd7STom Parkin 				trace_session_seqnum_reset(session);
49338d40b3fSJames Chapman 			}
4946b7bdcd7STom Parkin 			if (cb->ns != session->nr)
495fd558d18SJames Chapman 				goto out;
496fd558d18SJames Chapman 		}
497fd558d18SJames Chapman 		__skb_unlink(skb, &session->reorder_q);
498fd558d18SJames Chapman 
499fd558d18SJames Chapman 		/* Process the skb. We release the queue lock while we
500fd558d18SJames Chapman 		 * do so to let other contexts process the queue.
501fd558d18SJames Chapman 		 */
502fd558d18SJames Chapman 		spin_unlock_bh(&session->reorder_q.lock);
503fd558d18SJames Chapman 		l2tp_recv_dequeue_skb(session, skb);
504e2e210c0SEric Dumazet 		goto start;
505fd558d18SJames Chapman 	}
506fd558d18SJames Chapman 
507fd558d18SJames Chapman out:
508fd558d18SJames Chapman 	spin_unlock_bh(&session->reorder_q.lock);
509fd558d18SJames Chapman }
510fd558d18SJames Chapman 
l2tp_seq_check_rx_window(struct l2tp_session * session,u32 nr)5118a1631d5SJames Chapman static int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr)
5128a1631d5SJames Chapman {
5138a1631d5SJames Chapman 	u32 nws;
5148a1631d5SJames Chapman 
5158a1631d5SJames Chapman 	if (nr >= session->nr)
5168a1631d5SJames Chapman 		nws = nr - session->nr;
5178a1631d5SJames Chapman 	else
5188a1631d5SJames Chapman 		nws = (session->nr_max + 1) - (session->nr - nr);
5198a1631d5SJames Chapman 
5208a1631d5SJames Chapman 	return nws < session->nr_window_size;
5218a1631d5SJames Chapman }
5228a1631d5SJames Chapman 
523b6dc01a4SJames Chapman /* If packet has sequence numbers, queue it if acceptable. Returns 0 if
524b6dc01a4SJames Chapman  * acceptable, else non-zero.
525b6dc01a4SJames Chapman  */
l2tp_recv_data_seq(struct l2tp_session * session,struct sk_buff * skb)526b6dc01a4SJames Chapman static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb)
527b6dc01a4SJames Chapman {
5286b7bdcd7STom Parkin 	struct l2tp_skb_cb *cb = L2TP_SKB_CB(skb);
5296b7bdcd7STom Parkin 
5306b7bdcd7STom Parkin 	if (!l2tp_seq_check_rx_window(session, cb->ns)) {
5318a1631d5SJames Chapman 		/* Packet sequence number is outside allowed window.
5328a1631d5SJames Chapman 		 * Discard it.
5338a1631d5SJames Chapman 		 */
5346b7bdcd7STom Parkin 		trace_session_pkt_outside_rx_window(session, cb->ns);
5358a1631d5SJames Chapman 		goto discard;
5368a1631d5SJames Chapman 	}
5378a1631d5SJames Chapman 
538b6dc01a4SJames Chapman 	if (session->reorder_timeout != 0) {
539b6dc01a4SJames Chapman 		/* Packet reordering enabled. Add skb to session's
540b6dc01a4SJames Chapman 		 * reorder queue, in order of ns.
541b6dc01a4SJames Chapman 		 */
542b6dc01a4SJames Chapman 		l2tp_recv_queue_skb(session, skb);
543a0dbd822SJames Chapman 		goto out;
544a0dbd822SJames Chapman 	}
545a0dbd822SJames Chapman 
546a0dbd822SJames Chapman 	/* Packet reordering disabled. Discard out-of-sequence packets, while
547a0dbd822SJames Chapman 	 * tracking the number if in-sequence packets after the first OOS packet
548a0dbd822SJames Chapman 	 * is seen. After nr_oos_count_max in-sequence packets, reset the
549a0dbd822SJames Chapman 	 * sequence number to re-enable packet reception.
550b6dc01a4SJames Chapman 	 */
5516b7bdcd7STom Parkin 	if (cb->ns == session->nr) {
552a0dbd822SJames Chapman 		skb_queue_tail(&session->reorder_q, skb);
553a0dbd822SJames Chapman 	} else {
5546b7bdcd7STom Parkin 		u32 nr_oos = cb->ns;
555a0dbd822SJames Chapman 		u32 nr_next = (session->nr_oos + 1) & session->nr_max;
556a0dbd822SJames Chapman 
557a0dbd822SJames Chapman 		if (nr_oos == nr_next)
558a0dbd822SJames Chapman 			session->nr_oos_count++;
559a0dbd822SJames Chapman 		else
560a0dbd822SJames Chapman 			session->nr_oos_count = 0;
561a0dbd822SJames Chapman 
562a0dbd822SJames Chapman 		session->nr_oos = nr_oos;
563a0dbd822SJames Chapman 		if (session->nr_oos_count > session->nr_oos_count_max) {
564a0dbd822SJames Chapman 			session->reorder_skip = 1;
565a0dbd822SJames Chapman 		}
566a0dbd822SJames Chapman 		if (!session->reorder_skip) {
567b6dc01a4SJames Chapman 			atomic_long_inc(&session->stats.rx_seq_discards);
5686b7bdcd7STom Parkin 			trace_session_pkt_oos(session, cb->ns);
569b6dc01a4SJames Chapman 			goto discard;
570b6dc01a4SJames Chapman 		}
571b6dc01a4SJames Chapman 		skb_queue_tail(&session->reorder_q, skb);
572b6dc01a4SJames Chapman 	}
573b6dc01a4SJames Chapman 
574a0dbd822SJames Chapman out:
575b6dc01a4SJames Chapman 	return 0;
576b6dc01a4SJames Chapman 
577b6dc01a4SJames Chapman discard:
578b6dc01a4SJames Chapman 	return 1;
579b6dc01a4SJames Chapman }
580b6dc01a4SJames Chapman 
581f7faffa3SJames Chapman /* Do receive processing of L2TP data frames. We handle both L2TPv2
582f7faffa3SJames Chapman  * and L2TPv3 data frames here.
583f7faffa3SJames Chapman  *
584f7faffa3SJames Chapman  * L2TPv2 Data Message Header
585f7faffa3SJames Chapman  *
586f7faffa3SJames Chapman  *  0                   1                   2                   3
587f7faffa3SJames Chapman  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
588f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
589f7faffa3SJames Chapman  * |T|L|x|x|S|x|O|P|x|x|x|x|  Ver  |          Length (opt)         |
590f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
591f7faffa3SJames Chapman  * |           Tunnel ID           |           Session ID          |
592f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
593f7faffa3SJames Chapman  * |             Ns (opt)          |             Nr (opt)          |
594f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
595f7faffa3SJames Chapman  * |      Offset Size (opt)        |    Offset pad... (opt)
596f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
597f7faffa3SJames Chapman  *
598f7faffa3SJames Chapman  * Data frames are marked by T=0. All other fields are the same as
599f7faffa3SJames Chapman  * those in L2TP control frames.
600f7faffa3SJames Chapman  *
601f7faffa3SJames Chapman  * L2TPv3 Data Message Header
602f7faffa3SJames Chapman  *
603f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
604f7faffa3SJames Chapman  * |                      L2TP Session Header                      |
605f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
606f7faffa3SJames Chapman  * |                      L2-Specific Sublayer                     |
607f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
608f7faffa3SJames Chapman  * |                        Tunnel Payload                      ...
609f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
610f7faffa3SJames Chapman  *
611f7faffa3SJames Chapman  * L2TPv3 Session Header Over IP
612f7faffa3SJames Chapman  *
613f7faffa3SJames Chapman  *  0                   1                   2                   3
614f7faffa3SJames Chapman  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
615f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
616f7faffa3SJames Chapman  * |                           Session ID                          |
617f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
618f7faffa3SJames Chapman  * |               Cookie (optional, maximum 64 bits)...
619f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
620f7faffa3SJames Chapman  *                                                                 |
621f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
622f7faffa3SJames Chapman  *
623f7faffa3SJames Chapman  * L2TPv3 L2-Specific Sublayer Format
624f7faffa3SJames Chapman  *
625f7faffa3SJames Chapman  *  0                   1                   2                   3
626f7faffa3SJames Chapman  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
627f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
628f7faffa3SJames Chapman  * |x|S|x|x|x|x|x|x|              Sequence Number                  |
629f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
630f7faffa3SJames Chapman  *
63123fe846fSGuillaume Nault  * Cookie value and sublayer format are negotiated with the peer when
63223fe846fSGuillaume Nault  * the session is set up. Unlike L2TPv2, we do not need to parse the
63323fe846fSGuillaume Nault  * packet header to determine if optional fields are present.
634f7faffa3SJames Chapman  *
635f7faffa3SJames Chapman  * Caller must already have parsed the frame and determined that it is
636f7faffa3SJames Chapman  * a data (not control) frame before coming here. Fields up to the
637f7faffa3SJames Chapman  * session-id have already been parsed and ptr points to the data
638f7faffa3SJames Chapman  * after the session-id.
639f7faffa3SJames Chapman  */
l2tp_recv_common(struct l2tp_session * session,struct sk_buff * skb,unsigned char * ptr,unsigned char * optr,u16 hdrflags,int length)640f7faffa3SJames Chapman void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
641f7faffa3SJames Chapman 		      unsigned char *ptr, unsigned char *optr, u16 hdrflags,
6422b139e6bSGuillaume Nault 		      int length)
643f7faffa3SJames Chapman {
644f7faffa3SJames Chapman 	struct l2tp_tunnel *tunnel = session->tunnel;
645f7faffa3SJames Chapman 	int offset;
646f7faffa3SJames Chapman 
647f7faffa3SJames Chapman 	/* Parse and check optional cookie */
648f7faffa3SJames Chapman 	if (session->peer_cookie_len > 0) {
649f7faffa3SJames Chapman 		if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) {
6503e59e885SMatthias Schiffer 			pr_debug_ratelimited("%s: cookie mismatch (%u/%u). Discarding.\n",
651a4ca44faSJoe Perches 					     tunnel->name, tunnel->tunnel_id,
652a4ca44faSJoe Perches 					     session->session_id);
6537b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_cookie_discards);
654f7faffa3SJames Chapman 			goto discard;
655f7faffa3SJames Chapman 		}
656f7faffa3SJames Chapman 		ptr += session->peer_cookie_len;
657f7faffa3SJames Chapman 	}
658f7faffa3SJames Chapman 
659f7faffa3SJames Chapman 	/* Handle the optional sequence numbers. Sequence numbers are
660f7faffa3SJames Chapman 	 * in different places for L2TPv2 and L2TPv3.
661f7faffa3SJames Chapman 	 *
662f7faffa3SJames Chapman 	 * If we are the LAC, enable/disable sequence numbers under
663f7faffa3SJames Chapman 	 * the control of the LNS.  If no sequence numbers present but
664f7faffa3SJames Chapman 	 * we were expecting them, discard frame.
665f7faffa3SJames Chapman 	 */
666f7faffa3SJames Chapman 	L2TP_SKB_CB(skb)->has_seq = 0;
667f7faffa3SJames Chapman 	if (tunnel->version == L2TP_HDR_VER_2) {
668f7faffa3SJames Chapman 		if (hdrflags & L2TP_HDRFLAG_S) {
669f7faffa3SJames Chapman 			/* Store L2TP info in the skb */
67012923365STom Parkin 			L2TP_SKB_CB(skb)->ns = ntohs(*(__be16 *)ptr);
671f7faffa3SJames Chapman 			L2TP_SKB_CB(skb)->has_seq = 1;
67212923365STom Parkin 			ptr += 2;
67312923365STom Parkin 			/* Skip past nr in the header */
67412923365STom Parkin 			ptr += 2;
675f7faffa3SJames Chapman 
676f7faffa3SJames Chapman 		}
677f7faffa3SJames Chapman 	} else if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
678f7faffa3SJames Chapman 		u32 l2h = ntohl(*(__be32 *)ptr);
679f7faffa3SJames Chapman 
680f7faffa3SJames Chapman 		if (l2h & 0x40000000) {
681f7faffa3SJames Chapman 			/* Store L2TP info in the skb */
68212923365STom Parkin 			L2TP_SKB_CB(skb)->ns = l2h & 0x00ffffff;
683f7faffa3SJames Chapman 			L2TP_SKB_CB(skb)->has_seq = 1;
684f7faffa3SJames Chapman 		}
68562e7b6a5SLorenzo Bianconi 		ptr += 4;
686f7faffa3SJames Chapman 	}
687f7faffa3SJames Chapman 
688f7faffa3SJames Chapman 	if (L2TP_SKB_CB(skb)->has_seq) {
68920dcb110STom Parkin 		/* Received a packet with sequence numbers. If we're the LAC,
690f7faffa3SJames Chapman 		 * check if we sre sending sequence numbers and if not,
691f7faffa3SJames Chapman 		 * configure it so.
692f7faffa3SJames Chapman 		 */
6936c0ec37bSTom Parkin 		if (!session->lns_mode && !session->send_seq) {
6946b7bdcd7STom Parkin 			trace_session_seqnum_lns_enable(session);
6953f9b9770SAsbjørn Sloth Tønnesen 			session->send_seq = 1;
696f7faffa3SJames Chapman 			l2tp_session_set_header_len(session, tunnel->version);
697f7faffa3SJames Chapman 		}
698f7faffa3SJames Chapman 	} else {
699f7faffa3SJames Chapman 		/* No sequence numbers.
700f7faffa3SJames Chapman 		 * If user has configured mandatory sequence numbers, discard.
701f7faffa3SJames Chapman 		 */
702f7faffa3SJames Chapman 		if (session->recv_seq) {
7033e59e885SMatthias Schiffer 			pr_debug_ratelimited("%s: recv data has no seq numbers when required. Discarding.\n",
704a4ca44faSJoe Perches 					     session->name);
7057b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_seq_discards);
706f7faffa3SJames Chapman 			goto discard;
707f7faffa3SJames Chapman 		}
708f7faffa3SJames Chapman 
709f7faffa3SJames Chapman 		/* If we're the LAC and we're sending sequence numbers, the
710f7faffa3SJames Chapman 		 * LNS has requested that we no longer send sequence numbers.
711f7faffa3SJames Chapman 		 * If we're the LNS and we're sending sequence numbers, the
712f7faffa3SJames Chapman 		 * LAC is broken. Discard the frame.
713f7faffa3SJames Chapman 		 */
7146c0ec37bSTom Parkin 		if (!session->lns_mode && session->send_seq) {
7156b7bdcd7STom Parkin 			trace_session_seqnum_lns_disable(session);
716f7faffa3SJames Chapman 			session->send_seq = 0;
717f7faffa3SJames Chapman 			l2tp_session_set_header_len(session, tunnel->version);
718f7faffa3SJames Chapman 		} else if (session->send_seq) {
7193e59e885SMatthias Schiffer 			pr_debug_ratelimited("%s: recv data has no seq numbers when required. Discarding.\n",
720a4ca44faSJoe Perches 					     session->name);
7217b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_seq_discards);
722f7faffa3SJames Chapman 			goto discard;
723f7faffa3SJames Chapman 		}
724f7faffa3SJames Chapman 	}
725f7faffa3SJames Chapman 
726900631eeSJames Chapman 	/* Session data offset is defined only for L2TPv2 and is
727900631eeSJames Chapman 	 * indicated by an optional 16-bit value in the header.
728f7faffa3SJames Chapman 	 */
729f7faffa3SJames Chapman 	if (tunnel->version == L2TP_HDR_VER_2) {
730f7faffa3SJames Chapman 		/* If offset bit set, skip it. */
731f7faffa3SJames Chapman 		if (hdrflags & L2TP_HDRFLAG_O) {
732f7faffa3SJames Chapman 			offset = ntohs(*(__be16 *)ptr);
733f7faffa3SJames Chapman 			ptr += 2 + offset;
734f7faffa3SJames Chapman 		}
735900631eeSJames Chapman 	}
736f7faffa3SJames Chapman 
737f7faffa3SJames Chapman 	offset = ptr - optr;
738f7faffa3SJames Chapman 	if (!pskb_may_pull(skb, offset))
739f7faffa3SJames Chapman 		goto discard;
740f7faffa3SJames Chapman 
741f7faffa3SJames Chapman 	__skb_pull(skb, offset);
742f7faffa3SJames Chapman 
743f7faffa3SJames Chapman 	/* Prepare skb for adding to the session's reorder_q.  Hold
744f7faffa3SJames Chapman 	 * packets for max reorder_timeout or 1 second if not
745f7faffa3SJames Chapman 	 * reordering.
746f7faffa3SJames Chapman 	 */
747f7faffa3SJames Chapman 	L2TP_SKB_CB(skb)->length = length;
748f7faffa3SJames Chapman 	L2TP_SKB_CB(skb)->expires = jiffies +
749f7faffa3SJames Chapman 		(session->reorder_timeout ? session->reorder_timeout : HZ);
750f7faffa3SJames Chapman 
751f7faffa3SJames Chapman 	/* Add packet to the session's receive queue. Reordering is done here, if
752f7faffa3SJames Chapman 	 * enabled. Saved L2TP protocol info is stored in skb->sb[].
753f7faffa3SJames Chapman 	 */
754f7faffa3SJames Chapman 	if (L2TP_SKB_CB(skb)->has_seq) {
755b6dc01a4SJames Chapman 		if (l2tp_recv_data_seq(session, skb))
756f7faffa3SJames Chapman 			goto discard;
757f7faffa3SJames Chapman 	} else {
758f7faffa3SJames Chapman 		/* No sequence numbers. Add the skb to the tail of the
759f7faffa3SJames Chapman 		 * reorder queue. This ensures that it will be
760f7faffa3SJames Chapman 		 * delivered after all previous sequenced skbs.
761f7faffa3SJames Chapman 		 */
762f7faffa3SJames Chapman 		skb_queue_tail(&session->reorder_q, skb);
763f7faffa3SJames Chapman 	}
764f7faffa3SJames Chapman 
765f7faffa3SJames Chapman 	/* Try to dequeue as many skbs from reorder_q as we can. */
766f7faffa3SJames Chapman 	l2tp_recv_dequeue(session);
767f7faffa3SJames Chapman 
768f7faffa3SJames Chapman 	return;
769f7faffa3SJames Chapman 
770f7faffa3SJames Chapman discard:
7717b7c0719STom Parkin 	atomic_long_inc(&session->stats.rx_errors);
772f7faffa3SJames Chapman 	kfree_skb(skb);
773f7faffa3SJames Chapman }
774ca7885dbSTom Parkin EXPORT_SYMBOL_GPL(l2tp_recv_common);
775f7faffa3SJames Chapman 
77648f72f92STom Parkin /* Drop skbs from the session's reorder_q
77748f72f92STom Parkin  */
l2tp_session_queue_purge(struct l2tp_session * session)778493048f5STom Parkin static void l2tp_session_queue_purge(struct l2tp_session *session)
77948f72f92STom Parkin {
78048f72f92STom Parkin 	struct sk_buff *skb = NULL;
781b71a61ccSTom Parkin 
78248f72f92STom Parkin 	while ((skb = skb_dequeue(&session->reorder_q))) {
78348f72f92STom Parkin 		atomic_long_inc(&session->stats.rx_errors);
78448f72f92STom Parkin 		kfree_skb(skb);
78548f72f92STom Parkin 	}
78648f72f92STom Parkin }
78748f72f92STom Parkin 
788fd558d18SJames Chapman /* Internal UDP receive frame. Do the real work of receiving an L2TP data frame
789fd558d18SJames Chapman  * here. The skb is not on a list when we get here.
790fd558d18SJames Chapman  * Returns 0 if the packet was a data packet and was successfully passed on.
791fd558d18SJames Chapman  * Returns 1 if the packet was not a good data packet and could not be
792fd558d18SJames Chapman  * forwarded.  All such packets are passed up to userspace to deal with.
793fd558d18SJames Chapman  */
l2tp_udp_recv_core(struct l2tp_tunnel * tunnel,struct sk_buff * skb)7942b139e6bSGuillaume Nault static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
795fd558d18SJames Chapman {
796fd558d18SJames Chapman 	struct l2tp_session *session = NULL;
797fd558d18SJames Chapman 	unsigned char *ptr, *optr;
798fd558d18SJames Chapman 	u16 hdrflags;
799fd558d18SJames Chapman 	u32 tunnel_id, session_id;
800fd558d18SJames Chapman 	u16 version;
801f7faffa3SJames Chapman 	int length;
802fd558d18SJames Chapman 
803aa785f93SBhaskar Chowdhury 	/* UDP has verified checksum */
804fd558d18SJames Chapman 
805fd558d18SJames Chapman 	/* UDP always verifies the packet length. */
806fd558d18SJames Chapman 	__skb_pull(skb, sizeof(struct udphdr));
807fd558d18SJames Chapman 
808fd558d18SJames Chapman 	/* Short packet? */
80991c52470SJacob Wen 	if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX)) {
8103e59e885SMatthias Schiffer 		pr_debug_ratelimited("%s: recv short packet (len=%d)\n",
811a4ca44faSJoe Perches 				     tunnel->name, skb->len);
8123e59e885SMatthias Schiffer 		goto invalid;
813fd558d18SJames Chapman 	}
814fd558d18SJames Chapman 
815e50e705cSEric Dumazet 	/* Point to L2TP header */
81695075150STom Parkin 	optr = skb->data;
81795075150STom Parkin 	ptr = skb->data;
818e50e705cSEric Dumazet 
819fd558d18SJames Chapman 	/* Get L2TP header flags */
820fd558d18SJames Chapman 	hdrflags = ntohs(*(__be16 *)ptr);
821fd558d18SJames Chapman 
822fd558d18SJames Chapman 	/* Check protocol version */
823fd558d18SJames Chapman 	version = hdrflags & L2TP_HDR_VER_MASK;
824fd558d18SJames Chapman 	if (version != tunnel->version) {
8253e59e885SMatthias Schiffer 		pr_debug_ratelimited("%s: recv protocol version mismatch: got %d expected %d\n",
826fd558d18SJames Chapman 				     tunnel->name, version, tunnel->version);
8273e59e885SMatthias Schiffer 		goto invalid;
828fd558d18SJames Chapman 	}
829fd558d18SJames Chapman 
830fd558d18SJames Chapman 	/* Get length of L2TP packet */
831fd558d18SJames Chapman 	length = skb->len;
832fd558d18SJames Chapman 
833fd558d18SJames Chapman 	/* If type is control packet, it is handled by userspace. */
83412923365STom Parkin 	if (hdrflags & L2TP_HDRFLAG_T)
8353e59e885SMatthias Schiffer 		goto pass;
836fd558d18SJames Chapman 
837fd558d18SJames Chapman 	/* Skip flags */
838fd558d18SJames Chapman 	ptr += 2;
839fd558d18SJames Chapman 
840f7faffa3SJames Chapman 	if (tunnel->version == L2TP_HDR_VER_2) {
841fd558d18SJames Chapman 		/* If length is present, skip it */
842fd558d18SJames Chapman 		if (hdrflags & L2TP_HDRFLAG_L)
843fd558d18SJames Chapman 			ptr += 2;
844fd558d18SJames Chapman 
845fd558d18SJames Chapman 		/* Extract tunnel and session ID */
846fd558d18SJames Chapman 		tunnel_id = ntohs(*(__be16 *)ptr);
847fd558d18SJames Chapman 		ptr += 2;
848fd558d18SJames Chapman 		session_id = ntohs(*(__be16 *)ptr);
849fd558d18SJames Chapman 		ptr += 2;
850f7faffa3SJames Chapman 	} else {
851f7faffa3SJames Chapman 		ptr += 2;	/* skip reserved bits */
852f7faffa3SJames Chapman 		tunnel_id = tunnel->tunnel_id;
853f7faffa3SJames Chapman 		session_id = ntohl(*(__be32 *)ptr);
854f7faffa3SJames Chapman 		ptr += 4;
855f7faffa3SJames Chapman 	}
856fd558d18SJames Chapman 
857fd558d18SJames Chapman 	/* Find the session context */
85801e28b92SGuillaume Nault 	session = l2tp_tunnel_get_session(tunnel, session_id);
859309795f4SJames Chapman 	if (!session || !session->recv_skb) {
860a4346210SGuillaume Nault 		if (session)
86161b9a047SGuillaume Nault 			l2tp_session_dec_refcount(session);
86261b9a047SGuillaume Nault 
863fd558d18SJames Chapman 		/* Not found? Pass to userspace to deal with */
8643e59e885SMatthias Schiffer 		pr_debug_ratelimited("%s: no session found (%u/%u). Passing up.\n",
865fd558d18SJames Chapman 				     tunnel->name, tunnel_id, session_id);
8663e59e885SMatthias Schiffer 		goto pass;
867fd558d18SJames Chapman 	}
868fd558d18SJames Chapman 
8694522a70dSJacob Wen 	if (tunnel->version == L2TP_HDR_VER_3 &&
8709b6ff7ebSXiyu Yang 	    l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr)) {
8719b6ff7ebSXiyu Yang 		l2tp_session_dec_refcount(session);
8723e59e885SMatthias Schiffer 		goto invalid;
8739b6ff7ebSXiyu Yang 	}
8744522a70dSJacob Wen 
8752b139e6bSGuillaume Nault 	l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
87661b9a047SGuillaume Nault 	l2tp_session_dec_refcount(session);
877fd558d18SJames Chapman 
878fd558d18SJames Chapman 	return 0;
879fd558d18SJames Chapman 
8803e59e885SMatthias Schiffer invalid:
8813e59e885SMatthias Schiffer 	atomic_long_inc(&tunnel->stats.rx_invalid);
8823e59e885SMatthias Schiffer 
8833e59e885SMatthias Schiffer pass:
884fd558d18SJames Chapman 	/* Put UDP header back */
885fd558d18SJames Chapman 	__skb_push(skb, sizeof(struct udphdr));
886fd558d18SJames Chapman 
887fd558d18SJames Chapman 	return 1;
888fd558d18SJames Chapman }
889fd558d18SJames Chapman 
890fd558d18SJames Chapman /* UDP encapsulation receive handler. See net/ipv4/udp.c.
891fd558d18SJames Chapman  * Return codes:
892fd558d18SJames Chapman  * 0 : success.
893fd558d18SJames Chapman  * <0: error
894fd558d18SJames Chapman  * >0: skb should be passed up to userspace as UDP.
895fd558d18SJames Chapman  */
l2tp_udp_encap_recv(struct sock * sk,struct sk_buff * skb)896fd558d18SJames Chapman int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
897fd558d18SJames Chapman {
898fd558d18SJames Chapman 	struct l2tp_tunnel *tunnel;
899fd558d18SJames Chapman 
90045faeff1STom Parkin 	/* Note that this is called from the encap_rcv hook inside an
90145faeff1STom Parkin 	 * RCU-protected region, but without the socket being locked.
90245faeff1STom Parkin 	 * Hence we use rcu_dereference_sk_user_data to access the
90345faeff1STom Parkin 	 * tunnel data structure rather the usual l2tp_sk_to_tunnel
90445faeff1STom Parkin 	 * accessor function.
90545faeff1STom Parkin 	 */
906c1c47721SEric Dumazet 	tunnel = rcu_dereference_sk_user_data(sk);
9070febc7b3STom Parkin 	if (!tunnel)
908fd558d18SJames Chapman 		goto pass_up;
90945faeff1STom Parkin 	if (WARN_ON(tunnel->magic != L2TP_TUNNEL_MAGIC))
91045faeff1STom Parkin 		goto pass_up;
911fd558d18SJames Chapman 
9122b139e6bSGuillaume Nault 	if (l2tp_udp_recv_core(tunnel, skb))
913d00fa9adSJames Chapman 		goto pass_up;
914fd558d18SJames Chapman 
915fd558d18SJames Chapman 	return 0;
916fd558d18SJames Chapman 
917fd558d18SJames Chapman pass_up:
918fd558d18SJames Chapman 	return 1;
919fd558d18SJames Chapman }
920fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_udp_encap_recv);
921fd558d18SJames Chapman 
922fd558d18SJames Chapman /************************************************************************
923fd558d18SJames Chapman  * Transmit handling
924fd558d18SJames Chapman  ***********************************************************************/
925fd558d18SJames Chapman 
926fd558d18SJames Chapman /* Build an L2TP header for the session into the buffer provided.
927fd558d18SJames Chapman  */
l2tp_build_l2tpv2_header(struct l2tp_session * session,void * buf)928f7faffa3SJames Chapman static int l2tp_build_l2tpv2_header(struct l2tp_session *session, void *buf)
929fd558d18SJames Chapman {
930f7faffa3SJames Chapman 	struct l2tp_tunnel *tunnel = session->tunnel;
931fd558d18SJames Chapman 	__be16 *bufp = buf;
932f7faffa3SJames Chapman 	__be16 *optr = buf;
933fd558d18SJames Chapman 	u16 flags = L2TP_HDR_VER_2;
934fd558d18SJames Chapman 	u32 tunnel_id = tunnel->peer_tunnel_id;
935fd558d18SJames Chapman 	u32 session_id = session->peer_session_id;
936fd558d18SJames Chapman 
937fd558d18SJames Chapman 	if (session->send_seq)
938fd558d18SJames Chapman 		flags |= L2TP_HDRFLAG_S;
939fd558d18SJames Chapman 
940fd558d18SJames Chapman 	/* Setup L2TP header. */
941fd558d18SJames Chapman 	*bufp++ = htons(flags);
942fd558d18SJames Chapman 	*bufp++ = htons(tunnel_id);
943fd558d18SJames Chapman 	*bufp++ = htons(session_id);
944fd558d18SJames Chapman 	if (session->send_seq) {
945fd558d18SJames Chapman 		*bufp++ = htons(session->ns);
946fd558d18SJames Chapman 		*bufp++ = 0;
947fd558d18SJames Chapman 		session->ns++;
948f7faffa3SJames Chapman 		session->ns &= 0xffff;
9496b7bdcd7STom Parkin 		trace_session_seqnum_update(session);
950fd558d18SJames Chapman 	}
951fd558d18SJames Chapman 
952f7faffa3SJames Chapman 	return bufp - optr;
953f7faffa3SJames Chapman }
954f7faffa3SJames Chapman 
l2tp_build_l2tpv3_header(struct l2tp_session * session,void * buf)955f7faffa3SJames Chapman static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf)
956fd558d18SJames Chapman {
9570d76751fSJames Chapman 	struct l2tp_tunnel *tunnel = session->tunnel;
958f7faffa3SJames Chapman 	char *bufp = buf;
959f7faffa3SJames Chapman 	char *optr = bufp;
960fd558d18SJames Chapman 
9610d76751fSJames Chapman 	/* Setup L2TP header. The header differs slightly for UDP and
9620d76751fSJames Chapman 	 * IP encapsulations. For UDP, there is 4 bytes of flags.
9630d76751fSJames Chapman 	 */
9640d76751fSJames Chapman 	if (tunnel->encap == L2TP_ENCAPTYPE_UDP) {
9650d76751fSJames Chapman 		u16 flags = L2TP_HDR_VER_3;
966f7faffa3SJames Chapman 		*((__be16 *)bufp) = htons(flags);
967f7faffa3SJames Chapman 		bufp += 2;
968f7faffa3SJames Chapman 		*((__be16 *)bufp) = 0;
969f7faffa3SJames Chapman 		bufp += 2;
9700d76751fSJames Chapman 	}
9710d76751fSJames Chapman 
972f7faffa3SJames Chapman 	*((__be32 *)bufp) = htonl(session->peer_session_id);
973f7faffa3SJames Chapman 	bufp += 4;
974f7faffa3SJames Chapman 	if (session->cookie_len) {
975f7faffa3SJames Chapman 		memcpy(bufp, &session->cookie[0], session->cookie_len);
976f7faffa3SJames Chapman 		bufp += session->cookie_len;
977fd558d18SJames Chapman 	}
978f7faffa3SJames Chapman 	if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
979f7faffa3SJames Chapman 		u32 l2h = 0;
98062e7b6a5SLorenzo Bianconi 
981f7faffa3SJames Chapman 		if (session->send_seq) {
982f7faffa3SJames Chapman 			l2h = 0x40000000 | session->ns;
983f7faffa3SJames Chapman 			session->ns++;
984f7faffa3SJames Chapman 			session->ns &= 0xffffff;
9856b7bdcd7STom Parkin 			trace_session_seqnum_update(session);
986f7faffa3SJames Chapman 		}
987f7faffa3SJames Chapman 
988f7faffa3SJames Chapman 		*((__be32 *)bufp) = htonl(l2h);
98962e7b6a5SLorenzo Bianconi 		bufp += 4;
990f7faffa3SJames Chapman 	}
991f7faffa3SJames Chapman 
992f7faffa3SJames Chapman 	return bufp - optr;
993f7faffa3SJames Chapman }
994fd558d18SJames Chapman 
995de68b039STom Parkin /* Queue the packet to IP for output: tunnel socket lock must be held */
l2tp_xmit_queue(struct l2tp_tunnel * tunnel,struct sk_buff * skb,struct flowi * fl)996de68b039STom Parkin static int l2tp_xmit_queue(struct l2tp_tunnel *tunnel, struct sk_buff *skb, struct flowi *fl)
997fd558d18SJames Chapman {
998de68b039STom Parkin 	int err;
999fd558d18SJames Chapman 
100060ff7467SWANG Cong 	skb->ignore_df = 1;
100127d53323SXin Long 	skb_dst_drop(skb);
1002d2cf3361SBenjamin LaHaise #if IS_ENABLED(CONFIG_IPV6)
1003b954f940SPaolo Abeni 	if (l2tp_sk_is_v6(tunnel->sock))
1004de68b039STom Parkin 		err = inet6_csk_xmit(tunnel->sock, skb, NULL);
1005d2cf3361SBenjamin LaHaise 	else
1006d2cf3361SBenjamin LaHaise #endif
1007de68b039STom Parkin 		err = ip_queue_xmit(tunnel->sock, skb, fl);
1008fd558d18SJames Chapman 
1009de68b039STom Parkin 	return err >= 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
1010fd558d18SJames Chapman }
1011fd558d18SJames Chapman 
l2tp_xmit_core(struct l2tp_session * session,struct sk_buff * skb,unsigned int * len)1012f52e4b27STom Parkin static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, unsigned int *len)
1013fd558d18SJames Chapman {
10140d76751fSJames Chapman 	struct l2tp_tunnel *tunnel = session->tunnel;
1015de68b039STom Parkin 	unsigned int data_len = skb->len;
10160d76751fSJames Chapman 	struct sock *sk = tunnel->sock;
1017de68b039STom Parkin 	int headroom, uhlen, udp_len;
1018b8c84307SEric Dumazet 	int ret = NET_XMIT_SUCCESS;
1019de68b039STom Parkin 	struct inet_sock *inet;
1020de68b039STom Parkin 	struct udphdr *uh;
1021fd558d18SJames Chapman 
1022fd558d18SJames Chapman 	/* Check that there's enough headroom in the skb to insert IP,
1023fd558d18SJames Chapman 	 * UDP and L2TP headers. If not enough, expand it to
1024fd558d18SJames Chapman 	 * make room. Adjust truesize.
1025fd558d18SJames Chapman 	 */
1026de68b039STom Parkin 	uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(*uh) : 0;
1027de68b039STom Parkin 	headroom = NET_SKB_PAD + sizeof(struct iphdr) + uhlen + session->hdr_len;
1028835acf5dSEric Dumazet 	if (skb_cow_head(skb, headroom)) {
1029b8c84307SEric Dumazet 		kfree_skb(skb);
1030b8c84307SEric Dumazet 		return NET_XMIT_DROP;
1031835acf5dSEric Dumazet 	}
1032fd558d18SJames Chapman 
1033fd558d18SJames Chapman 	/* Setup L2TP header */
10342dedab6fSTom Parkin 	if (tunnel->version == L2TP_HDR_VER_2)
1035efe05278STom Parkin 		l2tp_build_l2tpv2_header(session, __skb_push(skb, session->hdr_len));
10362dedab6fSTom Parkin 	else
1037efe05278STom Parkin 		l2tp_build_l2tpv3_header(session, __skb_push(skb, session->hdr_len));
1038fd558d18SJames Chapman 
10390d76751fSJames Chapman 	/* Reset skb netfilter state */
1040fd558d18SJames Chapman 	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
1041de68b039STom Parkin 	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
1042895b5c9fSFlorian Westphal 	nf_reset_ct(skb);
1043fd558d18SJames Chapman 
10440b2c5972SCong Wang 	bh_lock_sock_nested(sk);
10456af88da1SDavid S. Miller 	if (sock_owned_by_user(sk)) {
1046b8c84307SEric Dumazet 		kfree_skb(skb);
1047b8c84307SEric Dumazet 		ret = NET_XMIT_DROP;
10486af88da1SDavid S. Miller 		goto out_unlock;
10496af88da1SDavid S. Miller 	}
10506af88da1SDavid S. Miller 
1051b954f940SPaolo Abeni 	/* The user-space may change the connection status for the user-space
1052b954f940SPaolo Abeni 	 * provided socket at run time: we must check it under the socket lock
1053b954f940SPaolo Abeni 	 */
1054b954f940SPaolo Abeni 	if (tunnel->fd >= 0 && sk->sk_state != TCP_ESTABLISHED) {
1055b954f940SPaolo Abeni 		kfree_skb(skb);
1056b954f940SPaolo Abeni 		ret = NET_XMIT_DROP;
1057b954f940SPaolo Abeni 		goto out_unlock;
1058b954f940SPaolo Abeni 	}
1059b954f940SPaolo Abeni 
1060f52e4b27STom Parkin 	/* Report transmitted length before we add encap header, which keeps
1061f52e4b27STom Parkin 	 * statistics consistent for both UDP and IP encap tx/rx paths.
1062f52e4b27STom Parkin 	 */
1063f52e4b27STom Parkin 	*len = skb->len;
1064f52e4b27STom Parkin 
1065d9d8da80SDavid S. Miller 	inet = inet_sk(sk);
10660d76751fSJames Chapman 	switch (tunnel->encap) {
10670d76751fSJames Chapman 	case L2TP_ENCAPTYPE_UDP:
10680d76751fSJames Chapman 		/* Setup UDP header */
10690d76751fSJames Chapman 		__skb_push(skb, sizeof(*uh));
10700d76751fSJames Chapman 		skb_reset_transport_header(skb);
10710d76751fSJames Chapman 		uh = udp_hdr(skb);
10720d76751fSJames Chapman 		uh->source = inet->inet_sport;
10730d76751fSJames Chapman 		uh->dest = inet->inet_dport;
1074efe05278STom Parkin 		udp_len = uhlen + session->hdr_len + data_len;
10750d76751fSJames Chapman 		uh->len = htons(udp_len);
1076fd558d18SJames Chapman 
1077fd558d18SJames Chapman 		/* Calculate UDP checksum if configured to do so */
1078d2cf3361SBenjamin LaHaise #if IS_ENABLED(CONFIG_IPV6)
1079b954f940SPaolo Abeni 		if (l2tp_sk_is_v6(sk))
108077157e19STom Herbert 			udp6_set_csum(udp_get_no_check6_tx(sk),
108177157e19STom Herbert 				      skb, &inet6_sk(sk)->saddr,
108277157e19STom Herbert 				      &sk->sk_v6_daddr, udp_len);
1083d2cf3361SBenjamin LaHaise 		else
1084d2cf3361SBenjamin LaHaise #endif
108577157e19STom Herbert 			udp_set_csum(sk->sk_no_check_tx, skb, inet->inet_saddr,
108677157e19STom Herbert 				     inet->inet_daddr, udp_len);
10870d76751fSJames Chapman 		break;
10880d76751fSJames Chapman 
10890d76751fSJames Chapman 	case L2TP_ENCAPTYPE_IP:
10900d76751fSJames Chapman 		break;
10910d76751fSJames Chapman 	}
10920d76751fSJames Chapman 
1093de68b039STom Parkin 	ret = l2tp_xmit_queue(tunnel, skb, &inet->cork.fl);
1094de68b039STom Parkin 
10956af88da1SDavid S. Miller out_unlock:
10966af88da1SDavid S. Miller 	bh_unlock_sock(sk);
1097fd558d18SJames Chapman 
1098b8c84307SEric Dumazet 	return ret;
1099fd558d18SJames Chapman }
1100de68b039STom Parkin 
1101de68b039STom Parkin /* If caller requires the skb to have a ppp header, the header must be
1102de68b039STom Parkin  * inserted in the skb data before calling this function.
1103de68b039STom Parkin  */
l2tp_xmit_skb(struct l2tp_session * session,struct sk_buff * skb)1104de68b039STom Parkin int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb)
1105de68b039STom Parkin {
1106f52e4b27STom Parkin 	unsigned int len = 0;
1107de68b039STom Parkin 	int ret;
1108de68b039STom Parkin 
1109f52e4b27STom Parkin 	ret = l2tp_xmit_core(session, skb, &len);
1110de68b039STom Parkin 	if (ret == NET_XMIT_SUCCESS) {
1111de68b039STom Parkin 		atomic_long_inc(&session->tunnel->stats.tx_packets);
1112de68b039STom Parkin 		atomic_long_add(len, &session->tunnel->stats.tx_bytes);
1113de68b039STom Parkin 		atomic_long_inc(&session->stats.tx_packets);
1114de68b039STom Parkin 		atomic_long_add(len, &session->stats.tx_bytes);
1115de68b039STom Parkin 	} else {
1116de68b039STom Parkin 		atomic_long_inc(&session->tunnel->stats.tx_errors);
1117de68b039STom Parkin 		atomic_long_inc(&session->stats.tx_errors);
1118de68b039STom Parkin 	}
1119de68b039STom Parkin 	return ret;
1120de68b039STom Parkin }
1121fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_xmit_skb);
1122fd558d18SJames Chapman 
1123fd558d18SJames Chapman /*****************************************************************************
1124fd558d18SJames Chapman  * Tinnel and session create/destroy.
1125fd558d18SJames Chapman  *****************************************************************************/
1126fd558d18SJames Chapman 
1127fd558d18SJames Chapman /* Tunnel socket destruct hook.
1128fd558d18SJames Chapman  * The tunnel context is deleted only when all session sockets have been
1129fd558d18SJames Chapman  * closed.
1130fd558d18SJames Chapman  */
l2tp_tunnel_destruct(struct sock * sk)1131fc130840Sstephen hemminger static void l2tp_tunnel_destruct(struct sock *sk)
1132fd558d18SJames Chapman {
113345faeff1STom Parkin 	struct l2tp_tunnel *tunnel = l2tp_sk_to_tunnel(sk);
1134fd558d18SJames Chapman 
11350febc7b3STom Parkin 	if (!tunnel)
1136fd558d18SJames Chapman 		goto end;
1137fd558d18SJames Chapman 
1138f8ccac0eSTom Parkin 	/* Disable udp encapsulation */
11390d76751fSJames Chapman 	switch (tunnel->encap) {
11400d76751fSJames Chapman 	case L2TP_ENCAPTYPE_UDP:
1141fd558d18SJames Chapman 		/* No longer an encapsulation socket. See net/ipv4/udp.c */
1142*4781a75dSEric Dumazet 		WRITE_ONCE(udp_sk(sk)->encap_type, 0);
1143*4781a75dSEric Dumazet 		udp_sk(sk)->encap_rcv = NULL;
1144*4781a75dSEric Dumazet 		udp_sk(sk)->encap_destroy = NULL;
11450d76751fSJames Chapman 		break;
11460d76751fSJames Chapman 	case L2TP_ENCAPTYPE_IP:
11470d76751fSJames Chapman 		break;
11480d76751fSJames Chapman 	}
1149fd558d18SJames Chapman 
1150fd558d18SJames Chapman 	/* Remove hooks into tunnel socket */
1151b68777d5SJakub Sitnicki 	write_lock_bh(&sk->sk_callback_lock);
1152fd558d18SJames Chapman 	sk->sk_destruct = tunnel->old_sk_destruct;
1153fd558d18SJames Chapman 	sk->sk_user_data = NULL;
1154b68777d5SJakub Sitnicki 	write_unlock_bh(&sk->sk_callback_lock);
1155f8ccac0eSTom Parkin 
1156fd558d18SJames Chapman 	/* Call the original destructor */
1157fd558d18SJames Chapman 	if (sk->sk_destruct)
1158fd558d18SJames Chapman 		(*sk->sk_destruct)(sk);
1159d00fa9adSJames Chapman 
1160d00fa9adSJames Chapman 	kfree_rcu(tunnel, rcu);
1161fd558d18SJames Chapman end:
1162fd558d18SJames Chapman 	return;
1163fd558d18SJames Chapman }
1164fd558d18SJames Chapman 
1165b2aecfe8STom Parkin /* Remove an l2tp session from l2tp_core's hash lists. */
l2tp_session_unhash(struct l2tp_session * session)1166b2aecfe8STom Parkin static void l2tp_session_unhash(struct l2tp_session *session)
1167b2aecfe8STom Parkin {
1168b2aecfe8STom Parkin 	struct l2tp_tunnel *tunnel = session->tunnel;
1169b2aecfe8STom Parkin 
1170b2aecfe8STom Parkin 	/* Remove the session from core hashes */
1171b2aecfe8STom Parkin 	if (tunnel) {
1172b2aecfe8STom Parkin 		/* Remove from the per-tunnel hash */
117307b8ca37STom Parkin 		spin_lock_bh(&tunnel->hlist_lock);
117407b8ca37STom Parkin 		hlist_del_init_rcu(&session->hlist);
117507b8ca37STom Parkin 		spin_unlock_bh(&tunnel->hlist_lock);
1176b2aecfe8STom Parkin 
1177b2aecfe8STom Parkin 		/* For L2TPv3 we have a per-net hash: remove from there, too */
1178b2aecfe8STom Parkin 		if (tunnel->version != L2TP_HDR_VER_2) {
1179b2aecfe8STom Parkin 			struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
1180b2aecfe8STom Parkin 
1181b2aecfe8STom Parkin 			spin_lock_bh(&pn->l2tp_session_hlist_lock);
1182b2aecfe8STom Parkin 			hlist_del_init_rcu(&session->global_hlist);
1183b2aecfe8STom Parkin 			spin_unlock_bh(&pn->l2tp_session_hlist_lock);
1184b2aecfe8STom Parkin 		}
118507b8ca37STom Parkin 
118607b8ca37STom Parkin 		synchronize_rcu();
1187b2aecfe8STom Parkin 	}
1188b2aecfe8STom Parkin }
1189b2aecfe8STom Parkin 
1190fd558d18SJames Chapman /* When the tunnel is closed, all the attached sessions need to go too.
1191fd558d18SJames Chapman  */
l2tp_tunnel_closeall(struct l2tp_tunnel * tunnel)1192d08532bbSGuillaume Nault static void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel)
1193fd558d18SJames Chapman {
1194fd558d18SJames Chapman 	struct l2tp_session *session;
119507b8ca37STom Parkin 	int hash;
1196fd558d18SJames Chapman 
119707b8ca37STom Parkin 	spin_lock_bh(&tunnel->hlist_lock);
1198f3c66d4eSGuillaume Nault 	tunnel->acpt_newsess = false;
1199fd558d18SJames Chapman 	for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
1200fd558d18SJames Chapman again:
120107b8ca37STom Parkin 		hlist_for_each_entry_rcu(session, &tunnel->session_hlist[hash], hlist) {
120207b8ca37STom Parkin 			hlist_del_init_rcu(&session->hlist);
1203fd558d18SJames Chapman 
120407b8ca37STom Parkin 			spin_unlock_bh(&tunnel->hlist_lock);
12059d319a8eSTom Parkin 			l2tp_session_delete(session);
120607b8ca37STom Parkin 			spin_lock_bh(&tunnel->hlist_lock);
1207fd558d18SJames Chapman 
1208fd558d18SJames Chapman 			/* Now restart from the beginning of this hash
1209fd558d18SJames Chapman 			 * chain.  We always remove a session from the
1210fd558d18SJames Chapman 			 * list so we are guaranteed to make forward
1211fd558d18SJames Chapman 			 * progress.
1212fd558d18SJames Chapman 			 */
1213fd558d18SJames Chapman 			goto again;
1214fd558d18SJames Chapman 		}
1215fd558d18SJames Chapman 	}
121607b8ca37STom Parkin 	spin_unlock_bh(&tunnel->hlist_lock);
1217fd558d18SJames Chapman }
1218fd558d18SJames Chapman 
12199980d001STom Parkin /* Tunnel socket destroy hook for UDP encapsulation */
l2tp_udp_encap_destroy(struct sock * sk)12209980d001STom Parkin static void l2tp_udp_encap_destroy(struct sock *sk)
12219980d001STom Parkin {
122245faeff1STom Parkin 	struct l2tp_tunnel *tunnel = l2tp_sk_to_tunnel(sk);
1223d00fa9adSJames Chapman 
1224d00fa9adSJames Chapman 	if (tunnel)
1225d00fa9adSJames Chapman 		l2tp_tunnel_delete(tunnel);
12269980d001STom Parkin }
12279980d001STom Parkin 
l2tp_tunnel_remove(struct net * net,struct l2tp_tunnel * tunnel)1228c4d48a58SCong Wang static void l2tp_tunnel_remove(struct net *net, struct l2tp_tunnel *tunnel)
1229c4d48a58SCong Wang {
1230c4d48a58SCong Wang 	struct l2tp_net *pn = l2tp_pernet(net);
1231c4d48a58SCong Wang 
1232c4d48a58SCong Wang 	spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
1233c4d48a58SCong Wang 	idr_remove(&pn->l2tp_tunnel_idr, tunnel->tunnel_id);
1234c4d48a58SCong Wang 	spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
1235c4d48a58SCong Wang }
1236c4d48a58SCong Wang 
1237f8ccac0eSTom Parkin /* Workqueue tunnel deletion function */
l2tp_tunnel_del_work(struct work_struct * work)1238f8ccac0eSTom Parkin static void l2tp_tunnel_del_work(struct work_struct *work)
1239f8ccac0eSTom Parkin {
1240d00fa9adSJames Chapman 	struct l2tp_tunnel *tunnel = container_of(work, struct l2tp_tunnel,
1241d00fa9adSJames Chapman 						  del_work);
1242d00fa9adSJames Chapman 	struct sock *sk = tunnel->sock;
1243d00fa9adSJames Chapman 	struct socket *sock = sk->sk_socket;
124412d656afSRidge Kennedy 
124512d656afSRidge Kennedy 	l2tp_tunnel_closeall(tunnel);
124612d656afSRidge Kennedy 
124776a6abdbSJames Chapman 	/* If the tunnel socket was created within the kernel, use
124802d13ed5STom Parkin 	 * the sk API to release it here.
1249f8ccac0eSTom Parkin 	 */
125076a6abdbSJames Chapman 	if (tunnel->fd < 0) {
125126abe143SEric W. Biederman 		if (sock) {
1252167eb17eSTom Parkin 			kernel_sock_shutdown(sock, SHUT_RDWR);
125326abe143SEric W. Biederman 			sock_release(sock);
125426abe143SEric W. Biederman 		}
1255167eb17eSTom Parkin 	}
1256f8ccac0eSTom Parkin 
1257c4d48a58SCong Wang 	l2tp_tunnel_remove(tunnel->l2tp_net, tunnel);
1258d00fa9adSJames Chapman 	/* drop initial ref */
1259d00fa9adSJames Chapman 	l2tp_tunnel_dec_refcount(tunnel);
1260d00fa9adSJames Chapman 
1261d00fa9adSJames Chapman 	/* drop workqueue ref */
126206a15f51SAlexander Couzens 	l2tp_tunnel_dec_refcount(tunnel);
1263fd558d18SJames Chapman }
1264fd558d18SJames Chapman 
1265789a4a2cSJames Chapman /* Create a socket for the tunnel, if one isn't set up by
1266789a4a2cSJames Chapman  * userspace. This is used for static tunnels where there is no
1267789a4a2cSJames Chapman  * managing L2TP daemon.
1268167eb17eSTom Parkin  *
1269167eb17eSTom Parkin  * Since we don't want these sockets to keep a namespace alive by
1270167eb17eSTom Parkin  * themselves, we drop the socket's namespace refcount after creation.
1271167eb17eSTom Parkin  * These sockets are freed when the namespace exits using the pernet
1272167eb17eSTom Parkin  * exit hook.
1273789a4a2cSJames Chapman  */
l2tp_tunnel_sock_create(struct net * net,u32 tunnel_id,u32 peer_tunnel_id,struct l2tp_tunnel_cfg * cfg,struct socket ** sockp)1274167eb17eSTom Parkin static int l2tp_tunnel_sock_create(struct net *net,
1275167eb17eSTom Parkin 				   u32 tunnel_id,
1276167eb17eSTom Parkin 				   u32 peer_tunnel_id,
1277167eb17eSTom Parkin 				   struct l2tp_tunnel_cfg *cfg,
1278167eb17eSTom Parkin 				   struct socket **sockp)
1279789a4a2cSJames Chapman {
1280789a4a2cSJames Chapman 	int err = -EINVAL;
12817bddd0dbSEric Dumazet 	struct socket *sock = NULL;
128285644b4dSTom Herbert 	struct udp_port_cfg udp_conf;
1283789a4a2cSJames Chapman 
1284789a4a2cSJames Chapman 	switch (cfg->encap) {
1285789a4a2cSJames Chapman 	case L2TP_ENCAPTYPE_UDP:
128685644b4dSTom Herbert 		memset(&udp_conf, 0, sizeof(udp_conf));
128785644b4dSTom Herbert 
1288f9bac8dfSChris Elston #if IS_ENABLED(CONFIG_IPV6)
1289f9bac8dfSChris Elston 		if (cfg->local_ip6 && cfg->peer_ip6) {
129085644b4dSTom Herbert 			udp_conf.family = AF_INET6;
129185644b4dSTom Herbert 			memcpy(&udp_conf.local_ip6, cfg->local_ip6,
129285644b4dSTom Herbert 			       sizeof(udp_conf.local_ip6));
129385644b4dSTom Herbert 			memcpy(&udp_conf.peer_ip6, cfg->peer_ip6,
129485644b4dSTom Herbert 			       sizeof(udp_conf.peer_ip6));
129585644b4dSTom Herbert 			udp_conf.use_udp6_tx_checksums =
1296018f8258SWang Shanker 			  !cfg->udp6_zero_tx_checksums;
129785644b4dSTom Herbert 			udp_conf.use_udp6_rx_checksums =
1298018f8258SWang Shanker 			  !cfg->udp6_zero_rx_checksums;
1299f9bac8dfSChris Elston 		} else
1300f9bac8dfSChris Elston #endif
1301f9bac8dfSChris Elston 		{
130285644b4dSTom Herbert 			udp_conf.family = AF_INET;
130385644b4dSTom Herbert 			udp_conf.local_ip = cfg->local_ip;
130485644b4dSTom Herbert 			udp_conf.peer_ip = cfg->peer_ip;
130585644b4dSTom Herbert 			udp_conf.use_udp_checksums = cfg->use_udp_checksums;
1306f9bac8dfSChris Elston 		}
1307789a4a2cSJames Chapman 
130885644b4dSTom Herbert 		udp_conf.local_udp_port = htons(cfg->local_udp_port);
130985644b4dSTom Herbert 		udp_conf.peer_udp_port = htons(cfg->peer_udp_port);
131085644b4dSTom Herbert 
131185644b4dSTom Herbert 		err = udp_sock_create(net, &udp_conf, &sock);
131285644b4dSTom Herbert 		if (err < 0)
131385644b4dSTom Herbert 			goto out;
1314789a4a2cSJames Chapman 
1315789a4a2cSJames Chapman 		break;
1316789a4a2cSJames Chapman 
1317789a4a2cSJames Chapman 	case L2TP_ENCAPTYPE_IP:
1318f9bac8dfSChris Elston #if IS_ENABLED(CONFIG_IPV6)
1319f9bac8dfSChris Elston 		if (cfg->local_ip6 && cfg->peer_ip6) {
132085644b4dSTom Herbert 			struct sockaddr_l2tpip6 ip6_addr = {0};
132185644b4dSTom Herbert 
132226abe143SEric W. Biederman 			err = sock_create_kern(net, AF_INET6, SOCK_DGRAM,
1323167eb17eSTom Parkin 					       IPPROTO_L2TP, &sock);
13245dac94e1SJames Chapman 			if (err < 0)
1325f9bac8dfSChris Elston 				goto out;
13265dac94e1SJames Chapman 
13275dac94e1SJames Chapman 			ip6_addr.l2tp_family = AF_INET6;
13285dac94e1SJames Chapman 			memcpy(&ip6_addr.l2tp_addr, cfg->local_ip6,
13295dac94e1SJames Chapman 			       sizeof(ip6_addr.l2tp_addr));
13305dac94e1SJames Chapman 			ip6_addr.l2tp_conn_id = tunnel_id;
13315dac94e1SJames Chapman 			err = kernel_bind(sock, (struct sockaddr *)&ip6_addr,
13325dac94e1SJames Chapman 					  sizeof(ip6_addr));
13335dac94e1SJames Chapman 			if (err < 0)
13345dac94e1SJames Chapman 				goto out;
13355dac94e1SJames Chapman 
13365dac94e1SJames Chapman 			ip6_addr.l2tp_family = AF_INET6;
13375dac94e1SJames Chapman 			memcpy(&ip6_addr.l2tp_addr, cfg->peer_ip6,
13385dac94e1SJames Chapman 			       sizeof(ip6_addr.l2tp_addr));
13395dac94e1SJames Chapman 			ip6_addr.l2tp_conn_id = peer_tunnel_id;
13405dac94e1SJames Chapman 			err = kernel_connect(sock,
13415dac94e1SJames Chapman 					     (struct sockaddr *)&ip6_addr,
13425dac94e1SJames Chapman 					     sizeof(ip6_addr), 0);
13435dac94e1SJames Chapman 			if (err < 0)
13445dac94e1SJames Chapman 				goto out;
13455dac94e1SJames Chapman 		} else
1346f9bac8dfSChris Elston #endif
13475dac94e1SJames Chapman 		{
134885644b4dSTom Herbert 			struct sockaddr_l2tpip ip_addr = {0};
134985644b4dSTom Herbert 
135026abe143SEric W. Biederman 			err = sock_create_kern(net, AF_INET, SOCK_DGRAM,
1351167eb17eSTom Parkin 					       IPPROTO_L2TP, &sock);
1352789a4a2cSJames Chapman 			if (err < 0)
1353789a4a2cSJames Chapman 				goto out;
1354789a4a2cSJames Chapman 
1355789a4a2cSJames Chapman 			ip_addr.l2tp_family = AF_INET;
1356789a4a2cSJames Chapman 			ip_addr.l2tp_addr = cfg->local_ip;
1357789a4a2cSJames Chapman 			ip_addr.l2tp_conn_id = tunnel_id;
13585dac94e1SJames Chapman 			err = kernel_bind(sock, (struct sockaddr *)&ip_addr,
13595dac94e1SJames Chapman 					  sizeof(ip_addr));
1360789a4a2cSJames Chapman 			if (err < 0)
1361789a4a2cSJames Chapman 				goto out;
1362789a4a2cSJames Chapman 
1363789a4a2cSJames Chapman 			ip_addr.l2tp_family = AF_INET;
1364789a4a2cSJames Chapman 			ip_addr.l2tp_addr = cfg->peer_ip;
1365789a4a2cSJames Chapman 			ip_addr.l2tp_conn_id = peer_tunnel_id;
13665dac94e1SJames Chapman 			err = kernel_connect(sock, (struct sockaddr *)&ip_addr,
13675dac94e1SJames Chapman 					     sizeof(ip_addr), 0);
1368789a4a2cSJames Chapman 			if (err < 0)
1369789a4a2cSJames Chapman 				goto out;
13705dac94e1SJames Chapman 		}
1371789a4a2cSJames Chapman 		break;
1372789a4a2cSJames Chapman 
1373789a4a2cSJames Chapman 	default:
1374789a4a2cSJames Chapman 		goto out;
1375789a4a2cSJames Chapman 	}
1376789a4a2cSJames Chapman 
1377789a4a2cSJames Chapman out:
1378167eb17eSTom Parkin 	*sockp = sock;
13796c0ec37bSTom Parkin 	if (err < 0 && sock) {
1380167eb17eSTom Parkin 		kernel_sock_shutdown(sock, SHUT_RDWR);
138126abe143SEric W. Biederman 		sock_release(sock);
1382789a4a2cSJames Chapman 		*sockp = NULL;
1383789a4a2cSJames Chapman 	}
1384789a4a2cSJames Chapman 
1385789a4a2cSJames Chapman 	return err;
1386789a4a2cSJames Chapman }
1387789a4a2cSJames Chapman 
l2tp_tunnel_create(int fd,int version,u32 tunnel_id,u32 peer_tunnel_id,struct l2tp_tunnel_cfg * cfg,struct l2tp_tunnel ** tunnelp)1388c9ccd4c6STom Parkin int l2tp_tunnel_create(int fd, int version, u32 tunnel_id, u32 peer_tunnel_id,
1389c0235fb3STom Parkin 		       struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp)
1390fd558d18SJames Chapman {
1391fd558d18SJames Chapman 	struct l2tp_tunnel *tunnel = NULL;
1392fd558d18SJames Chapman 	int err;
13930d76751fSJames Chapman 	enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP;
1394fd558d18SJames Chapman 
13950febc7b3STom Parkin 	if (cfg)
13960d76751fSJames Chapman 		encap = cfg->encap;
13970d76751fSJames Chapman 
139870c05bfaSTom Parkin 	tunnel = kzalloc(sizeof(*tunnel), GFP_KERNEL);
13990febc7b3STom Parkin 	if (!tunnel) {
1400fd558d18SJames Chapman 		err = -ENOMEM;
1401fd558d18SJames Chapman 		goto err;
1402fd558d18SJames Chapman 	}
1403fd558d18SJames Chapman 
1404fd558d18SJames Chapman 	tunnel->version = version;
1405fd558d18SJames Chapman 	tunnel->tunnel_id = tunnel_id;
1406fd558d18SJames Chapman 	tunnel->peer_tunnel_id = peer_tunnel_id;
1407fd558d18SJames Chapman 
1408fd558d18SJames Chapman 	tunnel->magic = L2TP_TUNNEL_MAGIC;
1409fd558d18SJames Chapman 	sprintf(&tunnel->name[0], "tunl %u", tunnel_id);
141007b8ca37STom Parkin 	spin_lock_init(&tunnel->hlist_lock);
1411f3c66d4eSGuillaume Nault 	tunnel->acpt_newsess = true;
1412fd558d18SJames Chapman 
14130d76751fSJames Chapman 	tunnel->encap = encap;
1414fd558d18SJames Chapman 
1415d00fa9adSJames Chapman 	refcount_set(&tunnel->ref_count, 1);
1416d00fa9adSJames Chapman 	tunnel->fd = fd;
1417d00fa9adSJames Chapman 
1418f8ccac0eSTom Parkin 	/* Init delete workqueue struct */
1419f8ccac0eSTom Parkin 	INIT_WORK(&tunnel->del_work, l2tp_tunnel_del_work);
1420f8ccac0eSTom Parkin 
1421fd558d18SJames Chapman 	INIT_LIST_HEAD(&tunnel->list);
1422fd558d18SJames Chapman 
1423fd558d18SJames Chapman 	err = 0;
1424fd558d18SJames Chapman err:
1425fd558d18SJames Chapman 	if (tunnelp)
1426fd558d18SJames Chapman 		*tunnelp = tunnel;
1427fd558d18SJames Chapman 
1428fd558d18SJames Chapman 	return err;
1429fd558d18SJames Chapman }
1430fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
1431fd558d18SJames Chapman 
l2tp_validate_socket(const struct sock * sk,const struct net * net,enum l2tp_encap_type encap)14326b9f3423SGuillaume Nault static int l2tp_validate_socket(const struct sock *sk, const struct net *net,
14336b9f3423SGuillaume Nault 				enum l2tp_encap_type encap)
14346b9f3423SGuillaume Nault {
14356b9f3423SGuillaume Nault 	if (!net_eq(sock_net(sk), net))
14366b9f3423SGuillaume Nault 		return -EINVAL;
14376b9f3423SGuillaume Nault 
14386b9f3423SGuillaume Nault 	if (sk->sk_type != SOCK_DGRAM)
14396b9f3423SGuillaume Nault 		return -EPROTONOSUPPORT;
14406b9f3423SGuillaume Nault 
1441d9a81a22SEric Dumazet 	if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
1442d9a81a22SEric Dumazet 		return -EPROTONOSUPPORT;
1443d9a81a22SEric Dumazet 
14446b9f3423SGuillaume Nault 	if ((encap == L2TP_ENCAPTYPE_UDP && sk->sk_protocol != IPPROTO_UDP) ||
14456b9f3423SGuillaume Nault 	    (encap == L2TP_ENCAPTYPE_IP && sk->sk_protocol != IPPROTO_L2TP))
14466b9f3423SGuillaume Nault 		return -EPROTONOSUPPORT;
14476b9f3423SGuillaume Nault 
14486b9f3423SGuillaume Nault 	if (sk->sk_user_data)
14496b9f3423SGuillaume Nault 		return -EBUSY;
14506b9f3423SGuillaume Nault 
14516b9f3423SGuillaume Nault 	return 0;
14526b9f3423SGuillaume Nault }
14536b9f3423SGuillaume Nault 
l2tp_tunnel_register(struct l2tp_tunnel * tunnel,struct net * net,struct l2tp_tunnel_cfg * cfg)14546b9f3423SGuillaume Nault int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
14556b9f3423SGuillaume Nault 			 struct l2tp_tunnel_cfg *cfg)
14566b9f3423SGuillaume Nault {
1457c4d48a58SCong Wang 	struct l2tp_net *pn = l2tp_pernet(net);
1458c4d48a58SCong Wang 	u32 tunnel_id = tunnel->tunnel_id;
14596b9f3423SGuillaume Nault 	struct socket *sock;
14606b9f3423SGuillaume Nault 	struct sock *sk;
14616b9f3423SGuillaume Nault 	int ret;
14626b9f3423SGuillaume Nault 
1463c4d48a58SCong Wang 	spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
1464c4d48a58SCong Wang 	ret = idr_alloc_u32(&pn->l2tp_tunnel_idr, NULL, &tunnel_id, tunnel_id,
1465c4d48a58SCong Wang 			    GFP_ATOMIC);
1466c4d48a58SCong Wang 	spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
1467c4d48a58SCong Wang 	if (ret)
1468c4d48a58SCong Wang 		return ret == -ENOSPC ? -EEXIST : ret;
1469c4d48a58SCong Wang 
14706b9f3423SGuillaume Nault 	if (tunnel->fd < 0) {
14716b9f3423SGuillaume Nault 		ret = l2tp_tunnel_sock_create(net, tunnel->tunnel_id,
14726b9f3423SGuillaume Nault 					      tunnel->peer_tunnel_id, cfg,
14736b9f3423SGuillaume Nault 					      &sock);
14746b9f3423SGuillaume Nault 		if (ret < 0)
14756b9f3423SGuillaume Nault 			goto err;
14766b9f3423SGuillaume Nault 	} else {
14776b9f3423SGuillaume Nault 		sock = sockfd_lookup(tunnel->fd, &ret);
14786b9f3423SGuillaume Nault 		if (!sock)
14796b9f3423SGuillaume Nault 			goto err;
1480b68777d5SJakub Sitnicki 	}
14816b9f3423SGuillaume Nault 
1482b68777d5SJakub Sitnicki 	sk = sock->sk;
14830b2c5972SCong Wang 	lock_sock(sk);
1484af295e85SJakub Sitnicki 	write_lock_bh(&sk->sk_callback_lock);
1485b68777d5SJakub Sitnicki 	ret = l2tp_validate_socket(sk, net, tunnel->encap);
1486b9fb10d1SEric Dumazet 	if (ret < 0)
1487af295e85SJakub Sitnicki 		goto err_inval_sock;
1488af295e85SJakub Sitnicki 	rcu_assign_sk_user_data(sk, tunnel);
1489af295e85SJakub Sitnicki 	write_unlock_bh(&sk->sk_callback_lock);
14906b9f3423SGuillaume Nault 
14916b9f3423SGuillaume Nault 	if (tunnel->encap == L2TP_ENCAPTYPE_UDP) {
14926b9f3423SGuillaume Nault 		struct udp_tunnel_sock_cfg udp_cfg = {
14936b9f3423SGuillaume Nault 			.sk_user_data = tunnel,
14946b9f3423SGuillaume Nault 			.encap_type = UDP_ENCAP_L2TPINUDP,
14956b9f3423SGuillaume Nault 			.encap_rcv = l2tp_udp_encap_recv,
14966b9f3423SGuillaume Nault 			.encap_destroy = l2tp_udp_encap_destroy,
14976b9f3423SGuillaume Nault 		};
14986b9f3423SGuillaume Nault 
14996b9f3423SGuillaume Nault 		setup_udp_tunnel_sock(net, sock, &udp_cfg);
15006b9f3423SGuillaume Nault 	}
15016b9f3423SGuillaume Nault 
15026b9f3423SGuillaume Nault 	tunnel->old_sk_destruct = sk->sk_destruct;
15036b9f3423SGuillaume Nault 	sk->sk_destruct = &l2tp_tunnel_destruct;
15046b9f3423SGuillaume Nault 	sk->sk_allocation = GFP_ATOMIC;
15050b2c5972SCong Wang 	release_sock(sk);
15060b2c5972SCong Wang 
15070b2c5972SCong Wang 	sock_hold(sk);
15080b2c5972SCong Wang 	tunnel->sock = sk;
15090b2c5972SCong Wang 	tunnel->l2tp_net = net;
15100b2c5972SCong Wang 
15110b2c5972SCong Wang 	spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
15120b2c5972SCong Wang 	idr_replace(&pn->l2tp_tunnel_idr, tunnel, tunnel->tunnel_id);
15130b2c5972SCong Wang 	spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
15146b9f3423SGuillaume Nault 
15156b7bdcd7STom Parkin 	trace_register_tunnel(tunnel);
15166b7bdcd7STom Parkin 
15176b9f3423SGuillaume Nault 	if (tunnel->fd >= 0)
15186b9f3423SGuillaume Nault 		sockfd_put(sock);
15196b9f3423SGuillaume Nault 
15206b9f3423SGuillaume Nault 	return 0;
15216b9f3423SGuillaume Nault 
1522af295e85SJakub Sitnicki err_inval_sock:
1523af295e85SJakub Sitnicki 	write_unlock_bh(&sk->sk_callback_lock);
1524b9fb10d1SEric Dumazet 	release_sock(sk);
1525af295e85SJakub Sitnicki 
1526f6cd651bSGuillaume Nault 	if (tunnel->fd < 0)
1527f6cd651bSGuillaume Nault 		sock_release(sock);
1528f6cd651bSGuillaume Nault 	else
15296b9f3423SGuillaume Nault 		sockfd_put(sock);
15306b9f3423SGuillaume Nault err:
1531c4d48a58SCong Wang 	l2tp_tunnel_remove(net, tunnel);
15326b9f3423SGuillaume Nault 	return ret;
15336b9f3423SGuillaume Nault }
15346b9f3423SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_tunnel_register);
15356b9f3423SGuillaume Nault 
1536309795f4SJames Chapman /* This function is used by the netlink TUNNEL_DELETE command.
1537309795f4SJames Chapman  */
l2tp_tunnel_delete(struct l2tp_tunnel * tunnel)153862b982eeSSabrina Dubroca void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
1539309795f4SJames Chapman {
154062b982eeSSabrina Dubroca 	if (!test_and_set_bit(0, &tunnel->dead)) {
15416b7bdcd7STom Parkin 		trace_delete_tunnel(tunnel);
154206a15f51SAlexander Couzens 		l2tp_tunnel_inc_refcount(tunnel);
154362b982eeSSabrina Dubroca 		queue_work(l2tp_wq, &tunnel->del_work);
154406a15f51SAlexander Couzens 	}
1545309795f4SJames Chapman }
1546309795f4SJames Chapman EXPORT_SYMBOL_GPL(l2tp_tunnel_delete);
1547309795f4SJames Chapman 
l2tp_session_delete(struct l2tp_session * session)1548628703f5STom Parkin void l2tp_session_delete(struct l2tp_session *session)
1549309795f4SJames Chapman {
1550b228a940SGuillaume Nault 	if (test_and_set_bit(0, &session->dead))
1551628703f5STom Parkin 		return;
1552b228a940SGuillaume Nault 
15536b7bdcd7STom Parkin 	trace_delete_session(session);
1554b2aecfe8STom Parkin 	l2tp_session_unhash(session);
15554c6e2fd3STom Parkin 	l2tp_session_queue_purge(session);
15560febc7b3STom Parkin 	if (session->session_close)
1557309795f4SJames Chapman 		(*session->session_close)(session);
1558a4346210SGuillaume Nault 
1559309795f4SJames Chapman 	l2tp_session_dec_refcount(session);
1560309795f4SJames Chapman }
1561309795f4SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_delete);
1562309795f4SJames Chapman 
1563f7faffa3SJames Chapman /* We come here whenever a session's send_seq, cookie_len or
156462e7b6a5SLorenzo Bianconi  * l2specific_type parameters are set.
1565f7faffa3SJames Chapman  */
l2tp_session_set_header_len(struct l2tp_session * session,int version)1566bb5016eaSGuillaume Nault void l2tp_session_set_header_len(struct l2tp_session *session, int version)
1567f7faffa3SJames Chapman {
1568f7faffa3SJames Chapman 	if (version == L2TP_HDR_VER_2) {
1569f7faffa3SJames Chapman 		session->hdr_len = 6;
1570f7faffa3SJames Chapman 		if (session->send_seq)
1571f7faffa3SJames Chapman 			session->hdr_len += 4;
1572f7faffa3SJames Chapman 	} else {
157362e7b6a5SLorenzo Bianconi 		session->hdr_len = 4 + session->cookie_len;
157462e7b6a5SLorenzo Bianconi 		session->hdr_len += l2tp_get_l2specific_len(session);
15750d76751fSJames Chapman 		if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP)
15760d76751fSJames Chapman 			session->hdr_len += 4;
1577f7faffa3SJames Chapman 	}
1578f7faffa3SJames Chapman }
1579bb5016eaSGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_set_header_len);
1580f7faffa3SJames Chapman 
l2tp_session_create(int priv_size,struct l2tp_tunnel * tunnel,u32 session_id,u32 peer_session_id,struct l2tp_session_cfg * cfg)1581c0235fb3STom Parkin struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id,
1582c0235fb3STom Parkin 					 u32 peer_session_id, struct l2tp_session_cfg *cfg)
1583fd558d18SJames Chapman {
1584fd558d18SJames Chapman 	struct l2tp_session *session;
1585fd558d18SJames Chapman 
158670c05bfaSTom Parkin 	session = kzalloc(sizeof(*session) + priv_size, GFP_KERNEL);
15870febc7b3STom Parkin 	if (session) {
1588fd558d18SJames Chapman 		session->magic = L2TP_SESSION_MAGIC;
1589fd558d18SJames Chapman 		session->tunnel = tunnel;
1590fd558d18SJames Chapman 
1591fd558d18SJames Chapman 		session->session_id = session_id;
1592fd558d18SJames Chapman 		session->peer_session_id = peer_session_id;
1593d301e325SJames Chapman 		session->nr = 0;
15948a1631d5SJames Chapman 		if (tunnel->version == L2TP_HDR_VER_2)
15958a1631d5SJames Chapman 			session->nr_max = 0xffff;
15968a1631d5SJames Chapman 		else
15978a1631d5SJames Chapman 			session->nr_max = 0xffffff;
15988a1631d5SJames Chapman 		session->nr_window_size = session->nr_max / 2;
1599a0dbd822SJames Chapman 		session->nr_oos_count_max = 4;
1600a0dbd822SJames Chapman 
1601a0dbd822SJames Chapman 		/* Use NR of first received packet */
1602a0dbd822SJames Chapman 		session->reorder_skip = 1;
1603fd558d18SJames Chapman 
1604fd558d18SJames Chapman 		sprintf(&session->name[0], "sess %u/%u",
1605fd558d18SJames Chapman 			tunnel->tunnel_id, session->session_id);
1606fd558d18SJames Chapman 
1607fd558d18SJames Chapman 		skb_queue_head_init(&session->reorder_q);
1608fd558d18SJames Chapman 
1609fd558d18SJames Chapman 		INIT_HLIST_NODE(&session->hlist);
1610f7faffa3SJames Chapman 		INIT_HLIST_NODE(&session->global_hlist);
1611fd558d18SJames Chapman 
1612fd558d18SJames Chapman 		if (cfg) {
1613f7faffa3SJames Chapman 			session->pwtype = cfg->pw_type;
1614fd558d18SJames Chapman 			session->send_seq = cfg->send_seq;
1615fd558d18SJames Chapman 			session->recv_seq = cfg->recv_seq;
1616fd558d18SJames Chapman 			session->lns_mode = cfg->lns_mode;
1617f7faffa3SJames Chapman 			session->reorder_timeout = cfg->reorder_timeout;
1618f7faffa3SJames Chapman 			session->l2specific_type = cfg->l2specific_type;
1619f7faffa3SJames Chapman 			session->cookie_len = cfg->cookie_len;
1620f7faffa3SJames Chapman 			memcpy(&session->cookie[0], &cfg->cookie[0], cfg->cookie_len);
1621f7faffa3SJames Chapman 			session->peer_cookie_len = cfg->peer_cookie_len;
1622f7faffa3SJames Chapman 			memcpy(&session->peer_cookie[0], &cfg->peer_cookie[0], cfg->peer_cookie_len);
1623fd558d18SJames Chapman 		}
1624fd558d18SJames Chapman 
1625f7faffa3SJames Chapman 		l2tp_session_set_header_len(session, tunnel->version);
1626f7faffa3SJames Chapman 
16279ee369a4SGuillaume Nault 		refcount_set(&session->ref_count, 1);
16289ee369a4SGuillaume Nault 
1629fd558d18SJames Chapman 		return session;
1630fd558d18SJames Chapman 	}
1631dbdbc73bSGuillaume Nault 
1632dbdbc73bSGuillaume Nault 	return ERR_PTR(-ENOMEM);
1633dbdbc73bSGuillaume Nault }
1634fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_create);
1635fd558d18SJames Chapman 
1636fd558d18SJames Chapman /*****************************************************************************
1637fd558d18SJames Chapman  * Init and cleanup
1638fd558d18SJames Chapman  *****************************************************************************/
1639fd558d18SJames Chapman 
l2tp_init_net(struct net * net)1640fd558d18SJames Chapman static __net_init int l2tp_init_net(struct net *net)
1641fd558d18SJames Chapman {
1642e773aaffSJiri Pirko 	struct l2tp_net *pn = net_generic(net, l2tp_net_id);
1643f7faffa3SJames Chapman 	int hash;
1644fd558d18SJames Chapman 
1645c4d48a58SCong Wang 	idr_init(&pn->l2tp_tunnel_idr);
1646c4d48a58SCong Wang 	spin_lock_init(&pn->l2tp_tunnel_idr_lock);
1647fd558d18SJames Chapman 
1648f7faffa3SJames Chapman 	for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++)
1649f7faffa3SJames Chapman 		INIT_HLIST_HEAD(&pn->l2tp_session_hlist[hash]);
1650f7faffa3SJames Chapman 
1651e02d494dSJames Chapman 	spin_lock_init(&pn->l2tp_session_hlist_lock);
1652f7faffa3SJames Chapman 
1653fd558d18SJames Chapman 	return 0;
1654fd558d18SJames Chapman }
1655fd558d18SJames Chapman 
l2tp_exit_net(struct net * net)1656167eb17eSTom Parkin static __net_exit void l2tp_exit_net(struct net *net)
1657167eb17eSTom Parkin {
1658167eb17eSTom Parkin 	struct l2tp_net *pn = l2tp_pernet(net);
1659167eb17eSTom Parkin 	struct l2tp_tunnel *tunnel = NULL;
1660c4d48a58SCong Wang 	unsigned long tunnel_id, tmp;
16611e7af3b2SVasily Averin 	int hash;
1662167eb17eSTom Parkin 
1663167eb17eSTom Parkin 	rcu_read_lock_bh();
1664c4d48a58SCong Wang 	idr_for_each_entry_ul(&pn->l2tp_tunnel_idr, tunnel, tmp, tunnel_id) {
1665c4d48a58SCong Wang 		if (tunnel)
16664dc12ffeSJiri Slaby 			l2tp_tunnel_delete(tunnel);
1667167eb17eSTom Parkin 	}
1668167eb17eSTom Parkin 	rcu_read_unlock_bh();
16692f86953eSSabrina Dubroca 
1670638a3a1eSYueHaibing 	if (l2tp_wq)
16712f86953eSSabrina Dubroca 		flush_workqueue(l2tp_wq);
16722f86953eSSabrina Dubroca 	rcu_barrier();
16731e7af3b2SVasily Averin 
16741e7af3b2SVasily Averin 	for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++)
16751e7af3b2SVasily Averin 		WARN_ON_ONCE(!hlist_empty(&pn->l2tp_session_hlist[hash]));
1676c4d48a58SCong Wang 	idr_destroy(&pn->l2tp_tunnel_idr);
1677167eb17eSTom Parkin }
1678167eb17eSTom Parkin 
1679fd558d18SJames Chapman static struct pernet_operations l2tp_net_ops = {
1680fd558d18SJames Chapman 	.init = l2tp_init_net,
1681167eb17eSTom Parkin 	.exit = l2tp_exit_net,
1682fd558d18SJames Chapman 	.id   = &l2tp_net_id,
1683fd558d18SJames Chapman 	.size = sizeof(struct l2tp_net),
1684fd558d18SJames Chapman };
1685fd558d18SJames Chapman 
l2tp_init(void)1686fd558d18SJames Chapman static int __init l2tp_init(void)
1687fd558d18SJames Chapman {
1688fd558d18SJames Chapman 	int rc = 0;
1689fd558d18SJames Chapman 
1690fd558d18SJames Chapman 	rc = register_pernet_device(&l2tp_net_ops);
1691fd558d18SJames Chapman 	if (rc)
1692fd558d18SJames Chapman 		goto out;
1693fd558d18SJames Chapman 
169459ff3eb6SZhangZhen 	l2tp_wq = alloc_workqueue("l2tp", WQ_UNBOUND, 0);
1695f8ccac0eSTom Parkin 	if (!l2tp_wq) {
1696f8ccac0eSTom Parkin 		pr_err("alloc_workqueue failed\n");
169767e04c29SWANG Cong 		unregister_pernet_device(&l2tp_net_ops);
1698f8ccac0eSTom Parkin 		rc = -ENOMEM;
1699f8ccac0eSTom Parkin 		goto out;
1700f8ccac0eSTom Parkin 	}
1701f8ccac0eSTom Parkin 
1702a4ca44faSJoe Perches 	pr_info("L2TP core driver, %s\n", L2TP_DRV_VERSION);
1703fd558d18SJames Chapman 
1704fd558d18SJames Chapman out:
1705fd558d18SJames Chapman 	return rc;
1706fd558d18SJames Chapman }
1707fd558d18SJames Chapman 
l2tp_exit(void)1708fd558d18SJames Chapman static void __exit l2tp_exit(void)
1709fd558d18SJames Chapman {
1710fd558d18SJames Chapman 	unregister_pernet_device(&l2tp_net_ops);
1711f8ccac0eSTom Parkin 	if (l2tp_wq) {
1712f8ccac0eSTom Parkin 		destroy_workqueue(l2tp_wq);
1713f8ccac0eSTom Parkin 		l2tp_wq = NULL;
1714f8ccac0eSTom Parkin 	}
1715fd558d18SJames Chapman }
1716fd558d18SJames Chapman 
1717fd558d18SJames Chapman module_init(l2tp_init);
1718fd558d18SJames Chapman module_exit(l2tp_exit);
1719fd558d18SJames Chapman 
1720fd558d18SJames Chapman MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
1721fd558d18SJames Chapman MODULE_DESCRIPTION("L2TP core");
1722fd558d18SJames Chapman MODULE_LICENSE("GPL");
1723fd558d18SJames Chapman MODULE_VERSION(L2TP_DRV_VERSION);
1724