162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/* L2TP core.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2008,2009,2010 Katalix Systems Ltd
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * This file contains some code of the original L2TPv2 pppol2tp
762306a36Sopenharmony_ci * driver, which has the following copyright:
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Authors:	Martijn van Oosterhout <kleptog@svana.org>
1062306a36Sopenharmony_ci *		James Chapman (jchapman@katalix.com)
1162306a36Sopenharmony_ci * Contributors:
1262306a36Sopenharmony_ci *		Michal Ostrowski <mostrows@speakeasy.net>
1362306a36Sopenharmony_ci *		Arnaldo Carvalho de Melo <acme@xconectiva.com.br>
1462306a36Sopenharmony_ci *		David S. Miller (davem@redhat.com)
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <linux/module.h>
2062306a36Sopenharmony_ci#include <linux/string.h>
2162306a36Sopenharmony_ci#include <linux/list.h>
2262306a36Sopenharmony_ci#include <linux/rculist.h>
2362306a36Sopenharmony_ci#include <linux/uaccess.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include <linux/kernel.h>
2662306a36Sopenharmony_ci#include <linux/spinlock.h>
2762306a36Sopenharmony_ci#include <linux/kthread.h>
2862306a36Sopenharmony_ci#include <linux/sched.h>
2962306a36Sopenharmony_ci#include <linux/slab.h>
3062306a36Sopenharmony_ci#include <linux/errno.h>
3162306a36Sopenharmony_ci#include <linux/jiffies.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#include <linux/netdevice.h>
3462306a36Sopenharmony_ci#include <linux/net.h>
3562306a36Sopenharmony_ci#include <linux/inetdevice.h>
3662306a36Sopenharmony_ci#include <linux/skbuff.h>
3762306a36Sopenharmony_ci#include <linux/init.h>
3862306a36Sopenharmony_ci#include <linux/in.h>
3962306a36Sopenharmony_ci#include <linux/ip.h>
4062306a36Sopenharmony_ci#include <linux/udp.h>
4162306a36Sopenharmony_ci#include <linux/l2tp.h>
4262306a36Sopenharmony_ci#include <linux/hash.h>
4362306a36Sopenharmony_ci#include <linux/sort.h>
4462306a36Sopenharmony_ci#include <linux/file.h>
4562306a36Sopenharmony_ci#include <linux/nsproxy.h>
4662306a36Sopenharmony_ci#include <net/net_namespace.h>
4762306a36Sopenharmony_ci#include <net/netns/generic.h>
4862306a36Sopenharmony_ci#include <net/dst.h>
4962306a36Sopenharmony_ci#include <net/ip.h>
5062306a36Sopenharmony_ci#include <net/udp.h>
5162306a36Sopenharmony_ci#include <net/udp_tunnel.h>
5262306a36Sopenharmony_ci#include <net/inet_common.h>
5362306a36Sopenharmony_ci#include <net/xfrm.h>
5462306a36Sopenharmony_ci#include <net/protocol.h>
5562306a36Sopenharmony_ci#include <net/inet6_connection_sock.h>
5662306a36Sopenharmony_ci#include <net/inet_ecn.h>
5762306a36Sopenharmony_ci#include <net/ip6_route.h>
5862306a36Sopenharmony_ci#include <net/ip6_checksum.h>
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#include <asm/byteorder.h>
6162306a36Sopenharmony_ci#include <linux/atomic.h>
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#include "l2tp_core.h"
6462306a36Sopenharmony_ci#include "trace.h"
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#define CREATE_TRACE_POINTS
6762306a36Sopenharmony_ci#include "trace.h"
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#define L2TP_DRV_VERSION	"V2.0"
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/* L2TP header constants */
7262306a36Sopenharmony_ci#define L2TP_HDRFLAG_T	   0x8000
7362306a36Sopenharmony_ci#define L2TP_HDRFLAG_L	   0x4000
7462306a36Sopenharmony_ci#define L2TP_HDRFLAG_S	   0x0800
7562306a36Sopenharmony_ci#define L2TP_HDRFLAG_O	   0x0200
7662306a36Sopenharmony_ci#define L2TP_HDRFLAG_P	   0x0100
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#define L2TP_HDR_VER_MASK  0x000F
7962306a36Sopenharmony_ci#define L2TP_HDR_VER_2	   0x0002
8062306a36Sopenharmony_ci#define L2TP_HDR_VER_3	   0x0003
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci/* L2TPv3 default L2-specific sublayer */
8362306a36Sopenharmony_ci#define L2TP_SLFLAG_S	   0x40000000
8462306a36Sopenharmony_ci#define L2TP_SL_SEQ_MASK   0x00ffffff
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci#define L2TP_HDR_SIZE_MAX		14
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci/* Default trace flags */
8962306a36Sopenharmony_ci#define L2TP_DEFAULT_DEBUG_FLAGS	0
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci/* Private data stored for received packets in the skb.
9262306a36Sopenharmony_ci */
9362306a36Sopenharmony_cistruct l2tp_skb_cb {
9462306a36Sopenharmony_ci	u32			ns;
9562306a36Sopenharmony_ci	u16			has_seq;
9662306a36Sopenharmony_ci	u16			length;
9762306a36Sopenharmony_ci	unsigned long		expires;
9862306a36Sopenharmony_ci};
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci#define L2TP_SKB_CB(skb)	((struct l2tp_skb_cb *)&(skb)->cb[sizeof(struct inet_skb_parm)])
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistatic struct workqueue_struct *l2tp_wq;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci/* per-net private data for this module */
10562306a36Sopenharmony_cistatic unsigned int l2tp_net_id;
10662306a36Sopenharmony_cistruct l2tp_net {
10762306a36Sopenharmony_ci	/* Lock for write access to l2tp_tunnel_idr */
10862306a36Sopenharmony_ci	spinlock_t l2tp_tunnel_idr_lock;
10962306a36Sopenharmony_ci	struct idr l2tp_tunnel_idr;
11062306a36Sopenharmony_ci	struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2];
11162306a36Sopenharmony_ci	/* Lock for write access to l2tp_session_hlist */
11262306a36Sopenharmony_ci	spinlock_t l2tp_session_hlist_lock;
11362306a36Sopenharmony_ci};
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
11662306a36Sopenharmony_cistatic bool l2tp_sk_is_v6(struct sock *sk)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	return sk->sk_family == PF_INET6 &&
11962306a36Sopenharmony_ci	       !ipv6_addr_v4mapped(&sk->sk_v6_daddr);
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci#endif
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic inline struct l2tp_net *l2tp_pernet(const struct net *net)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	return net_generic(net, l2tp_net_id);
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci/* Session hash global list for L2TPv3.
12962306a36Sopenharmony_ci * The session_id SHOULD be random according to RFC3931, but several
13062306a36Sopenharmony_ci * L2TP implementations use incrementing session_ids.  So we do a real
13162306a36Sopenharmony_ci * hash on the session_id, rather than a simple bitmask.
13262306a36Sopenharmony_ci */
13362306a36Sopenharmony_cistatic inline struct hlist_head *
13462306a36Sopenharmony_cil2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	return &pn->l2tp_session_hlist[hash_32(session_id, L2TP_HASH_BITS_2)];
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci/* Session hash list.
14062306a36Sopenharmony_ci * The session_id SHOULD be random according to RFC2661, but several
14162306a36Sopenharmony_ci * L2TP implementations (Cisco and Microsoft) use incrementing
14262306a36Sopenharmony_ci * session_ids.  So we do a real hash on the session_id, rather than a
14362306a36Sopenharmony_ci * simple bitmask.
14462306a36Sopenharmony_ci */
14562306a36Sopenharmony_cistatic inline struct hlist_head *
14662306a36Sopenharmony_cil2tp_session_id_hash(struct l2tp_tunnel *tunnel, u32 session_id)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	return &tunnel->session_hlist[hash_32(session_id, L2TP_HASH_BITS)];
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	trace_free_tunnel(tunnel);
15462306a36Sopenharmony_ci	sock_put(tunnel->sock);
15562306a36Sopenharmony_ci	/* the tunnel is freed in the socket destructor */
15662306a36Sopenharmony_ci}
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_cistatic void l2tp_session_free(struct l2tp_session *session)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	trace_free_session(session);
16162306a36Sopenharmony_ci	if (session->tunnel)
16262306a36Sopenharmony_ci		l2tp_tunnel_dec_refcount(session->tunnel);
16362306a36Sopenharmony_ci	kfree(session);
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_cistruct l2tp_tunnel *l2tp_sk_to_tunnel(struct sock *sk)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = sk->sk_user_data;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	if (tunnel)
17162306a36Sopenharmony_ci		if (WARN_ON(tunnel->magic != L2TP_TUNNEL_MAGIC))
17262306a36Sopenharmony_ci			return NULL;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	return tunnel;
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_sk_to_tunnel);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_civoid l2tp_tunnel_inc_refcount(struct l2tp_tunnel *tunnel)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	refcount_inc(&tunnel->ref_count);
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_tunnel_inc_refcount);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_civoid l2tp_tunnel_dec_refcount(struct l2tp_tunnel *tunnel)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	if (refcount_dec_and_test(&tunnel->ref_count))
18762306a36Sopenharmony_ci		l2tp_tunnel_free(tunnel);
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_tunnel_dec_refcount);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_civoid l2tp_session_inc_refcount(struct l2tp_session *session)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	refcount_inc(&session->ref_count);
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_session_inc_refcount);
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_civoid l2tp_session_dec_refcount(struct l2tp_session *session)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	if (refcount_dec_and_test(&session->ref_count))
20062306a36Sopenharmony_ci		l2tp_session_free(session);
20162306a36Sopenharmony_ci}
20262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_session_dec_refcount);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci/* Lookup a tunnel. A new reference is held on the returned tunnel. */
20562306a36Sopenharmony_cistruct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, u32 tunnel_id)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	const struct l2tp_net *pn = l2tp_pernet(net);
20862306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	rcu_read_lock_bh();
21162306a36Sopenharmony_ci	tunnel = idr_find(&pn->l2tp_tunnel_idr, tunnel_id);
21262306a36Sopenharmony_ci	if (tunnel && refcount_inc_not_zero(&tunnel->ref_count)) {
21362306a36Sopenharmony_ci		rcu_read_unlock_bh();
21462306a36Sopenharmony_ci		return tunnel;
21562306a36Sopenharmony_ci	}
21662306a36Sopenharmony_ci	rcu_read_unlock_bh();
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	return NULL;
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_tunnel_get);
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistruct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	struct l2tp_net *pn = l2tp_pernet(net);
22562306a36Sopenharmony_ci	unsigned long tunnel_id, tmp;
22662306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel;
22762306a36Sopenharmony_ci	int count = 0;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	rcu_read_lock_bh();
23062306a36Sopenharmony_ci	idr_for_each_entry_ul(&pn->l2tp_tunnel_idr, tunnel, tmp, tunnel_id) {
23162306a36Sopenharmony_ci		if (tunnel && ++count > nth &&
23262306a36Sopenharmony_ci		    refcount_inc_not_zero(&tunnel->ref_count)) {
23362306a36Sopenharmony_ci			rcu_read_unlock_bh();
23462306a36Sopenharmony_ci			return tunnel;
23562306a36Sopenharmony_ci		}
23662306a36Sopenharmony_ci	}
23762306a36Sopenharmony_ci	rcu_read_unlock_bh();
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	return NULL;
24062306a36Sopenharmony_ci}
24162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_tunnel_get_nth);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cistruct l2tp_session *l2tp_tunnel_get_session(struct l2tp_tunnel *tunnel,
24462306a36Sopenharmony_ci					     u32 session_id)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	struct hlist_head *session_list;
24762306a36Sopenharmony_ci	struct l2tp_session *session;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	session_list = l2tp_session_id_hash(tunnel, session_id);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	rcu_read_lock_bh();
25262306a36Sopenharmony_ci	hlist_for_each_entry_rcu(session, session_list, hlist)
25362306a36Sopenharmony_ci		if (session->session_id == session_id) {
25462306a36Sopenharmony_ci			l2tp_session_inc_refcount(session);
25562306a36Sopenharmony_ci			rcu_read_unlock_bh();
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci			return session;
25862306a36Sopenharmony_ci		}
25962306a36Sopenharmony_ci	rcu_read_unlock_bh();
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	return NULL;
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_tunnel_get_session);
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistruct l2tp_session *l2tp_session_get(const struct net *net, u32 session_id)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	struct hlist_head *session_list;
26862306a36Sopenharmony_ci	struct l2tp_session *session;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	session_list = l2tp_session_id_hash_2(l2tp_pernet(net), session_id);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	rcu_read_lock_bh();
27362306a36Sopenharmony_ci	hlist_for_each_entry_rcu(session, session_list, global_hlist)
27462306a36Sopenharmony_ci		if (session->session_id == session_id) {
27562306a36Sopenharmony_ci			l2tp_session_inc_refcount(session);
27662306a36Sopenharmony_ci			rcu_read_unlock_bh();
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci			return session;
27962306a36Sopenharmony_ci		}
28062306a36Sopenharmony_ci	rcu_read_unlock_bh();
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	return NULL;
28362306a36Sopenharmony_ci}
28462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_session_get);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_cistruct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	int hash;
28962306a36Sopenharmony_ci	struct l2tp_session *session;
29062306a36Sopenharmony_ci	int count = 0;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	rcu_read_lock_bh();
29362306a36Sopenharmony_ci	for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
29462306a36Sopenharmony_ci		hlist_for_each_entry_rcu(session, &tunnel->session_hlist[hash], hlist) {
29562306a36Sopenharmony_ci			if (++count > nth) {
29662306a36Sopenharmony_ci				l2tp_session_inc_refcount(session);
29762306a36Sopenharmony_ci				rcu_read_unlock_bh();
29862306a36Sopenharmony_ci				return session;
29962306a36Sopenharmony_ci			}
30062306a36Sopenharmony_ci		}
30162306a36Sopenharmony_ci	}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	rcu_read_unlock_bh();
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	return NULL;
30662306a36Sopenharmony_ci}
30762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_session_get_nth);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci/* Lookup a session by interface name.
31062306a36Sopenharmony_ci * This is very inefficient but is only used by management interfaces.
31162306a36Sopenharmony_ci */
31262306a36Sopenharmony_cistruct l2tp_session *l2tp_session_get_by_ifname(const struct net *net,
31362306a36Sopenharmony_ci						const char *ifname)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	struct l2tp_net *pn = l2tp_pernet(net);
31662306a36Sopenharmony_ci	int hash;
31762306a36Sopenharmony_ci	struct l2tp_session *session;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	rcu_read_lock_bh();
32062306a36Sopenharmony_ci	for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) {
32162306a36Sopenharmony_ci		hlist_for_each_entry_rcu(session, &pn->l2tp_session_hlist[hash], global_hlist) {
32262306a36Sopenharmony_ci			if (!strcmp(session->ifname, ifname)) {
32362306a36Sopenharmony_ci				l2tp_session_inc_refcount(session);
32462306a36Sopenharmony_ci				rcu_read_unlock_bh();
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci				return session;
32762306a36Sopenharmony_ci			}
32862306a36Sopenharmony_ci		}
32962306a36Sopenharmony_ci	}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	rcu_read_unlock_bh();
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	return NULL;
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_session_get_by_ifname);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ciint l2tp_session_register(struct l2tp_session *session,
33862306a36Sopenharmony_ci			  struct l2tp_tunnel *tunnel)
33962306a36Sopenharmony_ci{
34062306a36Sopenharmony_ci	struct l2tp_session *session_walk;
34162306a36Sopenharmony_ci	struct hlist_head *g_head;
34262306a36Sopenharmony_ci	struct hlist_head *head;
34362306a36Sopenharmony_ci	struct l2tp_net *pn;
34462306a36Sopenharmony_ci	int err;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	head = l2tp_session_id_hash(tunnel, session->session_id);
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	spin_lock_bh(&tunnel->hlist_lock);
34962306a36Sopenharmony_ci	if (!tunnel->acpt_newsess) {
35062306a36Sopenharmony_ci		err = -ENODEV;
35162306a36Sopenharmony_ci		goto err_tlock;
35262306a36Sopenharmony_ci	}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	hlist_for_each_entry(session_walk, head, hlist)
35562306a36Sopenharmony_ci		if (session_walk->session_id == session->session_id) {
35662306a36Sopenharmony_ci			err = -EEXIST;
35762306a36Sopenharmony_ci			goto err_tlock;
35862306a36Sopenharmony_ci		}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	if (tunnel->version == L2TP_HDR_VER_3) {
36162306a36Sopenharmony_ci		pn = l2tp_pernet(tunnel->l2tp_net);
36262306a36Sopenharmony_ci		g_head = l2tp_session_id_hash_2(pn, session->session_id);
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci		spin_lock_bh(&pn->l2tp_session_hlist_lock);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci		/* IP encap expects session IDs to be globally unique, while
36762306a36Sopenharmony_ci		 * UDP encap doesn't.
36862306a36Sopenharmony_ci		 */
36962306a36Sopenharmony_ci		hlist_for_each_entry(session_walk, g_head, global_hlist)
37062306a36Sopenharmony_ci			if (session_walk->session_id == session->session_id &&
37162306a36Sopenharmony_ci			    (session_walk->tunnel->encap == L2TP_ENCAPTYPE_IP ||
37262306a36Sopenharmony_ci			     tunnel->encap == L2TP_ENCAPTYPE_IP)) {
37362306a36Sopenharmony_ci				err = -EEXIST;
37462306a36Sopenharmony_ci				goto err_tlock_pnlock;
37562306a36Sopenharmony_ci			}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci		l2tp_tunnel_inc_refcount(tunnel);
37862306a36Sopenharmony_ci		hlist_add_head_rcu(&session->global_hlist, g_head);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci		spin_unlock_bh(&pn->l2tp_session_hlist_lock);
38162306a36Sopenharmony_ci	} else {
38262306a36Sopenharmony_ci		l2tp_tunnel_inc_refcount(tunnel);
38362306a36Sopenharmony_ci	}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	hlist_add_head_rcu(&session->hlist, head);
38662306a36Sopenharmony_ci	spin_unlock_bh(&tunnel->hlist_lock);
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	trace_register_session(session);
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	return 0;
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_cierr_tlock_pnlock:
39362306a36Sopenharmony_ci	spin_unlock_bh(&pn->l2tp_session_hlist_lock);
39462306a36Sopenharmony_cierr_tlock:
39562306a36Sopenharmony_ci	spin_unlock_bh(&tunnel->hlist_lock);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	return err;
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_session_register);
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci/*****************************************************************************
40262306a36Sopenharmony_ci * Receive data handling
40362306a36Sopenharmony_ci *****************************************************************************/
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci/* Queue a skb in order. We come here only if the skb has an L2TP sequence
40662306a36Sopenharmony_ci * number.
40762306a36Sopenharmony_ci */
40862306a36Sopenharmony_cistatic void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *skb)
40962306a36Sopenharmony_ci{
41062306a36Sopenharmony_ci	struct sk_buff *skbp;
41162306a36Sopenharmony_ci	struct sk_buff *tmp;
41262306a36Sopenharmony_ci	u32 ns = L2TP_SKB_CB(skb)->ns;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	spin_lock_bh(&session->reorder_q.lock);
41562306a36Sopenharmony_ci	skb_queue_walk_safe(&session->reorder_q, skbp, tmp) {
41662306a36Sopenharmony_ci		if (L2TP_SKB_CB(skbp)->ns > ns) {
41762306a36Sopenharmony_ci			__skb_queue_before(&session->reorder_q, skbp, skb);
41862306a36Sopenharmony_ci			atomic_long_inc(&session->stats.rx_oos_packets);
41962306a36Sopenharmony_ci			goto out;
42062306a36Sopenharmony_ci		}
42162306a36Sopenharmony_ci	}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	__skb_queue_tail(&session->reorder_q, skb);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ciout:
42662306a36Sopenharmony_ci	spin_unlock_bh(&session->reorder_q.lock);
42762306a36Sopenharmony_ci}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci/* Dequeue a single skb.
43062306a36Sopenharmony_ci */
43162306a36Sopenharmony_cistatic void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff *skb)
43262306a36Sopenharmony_ci{
43362306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = session->tunnel;
43462306a36Sopenharmony_ci	int length = L2TP_SKB_CB(skb)->length;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	/* We're about to requeue the skb, so return resources
43762306a36Sopenharmony_ci	 * to its current owner (a socket receive buffer).
43862306a36Sopenharmony_ci	 */
43962306a36Sopenharmony_ci	skb_orphan(skb);
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	atomic_long_inc(&tunnel->stats.rx_packets);
44262306a36Sopenharmony_ci	atomic_long_add(length, &tunnel->stats.rx_bytes);
44362306a36Sopenharmony_ci	atomic_long_inc(&session->stats.rx_packets);
44462306a36Sopenharmony_ci	atomic_long_add(length, &session->stats.rx_bytes);
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	if (L2TP_SKB_CB(skb)->has_seq) {
44762306a36Sopenharmony_ci		/* Bump our Nr */
44862306a36Sopenharmony_ci		session->nr++;
44962306a36Sopenharmony_ci		session->nr &= session->nr_max;
45062306a36Sopenharmony_ci		trace_session_seqnum_update(session);
45162306a36Sopenharmony_ci	}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	/* call private receive handler */
45462306a36Sopenharmony_ci	if (session->recv_skb)
45562306a36Sopenharmony_ci		(*session->recv_skb)(session, skb, L2TP_SKB_CB(skb)->length);
45662306a36Sopenharmony_ci	else
45762306a36Sopenharmony_ci		kfree_skb(skb);
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci/* Dequeue skbs from the session's reorder_q, subject to packet order.
46162306a36Sopenharmony_ci * Skbs that have been in the queue for too long are simply discarded.
46262306a36Sopenharmony_ci */
46362306a36Sopenharmony_cistatic void l2tp_recv_dequeue(struct l2tp_session *session)
46462306a36Sopenharmony_ci{
46562306a36Sopenharmony_ci	struct sk_buff *skb;
46662306a36Sopenharmony_ci	struct sk_buff *tmp;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	/* If the pkt at the head of the queue has the nr that we
46962306a36Sopenharmony_ci	 * expect to send up next, dequeue it and any other
47062306a36Sopenharmony_ci	 * in-sequence packets behind it.
47162306a36Sopenharmony_ci	 */
47262306a36Sopenharmony_cistart:
47362306a36Sopenharmony_ci	spin_lock_bh(&session->reorder_q.lock);
47462306a36Sopenharmony_ci	skb_queue_walk_safe(&session->reorder_q, skb, tmp) {
47562306a36Sopenharmony_ci		struct l2tp_skb_cb *cb = L2TP_SKB_CB(skb);
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci		/* If the packet has been pending on the queue for too long, discard it */
47862306a36Sopenharmony_ci		if (time_after(jiffies, cb->expires)) {
47962306a36Sopenharmony_ci			atomic_long_inc(&session->stats.rx_seq_discards);
48062306a36Sopenharmony_ci			atomic_long_inc(&session->stats.rx_errors);
48162306a36Sopenharmony_ci			trace_session_pkt_expired(session, cb->ns);
48262306a36Sopenharmony_ci			session->reorder_skip = 1;
48362306a36Sopenharmony_ci			__skb_unlink(skb, &session->reorder_q);
48462306a36Sopenharmony_ci			kfree_skb(skb);
48562306a36Sopenharmony_ci			continue;
48662306a36Sopenharmony_ci		}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci		if (cb->has_seq) {
48962306a36Sopenharmony_ci			if (session->reorder_skip) {
49062306a36Sopenharmony_ci				session->reorder_skip = 0;
49162306a36Sopenharmony_ci				session->nr = cb->ns;
49262306a36Sopenharmony_ci				trace_session_seqnum_reset(session);
49362306a36Sopenharmony_ci			}
49462306a36Sopenharmony_ci			if (cb->ns != session->nr)
49562306a36Sopenharmony_ci				goto out;
49662306a36Sopenharmony_ci		}
49762306a36Sopenharmony_ci		__skb_unlink(skb, &session->reorder_q);
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci		/* Process the skb. We release the queue lock while we
50062306a36Sopenharmony_ci		 * do so to let other contexts process the queue.
50162306a36Sopenharmony_ci		 */
50262306a36Sopenharmony_ci		spin_unlock_bh(&session->reorder_q.lock);
50362306a36Sopenharmony_ci		l2tp_recv_dequeue_skb(session, skb);
50462306a36Sopenharmony_ci		goto start;
50562306a36Sopenharmony_ci	}
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ciout:
50862306a36Sopenharmony_ci	spin_unlock_bh(&session->reorder_q.lock);
50962306a36Sopenharmony_ci}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_cistatic int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr)
51262306a36Sopenharmony_ci{
51362306a36Sopenharmony_ci	u32 nws;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	if (nr >= session->nr)
51662306a36Sopenharmony_ci		nws = nr - session->nr;
51762306a36Sopenharmony_ci	else
51862306a36Sopenharmony_ci		nws = (session->nr_max + 1) - (session->nr - nr);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	return nws < session->nr_window_size;
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci/* If packet has sequence numbers, queue it if acceptable. Returns 0 if
52462306a36Sopenharmony_ci * acceptable, else non-zero.
52562306a36Sopenharmony_ci */
52662306a36Sopenharmony_cistatic int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb)
52762306a36Sopenharmony_ci{
52862306a36Sopenharmony_ci	struct l2tp_skb_cb *cb = L2TP_SKB_CB(skb);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	if (!l2tp_seq_check_rx_window(session, cb->ns)) {
53162306a36Sopenharmony_ci		/* Packet sequence number is outside allowed window.
53262306a36Sopenharmony_ci		 * Discard it.
53362306a36Sopenharmony_ci		 */
53462306a36Sopenharmony_ci		trace_session_pkt_outside_rx_window(session, cb->ns);
53562306a36Sopenharmony_ci		goto discard;
53662306a36Sopenharmony_ci	}
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	if (session->reorder_timeout != 0) {
53962306a36Sopenharmony_ci		/* Packet reordering enabled. Add skb to session's
54062306a36Sopenharmony_ci		 * reorder queue, in order of ns.
54162306a36Sopenharmony_ci		 */
54262306a36Sopenharmony_ci		l2tp_recv_queue_skb(session, skb);
54362306a36Sopenharmony_ci		goto out;
54462306a36Sopenharmony_ci	}
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	/* Packet reordering disabled. Discard out-of-sequence packets, while
54762306a36Sopenharmony_ci	 * tracking the number if in-sequence packets after the first OOS packet
54862306a36Sopenharmony_ci	 * is seen. After nr_oos_count_max in-sequence packets, reset the
54962306a36Sopenharmony_ci	 * sequence number to re-enable packet reception.
55062306a36Sopenharmony_ci	 */
55162306a36Sopenharmony_ci	if (cb->ns == session->nr) {
55262306a36Sopenharmony_ci		skb_queue_tail(&session->reorder_q, skb);
55362306a36Sopenharmony_ci	} else {
55462306a36Sopenharmony_ci		u32 nr_oos = cb->ns;
55562306a36Sopenharmony_ci		u32 nr_next = (session->nr_oos + 1) & session->nr_max;
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci		if (nr_oos == nr_next)
55862306a36Sopenharmony_ci			session->nr_oos_count++;
55962306a36Sopenharmony_ci		else
56062306a36Sopenharmony_ci			session->nr_oos_count = 0;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci		session->nr_oos = nr_oos;
56362306a36Sopenharmony_ci		if (session->nr_oos_count > session->nr_oos_count_max) {
56462306a36Sopenharmony_ci			session->reorder_skip = 1;
56562306a36Sopenharmony_ci		}
56662306a36Sopenharmony_ci		if (!session->reorder_skip) {
56762306a36Sopenharmony_ci			atomic_long_inc(&session->stats.rx_seq_discards);
56862306a36Sopenharmony_ci			trace_session_pkt_oos(session, cb->ns);
56962306a36Sopenharmony_ci			goto discard;
57062306a36Sopenharmony_ci		}
57162306a36Sopenharmony_ci		skb_queue_tail(&session->reorder_q, skb);
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ciout:
57562306a36Sopenharmony_ci	return 0;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_cidiscard:
57862306a36Sopenharmony_ci	return 1;
57962306a36Sopenharmony_ci}
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci/* Do receive processing of L2TP data frames. We handle both L2TPv2
58262306a36Sopenharmony_ci * and L2TPv3 data frames here.
58362306a36Sopenharmony_ci *
58462306a36Sopenharmony_ci * L2TPv2 Data Message Header
58562306a36Sopenharmony_ci *
58662306a36Sopenharmony_ci *  0                   1                   2                   3
58762306a36Sopenharmony_ci *  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
58862306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58962306a36Sopenharmony_ci * |T|L|x|x|S|x|O|P|x|x|x|x|  Ver  |          Length (opt)         |
59062306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59162306a36Sopenharmony_ci * |           Tunnel ID           |           Session ID          |
59262306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59362306a36Sopenharmony_ci * |             Ns (opt)          |             Nr (opt)          |
59462306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59562306a36Sopenharmony_ci * |      Offset Size (opt)        |    Offset pad... (opt)
59662306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59762306a36Sopenharmony_ci *
59862306a36Sopenharmony_ci * Data frames are marked by T=0. All other fields are the same as
59962306a36Sopenharmony_ci * those in L2TP control frames.
60062306a36Sopenharmony_ci *
60162306a36Sopenharmony_ci * L2TPv3 Data Message Header
60262306a36Sopenharmony_ci *
60362306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60462306a36Sopenharmony_ci * |                      L2TP Session Header                      |
60562306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60662306a36Sopenharmony_ci * |                      L2-Specific Sublayer                     |
60762306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60862306a36Sopenharmony_ci * |                        Tunnel Payload                      ...
60962306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61062306a36Sopenharmony_ci *
61162306a36Sopenharmony_ci * L2TPv3 Session Header Over IP
61262306a36Sopenharmony_ci *
61362306a36Sopenharmony_ci *  0                   1                   2                   3
61462306a36Sopenharmony_ci *  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
61562306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61662306a36Sopenharmony_ci * |                           Session ID                          |
61762306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61862306a36Sopenharmony_ci * |               Cookie (optional, maximum 64 bits)...
61962306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62062306a36Sopenharmony_ci *                                                                 |
62162306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62262306a36Sopenharmony_ci *
62362306a36Sopenharmony_ci * L2TPv3 L2-Specific Sublayer Format
62462306a36Sopenharmony_ci *
62562306a36Sopenharmony_ci *  0                   1                   2                   3
62662306a36Sopenharmony_ci *  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
62762306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62862306a36Sopenharmony_ci * |x|S|x|x|x|x|x|x|              Sequence Number                  |
62962306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63062306a36Sopenharmony_ci *
63162306a36Sopenharmony_ci * Cookie value and sublayer format are negotiated with the peer when
63262306a36Sopenharmony_ci * the session is set up. Unlike L2TPv2, we do not need to parse the
63362306a36Sopenharmony_ci * packet header to determine if optional fields are present.
63462306a36Sopenharmony_ci *
63562306a36Sopenharmony_ci * Caller must already have parsed the frame and determined that it is
63662306a36Sopenharmony_ci * a data (not control) frame before coming here. Fields up to the
63762306a36Sopenharmony_ci * session-id have already been parsed and ptr points to the data
63862306a36Sopenharmony_ci * after the session-id.
63962306a36Sopenharmony_ci */
64062306a36Sopenharmony_civoid l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
64162306a36Sopenharmony_ci		      unsigned char *ptr, unsigned char *optr, u16 hdrflags,
64262306a36Sopenharmony_ci		      int length)
64362306a36Sopenharmony_ci{
64462306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = session->tunnel;
64562306a36Sopenharmony_ci	int offset;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	/* Parse and check optional cookie */
64862306a36Sopenharmony_ci	if (session->peer_cookie_len > 0) {
64962306a36Sopenharmony_ci		if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) {
65062306a36Sopenharmony_ci			pr_debug_ratelimited("%s: cookie mismatch (%u/%u). Discarding.\n",
65162306a36Sopenharmony_ci					     tunnel->name, tunnel->tunnel_id,
65262306a36Sopenharmony_ci					     session->session_id);
65362306a36Sopenharmony_ci			atomic_long_inc(&session->stats.rx_cookie_discards);
65462306a36Sopenharmony_ci			goto discard;
65562306a36Sopenharmony_ci		}
65662306a36Sopenharmony_ci		ptr += session->peer_cookie_len;
65762306a36Sopenharmony_ci	}
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	/* Handle the optional sequence numbers. Sequence numbers are
66062306a36Sopenharmony_ci	 * in different places for L2TPv2 and L2TPv3.
66162306a36Sopenharmony_ci	 *
66262306a36Sopenharmony_ci	 * If we are the LAC, enable/disable sequence numbers under
66362306a36Sopenharmony_ci	 * the control of the LNS.  If no sequence numbers present but
66462306a36Sopenharmony_ci	 * we were expecting them, discard frame.
66562306a36Sopenharmony_ci	 */
66662306a36Sopenharmony_ci	L2TP_SKB_CB(skb)->has_seq = 0;
66762306a36Sopenharmony_ci	if (tunnel->version == L2TP_HDR_VER_2) {
66862306a36Sopenharmony_ci		if (hdrflags & L2TP_HDRFLAG_S) {
66962306a36Sopenharmony_ci			/* Store L2TP info in the skb */
67062306a36Sopenharmony_ci			L2TP_SKB_CB(skb)->ns = ntohs(*(__be16 *)ptr);
67162306a36Sopenharmony_ci			L2TP_SKB_CB(skb)->has_seq = 1;
67262306a36Sopenharmony_ci			ptr += 2;
67362306a36Sopenharmony_ci			/* Skip past nr in the header */
67462306a36Sopenharmony_ci			ptr += 2;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci		}
67762306a36Sopenharmony_ci	} else if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
67862306a36Sopenharmony_ci		u32 l2h = ntohl(*(__be32 *)ptr);
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci		if (l2h & 0x40000000) {
68162306a36Sopenharmony_ci			/* Store L2TP info in the skb */
68262306a36Sopenharmony_ci			L2TP_SKB_CB(skb)->ns = l2h & 0x00ffffff;
68362306a36Sopenharmony_ci			L2TP_SKB_CB(skb)->has_seq = 1;
68462306a36Sopenharmony_ci		}
68562306a36Sopenharmony_ci		ptr += 4;
68662306a36Sopenharmony_ci	}
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	if (L2TP_SKB_CB(skb)->has_seq) {
68962306a36Sopenharmony_ci		/* Received a packet with sequence numbers. If we're the LAC,
69062306a36Sopenharmony_ci		 * check if we sre sending sequence numbers and if not,
69162306a36Sopenharmony_ci		 * configure it so.
69262306a36Sopenharmony_ci		 */
69362306a36Sopenharmony_ci		if (!session->lns_mode && !session->send_seq) {
69462306a36Sopenharmony_ci			trace_session_seqnum_lns_enable(session);
69562306a36Sopenharmony_ci			session->send_seq = 1;
69662306a36Sopenharmony_ci			l2tp_session_set_header_len(session, tunnel->version);
69762306a36Sopenharmony_ci		}
69862306a36Sopenharmony_ci	} else {
69962306a36Sopenharmony_ci		/* No sequence numbers.
70062306a36Sopenharmony_ci		 * If user has configured mandatory sequence numbers, discard.
70162306a36Sopenharmony_ci		 */
70262306a36Sopenharmony_ci		if (session->recv_seq) {
70362306a36Sopenharmony_ci			pr_debug_ratelimited("%s: recv data has no seq numbers when required. Discarding.\n",
70462306a36Sopenharmony_ci					     session->name);
70562306a36Sopenharmony_ci			atomic_long_inc(&session->stats.rx_seq_discards);
70662306a36Sopenharmony_ci			goto discard;
70762306a36Sopenharmony_ci		}
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci		/* If we're the LAC and we're sending sequence numbers, the
71062306a36Sopenharmony_ci		 * LNS has requested that we no longer send sequence numbers.
71162306a36Sopenharmony_ci		 * If we're the LNS and we're sending sequence numbers, the
71262306a36Sopenharmony_ci		 * LAC is broken. Discard the frame.
71362306a36Sopenharmony_ci		 */
71462306a36Sopenharmony_ci		if (!session->lns_mode && session->send_seq) {
71562306a36Sopenharmony_ci			trace_session_seqnum_lns_disable(session);
71662306a36Sopenharmony_ci			session->send_seq = 0;
71762306a36Sopenharmony_ci			l2tp_session_set_header_len(session, tunnel->version);
71862306a36Sopenharmony_ci		} else if (session->send_seq) {
71962306a36Sopenharmony_ci			pr_debug_ratelimited("%s: recv data has no seq numbers when required. Discarding.\n",
72062306a36Sopenharmony_ci					     session->name);
72162306a36Sopenharmony_ci			atomic_long_inc(&session->stats.rx_seq_discards);
72262306a36Sopenharmony_ci			goto discard;
72362306a36Sopenharmony_ci		}
72462306a36Sopenharmony_ci	}
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	/* Session data offset is defined only for L2TPv2 and is
72762306a36Sopenharmony_ci	 * indicated by an optional 16-bit value in the header.
72862306a36Sopenharmony_ci	 */
72962306a36Sopenharmony_ci	if (tunnel->version == L2TP_HDR_VER_2) {
73062306a36Sopenharmony_ci		/* If offset bit set, skip it. */
73162306a36Sopenharmony_ci		if (hdrflags & L2TP_HDRFLAG_O) {
73262306a36Sopenharmony_ci			offset = ntohs(*(__be16 *)ptr);
73362306a36Sopenharmony_ci			ptr += 2 + offset;
73462306a36Sopenharmony_ci		}
73562306a36Sopenharmony_ci	}
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	offset = ptr - optr;
73862306a36Sopenharmony_ci	if (!pskb_may_pull(skb, offset))
73962306a36Sopenharmony_ci		goto discard;
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	__skb_pull(skb, offset);
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	/* Prepare skb for adding to the session's reorder_q.  Hold
74462306a36Sopenharmony_ci	 * packets for max reorder_timeout or 1 second if not
74562306a36Sopenharmony_ci	 * reordering.
74662306a36Sopenharmony_ci	 */
74762306a36Sopenharmony_ci	L2TP_SKB_CB(skb)->length = length;
74862306a36Sopenharmony_ci	L2TP_SKB_CB(skb)->expires = jiffies +
74962306a36Sopenharmony_ci		(session->reorder_timeout ? session->reorder_timeout : HZ);
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	/* Add packet to the session's receive queue. Reordering is done here, if
75262306a36Sopenharmony_ci	 * enabled. Saved L2TP protocol info is stored in skb->sb[].
75362306a36Sopenharmony_ci	 */
75462306a36Sopenharmony_ci	if (L2TP_SKB_CB(skb)->has_seq) {
75562306a36Sopenharmony_ci		if (l2tp_recv_data_seq(session, skb))
75662306a36Sopenharmony_ci			goto discard;
75762306a36Sopenharmony_ci	} else {
75862306a36Sopenharmony_ci		/* No sequence numbers. Add the skb to the tail of the
75962306a36Sopenharmony_ci		 * reorder queue. This ensures that it will be
76062306a36Sopenharmony_ci		 * delivered after all previous sequenced skbs.
76162306a36Sopenharmony_ci		 */
76262306a36Sopenharmony_ci		skb_queue_tail(&session->reorder_q, skb);
76362306a36Sopenharmony_ci	}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	/* Try to dequeue as many skbs from reorder_q as we can. */
76662306a36Sopenharmony_ci	l2tp_recv_dequeue(session);
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	return;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_cidiscard:
77162306a36Sopenharmony_ci	atomic_long_inc(&session->stats.rx_errors);
77262306a36Sopenharmony_ci	kfree_skb(skb);
77362306a36Sopenharmony_ci}
77462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_recv_common);
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci/* Drop skbs from the session's reorder_q
77762306a36Sopenharmony_ci */
77862306a36Sopenharmony_cistatic void l2tp_session_queue_purge(struct l2tp_session *session)
77962306a36Sopenharmony_ci{
78062306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	while ((skb = skb_dequeue(&session->reorder_q))) {
78362306a36Sopenharmony_ci		atomic_long_inc(&session->stats.rx_errors);
78462306a36Sopenharmony_ci		kfree_skb(skb);
78562306a36Sopenharmony_ci	}
78662306a36Sopenharmony_ci}
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci/* Internal UDP receive frame. Do the real work of receiving an L2TP data frame
78962306a36Sopenharmony_ci * here. The skb is not on a list when we get here.
79062306a36Sopenharmony_ci * Returns 0 if the packet was a data packet and was successfully passed on.
79162306a36Sopenharmony_ci * Returns 1 if the packet was not a good data packet and could not be
79262306a36Sopenharmony_ci * forwarded.  All such packets are passed up to userspace to deal with.
79362306a36Sopenharmony_ci */
79462306a36Sopenharmony_cistatic int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
79562306a36Sopenharmony_ci{
79662306a36Sopenharmony_ci	struct l2tp_session *session = NULL;
79762306a36Sopenharmony_ci	unsigned char *ptr, *optr;
79862306a36Sopenharmony_ci	u16 hdrflags;
79962306a36Sopenharmony_ci	u32 tunnel_id, session_id;
80062306a36Sopenharmony_ci	u16 version;
80162306a36Sopenharmony_ci	int length;
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	/* UDP has verified checksum */
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	/* UDP always verifies the packet length. */
80662306a36Sopenharmony_ci	__skb_pull(skb, sizeof(struct udphdr));
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	/* Short packet? */
80962306a36Sopenharmony_ci	if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX)) {
81062306a36Sopenharmony_ci		pr_debug_ratelimited("%s: recv short packet (len=%d)\n",
81162306a36Sopenharmony_ci				     tunnel->name, skb->len);
81262306a36Sopenharmony_ci		goto invalid;
81362306a36Sopenharmony_ci	}
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	/* Point to L2TP header */
81662306a36Sopenharmony_ci	optr = skb->data;
81762306a36Sopenharmony_ci	ptr = skb->data;
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	/* Get L2TP header flags */
82062306a36Sopenharmony_ci	hdrflags = ntohs(*(__be16 *)ptr);
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	/* Check protocol version */
82362306a36Sopenharmony_ci	version = hdrflags & L2TP_HDR_VER_MASK;
82462306a36Sopenharmony_ci	if (version != tunnel->version) {
82562306a36Sopenharmony_ci		pr_debug_ratelimited("%s: recv protocol version mismatch: got %d expected %d\n",
82662306a36Sopenharmony_ci				     tunnel->name, version, tunnel->version);
82762306a36Sopenharmony_ci		goto invalid;
82862306a36Sopenharmony_ci	}
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	/* Get length of L2TP packet */
83162306a36Sopenharmony_ci	length = skb->len;
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	/* If type is control packet, it is handled by userspace. */
83462306a36Sopenharmony_ci	if (hdrflags & L2TP_HDRFLAG_T)
83562306a36Sopenharmony_ci		goto pass;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	/* Skip flags */
83862306a36Sopenharmony_ci	ptr += 2;
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci	if (tunnel->version == L2TP_HDR_VER_2) {
84162306a36Sopenharmony_ci		/* If length is present, skip it */
84262306a36Sopenharmony_ci		if (hdrflags & L2TP_HDRFLAG_L)
84362306a36Sopenharmony_ci			ptr += 2;
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci		/* Extract tunnel and session ID */
84662306a36Sopenharmony_ci		tunnel_id = ntohs(*(__be16 *)ptr);
84762306a36Sopenharmony_ci		ptr += 2;
84862306a36Sopenharmony_ci		session_id = ntohs(*(__be16 *)ptr);
84962306a36Sopenharmony_ci		ptr += 2;
85062306a36Sopenharmony_ci	} else {
85162306a36Sopenharmony_ci		ptr += 2;	/* skip reserved bits */
85262306a36Sopenharmony_ci		tunnel_id = tunnel->tunnel_id;
85362306a36Sopenharmony_ci		session_id = ntohl(*(__be32 *)ptr);
85462306a36Sopenharmony_ci		ptr += 4;
85562306a36Sopenharmony_ci	}
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	/* Find the session context */
85862306a36Sopenharmony_ci	session = l2tp_tunnel_get_session(tunnel, session_id);
85962306a36Sopenharmony_ci	if (!session || !session->recv_skb) {
86062306a36Sopenharmony_ci		if (session)
86162306a36Sopenharmony_ci			l2tp_session_dec_refcount(session);
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci		/* Not found? Pass to userspace to deal with */
86462306a36Sopenharmony_ci		pr_debug_ratelimited("%s: no session found (%u/%u). Passing up.\n",
86562306a36Sopenharmony_ci				     tunnel->name, tunnel_id, session_id);
86662306a36Sopenharmony_ci		goto pass;
86762306a36Sopenharmony_ci	}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	if (tunnel->version == L2TP_HDR_VER_3 &&
87062306a36Sopenharmony_ci	    l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr)) {
87162306a36Sopenharmony_ci		l2tp_session_dec_refcount(session);
87262306a36Sopenharmony_ci		goto invalid;
87362306a36Sopenharmony_ci	}
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
87662306a36Sopenharmony_ci	l2tp_session_dec_refcount(session);
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci	return 0;
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ciinvalid:
88162306a36Sopenharmony_ci	atomic_long_inc(&tunnel->stats.rx_invalid);
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_cipass:
88462306a36Sopenharmony_ci	/* Put UDP header back */
88562306a36Sopenharmony_ci	__skb_push(skb, sizeof(struct udphdr));
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	return 1;
88862306a36Sopenharmony_ci}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci/* UDP encapsulation receive handler. See net/ipv4/udp.c.
89162306a36Sopenharmony_ci * Return codes:
89262306a36Sopenharmony_ci * 0 : success.
89362306a36Sopenharmony_ci * <0: error
89462306a36Sopenharmony_ci * >0: skb should be passed up to userspace as UDP.
89562306a36Sopenharmony_ci */
89662306a36Sopenharmony_ciint l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
89762306a36Sopenharmony_ci{
89862306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel;
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	/* Note that this is called from the encap_rcv hook inside an
90162306a36Sopenharmony_ci	 * RCU-protected region, but without the socket being locked.
90262306a36Sopenharmony_ci	 * Hence we use rcu_dereference_sk_user_data to access the
90362306a36Sopenharmony_ci	 * tunnel data structure rather the usual l2tp_sk_to_tunnel
90462306a36Sopenharmony_ci	 * accessor function.
90562306a36Sopenharmony_ci	 */
90662306a36Sopenharmony_ci	tunnel = rcu_dereference_sk_user_data(sk);
90762306a36Sopenharmony_ci	if (!tunnel)
90862306a36Sopenharmony_ci		goto pass_up;
90962306a36Sopenharmony_ci	if (WARN_ON(tunnel->magic != L2TP_TUNNEL_MAGIC))
91062306a36Sopenharmony_ci		goto pass_up;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	if (l2tp_udp_recv_core(tunnel, skb))
91362306a36Sopenharmony_ci		goto pass_up;
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	return 0;
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_cipass_up:
91862306a36Sopenharmony_ci	return 1;
91962306a36Sopenharmony_ci}
92062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_udp_encap_recv);
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci/************************************************************************
92362306a36Sopenharmony_ci * Transmit handling
92462306a36Sopenharmony_ci ***********************************************************************/
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci/* Build an L2TP header for the session into the buffer provided.
92762306a36Sopenharmony_ci */
92862306a36Sopenharmony_cistatic int l2tp_build_l2tpv2_header(struct l2tp_session *session, void *buf)
92962306a36Sopenharmony_ci{
93062306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = session->tunnel;
93162306a36Sopenharmony_ci	__be16 *bufp = buf;
93262306a36Sopenharmony_ci	__be16 *optr = buf;
93362306a36Sopenharmony_ci	u16 flags = L2TP_HDR_VER_2;
93462306a36Sopenharmony_ci	u32 tunnel_id = tunnel->peer_tunnel_id;
93562306a36Sopenharmony_ci	u32 session_id = session->peer_session_id;
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	if (session->send_seq)
93862306a36Sopenharmony_ci		flags |= L2TP_HDRFLAG_S;
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci	/* Setup L2TP header. */
94162306a36Sopenharmony_ci	*bufp++ = htons(flags);
94262306a36Sopenharmony_ci	*bufp++ = htons(tunnel_id);
94362306a36Sopenharmony_ci	*bufp++ = htons(session_id);
94462306a36Sopenharmony_ci	if (session->send_seq) {
94562306a36Sopenharmony_ci		*bufp++ = htons(session->ns);
94662306a36Sopenharmony_ci		*bufp++ = 0;
94762306a36Sopenharmony_ci		session->ns++;
94862306a36Sopenharmony_ci		session->ns &= 0xffff;
94962306a36Sopenharmony_ci		trace_session_seqnum_update(session);
95062306a36Sopenharmony_ci	}
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	return bufp - optr;
95362306a36Sopenharmony_ci}
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_cistatic int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf)
95662306a36Sopenharmony_ci{
95762306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = session->tunnel;
95862306a36Sopenharmony_ci	char *bufp = buf;
95962306a36Sopenharmony_ci	char *optr = bufp;
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	/* Setup L2TP header. The header differs slightly for UDP and
96262306a36Sopenharmony_ci	 * IP encapsulations. For UDP, there is 4 bytes of flags.
96362306a36Sopenharmony_ci	 */
96462306a36Sopenharmony_ci	if (tunnel->encap == L2TP_ENCAPTYPE_UDP) {
96562306a36Sopenharmony_ci		u16 flags = L2TP_HDR_VER_3;
96662306a36Sopenharmony_ci		*((__be16 *)bufp) = htons(flags);
96762306a36Sopenharmony_ci		bufp += 2;
96862306a36Sopenharmony_ci		*((__be16 *)bufp) = 0;
96962306a36Sopenharmony_ci		bufp += 2;
97062306a36Sopenharmony_ci	}
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	*((__be32 *)bufp) = htonl(session->peer_session_id);
97362306a36Sopenharmony_ci	bufp += 4;
97462306a36Sopenharmony_ci	if (session->cookie_len) {
97562306a36Sopenharmony_ci		memcpy(bufp, &session->cookie[0], session->cookie_len);
97662306a36Sopenharmony_ci		bufp += session->cookie_len;
97762306a36Sopenharmony_ci	}
97862306a36Sopenharmony_ci	if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
97962306a36Sopenharmony_ci		u32 l2h = 0;
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci		if (session->send_seq) {
98262306a36Sopenharmony_ci			l2h = 0x40000000 | session->ns;
98362306a36Sopenharmony_ci			session->ns++;
98462306a36Sopenharmony_ci			session->ns &= 0xffffff;
98562306a36Sopenharmony_ci			trace_session_seqnum_update(session);
98662306a36Sopenharmony_ci		}
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci		*((__be32 *)bufp) = htonl(l2h);
98962306a36Sopenharmony_ci		bufp += 4;
99062306a36Sopenharmony_ci	}
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	return bufp - optr;
99362306a36Sopenharmony_ci}
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci/* Queue the packet to IP for output: tunnel socket lock must be held */
99662306a36Sopenharmony_cistatic int l2tp_xmit_queue(struct l2tp_tunnel *tunnel, struct sk_buff *skb, struct flowi *fl)
99762306a36Sopenharmony_ci{
99862306a36Sopenharmony_ci	int err;
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci	skb->ignore_df = 1;
100162306a36Sopenharmony_ci	skb_dst_drop(skb);
100262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
100362306a36Sopenharmony_ci	if (l2tp_sk_is_v6(tunnel->sock))
100462306a36Sopenharmony_ci		err = inet6_csk_xmit(tunnel->sock, skb, NULL);
100562306a36Sopenharmony_ci	else
100662306a36Sopenharmony_ci#endif
100762306a36Sopenharmony_ci		err = ip_queue_xmit(tunnel->sock, skb, fl);
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	return err >= 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
101062306a36Sopenharmony_ci}
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_cistatic int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, unsigned int *len)
101362306a36Sopenharmony_ci{
101462306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = session->tunnel;
101562306a36Sopenharmony_ci	unsigned int data_len = skb->len;
101662306a36Sopenharmony_ci	struct sock *sk = tunnel->sock;
101762306a36Sopenharmony_ci	int headroom, uhlen, udp_len;
101862306a36Sopenharmony_ci	int ret = NET_XMIT_SUCCESS;
101962306a36Sopenharmony_ci	struct inet_sock *inet;
102062306a36Sopenharmony_ci	struct udphdr *uh;
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	/* Check that there's enough headroom in the skb to insert IP,
102362306a36Sopenharmony_ci	 * UDP and L2TP headers. If not enough, expand it to
102462306a36Sopenharmony_ci	 * make room. Adjust truesize.
102562306a36Sopenharmony_ci	 */
102662306a36Sopenharmony_ci	uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(*uh) : 0;
102762306a36Sopenharmony_ci	headroom = NET_SKB_PAD + sizeof(struct iphdr) + uhlen + session->hdr_len;
102862306a36Sopenharmony_ci	if (skb_cow_head(skb, headroom)) {
102962306a36Sopenharmony_ci		kfree_skb(skb);
103062306a36Sopenharmony_ci		return NET_XMIT_DROP;
103162306a36Sopenharmony_ci	}
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	/* Setup L2TP header */
103462306a36Sopenharmony_ci	if (tunnel->version == L2TP_HDR_VER_2)
103562306a36Sopenharmony_ci		l2tp_build_l2tpv2_header(session, __skb_push(skb, session->hdr_len));
103662306a36Sopenharmony_ci	else
103762306a36Sopenharmony_ci		l2tp_build_l2tpv3_header(session, __skb_push(skb, session->hdr_len));
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	/* Reset skb netfilter state */
104062306a36Sopenharmony_ci	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
104162306a36Sopenharmony_ci	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
104262306a36Sopenharmony_ci	nf_reset_ct(skb);
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	bh_lock_sock_nested(sk);
104562306a36Sopenharmony_ci	if (sock_owned_by_user(sk)) {
104662306a36Sopenharmony_ci		kfree_skb(skb);
104762306a36Sopenharmony_ci		ret = NET_XMIT_DROP;
104862306a36Sopenharmony_ci		goto out_unlock;
104962306a36Sopenharmony_ci	}
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci	/* The user-space may change the connection status for the user-space
105262306a36Sopenharmony_ci	 * provided socket at run time: we must check it under the socket lock
105362306a36Sopenharmony_ci	 */
105462306a36Sopenharmony_ci	if (tunnel->fd >= 0 && sk->sk_state != TCP_ESTABLISHED) {
105562306a36Sopenharmony_ci		kfree_skb(skb);
105662306a36Sopenharmony_ci		ret = NET_XMIT_DROP;
105762306a36Sopenharmony_ci		goto out_unlock;
105862306a36Sopenharmony_ci	}
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	/* Report transmitted length before we add encap header, which keeps
106162306a36Sopenharmony_ci	 * statistics consistent for both UDP and IP encap tx/rx paths.
106262306a36Sopenharmony_ci	 */
106362306a36Sopenharmony_ci	*len = skb->len;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	inet = inet_sk(sk);
106662306a36Sopenharmony_ci	switch (tunnel->encap) {
106762306a36Sopenharmony_ci	case L2TP_ENCAPTYPE_UDP:
106862306a36Sopenharmony_ci		/* Setup UDP header */
106962306a36Sopenharmony_ci		__skb_push(skb, sizeof(*uh));
107062306a36Sopenharmony_ci		skb_reset_transport_header(skb);
107162306a36Sopenharmony_ci		uh = udp_hdr(skb);
107262306a36Sopenharmony_ci		uh->source = inet->inet_sport;
107362306a36Sopenharmony_ci		uh->dest = inet->inet_dport;
107462306a36Sopenharmony_ci		udp_len = uhlen + session->hdr_len + data_len;
107562306a36Sopenharmony_ci		uh->len = htons(udp_len);
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci		/* Calculate UDP checksum if configured to do so */
107862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
107962306a36Sopenharmony_ci		if (l2tp_sk_is_v6(sk))
108062306a36Sopenharmony_ci			udp6_set_csum(udp_get_no_check6_tx(sk),
108162306a36Sopenharmony_ci				      skb, &inet6_sk(sk)->saddr,
108262306a36Sopenharmony_ci				      &sk->sk_v6_daddr, udp_len);
108362306a36Sopenharmony_ci		else
108462306a36Sopenharmony_ci#endif
108562306a36Sopenharmony_ci			udp_set_csum(sk->sk_no_check_tx, skb, inet->inet_saddr,
108662306a36Sopenharmony_ci				     inet->inet_daddr, udp_len);
108762306a36Sopenharmony_ci		break;
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	case L2TP_ENCAPTYPE_IP:
109062306a36Sopenharmony_ci		break;
109162306a36Sopenharmony_ci	}
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	ret = l2tp_xmit_queue(tunnel, skb, &inet->cork.fl);
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ciout_unlock:
109662306a36Sopenharmony_ci	bh_unlock_sock(sk);
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci	return ret;
109962306a36Sopenharmony_ci}
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci/* If caller requires the skb to have a ppp header, the header must be
110262306a36Sopenharmony_ci * inserted in the skb data before calling this function.
110362306a36Sopenharmony_ci */
110462306a36Sopenharmony_ciint l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb)
110562306a36Sopenharmony_ci{
110662306a36Sopenharmony_ci	unsigned int len = 0;
110762306a36Sopenharmony_ci	int ret;
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	ret = l2tp_xmit_core(session, skb, &len);
111062306a36Sopenharmony_ci	if (ret == NET_XMIT_SUCCESS) {
111162306a36Sopenharmony_ci		atomic_long_inc(&session->tunnel->stats.tx_packets);
111262306a36Sopenharmony_ci		atomic_long_add(len, &session->tunnel->stats.tx_bytes);
111362306a36Sopenharmony_ci		atomic_long_inc(&session->stats.tx_packets);
111462306a36Sopenharmony_ci		atomic_long_add(len, &session->stats.tx_bytes);
111562306a36Sopenharmony_ci	} else {
111662306a36Sopenharmony_ci		atomic_long_inc(&session->tunnel->stats.tx_errors);
111762306a36Sopenharmony_ci		atomic_long_inc(&session->stats.tx_errors);
111862306a36Sopenharmony_ci	}
111962306a36Sopenharmony_ci	return ret;
112062306a36Sopenharmony_ci}
112162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_xmit_skb);
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci/*****************************************************************************
112462306a36Sopenharmony_ci * Tinnel and session create/destroy.
112562306a36Sopenharmony_ci *****************************************************************************/
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci/* Tunnel socket destruct hook.
112862306a36Sopenharmony_ci * The tunnel context is deleted only when all session sockets have been
112962306a36Sopenharmony_ci * closed.
113062306a36Sopenharmony_ci */
113162306a36Sopenharmony_cistatic void l2tp_tunnel_destruct(struct sock *sk)
113262306a36Sopenharmony_ci{
113362306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = l2tp_sk_to_tunnel(sk);
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	if (!tunnel)
113662306a36Sopenharmony_ci		goto end;
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	/* Disable udp encapsulation */
113962306a36Sopenharmony_ci	switch (tunnel->encap) {
114062306a36Sopenharmony_ci	case L2TP_ENCAPTYPE_UDP:
114162306a36Sopenharmony_ci		/* No longer an encapsulation socket. See net/ipv4/udp.c */
114262306a36Sopenharmony_ci		WRITE_ONCE(udp_sk(sk)->encap_type, 0);
114362306a36Sopenharmony_ci		udp_sk(sk)->encap_rcv = NULL;
114462306a36Sopenharmony_ci		udp_sk(sk)->encap_destroy = NULL;
114562306a36Sopenharmony_ci		break;
114662306a36Sopenharmony_ci	case L2TP_ENCAPTYPE_IP:
114762306a36Sopenharmony_ci		break;
114862306a36Sopenharmony_ci	}
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	/* Remove hooks into tunnel socket */
115162306a36Sopenharmony_ci	write_lock_bh(&sk->sk_callback_lock);
115262306a36Sopenharmony_ci	sk->sk_destruct = tunnel->old_sk_destruct;
115362306a36Sopenharmony_ci	sk->sk_user_data = NULL;
115462306a36Sopenharmony_ci	write_unlock_bh(&sk->sk_callback_lock);
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci	/* Call the original destructor */
115762306a36Sopenharmony_ci	if (sk->sk_destruct)
115862306a36Sopenharmony_ci		(*sk->sk_destruct)(sk);
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	kfree_rcu(tunnel, rcu);
116162306a36Sopenharmony_ciend:
116262306a36Sopenharmony_ci	return;
116362306a36Sopenharmony_ci}
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci/* Remove an l2tp session from l2tp_core's hash lists. */
116662306a36Sopenharmony_cistatic void l2tp_session_unhash(struct l2tp_session *session)
116762306a36Sopenharmony_ci{
116862306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = session->tunnel;
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	/* Remove the session from core hashes */
117162306a36Sopenharmony_ci	if (tunnel) {
117262306a36Sopenharmony_ci		/* Remove from the per-tunnel hash */
117362306a36Sopenharmony_ci		spin_lock_bh(&tunnel->hlist_lock);
117462306a36Sopenharmony_ci		hlist_del_init_rcu(&session->hlist);
117562306a36Sopenharmony_ci		spin_unlock_bh(&tunnel->hlist_lock);
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci		/* For L2TPv3 we have a per-net hash: remove from there, too */
117862306a36Sopenharmony_ci		if (tunnel->version != L2TP_HDR_VER_2) {
117962306a36Sopenharmony_ci			struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci			spin_lock_bh(&pn->l2tp_session_hlist_lock);
118262306a36Sopenharmony_ci			hlist_del_init_rcu(&session->global_hlist);
118362306a36Sopenharmony_ci			spin_unlock_bh(&pn->l2tp_session_hlist_lock);
118462306a36Sopenharmony_ci		}
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci		synchronize_rcu();
118762306a36Sopenharmony_ci	}
118862306a36Sopenharmony_ci}
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci/* When the tunnel is closed, all the attached sessions need to go too.
119162306a36Sopenharmony_ci */
119262306a36Sopenharmony_cistatic void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel)
119362306a36Sopenharmony_ci{
119462306a36Sopenharmony_ci	struct l2tp_session *session;
119562306a36Sopenharmony_ci	int hash;
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	spin_lock_bh(&tunnel->hlist_lock);
119862306a36Sopenharmony_ci	tunnel->acpt_newsess = false;
119962306a36Sopenharmony_ci	for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
120062306a36Sopenharmony_ciagain:
120162306a36Sopenharmony_ci		hlist_for_each_entry_rcu(session, &tunnel->session_hlist[hash], hlist) {
120262306a36Sopenharmony_ci			hlist_del_init_rcu(&session->hlist);
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci			spin_unlock_bh(&tunnel->hlist_lock);
120562306a36Sopenharmony_ci			l2tp_session_delete(session);
120662306a36Sopenharmony_ci			spin_lock_bh(&tunnel->hlist_lock);
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci			/* Now restart from the beginning of this hash
120962306a36Sopenharmony_ci			 * chain.  We always remove a session from the
121062306a36Sopenharmony_ci			 * list so we are guaranteed to make forward
121162306a36Sopenharmony_ci			 * progress.
121262306a36Sopenharmony_ci			 */
121362306a36Sopenharmony_ci			goto again;
121462306a36Sopenharmony_ci		}
121562306a36Sopenharmony_ci	}
121662306a36Sopenharmony_ci	spin_unlock_bh(&tunnel->hlist_lock);
121762306a36Sopenharmony_ci}
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci/* Tunnel socket destroy hook for UDP encapsulation */
122062306a36Sopenharmony_cistatic void l2tp_udp_encap_destroy(struct sock *sk)
122162306a36Sopenharmony_ci{
122262306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = l2tp_sk_to_tunnel(sk);
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	if (tunnel)
122562306a36Sopenharmony_ci		l2tp_tunnel_delete(tunnel);
122662306a36Sopenharmony_ci}
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_cistatic void l2tp_tunnel_remove(struct net *net, struct l2tp_tunnel *tunnel)
122962306a36Sopenharmony_ci{
123062306a36Sopenharmony_ci	struct l2tp_net *pn = l2tp_pernet(net);
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
123362306a36Sopenharmony_ci	idr_remove(&pn->l2tp_tunnel_idr, tunnel->tunnel_id);
123462306a36Sopenharmony_ci	spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
123562306a36Sopenharmony_ci}
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci/* Workqueue tunnel deletion function */
123862306a36Sopenharmony_cistatic void l2tp_tunnel_del_work(struct work_struct *work)
123962306a36Sopenharmony_ci{
124062306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = container_of(work, struct l2tp_tunnel,
124162306a36Sopenharmony_ci						  del_work);
124262306a36Sopenharmony_ci	struct sock *sk = tunnel->sock;
124362306a36Sopenharmony_ci	struct socket *sock = sk->sk_socket;
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	l2tp_tunnel_closeall(tunnel);
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	/* If the tunnel socket was created within the kernel, use
124862306a36Sopenharmony_ci	 * the sk API to release it here.
124962306a36Sopenharmony_ci	 */
125062306a36Sopenharmony_ci	if (tunnel->fd < 0) {
125162306a36Sopenharmony_ci		if (sock) {
125262306a36Sopenharmony_ci			kernel_sock_shutdown(sock, SHUT_RDWR);
125362306a36Sopenharmony_ci			sock_release(sock);
125462306a36Sopenharmony_ci		}
125562306a36Sopenharmony_ci	}
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci	l2tp_tunnel_remove(tunnel->l2tp_net, tunnel);
125862306a36Sopenharmony_ci	/* drop initial ref */
125962306a36Sopenharmony_ci	l2tp_tunnel_dec_refcount(tunnel);
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	/* drop workqueue ref */
126262306a36Sopenharmony_ci	l2tp_tunnel_dec_refcount(tunnel);
126362306a36Sopenharmony_ci}
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci/* Create a socket for the tunnel, if one isn't set up by
126662306a36Sopenharmony_ci * userspace. This is used for static tunnels where there is no
126762306a36Sopenharmony_ci * managing L2TP daemon.
126862306a36Sopenharmony_ci *
126962306a36Sopenharmony_ci * Since we don't want these sockets to keep a namespace alive by
127062306a36Sopenharmony_ci * themselves, we drop the socket's namespace refcount after creation.
127162306a36Sopenharmony_ci * These sockets are freed when the namespace exits using the pernet
127262306a36Sopenharmony_ci * exit hook.
127362306a36Sopenharmony_ci */
127462306a36Sopenharmony_cistatic int l2tp_tunnel_sock_create(struct net *net,
127562306a36Sopenharmony_ci				   u32 tunnel_id,
127662306a36Sopenharmony_ci				   u32 peer_tunnel_id,
127762306a36Sopenharmony_ci				   struct l2tp_tunnel_cfg *cfg,
127862306a36Sopenharmony_ci				   struct socket **sockp)
127962306a36Sopenharmony_ci{
128062306a36Sopenharmony_ci	int err = -EINVAL;
128162306a36Sopenharmony_ci	struct socket *sock = NULL;
128262306a36Sopenharmony_ci	struct udp_port_cfg udp_conf;
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ci	switch (cfg->encap) {
128562306a36Sopenharmony_ci	case L2TP_ENCAPTYPE_UDP:
128662306a36Sopenharmony_ci		memset(&udp_conf, 0, sizeof(udp_conf));
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
128962306a36Sopenharmony_ci		if (cfg->local_ip6 && cfg->peer_ip6) {
129062306a36Sopenharmony_ci			udp_conf.family = AF_INET6;
129162306a36Sopenharmony_ci			memcpy(&udp_conf.local_ip6, cfg->local_ip6,
129262306a36Sopenharmony_ci			       sizeof(udp_conf.local_ip6));
129362306a36Sopenharmony_ci			memcpy(&udp_conf.peer_ip6, cfg->peer_ip6,
129462306a36Sopenharmony_ci			       sizeof(udp_conf.peer_ip6));
129562306a36Sopenharmony_ci			udp_conf.use_udp6_tx_checksums =
129662306a36Sopenharmony_ci			  !cfg->udp6_zero_tx_checksums;
129762306a36Sopenharmony_ci			udp_conf.use_udp6_rx_checksums =
129862306a36Sopenharmony_ci			  !cfg->udp6_zero_rx_checksums;
129962306a36Sopenharmony_ci		} else
130062306a36Sopenharmony_ci#endif
130162306a36Sopenharmony_ci		{
130262306a36Sopenharmony_ci			udp_conf.family = AF_INET;
130362306a36Sopenharmony_ci			udp_conf.local_ip = cfg->local_ip;
130462306a36Sopenharmony_ci			udp_conf.peer_ip = cfg->peer_ip;
130562306a36Sopenharmony_ci			udp_conf.use_udp_checksums = cfg->use_udp_checksums;
130662306a36Sopenharmony_ci		}
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci		udp_conf.local_udp_port = htons(cfg->local_udp_port);
130962306a36Sopenharmony_ci		udp_conf.peer_udp_port = htons(cfg->peer_udp_port);
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci		err = udp_sock_create(net, &udp_conf, &sock);
131262306a36Sopenharmony_ci		if (err < 0)
131362306a36Sopenharmony_ci			goto out;
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_ci		break;
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	case L2TP_ENCAPTYPE_IP:
131862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
131962306a36Sopenharmony_ci		if (cfg->local_ip6 && cfg->peer_ip6) {
132062306a36Sopenharmony_ci			struct sockaddr_l2tpip6 ip6_addr = {0};
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci			err = sock_create_kern(net, AF_INET6, SOCK_DGRAM,
132362306a36Sopenharmony_ci					       IPPROTO_L2TP, &sock);
132462306a36Sopenharmony_ci			if (err < 0)
132562306a36Sopenharmony_ci				goto out;
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci			ip6_addr.l2tp_family = AF_INET6;
132862306a36Sopenharmony_ci			memcpy(&ip6_addr.l2tp_addr, cfg->local_ip6,
132962306a36Sopenharmony_ci			       sizeof(ip6_addr.l2tp_addr));
133062306a36Sopenharmony_ci			ip6_addr.l2tp_conn_id = tunnel_id;
133162306a36Sopenharmony_ci			err = kernel_bind(sock, (struct sockaddr *)&ip6_addr,
133262306a36Sopenharmony_ci					  sizeof(ip6_addr));
133362306a36Sopenharmony_ci			if (err < 0)
133462306a36Sopenharmony_ci				goto out;
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci			ip6_addr.l2tp_family = AF_INET6;
133762306a36Sopenharmony_ci			memcpy(&ip6_addr.l2tp_addr, cfg->peer_ip6,
133862306a36Sopenharmony_ci			       sizeof(ip6_addr.l2tp_addr));
133962306a36Sopenharmony_ci			ip6_addr.l2tp_conn_id = peer_tunnel_id;
134062306a36Sopenharmony_ci			err = kernel_connect(sock,
134162306a36Sopenharmony_ci					     (struct sockaddr *)&ip6_addr,
134262306a36Sopenharmony_ci					     sizeof(ip6_addr), 0);
134362306a36Sopenharmony_ci			if (err < 0)
134462306a36Sopenharmony_ci				goto out;
134562306a36Sopenharmony_ci		} else
134662306a36Sopenharmony_ci#endif
134762306a36Sopenharmony_ci		{
134862306a36Sopenharmony_ci			struct sockaddr_l2tpip ip_addr = {0};
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci			err = sock_create_kern(net, AF_INET, SOCK_DGRAM,
135162306a36Sopenharmony_ci					       IPPROTO_L2TP, &sock);
135262306a36Sopenharmony_ci			if (err < 0)
135362306a36Sopenharmony_ci				goto out;
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci			ip_addr.l2tp_family = AF_INET;
135662306a36Sopenharmony_ci			ip_addr.l2tp_addr = cfg->local_ip;
135762306a36Sopenharmony_ci			ip_addr.l2tp_conn_id = tunnel_id;
135862306a36Sopenharmony_ci			err = kernel_bind(sock, (struct sockaddr *)&ip_addr,
135962306a36Sopenharmony_ci					  sizeof(ip_addr));
136062306a36Sopenharmony_ci			if (err < 0)
136162306a36Sopenharmony_ci				goto out;
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci			ip_addr.l2tp_family = AF_INET;
136462306a36Sopenharmony_ci			ip_addr.l2tp_addr = cfg->peer_ip;
136562306a36Sopenharmony_ci			ip_addr.l2tp_conn_id = peer_tunnel_id;
136662306a36Sopenharmony_ci			err = kernel_connect(sock, (struct sockaddr *)&ip_addr,
136762306a36Sopenharmony_ci					     sizeof(ip_addr), 0);
136862306a36Sopenharmony_ci			if (err < 0)
136962306a36Sopenharmony_ci				goto out;
137062306a36Sopenharmony_ci		}
137162306a36Sopenharmony_ci		break;
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci	default:
137462306a36Sopenharmony_ci		goto out;
137562306a36Sopenharmony_ci	}
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ciout:
137862306a36Sopenharmony_ci	*sockp = sock;
137962306a36Sopenharmony_ci	if (err < 0 && sock) {
138062306a36Sopenharmony_ci		kernel_sock_shutdown(sock, SHUT_RDWR);
138162306a36Sopenharmony_ci		sock_release(sock);
138262306a36Sopenharmony_ci		*sockp = NULL;
138362306a36Sopenharmony_ci	}
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci	return err;
138662306a36Sopenharmony_ci}
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ciint l2tp_tunnel_create(int fd, int version, u32 tunnel_id, u32 peer_tunnel_id,
138962306a36Sopenharmony_ci		       struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp)
139062306a36Sopenharmony_ci{
139162306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = NULL;
139262306a36Sopenharmony_ci	int err;
139362306a36Sopenharmony_ci	enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP;
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	if (cfg)
139662306a36Sopenharmony_ci		encap = cfg->encap;
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	tunnel = kzalloc(sizeof(*tunnel), GFP_KERNEL);
139962306a36Sopenharmony_ci	if (!tunnel) {
140062306a36Sopenharmony_ci		err = -ENOMEM;
140162306a36Sopenharmony_ci		goto err;
140262306a36Sopenharmony_ci	}
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	tunnel->version = version;
140562306a36Sopenharmony_ci	tunnel->tunnel_id = tunnel_id;
140662306a36Sopenharmony_ci	tunnel->peer_tunnel_id = peer_tunnel_id;
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci	tunnel->magic = L2TP_TUNNEL_MAGIC;
140962306a36Sopenharmony_ci	sprintf(&tunnel->name[0], "tunl %u", tunnel_id);
141062306a36Sopenharmony_ci	spin_lock_init(&tunnel->hlist_lock);
141162306a36Sopenharmony_ci	tunnel->acpt_newsess = true;
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci	tunnel->encap = encap;
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	refcount_set(&tunnel->ref_count, 1);
141662306a36Sopenharmony_ci	tunnel->fd = fd;
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_ci	/* Init delete workqueue struct */
141962306a36Sopenharmony_ci	INIT_WORK(&tunnel->del_work, l2tp_tunnel_del_work);
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci	INIT_LIST_HEAD(&tunnel->list);
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	err = 0;
142462306a36Sopenharmony_cierr:
142562306a36Sopenharmony_ci	if (tunnelp)
142662306a36Sopenharmony_ci		*tunnelp = tunnel;
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	return err;
142962306a36Sopenharmony_ci}
143062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_tunnel_create);
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_cistatic int l2tp_validate_socket(const struct sock *sk, const struct net *net,
143362306a36Sopenharmony_ci				enum l2tp_encap_type encap)
143462306a36Sopenharmony_ci{
143562306a36Sopenharmony_ci	if (!net_eq(sock_net(sk), net))
143662306a36Sopenharmony_ci		return -EINVAL;
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci	if (sk->sk_type != SOCK_DGRAM)
143962306a36Sopenharmony_ci		return -EPROTONOSUPPORT;
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci	if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
144262306a36Sopenharmony_ci		return -EPROTONOSUPPORT;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	if ((encap == L2TP_ENCAPTYPE_UDP && sk->sk_protocol != IPPROTO_UDP) ||
144562306a36Sopenharmony_ci	    (encap == L2TP_ENCAPTYPE_IP && sk->sk_protocol != IPPROTO_L2TP))
144662306a36Sopenharmony_ci		return -EPROTONOSUPPORT;
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci	if (sk->sk_user_data)
144962306a36Sopenharmony_ci		return -EBUSY;
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_ci	return 0;
145262306a36Sopenharmony_ci}
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ciint l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
145562306a36Sopenharmony_ci			 struct l2tp_tunnel_cfg *cfg)
145662306a36Sopenharmony_ci{
145762306a36Sopenharmony_ci	struct l2tp_net *pn = l2tp_pernet(net);
145862306a36Sopenharmony_ci	u32 tunnel_id = tunnel->tunnel_id;
145962306a36Sopenharmony_ci	struct socket *sock;
146062306a36Sopenharmony_ci	struct sock *sk;
146162306a36Sopenharmony_ci	int ret;
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
146462306a36Sopenharmony_ci	ret = idr_alloc_u32(&pn->l2tp_tunnel_idr, NULL, &tunnel_id, tunnel_id,
146562306a36Sopenharmony_ci			    GFP_ATOMIC);
146662306a36Sopenharmony_ci	spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
146762306a36Sopenharmony_ci	if (ret)
146862306a36Sopenharmony_ci		return ret == -ENOSPC ? -EEXIST : ret;
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	if (tunnel->fd < 0) {
147162306a36Sopenharmony_ci		ret = l2tp_tunnel_sock_create(net, tunnel->tunnel_id,
147262306a36Sopenharmony_ci					      tunnel->peer_tunnel_id, cfg,
147362306a36Sopenharmony_ci					      &sock);
147462306a36Sopenharmony_ci		if (ret < 0)
147562306a36Sopenharmony_ci			goto err;
147662306a36Sopenharmony_ci	} else {
147762306a36Sopenharmony_ci		sock = sockfd_lookup(tunnel->fd, &ret);
147862306a36Sopenharmony_ci		if (!sock)
147962306a36Sopenharmony_ci			goto err;
148062306a36Sopenharmony_ci	}
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci	sk = sock->sk;
148362306a36Sopenharmony_ci	lock_sock(sk);
148462306a36Sopenharmony_ci	write_lock_bh(&sk->sk_callback_lock);
148562306a36Sopenharmony_ci	ret = l2tp_validate_socket(sk, net, tunnel->encap);
148662306a36Sopenharmony_ci	if (ret < 0)
148762306a36Sopenharmony_ci		goto err_inval_sock;
148862306a36Sopenharmony_ci	rcu_assign_sk_user_data(sk, tunnel);
148962306a36Sopenharmony_ci	write_unlock_bh(&sk->sk_callback_lock);
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	if (tunnel->encap == L2TP_ENCAPTYPE_UDP) {
149262306a36Sopenharmony_ci		struct udp_tunnel_sock_cfg udp_cfg = {
149362306a36Sopenharmony_ci			.sk_user_data = tunnel,
149462306a36Sopenharmony_ci			.encap_type = UDP_ENCAP_L2TPINUDP,
149562306a36Sopenharmony_ci			.encap_rcv = l2tp_udp_encap_recv,
149662306a36Sopenharmony_ci			.encap_destroy = l2tp_udp_encap_destroy,
149762306a36Sopenharmony_ci		};
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci		setup_udp_tunnel_sock(net, sock, &udp_cfg);
150062306a36Sopenharmony_ci	}
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	tunnel->old_sk_destruct = sk->sk_destruct;
150362306a36Sopenharmony_ci	sk->sk_destruct = &l2tp_tunnel_destruct;
150462306a36Sopenharmony_ci	sk->sk_allocation = GFP_ATOMIC;
150562306a36Sopenharmony_ci	release_sock(sk);
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	sock_hold(sk);
150862306a36Sopenharmony_ci	tunnel->sock = sk;
150962306a36Sopenharmony_ci	tunnel->l2tp_net = net;
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
151262306a36Sopenharmony_ci	idr_replace(&pn->l2tp_tunnel_idr, tunnel, tunnel->tunnel_id);
151362306a36Sopenharmony_ci	spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci	trace_register_tunnel(tunnel);
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	if (tunnel->fd >= 0)
151862306a36Sopenharmony_ci		sockfd_put(sock);
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci	return 0;
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_cierr_inval_sock:
152362306a36Sopenharmony_ci	write_unlock_bh(&sk->sk_callback_lock);
152462306a36Sopenharmony_ci	release_sock(sk);
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	if (tunnel->fd < 0)
152762306a36Sopenharmony_ci		sock_release(sock);
152862306a36Sopenharmony_ci	else
152962306a36Sopenharmony_ci		sockfd_put(sock);
153062306a36Sopenharmony_cierr:
153162306a36Sopenharmony_ci	l2tp_tunnel_remove(net, tunnel);
153262306a36Sopenharmony_ci	return ret;
153362306a36Sopenharmony_ci}
153462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_tunnel_register);
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_ci/* This function is used by the netlink TUNNEL_DELETE command.
153762306a36Sopenharmony_ci */
153862306a36Sopenharmony_civoid l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
153962306a36Sopenharmony_ci{
154062306a36Sopenharmony_ci	if (!test_and_set_bit(0, &tunnel->dead)) {
154162306a36Sopenharmony_ci		trace_delete_tunnel(tunnel);
154262306a36Sopenharmony_ci		l2tp_tunnel_inc_refcount(tunnel);
154362306a36Sopenharmony_ci		queue_work(l2tp_wq, &tunnel->del_work);
154462306a36Sopenharmony_ci	}
154562306a36Sopenharmony_ci}
154662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_tunnel_delete);
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_civoid l2tp_session_delete(struct l2tp_session *session)
154962306a36Sopenharmony_ci{
155062306a36Sopenharmony_ci	if (test_and_set_bit(0, &session->dead))
155162306a36Sopenharmony_ci		return;
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_ci	trace_delete_session(session);
155462306a36Sopenharmony_ci	l2tp_session_unhash(session);
155562306a36Sopenharmony_ci	l2tp_session_queue_purge(session);
155662306a36Sopenharmony_ci	if (session->session_close)
155762306a36Sopenharmony_ci		(*session->session_close)(session);
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	l2tp_session_dec_refcount(session);
156062306a36Sopenharmony_ci}
156162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_session_delete);
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_ci/* We come here whenever a session's send_seq, cookie_len or
156462306a36Sopenharmony_ci * l2specific_type parameters are set.
156562306a36Sopenharmony_ci */
156662306a36Sopenharmony_civoid l2tp_session_set_header_len(struct l2tp_session *session, int version)
156762306a36Sopenharmony_ci{
156862306a36Sopenharmony_ci	if (version == L2TP_HDR_VER_2) {
156962306a36Sopenharmony_ci		session->hdr_len = 6;
157062306a36Sopenharmony_ci		if (session->send_seq)
157162306a36Sopenharmony_ci			session->hdr_len += 4;
157262306a36Sopenharmony_ci	} else {
157362306a36Sopenharmony_ci		session->hdr_len = 4 + session->cookie_len;
157462306a36Sopenharmony_ci		session->hdr_len += l2tp_get_l2specific_len(session);
157562306a36Sopenharmony_ci		if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP)
157662306a36Sopenharmony_ci			session->hdr_len += 4;
157762306a36Sopenharmony_ci	}
157862306a36Sopenharmony_ci}
157962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_session_set_header_len);
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_cistruct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id,
158262306a36Sopenharmony_ci					 u32 peer_session_id, struct l2tp_session_cfg *cfg)
158362306a36Sopenharmony_ci{
158462306a36Sopenharmony_ci	struct l2tp_session *session;
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci	session = kzalloc(sizeof(*session) + priv_size, GFP_KERNEL);
158762306a36Sopenharmony_ci	if (session) {
158862306a36Sopenharmony_ci		session->magic = L2TP_SESSION_MAGIC;
158962306a36Sopenharmony_ci		session->tunnel = tunnel;
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci		session->session_id = session_id;
159262306a36Sopenharmony_ci		session->peer_session_id = peer_session_id;
159362306a36Sopenharmony_ci		session->nr = 0;
159462306a36Sopenharmony_ci		if (tunnel->version == L2TP_HDR_VER_2)
159562306a36Sopenharmony_ci			session->nr_max = 0xffff;
159662306a36Sopenharmony_ci		else
159762306a36Sopenharmony_ci			session->nr_max = 0xffffff;
159862306a36Sopenharmony_ci		session->nr_window_size = session->nr_max / 2;
159962306a36Sopenharmony_ci		session->nr_oos_count_max = 4;
160062306a36Sopenharmony_ci
160162306a36Sopenharmony_ci		/* Use NR of first received packet */
160262306a36Sopenharmony_ci		session->reorder_skip = 1;
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci		sprintf(&session->name[0], "sess %u/%u",
160562306a36Sopenharmony_ci			tunnel->tunnel_id, session->session_id);
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_ci		skb_queue_head_init(&session->reorder_q);
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci		INIT_HLIST_NODE(&session->hlist);
161062306a36Sopenharmony_ci		INIT_HLIST_NODE(&session->global_hlist);
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci		if (cfg) {
161362306a36Sopenharmony_ci			session->pwtype = cfg->pw_type;
161462306a36Sopenharmony_ci			session->send_seq = cfg->send_seq;
161562306a36Sopenharmony_ci			session->recv_seq = cfg->recv_seq;
161662306a36Sopenharmony_ci			session->lns_mode = cfg->lns_mode;
161762306a36Sopenharmony_ci			session->reorder_timeout = cfg->reorder_timeout;
161862306a36Sopenharmony_ci			session->l2specific_type = cfg->l2specific_type;
161962306a36Sopenharmony_ci			session->cookie_len = cfg->cookie_len;
162062306a36Sopenharmony_ci			memcpy(&session->cookie[0], &cfg->cookie[0], cfg->cookie_len);
162162306a36Sopenharmony_ci			session->peer_cookie_len = cfg->peer_cookie_len;
162262306a36Sopenharmony_ci			memcpy(&session->peer_cookie[0], &cfg->peer_cookie[0], cfg->peer_cookie_len);
162362306a36Sopenharmony_ci		}
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci		l2tp_session_set_header_len(session, tunnel->version);
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci		refcount_set(&session->ref_count, 1);
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci		return session;
163062306a36Sopenharmony_ci	}
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	return ERR_PTR(-ENOMEM);
163362306a36Sopenharmony_ci}
163462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(l2tp_session_create);
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci/*****************************************************************************
163762306a36Sopenharmony_ci * Init and cleanup
163862306a36Sopenharmony_ci *****************************************************************************/
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_cistatic __net_init int l2tp_init_net(struct net *net)
164162306a36Sopenharmony_ci{
164262306a36Sopenharmony_ci	struct l2tp_net *pn = net_generic(net, l2tp_net_id);
164362306a36Sopenharmony_ci	int hash;
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	idr_init(&pn->l2tp_tunnel_idr);
164662306a36Sopenharmony_ci	spin_lock_init(&pn->l2tp_tunnel_idr_lock);
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci	for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++)
164962306a36Sopenharmony_ci		INIT_HLIST_HEAD(&pn->l2tp_session_hlist[hash]);
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	spin_lock_init(&pn->l2tp_session_hlist_lock);
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci	return 0;
165462306a36Sopenharmony_ci}
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_cistatic __net_exit void l2tp_exit_net(struct net *net)
165762306a36Sopenharmony_ci{
165862306a36Sopenharmony_ci	struct l2tp_net *pn = l2tp_pernet(net);
165962306a36Sopenharmony_ci	struct l2tp_tunnel *tunnel = NULL;
166062306a36Sopenharmony_ci	unsigned long tunnel_id, tmp;
166162306a36Sopenharmony_ci	int hash;
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ci	rcu_read_lock_bh();
166462306a36Sopenharmony_ci	idr_for_each_entry_ul(&pn->l2tp_tunnel_idr, tunnel, tmp, tunnel_id) {
166562306a36Sopenharmony_ci		if (tunnel)
166662306a36Sopenharmony_ci			l2tp_tunnel_delete(tunnel);
166762306a36Sopenharmony_ci	}
166862306a36Sopenharmony_ci	rcu_read_unlock_bh();
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	if (l2tp_wq)
167162306a36Sopenharmony_ci		flush_workqueue(l2tp_wq);
167262306a36Sopenharmony_ci	rcu_barrier();
167362306a36Sopenharmony_ci
167462306a36Sopenharmony_ci	for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++)
167562306a36Sopenharmony_ci		WARN_ON_ONCE(!hlist_empty(&pn->l2tp_session_hlist[hash]));
167662306a36Sopenharmony_ci	idr_destroy(&pn->l2tp_tunnel_idr);
167762306a36Sopenharmony_ci}
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_cistatic struct pernet_operations l2tp_net_ops = {
168062306a36Sopenharmony_ci	.init = l2tp_init_net,
168162306a36Sopenharmony_ci	.exit = l2tp_exit_net,
168262306a36Sopenharmony_ci	.id   = &l2tp_net_id,
168362306a36Sopenharmony_ci	.size = sizeof(struct l2tp_net),
168462306a36Sopenharmony_ci};
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_cistatic int __init l2tp_init(void)
168762306a36Sopenharmony_ci{
168862306a36Sopenharmony_ci	int rc = 0;
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci	rc = register_pernet_device(&l2tp_net_ops);
169162306a36Sopenharmony_ci	if (rc)
169262306a36Sopenharmony_ci		goto out;
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci	l2tp_wq = alloc_workqueue("l2tp", WQ_UNBOUND, 0);
169562306a36Sopenharmony_ci	if (!l2tp_wq) {
169662306a36Sopenharmony_ci		pr_err("alloc_workqueue failed\n");
169762306a36Sopenharmony_ci		unregister_pernet_device(&l2tp_net_ops);
169862306a36Sopenharmony_ci		rc = -ENOMEM;
169962306a36Sopenharmony_ci		goto out;
170062306a36Sopenharmony_ci	}
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_ci	pr_info("L2TP core driver, %s\n", L2TP_DRV_VERSION);
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_ciout:
170562306a36Sopenharmony_ci	return rc;
170662306a36Sopenharmony_ci}
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_cistatic void __exit l2tp_exit(void)
170962306a36Sopenharmony_ci{
171062306a36Sopenharmony_ci	unregister_pernet_device(&l2tp_net_ops);
171162306a36Sopenharmony_ci	if (l2tp_wq) {
171262306a36Sopenharmony_ci		destroy_workqueue(l2tp_wq);
171362306a36Sopenharmony_ci		l2tp_wq = NULL;
171462306a36Sopenharmony_ci	}
171562306a36Sopenharmony_ci}
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_cimodule_init(l2tp_init);
171862306a36Sopenharmony_cimodule_exit(l2tp_exit);
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ciMODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
172162306a36Sopenharmony_ciMODULE_DESCRIPTION("L2TP core");
172262306a36Sopenharmony_ciMODULE_LICENSE("GPL");
172362306a36Sopenharmony_ciMODULE_VERSION(L2TP_DRV_VERSION);
1724