xref: /openbmc/linux/net/l2tp/l2tp_core.c (revision 6b7bdcd7)
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 {
107fd558d18SJames Chapman 	struct list_head l2tp_tunnel_list;
10820dcb110STom Parkin 	/* Lock for write access to l2tp_tunnel_list */
109e02d494dSJames Chapman 	spinlock_t l2tp_tunnel_list_lock;
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)
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 
1238d8a51e2SDavid S. Miller static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk)
1248d8a51e2SDavid S. Miller {
1258d8a51e2SDavid S. Miller 	return sk->sk_user_data;
1268d8a51e2SDavid S. Miller }
1278d8a51e2SDavid S. Miller 
1289aaef50cSGuillaume Nault static inline struct l2tp_net *l2tp_pernet(const struct net *net)
129fd558d18SJames Chapman {
130fd558d18SJames Chapman 	return net_generic(net, l2tp_net_id);
131fd558d18SJames Chapman }
132fd558d18SJames Chapman 
133f7faffa3SJames Chapman /* Session hash global list for L2TPv3.
134f7faffa3SJames Chapman  * The session_id SHOULD be random according to RFC3931, but several
135f7faffa3SJames Chapman  * L2TP implementations use incrementing session_ids.  So we do a real
136f7faffa3SJames Chapman  * hash on the session_id, rather than a simple bitmask.
137f7faffa3SJames Chapman  */
138f7faffa3SJames Chapman static inline struct hlist_head *
139f7faffa3SJames Chapman l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id)
140f7faffa3SJames Chapman {
141f7faffa3SJames Chapman 	return &pn->l2tp_session_hlist[hash_32(session_id, L2TP_HASH_BITS_2)];
142f7faffa3SJames Chapman }
143f7faffa3SJames Chapman 
144fd558d18SJames Chapman /* Session hash list.
145fd558d18SJames Chapman  * The session_id SHOULD be random according to RFC2661, but several
146fd558d18SJames Chapman  * L2TP implementations (Cisco and Microsoft) use incrementing
147fd558d18SJames Chapman  * session_ids.  So we do a real hash on the session_id, rather than a
148fd558d18SJames Chapman  * simple bitmask.
149fd558d18SJames Chapman  */
150fd558d18SJames Chapman static inline struct hlist_head *
151fd558d18SJames Chapman l2tp_session_id_hash(struct l2tp_tunnel *tunnel, u32 session_id)
152fd558d18SJames Chapman {
153fd558d18SJames Chapman 	return &tunnel->session_hlist[hash_32(session_id, L2TP_HASH_BITS)];
154fd558d18SJames Chapman }
155fd558d18SJames Chapman 
15652016e25STom Parkin static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
157d00fa9adSJames Chapman {
1586b7bdcd7STom Parkin 	trace_free_tunnel(tunnel);
159d00fa9adSJames Chapman 	sock_put(tunnel->sock);
160d00fa9adSJames Chapman 	/* the tunnel is freed in the socket destructor */
161d00fa9adSJames Chapman }
16252016e25STom Parkin 
16352016e25STom Parkin static void l2tp_session_free(struct l2tp_session *session)
16452016e25STom Parkin {
16552016e25STom Parkin 	struct l2tp_tunnel *tunnel = session->tunnel;
16652016e25STom Parkin 
1676b7bdcd7STom Parkin 	trace_free_session(session);
1686b7bdcd7STom Parkin 
16952016e25STom Parkin 	if (tunnel) {
17052016e25STom Parkin 		if (WARN_ON(tunnel->magic != L2TP_TUNNEL_MAGIC))
17152016e25STom Parkin 			goto out;
17252016e25STom Parkin 		l2tp_tunnel_dec_refcount(tunnel);
17352016e25STom Parkin 	}
17452016e25STom Parkin 
17552016e25STom Parkin out:
17652016e25STom Parkin 	kfree(session);
17752016e25STom Parkin }
17852016e25STom Parkin 
17952016e25STom Parkin void l2tp_tunnel_inc_refcount(struct l2tp_tunnel *tunnel)
18052016e25STom Parkin {
18152016e25STom Parkin 	refcount_inc(&tunnel->ref_count);
18252016e25STom Parkin }
18352016e25STom Parkin EXPORT_SYMBOL_GPL(l2tp_tunnel_inc_refcount);
18452016e25STom Parkin 
18552016e25STom Parkin void l2tp_tunnel_dec_refcount(struct l2tp_tunnel *tunnel)
18652016e25STom Parkin {
18752016e25STom Parkin 	if (refcount_dec_and_test(&tunnel->ref_count))
18852016e25STom Parkin 		l2tp_tunnel_free(tunnel);
18952016e25STom Parkin }
19052016e25STom Parkin EXPORT_SYMBOL_GPL(l2tp_tunnel_dec_refcount);
19152016e25STom Parkin 
19252016e25STom Parkin void l2tp_session_inc_refcount(struct l2tp_session *session)
19352016e25STom Parkin {
19452016e25STom Parkin 	refcount_inc(&session->ref_count);
19552016e25STom Parkin }
19652016e25STom Parkin EXPORT_SYMBOL_GPL(l2tp_session_inc_refcount);
19752016e25STom Parkin 
19852016e25STom Parkin void l2tp_session_dec_refcount(struct l2tp_session *session)
19952016e25STom Parkin {
20052016e25STom Parkin 	if (refcount_dec_and_test(&session->ref_count))
20152016e25STom Parkin 		l2tp_session_free(session);
20252016e25STom Parkin }
20352016e25STom Parkin EXPORT_SYMBOL_GPL(l2tp_session_dec_refcount);
204d00fa9adSJames Chapman 
20554652eb1SGuillaume Nault /* Lookup a tunnel. A new reference is held on the returned tunnel. */
20654652eb1SGuillaume Nault struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, u32 tunnel_id)
20754652eb1SGuillaume Nault {
20854652eb1SGuillaume Nault 	const struct l2tp_net *pn = l2tp_pernet(net);
20954652eb1SGuillaume Nault 	struct l2tp_tunnel *tunnel;
21054652eb1SGuillaume Nault 
21154652eb1SGuillaume Nault 	rcu_read_lock_bh();
21254652eb1SGuillaume Nault 	list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
213a622b400SEric Dumazet 		if (tunnel->tunnel_id == tunnel_id &&
214a622b400SEric Dumazet 		    refcount_inc_not_zero(&tunnel->ref_count)) {
21554652eb1SGuillaume Nault 			rcu_read_unlock_bh();
21654652eb1SGuillaume Nault 
21754652eb1SGuillaume Nault 			return tunnel;
21854652eb1SGuillaume Nault 		}
21954652eb1SGuillaume Nault 	}
22054652eb1SGuillaume Nault 	rcu_read_unlock_bh();
22154652eb1SGuillaume Nault 
22254652eb1SGuillaume Nault 	return NULL;
22354652eb1SGuillaume Nault }
22454652eb1SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_tunnel_get);
22554652eb1SGuillaume Nault 
2265846c131SGuillaume Nault struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth)
2275846c131SGuillaume Nault {
2285846c131SGuillaume Nault 	const struct l2tp_net *pn = l2tp_pernet(net);
2295846c131SGuillaume Nault 	struct l2tp_tunnel *tunnel;
2305846c131SGuillaume Nault 	int count = 0;
2315846c131SGuillaume Nault 
2325846c131SGuillaume Nault 	rcu_read_lock_bh();
2335846c131SGuillaume Nault 	list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
234a622b400SEric Dumazet 		if (++count > nth &&
235a622b400SEric Dumazet 		    refcount_inc_not_zero(&tunnel->ref_count)) {
2365846c131SGuillaume Nault 			rcu_read_unlock_bh();
2375846c131SGuillaume Nault 			return tunnel;
2385846c131SGuillaume Nault 		}
2395846c131SGuillaume Nault 	}
2405846c131SGuillaume Nault 	rcu_read_unlock_bh();
2415846c131SGuillaume Nault 
2425846c131SGuillaume Nault 	return NULL;
2435846c131SGuillaume Nault }
2445846c131SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_tunnel_get_nth);
2455846c131SGuillaume Nault 
24601e28b92SGuillaume Nault struct l2tp_session *l2tp_tunnel_get_session(struct l2tp_tunnel *tunnel,
247a4346210SGuillaume Nault 					     u32 session_id)
24861b9a047SGuillaume Nault {
24961b9a047SGuillaume Nault 	struct hlist_head *session_list;
25061b9a047SGuillaume Nault 	struct l2tp_session *session;
25161b9a047SGuillaume Nault 
25201e28b92SGuillaume Nault 	session_list = l2tp_session_id_hash(tunnel, session_id);
25361b9a047SGuillaume Nault 
25401e28b92SGuillaume Nault 	read_lock_bh(&tunnel->hlist_lock);
25501e28b92SGuillaume Nault 	hlist_for_each_entry(session, session_list, hlist)
25661b9a047SGuillaume Nault 		if (session->session_id == session_id) {
25761b9a047SGuillaume Nault 			l2tp_session_inc_refcount(session);
25801e28b92SGuillaume Nault 			read_unlock_bh(&tunnel->hlist_lock);
25961b9a047SGuillaume Nault 
26061b9a047SGuillaume Nault 			return session;
26161b9a047SGuillaume Nault 		}
26201e28b92SGuillaume Nault 	read_unlock_bh(&tunnel->hlist_lock);
26361b9a047SGuillaume Nault 
26461b9a047SGuillaume Nault 	return NULL;
26561b9a047SGuillaume Nault }
26601e28b92SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_tunnel_get_session);
26761b9a047SGuillaume Nault 
26801e28b92SGuillaume Nault struct l2tp_session *l2tp_session_get(const struct net *net, u32 session_id)
26901e28b92SGuillaume Nault {
27001e28b92SGuillaume Nault 	struct hlist_head *session_list;
27101e28b92SGuillaume Nault 	struct l2tp_session *session;
27201e28b92SGuillaume Nault 
27301e28b92SGuillaume Nault 	session_list = l2tp_session_id_hash_2(l2tp_pernet(net), session_id);
27401e28b92SGuillaume Nault 
27501e28b92SGuillaume Nault 	rcu_read_lock_bh();
27601e28b92SGuillaume Nault 	hlist_for_each_entry_rcu(session, session_list, global_hlist)
27761b9a047SGuillaume Nault 		if (session->session_id == session_id) {
27861b9a047SGuillaume Nault 			l2tp_session_inc_refcount(session);
27901e28b92SGuillaume Nault 			rcu_read_unlock_bh();
28061b9a047SGuillaume Nault 
28161b9a047SGuillaume Nault 			return session;
28261b9a047SGuillaume Nault 		}
28301e28b92SGuillaume Nault 	rcu_read_unlock_bh();
28461b9a047SGuillaume Nault 
28561b9a047SGuillaume Nault 	return NULL;
28661b9a047SGuillaume Nault }
28761b9a047SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_get);
28861b9a047SGuillaume Nault 
289a4346210SGuillaume Nault struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth)
290fd558d18SJames Chapman {
291fd558d18SJames Chapman 	int hash;
292fd558d18SJames Chapman 	struct l2tp_session *session;
293fd558d18SJames Chapman 	int count = 0;
294fd558d18SJames Chapman 
295fd558d18SJames Chapman 	read_lock_bh(&tunnel->hlist_lock);
296fd558d18SJames Chapman 	for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
297b67bfe0dSSasha Levin 		hlist_for_each_entry(session, &tunnel->session_hlist[hash], hlist) {
298fd558d18SJames Chapman 			if (++count > nth) {
299e08293a4SGuillaume Nault 				l2tp_session_inc_refcount(session);
300fd558d18SJames Chapman 				read_unlock_bh(&tunnel->hlist_lock);
301fd558d18SJames Chapman 				return session;
302fd558d18SJames Chapman 			}
303fd558d18SJames Chapman 		}
304fd558d18SJames Chapman 	}
305fd558d18SJames Chapman 
306fd558d18SJames Chapman 	read_unlock_bh(&tunnel->hlist_lock);
307fd558d18SJames Chapman 
308fd558d18SJames Chapman 	return NULL;
309fd558d18SJames Chapman }
310e08293a4SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_get_nth);
311fd558d18SJames Chapman 
312309795f4SJames Chapman /* Lookup a session by interface name.
313309795f4SJames Chapman  * This is very inefficient but is only used by management interfaces.
314309795f4SJames Chapman  */
3159aaef50cSGuillaume Nault struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net,
316a4346210SGuillaume Nault 						const char *ifname)
317309795f4SJames Chapman {
318309795f4SJames Chapman 	struct l2tp_net *pn = l2tp_pernet(net);
319309795f4SJames Chapman 	int hash;
320309795f4SJames Chapman 	struct l2tp_session *session;
321309795f4SJames Chapman 
322e02d494dSJames Chapman 	rcu_read_lock_bh();
323309795f4SJames Chapman 	for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) {
324b67bfe0dSSasha Levin 		hlist_for_each_entry_rcu(session, &pn->l2tp_session_hlist[hash], global_hlist) {
325309795f4SJames Chapman 			if (!strcmp(session->ifname, ifname)) {
3262777e2abSGuillaume Nault 				l2tp_session_inc_refcount(session);
327e02d494dSJames Chapman 				rcu_read_unlock_bh();
3282777e2abSGuillaume Nault 
329309795f4SJames Chapman 				return session;
330309795f4SJames Chapman 			}
331309795f4SJames Chapman 		}
332309795f4SJames Chapman 	}
333309795f4SJames Chapman 
334e02d494dSJames Chapman 	rcu_read_unlock_bh();
335309795f4SJames Chapman 
336309795f4SJames Chapman 	return NULL;
337309795f4SJames Chapman }
3382777e2abSGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_get_by_ifname);
339309795f4SJames Chapman 
3403953ae7bSGuillaume Nault int l2tp_session_register(struct l2tp_session *session,
3413953ae7bSGuillaume Nault 			  struct l2tp_tunnel *tunnel)
342dbdbc73bSGuillaume Nault {
343dbdbc73bSGuillaume Nault 	struct l2tp_session *session_walk;
344dbdbc73bSGuillaume Nault 	struct hlist_head *g_head;
345dbdbc73bSGuillaume Nault 	struct hlist_head *head;
346dbdbc73bSGuillaume Nault 	struct l2tp_net *pn;
347f3c66d4eSGuillaume Nault 	int err;
348dbdbc73bSGuillaume Nault 
349dbdbc73bSGuillaume Nault 	head = l2tp_session_id_hash(tunnel, session->session_id);
350dbdbc73bSGuillaume Nault 
351dbdbc73bSGuillaume Nault 	write_lock_bh(&tunnel->hlist_lock);
352f3c66d4eSGuillaume Nault 	if (!tunnel->acpt_newsess) {
353f3c66d4eSGuillaume Nault 		err = -ENODEV;
354f3c66d4eSGuillaume Nault 		goto err_tlock;
355f3c66d4eSGuillaume Nault 	}
356f3c66d4eSGuillaume Nault 
357dbdbc73bSGuillaume Nault 	hlist_for_each_entry(session_walk, head, hlist)
358f3c66d4eSGuillaume Nault 		if (session_walk->session_id == session->session_id) {
359f3c66d4eSGuillaume Nault 			err = -EEXIST;
360f3c66d4eSGuillaume Nault 			goto err_tlock;
361f3c66d4eSGuillaume Nault 		}
362dbdbc73bSGuillaume Nault 
363dbdbc73bSGuillaume Nault 	if (tunnel->version == L2TP_HDR_VER_3) {
364dbdbc73bSGuillaume Nault 		pn = l2tp_pernet(tunnel->l2tp_net);
365363a341dSGuillaume Nault 		g_head = l2tp_session_id_hash_2(pn, session->session_id);
366dbdbc73bSGuillaume Nault 
367dbdbc73bSGuillaume Nault 		spin_lock_bh(&pn->l2tp_session_hlist_lock);
368dbdbc73bSGuillaume Nault 
3690d0d9a38SRidge Kennedy 		/* IP encap expects session IDs to be globally unique, while
3700d0d9a38SRidge Kennedy 		 * UDP encap doesn't.
3710d0d9a38SRidge Kennedy 		 */
372f3c66d4eSGuillaume Nault 		hlist_for_each_entry(session_walk, g_head, global_hlist)
3730d0d9a38SRidge Kennedy 			if (session_walk->session_id == session->session_id &&
3740d0d9a38SRidge Kennedy 			    (session_walk->tunnel->encap == L2TP_ENCAPTYPE_IP ||
3750d0d9a38SRidge Kennedy 			     tunnel->encap == L2TP_ENCAPTYPE_IP)) {
376f3c66d4eSGuillaume Nault 				err = -EEXIST;
377f3c66d4eSGuillaume Nault 				goto err_tlock_pnlock;
378f3c66d4eSGuillaume Nault 			}
379f3c66d4eSGuillaume Nault 
380f3c66d4eSGuillaume Nault 		l2tp_tunnel_inc_refcount(tunnel);
381dbdbc73bSGuillaume Nault 		hlist_add_head_rcu(&session->global_hlist, g_head);
382f3c66d4eSGuillaume Nault 
383dbdbc73bSGuillaume Nault 		spin_unlock_bh(&pn->l2tp_session_hlist_lock);
384f3c66d4eSGuillaume Nault 	} else {
385f3c66d4eSGuillaume Nault 		l2tp_tunnel_inc_refcount(tunnel);
386dbdbc73bSGuillaume Nault 	}
387dbdbc73bSGuillaume Nault 
388dbdbc73bSGuillaume Nault 	hlist_add_head(&session->hlist, head);
389dbdbc73bSGuillaume Nault 	write_unlock_bh(&tunnel->hlist_lock);
390dbdbc73bSGuillaume Nault 
3916b7bdcd7STom Parkin 	trace_register_session(session);
3926b7bdcd7STom Parkin 
393dbdbc73bSGuillaume Nault 	return 0;
394dbdbc73bSGuillaume Nault 
395f3c66d4eSGuillaume Nault err_tlock_pnlock:
396dbdbc73bSGuillaume Nault 	spin_unlock_bh(&pn->l2tp_session_hlist_lock);
397f3c66d4eSGuillaume Nault err_tlock:
398dbdbc73bSGuillaume Nault 	write_unlock_bh(&tunnel->hlist_lock);
399dbdbc73bSGuillaume Nault 
400f3c66d4eSGuillaume Nault 	return err;
401dbdbc73bSGuillaume Nault }
4023953ae7bSGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_register);
403dbdbc73bSGuillaume Nault 
404fd558d18SJames Chapman /*****************************************************************************
405fd558d18SJames Chapman  * Receive data handling
406fd558d18SJames Chapman  *****************************************************************************/
407fd558d18SJames Chapman 
408fd558d18SJames Chapman /* Queue a skb in order. We come here only if the skb has an L2TP sequence
409fd558d18SJames Chapman  * number.
410fd558d18SJames Chapman  */
411fd558d18SJames Chapman static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *skb)
412fd558d18SJames Chapman {
413fd558d18SJames Chapman 	struct sk_buff *skbp;
414fd558d18SJames Chapman 	struct sk_buff *tmp;
415f7faffa3SJames Chapman 	u32 ns = L2TP_SKB_CB(skb)->ns;
416fd558d18SJames Chapman 
417fd558d18SJames Chapman 	spin_lock_bh(&session->reorder_q.lock);
418fd558d18SJames Chapman 	skb_queue_walk_safe(&session->reorder_q, skbp, tmp) {
419fd558d18SJames Chapman 		if (L2TP_SKB_CB(skbp)->ns > ns) {
420fd558d18SJames Chapman 			__skb_queue_before(&session->reorder_q, skbp, skb);
4217b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_oos_packets);
422fd558d18SJames Chapman 			goto out;
423fd558d18SJames Chapman 		}
424fd558d18SJames Chapman 	}
425fd558d18SJames Chapman 
426fd558d18SJames Chapman 	__skb_queue_tail(&session->reorder_q, skb);
427fd558d18SJames Chapman 
428fd558d18SJames Chapman out:
429fd558d18SJames Chapman 	spin_unlock_bh(&session->reorder_q.lock);
430fd558d18SJames Chapman }
431fd558d18SJames Chapman 
432fd558d18SJames Chapman /* Dequeue a single skb.
433fd558d18SJames Chapman  */
434fd558d18SJames Chapman static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff *skb)
435fd558d18SJames Chapman {
436fd558d18SJames Chapman 	struct l2tp_tunnel *tunnel = session->tunnel;
437fd558d18SJames Chapman 	int length = L2TP_SKB_CB(skb)->length;
438fd558d18SJames Chapman 
439fd558d18SJames Chapman 	/* We're about to requeue the skb, so return resources
440fd558d18SJames Chapman 	 * to its current owner (a socket receive buffer).
441fd558d18SJames Chapman 	 */
442fd558d18SJames Chapman 	skb_orphan(skb);
443fd558d18SJames Chapman 
4447b7c0719STom Parkin 	atomic_long_inc(&tunnel->stats.rx_packets);
4457b7c0719STom Parkin 	atomic_long_add(length, &tunnel->stats.rx_bytes);
4467b7c0719STom Parkin 	atomic_long_inc(&session->stats.rx_packets);
4477b7c0719STom Parkin 	atomic_long_add(length, &session->stats.rx_bytes);
448fd558d18SJames Chapman 
449fd558d18SJames Chapman 	if (L2TP_SKB_CB(skb)->has_seq) {
450fd558d18SJames Chapman 		/* Bump our Nr */
451fd558d18SJames Chapman 		session->nr++;
4528a1631d5SJames Chapman 		session->nr &= session->nr_max;
4536b7bdcd7STom Parkin 		trace_session_seqnum_update(session);
454fd558d18SJames Chapman 	}
455fd558d18SJames Chapman 
456fd558d18SJames Chapman 	/* call private receive handler */
4570febc7b3STom Parkin 	if (session->recv_skb)
458fd558d18SJames Chapman 		(*session->recv_skb)(session, skb, L2TP_SKB_CB(skb)->length);
459fd558d18SJames Chapman 	else
460fd558d18SJames Chapman 		kfree_skb(skb);
461fd558d18SJames Chapman }
462fd558d18SJames Chapman 
463fd558d18SJames Chapman /* Dequeue skbs from the session's reorder_q, subject to packet order.
464fd558d18SJames Chapman  * Skbs that have been in the queue for too long are simply discarded.
465fd558d18SJames Chapman  */
466fd558d18SJames Chapman static void l2tp_recv_dequeue(struct l2tp_session *session)
467fd558d18SJames Chapman {
468fd558d18SJames Chapman 	struct sk_buff *skb;
469fd558d18SJames Chapman 	struct sk_buff *tmp;
470fd558d18SJames Chapman 
471fd558d18SJames Chapman 	/* If the pkt at the head of the queue has the nr that we
472fd558d18SJames Chapman 	 * expect to send up next, dequeue it and any other
473fd558d18SJames Chapman 	 * in-sequence packets behind it.
474fd558d18SJames Chapman 	 */
475e2e210c0SEric Dumazet start:
476fd558d18SJames Chapman 	spin_lock_bh(&session->reorder_q.lock);
477fd558d18SJames Chapman 	skb_queue_walk_safe(&session->reorder_q, skb, tmp) {
4786b7bdcd7STom Parkin 		struct l2tp_skb_cb *cb = L2TP_SKB_CB(skb);
4796b7bdcd7STom Parkin 
4806b7bdcd7STom Parkin 		/* If the packet has been pending on the queue for too long, discard it */
4816b7bdcd7STom Parkin 		if (time_after(jiffies, cb->expires)) {
4827b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_seq_discards);
4837b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_errors);
4846b7bdcd7STom Parkin 			trace_session_pkt_expired(session, cb->ns);
48538d40b3fSJames Chapman 			session->reorder_skip = 1;
486fd558d18SJames Chapman 			__skb_unlink(skb, &session->reorder_q);
487fd558d18SJames Chapman 			kfree_skb(skb);
488fd558d18SJames Chapman 			continue;
489fd558d18SJames Chapman 		}
490fd558d18SJames Chapman 
4916b7bdcd7STom Parkin 		if (cb->has_seq) {
49238d40b3fSJames Chapman 			if (session->reorder_skip) {
49338d40b3fSJames Chapman 				session->reorder_skip = 0;
4946b7bdcd7STom Parkin 				session->nr = cb->ns;
4956b7bdcd7STom Parkin 				trace_session_seqnum_reset(session);
49638d40b3fSJames Chapman 			}
4976b7bdcd7STom Parkin 			if (cb->ns != session->nr)
498fd558d18SJames Chapman 				goto out;
499fd558d18SJames Chapman 		}
500fd558d18SJames Chapman 		__skb_unlink(skb, &session->reorder_q);
501fd558d18SJames Chapman 
502fd558d18SJames Chapman 		/* Process the skb. We release the queue lock while we
503fd558d18SJames Chapman 		 * do so to let other contexts process the queue.
504fd558d18SJames Chapman 		 */
505fd558d18SJames Chapman 		spin_unlock_bh(&session->reorder_q.lock);
506fd558d18SJames Chapman 		l2tp_recv_dequeue_skb(session, skb);
507e2e210c0SEric Dumazet 		goto start;
508fd558d18SJames Chapman 	}
509fd558d18SJames Chapman 
510fd558d18SJames Chapman out:
511fd558d18SJames Chapman 	spin_unlock_bh(&session->reorder_q.lock);
512fd558d18SJames Chapman }
513fd558d18SJames Chapman 
5148a1631d5SJames Chapman static int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr)
5158a1631d5SJames Chapman {
5168a1631d5SJames Chapman 	u32 nws;
5178a1631d5SJames Chapman 
5188a1631d5SJames Chapman 	if (nr >= session->nr)
5198a1631d5SJames Chapman 		nws = nr - session->nr;
5208a1631d5SJames Chapman 	else
5218a1631d5SJames Chapman 		nws = (session->nr_max + 1) - (session->nr - nr);
5228a1631d5SJames Chapman 
5238a1631d5SJames Chapman 	return nws < session->nr_window_size;
5248a1631d5SJames Chapman }
5258a1631d5SJames Chapman 
526b6dc01a4SJames Chapman /* If packet has sequence numbers, queue it if acceptable. Returns 0 if
527b6dc01a4SJames Chapman  * acceptable, else non-zero.
528b6dc01a4SJames Chapman  */
529b6dc01a4SJames Chapman static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb)
530b6dc01a4SJames Chapman {
5316b7bdcd7STom Parkin 	struct l2tp_skb_cb *cb = L2TP_SKB_CB(skb);
5326b7bdcd7STom Parkin 
5336b7bdcd7STom Parkin 	if (!l2tp_seq_check_rx_window(session, cb->ns)) {
5348a1631d5SJames Chapman 		/* Packet sequence number is outside allowed window.
5358a1631d5SJames Chapman 		 * Discard it.
5368a1631d5SJames Chapman 		 */
5376b7bdcd7STom Parkin 		trace_session_pkt_outside_rx_window(session, cb->ns);
5388a1631d5SJames Chapman 		goto discard;
5398a1631d5SJames Chapman 	}
5408a1631d5SJames Chapman 
541b6dc01a4SJames Chapman 	if (session->reorder_timeout != 0) {
542b6dc01a4SJames Chapman 		/* Packet reordering enabled. Add skb to session's
543b6dc01a4SJames Chapman 		 * reorder queue, in order of ns.
544b6dc01a4SJames Chapman 		 */
545b6dc01a4SJames Chapman 		l2tp_recv_queue_skb(session, skb);
546a0dbd822SJames Chapman 		goto out;
547a0dbd822SJames Chapman 	}
548a0dbd822SJames Chapman 
549a0dbd822SJames Chapman 	/* Packet reordering disabled. Discard out-of-sequence packets, while
550a0dbd822SJames Chapman 	 * tracking the number if in-sequence packets after the first OOS packet
551a0dbd822SJames Chapman 	 * is seen. After nr_oos_count_max in-sequence packets, reset the
552a0dbd822SJames Chapman 	 * sequence number to re-enable packet reception.
553b6dc01a4SJames Chapman 	 */
5546b7bdcd7STom Parkin 	if (cb->ns == session->nr) {
555a0dbd822SJames Chapman 		skb_queue_tail(&session->reorder_q, skb);
556a0dbd822SJames Chapman 	} else {
5576b7bdcd7STom Parkin 		u32 nr_oos = cb->ns;
558a0dbd822SJames Chapman 		u32 nr_next = (session->nr_oos + 1) & session->nr_max;
559a0dbd822SJames Chapman 
560a0dbd822SJames Chapman 		if (nr_oos == nr_next)
561a0dbd822SJames Chapman 			session->nr_oos_count++;
562a0dbd822SJames Chapman 		else
563a0dbd822SJames Chapman 			session->nr_oos_count = 0;
564a0dbd822SJames Chapman 
565a0dbd822SJames Chapman 		session->nr_oos = nr_oos;
566a0dbd822SJames Chapman 		if (session->nr_oos_count > session->nr_oos_count_max) {
567a0dbd822SJames Chapman 			session->reorder_skip = 1;
568a0dbd822SJames Chapman 		}
569a0dbd822SJames Chapman 		if (!session->reorder_skip) {
570b6dc01a4SJames Chapman 			atomic_long_inc(&session->stats.rx_seq_discards);
5716b7bdcd7STom Parkin 			trace_session_pkt_oos(session, cb->ns);
572b6dc01a4SJames Chapman 			goto discard;
573b6dc01a4SJames Chapman 		}
574b6dc01a4SJames Chapman 		skb_queue_tail(&session->reorder_q, skb);
575b6dc01a4SJames Chapman 	}
576b6dc01a4SJames Chapman 
577a0dbd822SJames Chapman out:
578b6dc01a4SJames Chapman 	return 0;
579b6dc01a4SJames Chapman 
580b6dc01a4SJames Chapman discard:
581b6dc01a4SJames Chapman 	return 1;
582b6dc01a4SJames Chapman }
583b6dc01a4SJames Chapman 
584f7faffa3SJames Chapman /* Do receive processing of L2TP data frames. We handle both L2TPv2
585f7faffa3SJames Chapman  * and L2TPv3 data frames here.
586f7faffa3SJames Chapman  *
587f7faffa3SJames Chapman  * L2TPv2 Data Message Header
588f7faffa3SJames Chapman  *
589f7faffa3SJames Chapman  *  0                   1                   2                   3
590f7faffa3SJames 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
591f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
592f7faffa3SJames Chapman  * |T|L|x|x|S|x|O|P|x|x|x|x|  Ver  |          Length (opt)         |
593f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
594f7faffa3SJames Chapman  * |           Tunnel ID           |           Session ID          |
595f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
596f7faffa3SJames Chapman  * |             Ns (opt)          |             Nr (opt)          |
597f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
598f7faffa3SJames Chapman  * |      Offset Size (opt)        |    Offset pad... (opt)
599f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
600f7faffa3SJames Chapman  *
601f7faffa3SJames Chapman  * Data frames are marked by T=0. All other fields are the same as
602f7faffa3SJames Chapman  * those in L2TP control frames.
603f7faffa3SJames Chapman  *
604f7faffa3SJames Chapman  * L2TPv3 Data Message Header
605f7faffa3SJames Chapman  *
606f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
607f7faffa3SJames Chapman  * |                      L2TP Session Header                      |
608f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
609f7faffa3SJames Chapman  * |                      L2-Specific Sublayer                     |
610f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
611f7faffa3SJames Chapman  * |                        Tunnel Payload                      ...
612f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
613f7faffa3SJames Chapman  *
614f7faffa3SJames Chapman  * L2TPv3 Session Header Over IP
615f7faffa3SJames Chapman  *
616f7faffa3SJames Chapman  *  0                   1                   2                   3
617f7faffa3SJames 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
618f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
619f7faffa3SJames Chapman  * |                           Session ID                          |
620f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
621f7faffa3SJames Chapman  * |               Cookie (optional, maximum 64 bits)...
622f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
623f7faffa3SJames Chapman  *                                                                 |
624f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
625f7faffa3SJames Chapman  *
626f7faffa3SJames Chapman  * L2TPv3 L2-Specific Sublayer Format
627f7faffa3SJames Chapman  *
628f7faffa3SJames Chapman  *  0                   1                   2                   3
629f7faffa3SJames 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
630f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
631f7faffa3SJames Chapman  * |x|S|x|x|x|x|x|x|              Sequence Number                  |
632f7faffa3SJames Chapman  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
633f7faffa3SJames Chapman  *
63423fe846fSGuillaume Nault  * Cookie value and sublayer format are negotiated with the peer when
63523fe846fSGuillaume Nault  * the session is set up. Unlike L2TPv2, we do not need to parse the
63623fe846fSGuillaume Nault  * packet header to determine if optional fields are present.
637f7faffa3SJames Chapman  *
638f7faffa3SJames Chapman  * Caller must already have parsed the frame and determined that it is
639f7faffa3SJames Chapman  * a data (not control) frame before coming here. Fields up to the
640f7faffa3SJames Chapman  * session-id have already been parsed and ptr points to the data
641f7faffa3SJames Chapman  * after the session-id.
642f7faffa3SJames Chapman  */
643f7faffa3SJames Chapman void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
644f7faffa3SJames Chapman 		      unsigned char *ptr, unsigned char *optr, u16 hdrflags,
6452b139e6bSGuillaume Nault 		      int length)
646f7faffa3SJames Chapman {
647f7faffa3SJames Chapman 	struct l2tp_tunnel *tunnel = session->tunnel;
648f7faffa3SJames Chapman 	int offset;
649f7faffa3SJames Chapman 
650f7faffa3SJames Chapman 	/* Parse and check optional cookie */
651f7faffa3SJames Chapman 	if (session->peer_cookie_len > 0) {
652f7faffa3SJames Chapman 		if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) {
6535ee759cdSTom Parkin 			pr_warn_ratelimited("%s: cookie mismatch (%u/%u). Discarding.\n",
654a4ca44faSJoe Perches 					    tunnel->name, tunnel->tunnel_id,
655a4ca44faSJoe Perches 					    session->session_id);
6567b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_cookie_discards);
657f7faffa3SJames Chapman 			goto discard;
658f7faffa3SJames Chapman 		}
659f7faffa3SJames Chapman 		ptr += session->peer_cookie_len;
660f7faffa3SJames Chapman 	}
661f7faffa3SJames Chapman 
662f7faffa3SJames Chapman 	/* Handle the optional sequence numbers. Sequence numbers are
663f7faffa3SJames Chapman 	 * in different places for L2TPv2 and L2TPv3.
664f7faffa3SJames Chapman 	 *
665f7faffa3SJames Chapman 	 * If we are the LAC, enable/disable sequence numbers under
666f7faffa3SJames Chapman 	 * the control of the LNS.  If no sequence numbers present but
667f7faffa3SJames Chapman 	 * we were expecting them, discard frame.
668f7faffa3SJames Chapman 	 */
669f7faffa3SJames Chapman 	L2TP_SKB_CB(skb)->has_seq = 0;
670f7faffa3SJames Chapman 	if (tunnel->version == L2TP_HDR_VER_2) {
671f7faffa3SJames Chapman 		if (hdrflags & L2TP_HDRFLAG_S) {
672f7faffa3SJames Chapman 			/* Store L2TP info in the skb */
67312923365STom Parkin 			L2TP_SKB_CB(skb)->ns = ntohs(*(__be16 *)ptr);
674f7faffa3SJames Chapman 			L2TP_SKB_CB(skb)->has_seq = 1;
67512923365STom Parkin 			ptr += 2;
67612923365STom Parkin 			/* Skip past nr in the header */
67712923365STom Parkin 			ptr += 2;
678f7faffa3SJames Chapman 
679f7faffa3SJames Chapman 		}
680f7faffa3SJames Chapman 	} else if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
681f7faffa3SJames Chapman 		u32 l2h = ntohl(*(__be32 *)ptr);
682f7faffa3SJames Chapman 
683f7faffa3SJames Chapman 		if (l2h & 0x40000000) {
684f7faffa3SJames Chapman 			/* Store L2TP info in the skb */
68512923365STom Parkin 			L2TP_SKB_CB(skb)->ns = l2h & 0x00ffffff;
686f7faffa3SJames Chapman 			L2TP_SKB_CB(skb)->has_seq = 1;
687f7faffa3SJames Chapman 		}
68862e7b6a5SLorenzo Bianconi 		ptr += 4;
689f7faffa3SJames Chapman 	}
690f7faffa3SJames Chapman 
691f7faffa3SJames Chapman 	if (L2TP_SKB_CB(skb)->has_seq) {
69220dcb110STom Parkin 		/* Received a packet with sequence numbers. If we're the LAC,
693f7faffa3SJames Chapman 		 * check if we sre sending sequence numbers and if not,
694f7faffa3SJames Chapman 		 * configure it so.
695f7faffa3SJames Chapman 		 */
6966c0ec37bSTom Parkin 		if (!session->lns_mode && !session->send_seq) {
6976b7bdcd7STom Parkin 			trace_session_seqnum_lns_enable(session);
6983f9b9770SAsbjørn Sloth Tønnesen 			session->send_seq = 1;
699f7faffa3SJames Chapman 			l2tp_session_set_header_len(session, tunnel->version);
700f7faffa3SJames Chapman 		}
701f7faffa3SJames Chapman 	} else {
702f7faffa3SJames Chapman 		/* No sequence numbers.
703f7faffa3SJames Chapman 		 * If user has configured mandatory sequence numbers, discard.
704f7faffa3SJames Chapman 		 */
705f7faffa3SJames Chapman 		if (session->recv_seq) {
7065ee759cdSTom Parkin 			pr_warn_ratelimited("%s: recv data has no seq numbers when required. Discarding.\n",
707a4ca44faSJoe Perches 					    session->name);
7087b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_seq_discards);
709f7faffa3SJames Chapman 			goto discard;
710f7faffa3SJames Chapman 		}
711f7faffa3SJames Chapman 
712f7faffa3SJames Chapman 		/* If we're the LAC and we're sending sequence numbers, the
713f7faffa3SJames Chapman 		 * LNS has requested that we no longer send sequence numbers.
714f7faffa3SJames Chapman 		 * If we're the LNS and we're sending sequence numbers, the
715f7faffa3SJames Chapman 		 * LAC is broken. Discard the frame.
716f7faffa3SJames Chapman 		 */
7176c0ec37bSTom Parkin 		if (!session->lns_mode && session->send_seq) {
7186b7bdcd7STom Parkin 			trace_session_seqnum_lns_disable(session);
719f7faffa3SJames Chapman 			session->send_seq = 0;
720f7faffa3SJames Chapman 			l2tp_session_set_header_len(session, tunnel->version);
721f7faffa3SJames Chapman 		} else if (session->send_seq) {
7225ee759cdSTom Parkin 			pr_warn_ratelimited("%s: recv data has no seq numbers when required. Discarding.\n",
723a4ca44faSJoe Perches 					    session->name);
7247b7c0719STom Parkin 			atomic_long_inc(&session->stats.rx_seq_discards);
725f7faffa3SJames Chapman 			goto discard;
726f7faffa3SJames Chapman 		}
727f7faffa3SJames Chapman 	}
728f7faffa3SJames Chapman 
729900631eeSJames Chapman 	/* Session data offset is defined only for L2TPv2 and is
730900631eeSJames Chapman 	 * indicated by an optional 16-bit value in the header.
731f7faffa3SJames Chapman 	 */
732f7faffa3SJames Chapman 	if (tunnel->version == L2TP_HDR_VER_2) {
733f7faffa3SJames Chapman 		/* If offset bit set, skip it. */
734f7faffa3SJames Chapman 		if (hdrflags & L2TP_HDRFLAG_O) {
735f7faffa3SJames Chapman 			offset = ntohs(*(__be16 *)ptr);
736f7faffa3SJames Chapman 			ptr += 2 + offset;
737f7faffa3SJames Chapman 		}
738900631eeSJames Chapman 	}
739f7faffa3SJames Chapman 
740f7faffa3SJames Chapman 	offset = ptr - optr;
741f7faffa3SJames Chapman 	if (!pskb_may_pull(skb, offset))
742f7faffa3SJames Chapman 		goto discard;
743f7faffa3SJames Chapman 
744f7faffa3SJames Chapman 	__skb_pull(skb, offset);
745f7faffa3SJames Chapman 
746f7faffa3SJames Chapman 	/* Prepare skb for adding to the session's reorder_q.  Hold
747f7faffa3SJames Chapman 	 * packets for max reorder_timeout or 1 second if not
748f7faffa3SJames Chapman 	 * reordering.
749f7faffa3SJames Chapman 	 */
750f7faffa3SJames Chapman 	L2TP_SKB_CB(skb)->length = length;
751f7faffa3SJames Chapman 	L2TP_SKB_CB(skb)->expires = jiffies +
752f7faffa3SJames Chapman 		(session->reorder_timeout ? session->reorder_timeout : HZ);
753f7faffa3SJames Chapman 
754f7faffa3SJames Chapman 	/* Add packet to the session's receive queue. Reordering is done here, if
755f7faffa3SJames Chapman 	 * enabled. Saved L2TP protocol info is stored in skb->sb[].
756f7faffa3SJames Chapman 	 */
757f7faffa3SJames Chapman 	if (L2TP_SKB_CB(skb)->has_seq) {
758b6dc01a4SJames Chapman 		if (l2tp_recv_data_seq(session, skb))
759f7faffa3SJames Chapman 			goto discard;
760f7faffa3SJames Chapman 	} else {
761f7faffa3SJames Chapman 		/* No sequence numbers. Add the skb to the tail of the
762f7faffa3SJames Chapman 		 * reorder queue. This ensures that it will be
763f7faffa3SJames Chapman 		 * delivered after all previous sequenced skbs.
764f7faffa3SJames Chapman 		 */
765f7faffa3SJames Chapman 		skb_queue_tail(&session->reorder_q, skb);
766f7faffa3SJames Chapman 	}
767f7faffa3SJames Chapman 
768f7faffa3SJames Chapman 	/* Try to dequeue as many skbs from reorder_q as we can. */
769f7faffa3SJames Chapman 	l2tp_recv_dequeue(session);
770f7faffa3SJames Chapman 
771f7faffa3SJames Chapman 	return;
772f7faffa3SJames Chapman 
773f7faffa3SJames Chapman discard:
7747b7c0719STom Parkin 	atomic_long_inc(&session->stats.rx_errors);
775f7faffa3SJames Chapman 	kfree_skb(skb);
776f7faffa3SJames Chapman }
777ca7885dbSTom Parkin EXPORT_SYMBOL_GPL(l2tp_recv_common);
778f7faffa3SJames Chapman 
77948f72f92STom Parkin /* Drop skbs from the session's reorder_q
78048f72f92STom Parkin  */
781493048f5STom Parkin static void l2tp_session_queue_purge(struct l2tp_session *session)
78248f72f92STom Parkin {
78348f72f92STom Parkin 	struct sk_buff *skb = NULL;
784b71a61ccSTom Parkin 
785493048f5STom Parkin 	if (WARN_ON(session->magic != L2TP_SESSION_MAGIC))
786493048f5STom Parkin 		return;
787493048f5STom Parkin 
78848f72f92STom Parkin 	while ((skb = skb_dequeue(&session->reorder_q))) {
78948f72f92STom Parkin 		atomic_long_inc(&session->stats.rx_errors);
79048f72f92STom Parkin 		kfree_skb(skb);
79148f72f92STom Parkin 	}
79248f72f92STom Parkin }
79348f72f92STom Parkin 
794fd558d18SJames Chapman /* Internal UDP receive frame. Do the real work of receiving an L2TP data frame
795fd558d18SJames Chapman  * here. The skb is not on a list when we get here.
796fd558d18SJames Chapman  * Returns 0 if the packet was a data packet and was successfully passed on.
797fd558d18SJames Chapman  * Returns 1 if the packet was not a good data packet and could not be
798fd558d18SJames Chapman  * forwarded.  All such packets are passed up to userspace to deal with.
799fd558d18SJames Chapman  */
8002b139e6bSGuillaume Nault static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
801fd558d18SJames Chapman {
802fd558d18SJames Chapman 	struct l2tp_session *session = NULL;
803fd558d18SJames Chapman 	unsigned char *ptr, *optr;
804fd558d18SJames Chapman 	u16 hdrflags;
805fd558d18SJames Chapman 	u32 tunnel_id, session_id;
806fd558d18SJames Chapman 	u16 version;
807f7faffa3SJames Chapman 	int length;
808fd558d18SJames Chapman 
80958d6085cSTom Herbert 	/* UDP has verifed checksum */
810fd558d18SJames Chapman 
811fd558d18SJames Chapman 	/* UDP always verifies the packet length. */
812fd558d18SJames Chapman 	__skb_pull(skb, sizeof(struct udphdr));
813fd558d18SJames Chapman 
814fd558d18SJames Chapman 	/* Short packet? */
81591c52470SJacob Wen 	if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX)) {
8165ee759cdSTom Parkin 		pr_warn_ratelimited("%s: recv short packet (len=%d)\n",
817a4ca44faSJoe Perches 				    tunnel->name, skb->len);
818fd558d18SJames Chapman 		goto error;
819fd558d18SJames Chapman 	}
820fd558d18SJames Chapman 
821e50e705cSEric Dumazet 	/* Point to L2TP header */
82295075150STom Parkin 	optr = skb->data;
82395075150STom Parkin 	ptr = skb->data;
824e50e705cSEric Dumazet 
825fd558d18SJames Chapman 	/* Get L2TP header flags */
826fd558d18SJames Chapman 	hdrflags = ntohs(*(__be16 *)ptr);
827fd558d18SJames Chapman 
828fd558d18SJames Chapman 	/* Check protocol version */
829fd558d18SJames Chapman 	version = hdrflags & L2TP_HDR_VER_MASK;
830fd558d18SJames Chapman 	if (version != tunnel->version) {
8315ee759cdSTom Parkin 		pr_warn_ratelimited("%s: recv protocol version mismatch: got %d expected %d\n",
832fd558d18SJames Chapman 				    tunnel->name, version, tunnel->version);
833fd558d18SJames Chapman 		goto error;
834fd558d18SJames Chapman 	}
835fd558d18SJames Chapman 
836fd558d18SJames Chapman 	/* Get length of L2TP packet */
837fd558d18SJames Chapman 	length = skb->len;
838fd558d18SJames Chapman 
839fd558d18SJames Chapman 	/* If type is control packet, it is handled by userspace. */
84012923365STom Parkin 	if (hdrflags & L2TP_HDRFLAG_T)
841fd558d18SJames Chapman 		goto error;
842fd558d18SJames Chapman 
843fd558d18SJames Chapman 	/* Skip flags */
844fd558d18SJames Chapman 	ptr += 2;
845fd558d18SJames Chapman 
846f7faffa3SJames Chapman 	if (tunnel->version == L2TP_HDR_VER_2) {
847fd558d18SJames Chapman 		/* If length is present, skip it */
848fd558d18SJames Chapman 		if (hdrflags & L2TP_HDRFLAG_L)
849fd558d18SJames Chapman 			ptr += 2;
850fd558d18SJames Chapman 
851fd558d18SJames Chapman 		/* Extract tunnel and session ID */
852fd558d18SJames Chapman 		tunnel_id = ntohs(*(__be16 *)ptr);
853fd558d18SJames Chapman 		ptr += 2;
854fd558d18SJames Chapman 		session_id = ntohs(*(__be16 *)ptr);
855fd558d18SJames Chapman 		ptr += 2;
856f7faffa3SJames Chapman 	} else {
857f7faffa3SJames Chapman 		ptr += 2;	/* skip reserved bits */
858f7faffa3SJames Chapman 		tunnel_id = tunnel->tunnel_id;
859f7faffa3SJames Chapman 		session_id = ntohl(*(__be32 *)ptr);
860f7faffa3SJames Chapman 		ptr += 4;
861f7faffa3SJames Chapman 	}
862fd558d18SJames Chapman 
863fd558d18SJames Chapman 	/* Find the session context */
86401e28b92SGuillaume Nault 	session = l2tp_tunnel_get_session(tunnel, session_id);
865309795f4SJames Chapman 	if (!session || !session->recv_skb) {
866a4346210SGuillaume Nault 		if (session)
86761b9a047SGuillaume Nault 			l2tp_session_dec_refcount(session);
86861b9a047SGuillaume Nault 
869fd558d18SJames Chapman 		/* Not found? Pass to userspace to deal with */
8705ee759cdSTom Parkin 		pr_warn_ratelimited("%s: no session found (%u/%u). Passing up.\n",
871fd558d18SJames Chapman 				    tunnel->name, tunnel_id, session_id);
872fd558d18SJames Chapman 		goto error;
873fd558d18SJames Chapman 	}
874fd558d18SJames Chapman 
8754522a70dSJacob Wen 	if (tunnel->version == L2TP_HDR_VER_3 &&
8764522a70dSJacob Wen 	    l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
8774522a70dSJacob Wen 		goto error;
8784522a70dSJacob Wen 
8792b139e6bSGuillaume Nault 	l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
88061b9a047SGuillaume Nault 	l2tp_session_dec_refcount(session);
881fd558d18SJames Chapman 
882fd558d18SJames Chapman 	return 0;
883fd558d18SJames Chapman 
884fd558d18SJames Chapman error:
885fd558d18SJames Chapman 	/* Put UDP header back */
886fd558d18SJames Chapman 	__skb_push(skb, sizeof(struct udphdr));
887fd558d18SJames Chapman 
888fd558d18SJames Chapman 	return 1;
889fd558d18SJames Chapman }
890fd558d18SJames Chapman 
891fd558d18SJames Chapman /* UDP encapsulation receive handler. See net/ipv4/udp.c.
892fd558d18SJames Chapman  * Return codes:
893fd558d18SJames Chapman  * 0 : success.
894fd558d18SJames Chapman  * <0: error
895fd558d18SJames Chapman  * >0: skb should be passed up to userspace as UDP.
896fd558d18SJames Chapman  */
897fd558d18SJames Chapman int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
898fd558d18SJames Chapman {
899fd558d18SJames Chapman 	struct l2tp_tunnel *tunnel;
900fd558d18SJames Chapman 
901c1c47721SEric Dumazet 	tunnel = rcu_dereference_sk_user_data(sk);
9020febc7b3STom Parkin 	if (!tunnel)
903fd558d18SJames Chapman 		goto pass_up;
904fd558d18SJames Chapman 
9052b139e6bSGuillaume Nault 	if (l2tp_udp_recv_core(tunnel, skb))
906d00fa9adSJames Chapman 		goto pass_up;
907fd558d18SJames Chapman 
908fd558d18SJames Chapman 	return 0;
909fd558d18SJames Chapman 
910fd558d18SJames Chapman pass_up:
911fd558d18SJames Chapman 	return 1;
912fd558d18SJames Chapman }
913fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_udp_encap_recv);
914fd558d18SJames Chapman 
915fd558d18SJames Chapman /************************************************************************
916fd558d18SJames Chapman  * Transmit handling
917fd558d18SJames Chapman  ***********************************************************************/
918fd558d18SJames Chapman 
919fd558d18SJames Chapman /* Build an L2TP header for the session into the buffer provided.
920fd558d18SJames Chapman  */
921f7faffa3SJames Chapman static int l2tp_build_l2tpv2_header(struct l2tp_session *session, void *buf)
922fd558d18SJames Chapman {
923f7faffa3SJames Chapman 	struct l2tp_tunnel *tunnel = session->tunnel;
924fd558d18SJames Chapman 	__be16 *bufp = buf;
925f7faffa3SJames Chapman 	__be16 *optr = buf;
926fd558d18SJames Chapman 	u16 flags = L2TP_HDR_VER_2;
927fd558d18SJames Chapman 	u32 tunnel_id = tunnel->peer_tunnel_id;
928fd558d18SJames Chapman 	u32 session_id = session->peer_session_id;
929fd558d18SJames Chapman 
930fd558d18SJames Chapman 	if (session->send_seq)
931fd558d18SJames Chapman 		flags |= L2TP_HDRFLAG_S;
932fd558d18SJames Chapman 
933fd558d18SJames Chapman 	/* Setup L2TP header. */
934fd558d18SJames Chapman 	*bufp++ = htons(flags);
935fd558d18SJames Chapman 	*bufp++ = htons(tunnel_id);
936fd558d18SJames Chapman 	*bufp++ = htons(session_id);
937fd558d18SJames Chapman 	if (session->send_seq) {
938fd558d18SJames Chapman 		*bufp++ = htons(session->ns);
939fd558d18SJames Chapman 		*bufp++ = 0;
940fd558d18SJames Chapman 		session->ns++;
941f7faffa3SJames Chapman 		session->ns &= 0xffff;
9426b7bdcd7STom Parkin 		trace_session_seqnum_update(session);
943fd558d18SJames Chapman 	}
944fd558d18SJames Chapman 
945f7faffa3SJames Chapman 	return bufp - optr;
946f7faffa3SJames Chapman }
947f7faffa3SJames Chapman 
948f7faffa3SJames Chapman static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf)
949fd558d18SJames Chapman {
9500d76751fSJames Chapman 	struct l2tp_tunnel *tunnel = session->tunnel;
951f7faffa3SJames Chapman 	char *bufp = buf;
952f7faffa3SJames Chapman 	char *optr = bufp;
953fd558d18SJames Chapman 
9540d76751fSJames Chapman 	/* Setup L2TP header. The header differs slightly for UDP and
9550d76751fSJames Chapman 	 * IP encapsulations. For UDP, there is 4 bytes of flags.
9560d76751fSJames Chapman 	 */
9570d76751fSJames Chapman 	if (tunnel->encap == L2TP_ENCAPTYPE_UDP) {
9580d76751fSJames Chapman 		u16 flags = L2TP_HDR_VER_3;
959f7faffa3SJames Chapman 		*((__be16 *)bufp) = htons(flags);
960f7faffa3SJames Chapman 		bufp += 2;
961f7faffa3SJames Chapman 		*((__be16 *)bufp) = 0;
962f7faffa3SJames Chapman 		bufp += 2;
9630d76751fSJames Chapman 	}
9640d76751fSJames Chapman 
965f7faffa3SJames Chapman 	*((__be32 *)bufp) = htonl(session->peer_session_id);
966f7faffa3SJames Chapman 	bufp += 4;
967f7faffa3SJames Chapman 	if (session->cookie_len) {
968f7faffa3SJames Chapman 		memcpy(bufp, &session->cookie[0], session->cookie_len);
969f7faffa3SJames Chapman 		bufp += session->cookie_len;
970fd558d18SJames Chapman 	}
971f7faffa3SJames Chapman 	if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
972f7faffa3SJames Chapman 		u32 l2h = 0;
97362e7b6a5SLorenzo Bianconi 
974f7faffa3SJames Chapman 		if (session->send_seq) {
975f7faffa3SJames Chapman 			l2h = 0x40000000 | session->ns;
976f7faffa3SJames Chapman 			session->ns++;
977f7faffa3SJames Chapman 			session->ns &= 0xffffff;
9786b7bdcd7STom Parkin 			trace_session_seqnum_update(session);
979f7faffa3SJames Chapman 		}
980f7faffa3SJames Chapman 
981f7faffa3SJames Chapman 		*((__be32 *)bufp) = htonl(l2h);
98262e7b6a5SLorenzo Bianconi 		bufp += 4;
983f7faffa3SJames Chapman 	}
984f7faffa3SJames Chapman 
985f7faffa3SJames Chapman 	return bufp - optr;
986f7faffa3SJames Chapman }
987fd558d18SJames Chapman 
9882685fbb8SGuillaume Nault static void l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
989d9d8da80SDavid S. Miller 			   struct flowi *fl, size_t data_len)
990fd558d18SJames Chapman {
991fd558d18SJames Chapman 	struct l2tp_tunnel *tunnel = session->tunnel;
992fd558d18SJames Chapman 	unsigned int len = skb->len;
993fd558d18SJames Chapman 	int error;
994fd558d18SJames Chapman 
995fd558d18SJames Chapman 	/* Queue the packet to IP for output */
99660ff7467SWANG Cong 	skb->ignore_df = 1;
99727d53323SXin Long 	skb_dst_drop(skb);
998d2cf3361SBenjamin LaHaise #if IS_ENABLED(CONFIG_IPV6)
999b954f940SPaolo Abeni 	if (l2tp_sk_is_v6(tunnel->sock))
1000b0270e91SEric Dumazet 		error = inet6_csk_xmit(tunnel->sock, skb, NULL);
1001d2cf3361SBenjamin LaHaise 	else
1002d2cf3361SBenjamin LaHaise #endif
1003b0270e91SEric Dumazet 		error = ip_queue_xmit(tunnel->sock, skb, fl);
1004fd558d18SJames Chapman 
1005fd558d18SJames Chapman 	/* Update stats */
1006fd558d18SJames Chapman 	if (error >= 0) {
10077b7c0719STom Parkin 		atomic_long_inc(&tunnel->stats.tx_packets);
10087b7c0719STom Parkin 		atomic_long_add(len, &tunnel->stats.tx_bytes);
10097b7c0719STom Parkin 		atomic_long_inc(&session->stats.tx_packets);
10107b7c0719STom Parkin 		atomic_long_add(len, &session->stats.tx_bytes);
1011fd558d18SJames Chapman 	} else {
10127b7c0719STom Parkin 		atomic_long_inc(&tunnel->stats.tx_errors);
10137b7c0719STom Parkin 		atomic_long_inc(&session->stats.tx_errors);
1014fd558d18SJames Chapman 	}
1015fd558d18SJames Chapman }
1016fd558d18SJames Chapman 
1017fd558d18SJames Chapman /* If caller requires the skb to have a ppp header, the header must be
1018fd558d18SJames Chapman  * inserted in the skb data before calling this function.
1019fd558d18SJames Chapman  */
1020fd558d18SJames Chapman int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len)
1021fd558d18SJames Chapman {
1022fd558d18SJames Chapman 	int data_len = skb->len;
10230d76751fSJames Chapman 	struct l2tp_tunnel *tunnel = session->tunnel;
10240d76751fSJames Chapman 	struct sock *sk = tunnel->sock;
1025d9d8da80SDavid S. Miller 	struct flowi *fl;
1026fd558d18SJames Chapman 	struct udphdr *uh;
1027fd558d18SJames Chapman 	struct inet_sock *inet;
1028fd558d18SJames Chapman 	int headroom;
10290d76751fSJames Chapman 	int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0;
10300d76751fSJames Chapman 	int udp_len;
1031b8c84307SEric Dumazet 	int ret = NET_XMIT_SUCCESS;
1032fd558d18SJames Chapman 
1033fd558d18SJames Chapman 	/* Check that there's enough headroom in the skb to insert IP,
1034fd558d18SJames Chapman 	 * UDP and L2TP headers. If not enough, expand it to
1035fd558d18SJames Chapman 	 * make room. Adjust truesize.
1036fd558d18SJames Chapman 	 */
1037fd558d18SJames Chapman 	headroom = NET_SKB_PAD + sizeof(struct iphdr) +
10380d76751fSJames Chapman 		uhlen + hdr_len;
1039835acf5dSEric Dumazet 	if (skb_cow_head(skb, headroom)) {
1040b8c84307SEric Dumazet 		kfree_skb(skb);
1041b8c84307SEric Dumazet 		return NET_XMIT_DROP;
1042835acf5dSEric Dumazet 	}
1043fd558d18SJames Chapman 
1044fd558d18SJames Chapman 	/* Setup L2TP header */
10452dedab6fSTom Parkin 	if (tunnel->version == L2TP_HDR_VER_2)
10462dedab6fSTom Parkin 		l2tp_build_l2tpv2_header(session, __skb_push(skb, hdr_len));
10472dedab6fSTom Parkin 	else
10482dedab6fSTom Parkin 		l2tp_build_l2tpv3_header(session, __skb_push(skb, hdr_len));
1049fd558d18SJames Chapman 
10500d76751fSJames Chapman 	/* Reset skb netfilter state */
1051fd558d18SJames Chapman 	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
1052fd558d18SJames Chapman 	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
1053fd558d18SJames Chapman 			      IPSKB_REROUTED);
1054895b5c9fSFlorian Westphal 	nf_reset_ct(skb);
1055fd558d18SJames Chapman 
10566af88da1SDavid S. Miller 	bh_lock_sock(sk);
10576af88da1SDavid S. Miller 	if (sock_owned_by_user(sk)) {
1058b8c84307SEric Dumazet 		kfree_skb(skb);
1059b8c84307SEric Dumazet 		ret = NET_XMIT_DROP;
10606af88da1SDavid S. Miller 		goto out_unlock;
10616af88da1SDavid S. Miller 	}
10626af88da1SDavid S. Miller 
1063b954f940SPaolo Abeni 	/* The user-space may change the connection status for the user-space
1064b954f940SPaolo Abeni 	 * provided socket at run time: we must check it under the socket lock
1065b954f940SPaolo Abeni 	 */
1066b954f940SPaolo Abeni 	if (tunnel->fd >= 0 && sk->sk_state != TCP_ESTABLISHED) {
1067b954f940SPaolo Abeni 		kfree_skb(skb);
1068b954f940SPaolo Abeni 		ret = NET_XMIT_DROP;
1069b954f940SPaolo Abeni 		goto out_unlock;
1070b954f940SPaolo Abeni 	}
1071b954f940SPaolo Abeni 
1072d9d8da80SDavid S. Miller 	inet = inet_sk(sk);
1073d9d8da80SDavid S. Miller 	fl = &inet->cork.fl;
10740d76751fSJames Chapman 	switch (tunnel->encap) {
10750d76751fSJames Chapman 	case L2TP_ENCAPTYPE_UDP:
10760d76751fSJames Chapman 		/* Setup UDP header */
10770d76751fSJames Chapman 		__skb_push(skb, sizeof(*uh));
10780d76751fSJames Chapman 		skb_reset_transport_header(skb);
10790d76751fSJames Chapman 		uh = udp_hdr(skb);
10800d76751fSJames Chapman 		uh->source = inet->inet_sport;
10810d76751fSJames Chapman 		uh->dest = inet->inet_dport;
10820d76751fSJames Chapman 		udp_len = uhlen + hdr_len + data_len;
10830d76751fSJames Chapman 		uh->len = htons(udp_len);
1084fd558d18SJames Chapman 
1085fd558d18SJames Chapman 		/* Calculate UDP checksum if configured to do so */
1086d2cf3361SBenjamin LaHaise #if IS_ENABLED(CONFIG_IPV6)
1087b954f940SPaolo Abeni 		if (l2tp_sk_is_v6(sk))
108877157e19STom Herbert 			udp6_set_csum(udp_get_no_check6_tx(sk),
108977157e19STom Herbert 				      skb, &inet6_sk(sk)->saddr,
109077157e19STom Herbert 				      &sk->sk_v6_daddr, udp_len);
1091d2cf3361SBenjamin LaHaise 		else
1092d2cf3361SBenjamin LaHaise #endif
109377157e19STom Herbert 			udp_set_csum(sk->sk_no_check_tx, skb, inet->inet_saddr,
109477157e19STom Herbert 				     inet->inet_daddr, udp_len);
10950d76751fSJames Chapman 		break;
10960d76751fSJames Chapman 
10970d76751fSJames Chapman 	case L2TP_ENCAPTYPE_IP:
10980d76751fSJames Chapman 		break;
10990d76751fSJames Chapman 	}
11000d76751fSJames Chapman 
1101d9d8da80SDavid S. Miller 	l2tp_xmit_core(session, skb, fl, data_len);
11026af88da1SDavid S. Miller out_unlock:
11036af88da1SDavid S. Miller 	bh_unlock_sock(sk);
1104fd558d18SJames Chapman 
1105b8c84307SEric Dumazet 	return ret;
1106fd558d18SJames Chapman }
1107fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_xmit_skb);
1108fd558d18SJames Chapman 
1109fd558d18SJames Chapman /*****************************************************************************
1110fd558d18SJames Chapman  * Tinnel and session create/destroy.
1111fd558d18SJames Chapman  *****************************************************************************/
1112fd558d18SJames Chapman 
1113fd558d18SJames Chapman /* Tunnel socket destruct hook.
1114fd558d18SJames Chapman  * The tunnel context is deleted only when all session sockets have been
1115fd558d18SJames Chapman  * closed.
1116fd558d18SJames Chapman  */
1117fc130840Sstephen hemminger static void l2tp_tunnel_destruct(struct sock *sk)
1118fd558d18SJames Chapman {
11198d8a51e2SDavid S. Miller 	struct l2tp_tunnel *tunnel = l2tp_tunnel(sk);
1120fd558d18SJames Chapman 
11210febc7b3STom Parkin 	if (!tunnel)
1122fd558d18SJames Chapman 		goto end;
1123fd558d18SJames Chapman 
1124f8ccac0eSTom Parkin 	/* Disable udp encapsulation */
11250d76751fSJames Chapman 	switch (tunnel->encap) {
11260d76751fSJames Chapman 	case L2TP_ENCAPTYPE_UDP:
1127fd558d18SJames Chapman 		/* No longer an encapsulation socket. See net/ipv4/udp.c */
1128fd558d18SJames Chapman 		(udp_sk(sk))->encap_type = 0;
1129fd558d18SJames Chapman 		(udp_sk(sk))->encap_rcv = NULL;
11309980d001STom Parkin 		(udp_sk(sk))->encap_destroy = NULL;
11310d76751fSJames Chapman 		break;
11320d76751fSJames Chapman 	case L2TP_ENCAPTYPE_IP:
11330d76751fSJames Chapman 		break;
11340d76751fSJames Chapman 	}
1135fd558d18SJames Chapman 
1136fd558d18SJames Chapman 	/* Remove hooks into tunnel socket */
1137fd558d18SJames Chapman 	sk->sk_destruct = tunnel->old_sk_destruct;
1138fd558d18SJames Chapman 	sk->sk_user_data = NULL;
1139f8ccac0eSTom Parkin 
1140fd558d18SJames Chapman 	/* Call the original destructor */
1141fd558d18SJames Chapman 	if (sk->sk_destruct)
1142fd558d18SJames Chapman 		(*sk->sk_destruct)(sk);
1143d00fa9adSJames Chapman 
1144d00fa9adSJames Chapman 	kfree_rcu(tunnel, rcu);
1145fd558d18SJames Chapman end:
1146fd558d18SJames Chapman 	return;
1147fd558d18SJames Chapman }
1148fd558d18SJames Chapman 
1149b2aecfe8STom Parkin /* Remove an l2tp session from l2tp_core's hash lists. */
1150b2aecfe8STom Parkin static void l2tp_session_unhash(struct l2tp_session *session)
1151b2aecfe8STom Parkin {
1152b2aecfe8STom Parkin 	struct l2tp_tunnel *tunnel = session->tunnel;
1153b2aecfe8STom Parkin 
1154b2aecfe8STom Parkin 	/* Remove the session from core hashes */
1155b2aecfe8STom Parkin 	if (tunnel) {
1156b2aecfe8STom Parkin 		/* Remove from the per-tunnel hash */
1157b2aecfe8STom Parkin 		write_lock_bh(&tunnel->hlist_lock);
1158b2aecfe8STom Parkin 		hlist_del_init(&session->hlist);
1159b2aecfe8STom Parkin 		write_unlock_bh(&tunnel->hlist_lock);
1160b2aecfe8STom Parkin 
1161b2aecfe8STom Parkin 		/* For L2TPv3 we have a per-net hash: remove from there, too */
1162b2aecfe8STom Parkin 		if (tunnel->version != L2TP_HDR_VER_2) {
1163b2aecfe8STom Parkin 			struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
1164b2aecfe8STom Parkin 
1165b2aecfe8STom Parkin 			spin_lock_bh(&pn->l2tp_session_hlist_lock);
1166b2aecfe8STom Parkin 			hlist_del_init_rcu(&session->global_hlist);
1167b2aecfe8STom Parkin 			spin_unlock_bh(&pn->l2tp_session_hlist_lock);
1168b2aecfe8STom Parkin 			synchronize_rcu();
1169b2aecfe8STom Parkin 		}
1170b2aecfe8STom Parkin 	}
1171b2aecfe8STom Parkin }
1172b2aecfe8STom Parkin 
1173fd558d18SJames Chapman /* When the tunnel is closed, all the attached sessions need to go too.
1174fd558d18SJames Chapman  */
1175d08532bbSGuillaume Nault static void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel)
1176fd558d18SJames Chapman {
1177fd558d18SJames Chapman 	int hash;
1178fd558d18SJames Chapman 	struct hlist_node *walk;
1179fd558d18SJames Chapman 	struct hlist_node *tmp;
1180fd558d18SJames Chapman 	struct l2tp_session *session;
1181fd558d18SJames Chapman 
1182fd558d18SJames Chapman 	write_lock_bh(&tunnel->hlist_lock);
1183f3c66d4eSGuillaume Nault 	tunnel->acpt_newsess = false;
1184fd558d18SJames Chapman 	for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
1185fd558d18SJames Chapman again:
1186fd558d18SJames Chapman 		hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) {
1187fd558d18SJames Chapman 			session = hlist_entry(walk, struct l2tp_session, hlist);
1188fd558d18SJames Chapman 
1189fd558d18SJames Chapman 			hlist_del_init(&session->hlist);
1190fd558d18SJames Chapman 
1191b228a940SGuillaume Nault 			if (test_and_set_bit(0, &session->dead))
1192b228a940SGuillaume Nault 				goto again;
1193b228a940SGuillaume Nault 
1194fd558d18SJames Chapman 			write_unlock_bh(&tunnel->hlist_lock);
1195fd558d18SJames Chapman 
1196b2aecfe8STom Parkin 			l2tp_session_unhash(session);
11974c6e2fd3STom Parkin 			l2tp_session_queue_purge(session);
11984c6e2fd3STom Parkin 
11990febc7b3STom Parkin 			if (session->session_close)
1200fd558d18SJames Chapman 				(*session->session_close)(session);
1201fd558d18SJames Chapman 
12029980d001STom Parkin 			l2tp_session_dec_refcount(session);
12039980d001STom Parkin 
1204fd558d18SJames Chapman 			write_lock_bh(&tunnel->hlist_lock);
1205fd558d18SJames Chapman 
1206fd558d18SJames Chapman 			/* Now restart from the beginning of this hash
1207fd558d18SJames Chapman 			 * chain.  We always remove a session from the
1208fd558d18SJames Chapman 			 * list so we are guaranteed to make forward
1209fd558d18SJames Chapman 			 * progress.
1210fd558d18SJames Chapman 			 */
1211fd558d18SJames Chapman 			goto again;
1212fd558d18SJames Chapman 		}
1213fd558d18SJames Chapman 	}
1214fd558d18SJames Chapman 	write_unlock_bh(&tunnel->hlist_lock);
1215fd558d18SJames Chapman }
1216fd558d18SJames Chapman 
12179980d001STom Parkin /* Tunnel socket destroy hook for UDP encapsulation */
12189980d001STom Parkin static void l2tp_udp_encap_destroy(struct sock *sk)
12199980d001STom Parkin {
1220d00fa9adSJames Chapman 	struct l2tp_tunnel *tunnel = l2tp_tunnel(sk);
1221d00fa9adSJames Chapman 
1222d00fa9adSJames Chapman 	if (tunnel)
1223d00fa9adSJames Chapman 		l2tp_tunnel_delete(tunnel);
12249980d001STom Parkin }
12259980d001STom Parkin 
1226f8ccac0eSTom Parkin /* Workqueue tunnel deletion function */
1227f8ccac0eSTom Parkin static void l2tp_tunnel_del_work(struct work_struct *work)
1228f8ccac0eSTom Parkin {
1229d00fa9adSJames Chapman 	struct l2tp_tunnel *tunnel = container_of(work, struct l2tp_tunnel,
1230d00fa9adSJames Chapman 						  del_work);
1231d00fa9adSJames Chapman 	struct sock *sk = tunnel->sock;
1232d00fa9adSJames Chapman 	struct socket *sock = sk->sk_socket;
123328f5bfb8SJames Chapman 	struct l2tp_net *pn;
123412d656afSRidge Kennedy 
123512d656afSRidge Kennedy 	l2tp_tunnel_closeall(tunnel);
123612d656afSRidge Kennedy 
123776a6abdbSJames Chapman 	/* If the tunnel socket was created within the kernel, use
123802d13ed5STom Parkin 	 * the sk API to release it here.
1239f8ccac0eSTom Parkin 	 */
124076a6abdbSJames Chapman 	if (tunnel->fd < 0) {
124126abe143SEric W. Biederman 		if (sock) {
1242167eb17eSTom Parkin 			kernel_sock_shutdown(sock, SHUT_RDWR);
124326abe143SEric W. Biederman 			sock_release(sock);
124426abe143SEric W. Biederman 		}
1245167eb17eSTom Parkin 	}
1246f8ccac0eSTom Parkin 
124728f5bfb8SJames Chapman 	/* Remove the tunnel struct from the tunnel list */
124828f5bfb8SJames Chapman 	pn = l2tp_pernet(tunnel->l2tp_net);
124928f5bfb8SJames Chapman 	spin_lock_bh(&pn->l2tp_tunnel_list_lock);
125028f5bfb8SJames Chapman 	list_del_rcu(&tunnel->list);
125128f5bfb8SJames Chapman 	spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
125228f5bfb8SJames Chapman 
1253d00fa9adSJames Chapman 	/* drop initial ref */
1254d00fa9adSJames Chapman 	l2tp_tunnel_dec_refcount(tunnel);
1255d00fa9adSJames Chapman 
1256d00fa9adSJames Chapman 	/* drop workqueue ref */
125706a15f51SAlexander Couzens 	l2tp_tunnel_dec_refcount(tunnel);
1258fd558d18SJames Chapman }
1259fd558d18SJames Chapman 
1260789a4a2cSJames Chapman /* Create a socket for the tunnel, if one isn't set up by
1261789a4a2cSJames Chapman  * userspace. This is used for static tunnels where there is no
1262789a4a2cSJames Chapman  * managing L2TP daemon.
1263167eb17eSTom Parkin  *
1264167eb17eSTom Parkin  * Since we don't want these sockets to keep a namespace alive by
1265167eb17eSTom Parkin  * themselves, we drop the socket's namespace refcount after creation.
1266167eb17eSTom Parkin  * These sockets are freed when the namespace exits using the pernet
1267167eb17eSTom Parkin  * exit hook.
1268789a4a2cSJames Chapman  */
1269167eb17eSTom Parkin static int l2tp_tunnel_sock_create(struct net *net,
1270167eb17eSTom Parkin 				   u32 tunnel_id,
1271167eb17eSTom Parkin 				   u32 peer_tunnel_id,
1272167eb17eSTom Parkin 				   struct l2tp_tunnel_cfg *cfg,
1273167eb17eSTom Parkin 				   struct socket **sockp)
1274789a4a2cSJames Chapman {
1275789a4a2cSJames Chapman 	int err = -EINVAL;
12767bddd0dbSEric Dumazet 	struct socket *sock = NULL;
127785644b4dSTom Herbert 	struct udp_port_cfg udp_conf;
1278789a4a2cSJames Chapman 
1279789a4a2cSJames Chapman 	switch (cfg->encap) {
1280789a4a2cSJames Chapman 	case L2TP_ENCAPTYPE_UDP:
128185644b4dSTom Herbert 		memset(&udp_conf, 0, sizeof(udp_conf));
128285644b4dSTom Herbert 
1283f9bac8dfSChris Elston #if IS_ENABLED(CONFIG_IPV6)
1284f9bac8dfSChris Elston 		if (cfg->local_ip6 && cfg->peer_ip6) {
128585644b4dSTom Herbert 			udp_conf.family = AF_INET6;
128685644b4dSTom Herbert 			memcpy(&udp_conf.local_ip6, cfg->local_ip6,
128785644b4dSTom Herbert 			       sizeof(udp_conf.local_ip6));
128885644b4dSTom Herbert 			memcpy(&udp_conf.peer_ip6, cfg->peer_ip6,
128985644b4dSTom Herbert 			       sizeof(udp_conf.peer_ip6));
129085644b4dSTom Herbert 			udp_conf.use_udp6_tx_checksums =
1291018f8258SWang Shanker 			  !cfg->udp6_zero_tx_checksums;
129285644b4dSTom Herbert 			udp_conf.use_udp6_rx_checksums =
1293018f8258SWang Shanker 			  !cfg->udp6_zero_rx_checksums;
1294f9bac8dfSChris Elston 		} else
1295f9bac8dfSChris Elston #endif
1296f9bac8dfSChris Elston 		{
129785644b4dSTom Herbert 			udp_conf.family = AF_INET;
129885644b4dSTom Herbert 			udp_conf.local_ip = cfg->local_ip;
129985644b4dSTom Herbert 			udp_conf.peer_ip = cfg->peer_ip;
130085644b4dSTom Herbert 			udp_conf.use_udp_checksums = cfg->use_udp_checksums;
1301f9bac8dfSChris Elston 		}
1302789a4a2cSJames Chapman 
130385644b4dSTom Herbert 		udp_conf.local_udp_port = htons(cfg->local_udp_port);
130485644b4dSTom Herbert 		udp_conf.peer_udp_port = htons(cfg->peer_udp_port);
130585644b4dSTom Herbert 
130685644b4dSTom Herbert 		err = udp_sock_create(net, &udp_conf, &sock);
130785644b4dSTom Herbert 		if (err < 0)
130885644b4dSTom Herbert 			goto out;
1309789a4a2cSJames Chapman 
1310789a4a2cSJames Chapman 		break;
1311789a4a2cSJames Chapman 
1312789a4a2cSJames Chapman 	case L2TP_ENCAPTYPE_IP:
1313f9bac8dfSChris Elston #if IS_ENABLED(CONFIG_IPV6)
1314f9bac8dfSChris Elston 		if (cfg->local_ip6 && cfg->peer_ip6) {
131585644b4dSTom Herbert 			struct sockaddr_l2tpip6 ip6_addr = {0};
131685644b4dSTom Herbert 
131726abe143SEric W. Biederman 			err = sock_create_kern(net, AF_INET6, SOCK_DGRAM,
1318167eb17eSTom Parkin 					       IPPROTO_L2TP, &sock);
13195dac94e1SJames Chapman 			if (err < 0)
1320f9bac8dfSChris Elston 				goto out;
13215dac94e1SJames Chapman 
13225dac94e1SJames Chapman 			ip6_addr.l2tp_family = AF_INET6;
13235dac94e1SJames Chapman 			memcpy(&ip6_addr.l2tp_addr, cfg->local_ip6,
13245dac94e1SJames Chapman 			       sizeof(ip6_addr.l2tp_addr));
13255dac94e1SJames Chapman 			ip6_addr.l2tp_conn_id = tunnel_id;
13265dac94e1SJames Chapman 			err = kernel_bind(sock, (struct sockaddr *)&ip6_addr,
13275dac94e1SJames Chapman 					  sizeof(ip6_addr));
13285dac94e1SJames Chapman 			if (err < 0)
13295dac94e1SJames Chapman 				goto out;
13305dac94e1SJames Chapman 
13315dac94e1SJames Chapman 			ip6_addr.l2tp_family = AF_INET6;
13325dac94e1SJames Chapman 			memcpy(&ip6_addr.l2tp_addr, cfg->peer_ip6,
13335dac94e1SJames Chapman 			       sizeof(ip6_addr.l2tp_addr));
13345dac94e1SJames Chapman 			ip6_addr.l2tp_conn_id = peer_tunnel_id;
13355dac94e1SJames Chapman 			err = kernel_connect(sock,
13365dac94e1SJames Chapman 					     (struct sockaddr *)&ip6_addr,
13375dac94e1SJames Chapman 					     sizeof(ip6_addr), 0);
13385dac94e1SJames Chapman 			if (err < 0)
13395dac94e1SJames Chapman 				goto out;
13405dac94e1SJames Chapman 		} else
1341f9bac8dfSChris Elston #endif
13425dac94e1SJames Chapman 		{
134385644b4dSTom Herbert 			struct sockaddr_l2tpip ip_addr = {0};
134485644b4dSTom Herbert 
134526abe143SEric W. Biederman 			err = sock_create_kern(net, AF_INET, SOCK_DGRAM,
1346167eb17eSTom Parkin 					       IPPROTO_L2TP, &sock);
1347789a4a2cSJames Chapman 			if (err < 0)
1348789a4a2cSJames Chapman 				goto out;
1349789a4a2cSJames Chapman 
1350789a4a2cSJames Chapman 			ip_addr.l2tp_family = AF_INET;
1351789a4a2cSJames Chapman 			ip_addr.l2tp_addr = cfg->local_ip;
1352789a4a2cSJames Chapman 			ip_addr.l2tp_conn_id = tunnel_id;
13535dac94e1SJames Chapman 			err = kernel_bind(sock, (struct sockaddr *)&ip_addr,
13545dac94e1SJames Chapman 					  sizeof(ip_addr));
1355789a4a2cSJames Chapman 			if (err < 0)
1356789a4a2cSJames Chapman 				goto out;
1357789a4a2cSJames Chapman 
1358789a4a2cSJames Chapman 			ip_addr.l2tp_family = AF_INET;
1359789a4a2cSJames Chapman 			ip_addr.l2tp_addr = cfg->peer_ip;
1360789a4a2cSJames Chapman 			ip_addr.l2tp_conn_id = peer_tunnel_id;
13615dac94e1SJames Chapman 			err = kernel_connect(sock, (struct sockaddr *)&ip_addr,
13625dac94e1SJames Chapman 					     sizeof(ip_addr), 0);
1363789a4a2cSJames Chapman 			if (err < 0)
1364789a4a2cSJames Chapman 				goto out;
13655dac94e1SJames Chapman 		}
1366789a4a2cSJames Chapman 		break;
1367789a4a2cSJames Chapman 
1368789a4a2cSJames Chapman 	default:
1369789a4a2cSJames Chapman 		goto out;
1370789a4a2cSJames Chapman 	}
1371789a4a2cSJames Chapman 
1372789a4a2cSJames Chapman out:
1373167eb17eSTom Parkin 	*sockp = sock;
13746c0ec37bSTom Parkin 	if (err < 0 && sock) {
1375167eb17eSTom Parkin 		kernel_sock_shutdown(sock, SHUT_RDWR);
137626abe143SEric W. Biederman 		sock_release(sock);
1377789a4a2cSJames Chapman 		*sockp = NULL;
1378789a4a2cSJames Chapman 	}
1379789a4a2cSJames Chapman 
1380789a4a2cSJames Chapman 	return err;
1381789a4a2cSJames Chapman }
1382789a4a2cSJames Chapman 
138337159ef2SEric Dumazet static struct lock_class_key l2tp_socket_class;
138437159ef2SEric Dumazet 
1385c0235fb3STom Parkin int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id,
1386c0235fb3STom Parkin 		       struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp)
1387fd558d18SJames Chapman {
1388fd558d18SJames Chapman 	struct l2tp_tunnel *tunnel = NULL;
1389fd558d18SJames Chapman 	int err;
13900d76751fSJames Chapman 	enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP;
1391fd558d18SJames Chapman 
13920febc7b3STom Parkin 	if (cfg)
13930d76751fSJames Chapman 		encap = cfg->encap;
13940d76751fSJames Chapman 
139570c05bfaSTom Parkin 	tunnel = kzalloc(sizeof(*tunnel), GFP_KERNEL);
13960febc7b3STom Parkin 	if (!tunnel) {
1397fd558d18SJames Chapman 		err = -ENOMEM;
1398fd558d18SJames Chapman 		goto err;
1399fd558d18SJames Chapman 	}
1400fd558d18SJames Chapman 
1401fd558d18SJames Chapman 	tunnel->version = version;
1402fd558d18SJames Chapman 	tunnel->tunnel_id = tunnel_id;
1403fd558d18SJames Chapman 	tunnel->peer_tunnel_id = peer_tunnel_id;
1404fd558d18SJames Chapman 	tunnel->debug = L2TP_DEFAULT_DEBUG_FLAGS;
1405fd558d18SJames Chapman 
1406fd558d18SJames Chapman 	tunnel->magic = L2TP_TUNNEL_MAGIC;
1407fd558d18SJames Chapman 	sprintf(&tunnel->name[0], "tunl %u", tunnel_id);
1408fd558d18SJames Chapman 	rwlock_init(&tunnel->hlist_lock);
1409f3c66d4eSGuillaume Nault 	tunnel->acpt_newsess = true;
1410fd558d18SJames Chapman 
14110febc7b3STom Parkin 	if (cfg)
1412fd558d18SJames Chapman 		tunnel->debug = cfg->debug;
1413fd558d18SJames Chapman 
14140d76751fSJames Chapman 	tunnel->encap = encap;
1415fd558d18SJames Chapman 
1416d00fa9adSJames Chapman 	refcount_set(&tunnel->ref_count, 1);
1417d00fa9adSJames Chapman 	tunnel->fd = fd;
1418d00fa9adSJames Chapman 
1419f8ccac0eSTom Parkin 	/* Init delete workqueue struct */
1420f8ccac0eSTom Parkin 	INIT_WORK(&tunnel->del_work, l2tp_tunnel_del_work);
1421f8ccac0eSTom Parkin 
1422fd558d18SJames Chapman 	INIT_LIST_HEAD(&tunnel->list);
1423fd558d18SJames Chapman 
1424fd558d18SJames Chapman 	err = 0;
1425fd558d18SJames Chapman err:
1426fd558d18SJames Chapman 	if (tunnelp)
1427fd558d18SJames Chapman 		*tunnelp = tunnel;
1428fd558d18SJames Chapman 
1429fd558d18SJames Chapman 	return err;
1430fd558d18SJames Chapman }
1431fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
1432fd558d18SJames Chapman 
14336b9f3423SGuillaume Nault static int l2tp_validate_socket(const struct sock *sk, const struct net *net,
14346b9f3423SGuillaume Nault 				enum l2tp_encap_type encap)
14356b9f3423SGuillaume Nault {
14366b9f3423SGuillaume Nault 	if (!net_eq(sock_net(sk), net))
14376b9f3423SGuillaume Nault 		return -EINVAL;
14386b9f3423SGuillaume Nault 
14396b9f3423SGuillaume Nault 	if (sk->sk_type != SOCK_DGRAM)
14406b9f3423SGuillaume Nault 		return -EPROTONOSUPPORT;
14416b9f3423SGuillaume Nault 
1442d9a81a22SEric Dumazet 	if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
1443d9a81a22SEric Dumazet 		return -EPROTONOSUPPORT;
1444d9a81a22SEric Dumazet 
14456b9f3423SGuillaume Nault 	if ((encap == L2TP_ENCAPTYPE_UDP && sk->sk_protocol != IPPROTO_UDP) ||
14466b9f3423SGuillaume Nault 	    (encap == L2TP_ENCAPTYPE_IP && sk->sk_protocol != IPPROTO_L2TP))
14476b9f3423SGuillaume Nault 		return -EPROTONOSUPPORT;
14486b9f3423SGuillaume Nault 
14496b9f3423SGuillaume Nault 	if (sk->sk_user_data)
14506b9f3423SGuillaume Nault 		return -EBUSY;
14516b9f3423SGuillaume Nault 
14526b9f3423SGuillaume Nault 	return 0;
14536b9f3423SGuillaume Nault }
14546b9f3423SGuillaume Nault 
14556b9f3423SGuillaume Nault int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
14566b9f3423SGuillaume Nault 			 struct l2tp_tunnel_cfg *cfg)
14576b9f3423SGuillaume Nault {
1458f6cd651bSGuillaume Nault 	struct l2tp_tunnel *tunnel_walk;
14596b9f3423SGuillaume Nault 	struct l2tp_net *pn;
14606b9f3423SGuillaume Nault 	struct socket *sock;
14616b9f3423SGuillaume Nault 	struct sock *sk;
14626b9f3423SGuillaume Nault 	int ret;
14636b9f3423SGuillaume Nault 
14646b9f3423SGuillaume Nault 	if (tunnel->fd < 0) {
14656b9f3423SGuillaume Nault 		ret = l2tp_tunnel_sock_create(net, tunnel->tunnel_id,
14666b9f3423SGuillaume Nault 					      tunnel->peer_tunnel_id, cfg,
14676b9f3423SGuillaume Nault 					      &sock);
14686b9f3423SGuillaume Nault 		if (ret < 0)
14696b9f3423SGuillaume Nault 			goto err;
14706b9f3423SGuillaume Nault 	} else {
14716b9f3423SGuillaume Nault 		sock = sockfd_lookup(tunnel->fd, &ret);
14726b9f3423SGuillaume Nault 		if (!sock)
14736b9f3423SGuillaume Nault 			goto err;
14746b9f3423SGuillaume Nault 
14756b9f3423SGuillaume Nault 		ret = l2tp_validate_socket(sock->sk, net, tunnel->encap);
14766b9f3423SGuillaume Nault 		if (ret < 0)
14776b9f3423SGuillaume Nault 			goto err_sock;
14786b9f3423SGuillaume Nault 	}
14796b9f3423SGuillaume Nault 
14806b9f3423SGuillaume Nault 	tunnel->l2tp_net = net;
14816b9f3423SGuillaume Nault 	pn = l2tp_pernet(net);
1482f6cd651bSGuillaume Nault 
14836b9f3423SGuillaume Nault 	spin_lock_bh(&pn->l2tp_tunnel_list_lock);
1484f6cd651bSGuillaume Nault 	list_for_each_entry(tunnel_walk, &pn->l2tp_tunnel_list, list) {
1485f6cd651bSGuillaume Nault 		if (tunnel_walk->tunnel_id == tunnel->tunnel_id) {
1486f6cd651bSGuillaume Nault 			spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
1487f6cd651bSGuillaume Nault 
1488f6cd651bSGuillaume Nault 			ret = -EEXIST;
1489f6cd651bSGuillaume Nault 			goto err_sock;
1490f6cd651bSGuillaume Nault 		}
1491f6cd651bSGuillaume Nault 	}
14926b9f3423SGuillaume Nault 	list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
14936b9f3423SGuillaume Nault 	spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
14946b9f3423SGuillaume Nault 
1495f8504f4cSXin Long 	sk = sock->sk;
1496f8504f4cSXin Long 	sock_hold(sk);
1497f8504f4cSXin Long 	tunnel->sock = sk;
1498f8504f4cSXin Long 
14996b9f3423SGuillaume Nault 	if (tunnel->encap == L2TP_ENCAPTYPE_UDP) {
15006b9f3423SGuillaume Nault 		struct udp_tunnel_sock_cfg udp_cfg = {
15016b9f3423SGuillaume Nault 			.sk_user_data = tunnel,
15026b9f3423SGuillaume Nault 			.encap_type = UDP_ENCAP_L2TPINUDP,
15036b9f3423SGuillaume Nault 			.encap_rcv = l2tp_udp_encap_recv,
15046b9f3423SGuillaume Nault 			.encap_destroy = l2tp_udp_encap_destroy,
15056b9f3423SGuillaume Nault 		};
15066b9f3423SGuillaume Nault 
15076b9f3423SGuillaume Nault 		setup_udp_tunnel_sock(net, sock, &udp_cfg);
15086b9f3423SGuillaume Nault 	} else {
15096b9f3423SGuillaume Nault 		sk->sk_user_data = tunnel;
15106b9f3423SGuillaume Nault 	}
15116b9f3423SGuillaume Nault 
15126b9f3423SGuillaume Nault 	tunnel->old_sk_destruct = sk->sk_destruct;
15136b9f3423SGuillaume Nault 	sk->sk_destruct = &l2tp_tunnel_destruct;
15146b9f3423SGuillaume Nault 	lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class,
15156b9f3423SGuillaume Nault 				   "l2tp_sock");
15166b9f3423SGuillaume Nault 	sk->sk_allocation = GFP_ATOMIC;
15176b9f3423SGuillaume Nault 
15186b7bdcd7STom Parkin 	trace_register_tunnel(tunnel);
15196b7bdcd7STom Parkin 
15206b9f3423SGuillaume Nault 	if (tunnel->fd >= 0)
15216b9f3423SGuillaume Nault 		sockfd_put(sock);
15226b9f3423SGuillaume Nault 
15236b9f3423SGuillaume Nault 	return 0;
15246b9f3423SGuillaume Nault 
15256b9f3423SGuillaume Nault err_sock:
1526f6cd651bSGuillaume Nault 	if (tunnel->fd < 0)
1527f6cd651bSGuillaume Nault 		sock_release(sock);
1528f6cd651bSGuillaume Nault 	else
15296b9f3423SGuillaume Nault 		sockfd_put(sock);
15306b9f3423SGuillaume Nault err:
15316b9f3423SGuillaume Nault 	return ret;
15326b9f3423SGuillaume Nault }
15336b9f3423SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_tunnel_register);
15346b9f3423SGuillaume Nault 
1535309795f4SJames Chapman /* This function is used by the netlink TUNNEL_DELETE command.
1536309795f4SJames Chapman  */
153762b982eeSSabrina Dubroca void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
1538309795f4SJames Chapman {
153962b982eeSSabrina Dubroca 	if (!test_and_set_bit(0, &tunnel->dead)) {
15406b7bdcd7STom Parkin 		trace_delete_tunnel(tunnel);
154106a15f51SAlexander Couzens 		l2tp_tunnel_inc_refcount(tunnel);
154262b982eeSSabrina Dubroca 		queue_work(l2tp_wq, &tunnel->del_work);
154306a15f51SAlexander Couzens 	}
1544309795f4SJames Chapman }
1545309795f4SJames Chapman EXPORT_SYMBOL_GPL(l2tp_tunnel_delete);
1546309795f4SJames Chapman 
1547628703f5STom Parkin void l2tp_session_delete(struct l2tp_session *session)
1548309795f4SJames Chapman {
1549b228a940SGuillaume Nault 	if (test_and_set_bit(0, &session->dead))
1550628703f5STom Parkin 		return;
1551b228a940SGuillaume Nault 
15526b7bdcd7STom Parkin 	trace_delete_session(session);
1553b2aecfe8STom Parkin 	l2tp_session_unhash(session);
15544c6e2fd3STom Parkin 	l2tp_session_queue_purge(session);
15550febc7b3STom Parkin 	if (session->session_close)
1556309795f4SJames Chapman 		(*session->session_close)(session);
1557a4346210SGuillaume Nault 
1558309795f4SJames Chapman 	l2tp_session_dec_refcount(session);
1559309795f4SJames Chapman }
1560309795f4SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_delete);
1561309795f4SJames Chapman 
1562f7faffa3SJames Chapman /* We come here whenever a session's send_seq, cookie_len or
156362e7b6a5SLorenzo Bianconi  * l2specific_type parameters are set.
1564f7faffa3SJames Chapman  */
1565bb5016eaSGuillaume Nault void l2tp_session_set_header_len(struct l2tp_session *session, int version)
1566f7faffa3SJames Chapman {
1567f7faffa3SJames Chapman 	if (version == L2TP_HDR_VER_2) {
1568f7faffa3SJames Chapman 		session->hdr_len = 6;
1569f7faffa3SJames Chapman 		if (session->send_seq)
1570f7faffa3SJames Chapman 			session->hdr_len += 4;
1571f7faffa3SJames Chapman 	} else {
157262e7b6a5SLorenzo Bianconi 		session->hdr_len = 4 + session->cookie_len;
157362e7b6a5SLorenzo Bianconi 		session->hdr_len += l2tp_get_l2specific_len(session);
15740d76751fSJames Chapman 		if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP)
15750d76751fSJames Chapman 			session->hdr_len += 4;
1576f7faffa3SJames Chapman 	}
1577f7faffa3SJames Chapman }
1578bb5016eaSGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_set_header_len);
1579f7faffa3SJames Chapman 
1580c0235fb3STom Parkin struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id,
1581c0235fb3STom Parkin 					 u32 peer_session_id, struct l2tp_session_cfg *cfg)
1582fd558d18SJames Chapman {
1583fd558d18SJames Chapman 	struct l2tp_session *session;
1584fd558d18SJames Chapman 
158570c05bfaSTom Parkin 	session = kzalloc(sizeof(*session) + priv_size, GFP_KERNEL);
15860febc7b3STom Parkin 	if (session) {
1587fd558d18SJames Chapman 		session->magic = L2TP_SESSION_MAGIC;
1588fd558d18SJames Chapman 		session->tunnel = tunnel;
1589fd558d18SJames Chapman 
1590fd558d18SJames Chapman 		session->session_id = session_id;
1591fd558d18SJames Chapman 		session->peer_session_id = peer_session_id;
1592d301e325SJames Chapman 		session->nr = 0;
15938a1631d5SJames Chapman 		if (tunnel->version == L2TP_HDR_VER_2)
15948a1631d5SJames Chapman 			session->nr_max = 0xffff;
15958a1631d5SJames Chapman 		else
15968a1631d5SJames Chapman 			session->nr_max = 0xffffff;
15978a1631d5SJames Chapman 		session->nr_window_size = session->nr_max / 2;
1598a0dbd822SJames Chapman 		session->nr_oos_count_max = 4;
1599a0dbd822SJames Chapman 
1600a0dbd822SJames Chapman 		/* Use NR of first received packet */
1601a0dbd822SJames Chapman 		session->reorder_skip = 1;
1602fd558d18SJames Chapman 
1603fd558d18SJames Chapman 		sprintf(&session->name[0], "sess %u/%u",
1604fd558d18SJames Chapman 			tunnel->tunnel_id, session->session_id);
1605fd558d18SJames Chapman 
1606fd558d18SJames Chapman 		skb_queue_head_init(&session->reorder_q);
1607fd558d18SJames Chapman 
1608fd558d18SJames Chapman 		INIT_HLIST_NODE(&session->hlist);
1609f7faffa3SJames Chapman 		INIT_HLIST_NODE(&session->global_hlist);
1610fd558d18SJames Chapman 
1611fd558d18SJames Chapman 		/* Inherit debug options from tunnel */
1612fd558d18SJames Chapman 		session->debug = tunnel->debug;
1613fd558d18SJames Chapman 
1614fd558d18SJames Chapman 		if (cfg) {
1615f7faffa3SJames Chapman 			session->pwtype = cfg->pw_type;
1616fd558d18SJames Chapman 			session->debug = cfg->debug;
1617fd558d18SJames Chapman 			session->send_seq = cfg->send_seq;
1618fd558d18SJames Chapman 			session->recv_seq = cfg->recv_seq;
1619fd558d18SJames Chapman 			session->lns_mode = cfg->lns_mode;
1620f7faffa3SJames Chapman 			session->reorder_timeout = cfg->reorder_timeout;
1621f7faffa3SJames Chapman 			session->l2specific_type = cfg->l2specific_type;
1622f7faffa3SJames Chapman 			session->cookie_len = cfg->cookie_len;
1623f7faffa3SJames Chapman 			memcpy(&session->cookie[0], &cfg->cookie[0], cfg->cookie_len);
1624f7faffa3SJames Chapman 			session->peer_cookie_len = cfg->peer_cookie_len;
1625f7faffa3SJames Chapman 			memcpy(&session->peer_cookie[0], &cfg->peer_cookie[0], cfg->peer_cookie_len);
1626fd558d18SJames Chapman 		}
1627fd558d18SJames Chapman 
1628f7faffa3SJames Chapman 		l2tp_session_set_header_len(session, tunnel->version);
1629f7faffa3SJames Chapman 
16309ee369a4SGuillaume Nault 		refcount_set(&session->ref_count, 1);
16319ee369a4SGuillaume Nault 
1632fd558d18SJames Chapman 		return session;
1633fd558d18SJames Chapman 	}
1634dbdbc73bSGuillaume Nault 
1635dbdbc73bSGuillaume Nault 	return ERR_PTR(-ENOMEM);
1636dbdbc73bSGuillaume Nault }
1637fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_create);
1638fd558d18SJames Chapman 
1639fd558d18SJames Chapman /*****************************************************************************
1640fd558d18SJames Chapman  * Init and cleanup
1641fd558d18SJames Chapman  *****************************************************************************/
1642fd558d18SJames Chapman 
1643fd558d18SJames Chapman static __net_init int l2tp_init_net(struct net *net)
1644fd558d18SJames Chapman {
1645e773aaffSJiri Pirko 	struct l2tp_net *pn = net_generic(net, l2tp_net_id);
1646f7faffa3SJames Chapman 	int hash;
1647fd558d18SJames Chapman 
1648fd558d18SJames Chapman 	INIT_LIST_HEAD(&pn->l2tp_tunnel_list);
1649e02d494dSJames Chapman 	spin_lock_init(&pn->l2tp_tunnel_list_lock);
1650fd558d18SJames Chapman 
1651f7faffa3SJames Chapman 	for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++)
1652f7faffa3SJames Chapman 		INIT_HLIST_HEAD(&pn->l2tp_session_hlist[hash]);
1653f7faffa3SJames Chapman 
1654e02d494dSJames Chapman 	spin_lock_init(&pn->l2tp_session_hlist_lock);
1655f7faffa3SJames Chapman 
1656fd558d18SJames Chapman 	return 0;
1657fd558d18SJames Chapman }
1658fd558d18SJames Chapman 
1659167eb17eSTom Parkin static __net_exit void l2tp_exit_net(struct net *net)
1660167eb17eSTom Parkin {
1661167eb17eSTom Parkin 	struct l2tp_net *pn = l2tp_pernet(net);
1662167eb17eSTom Parkin 	struct l2tp_tunnel *tunnel = NULL;
16631e7af3b2SVasily Averin 	int hash;
1664167eb17eSTom Parkin 
1665167eb17eSTom Parkin 	rcu_read_lock_bh();
1666167eb17eSTom Parkin 	list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
16674dc12ffeSJiri Slaby 		l2tp_tunnel_delete(tunnel);
1668167eb17eSTom Parkin 	}
1669167eb17eSTom Parkin 	rcu_read_unlock_bh();
16702f86953eSSabrina Dubroca 
1671638a3a1eSYueHaibing 	if (l2tp_wq)
16722f86953eSSabrina Dubroca 		flush_workqueue(l2tp_wq);
16732f86953eSSabrina Dubroca 	rcu_barrier();
16741e7af3b2SVasily Averin 
16751e7af3b2SVasily Averin 	for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++)
16761e7af3b2SVasily Averin 		WARN_ON_ONCE(!hlist_empty(&pn->l2tp_session_hlist[hash]));
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 
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 
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