1fd558d18SJames Chapman /* 2fd558d18SJames Chapman * 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 * This program is free software; you can redistribute it and/or modify 17fd558d18SJames Chapman * it under the terms of the GNU General Public License version 2 as 18fd558d18SJames Chapman * published by the Free Software Foundation. 19fd558d18SJames Chapman */ 20fd558d18SJames Chapman 21a4ca44faSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 22a4ca44faSJoe Perches 23fd558d18SJames Chapman #include <linux/module.h> 24fd558d18SJames Chapman #include <linux/string.h> 25fd558d18SJames Chapman #include <linux/list.h> 26e02d494dSJames Chapman #include <linux/rculist.h> 27fd558d18SJames Chapman #include <linux/uaccess.h> 28fd558d18SJames Chapman 29fd558d18SJames Chapman #include <linux/kernel.h> 30fd558d18SJames Chapman #include <linux/spinlock.h> 31fd558d18SJames Chapman #include <linux/kthread.h> 32fd558d18SJames Chapman #include <linux/sched.h> 33fd558d18SJames Chapman #include <linux/slab.h> 34fd558d18SJames Chapman #include <linux/errno.h> 35fd558d18SJames Chapman #include <linux/jiffies.h> 36fd558d18SJames Chapman 37fd558d18SJames Chapman #include <linux/netdevice.h> 38fd558d18SJames Chapman #include <linux/net.h> 39fd558d18SJames Chapman #include <linux/inetdevice.h> 40fd558d18SJames Chapman #include <linux/skbuff.h> 41fd558d18SJames Chapman #include <linux/init.h> 420d76751fSJames Chapman #include <linux/in.h> 43fd558d18SJames Chapman #include <linux/ip.h> 44fd558d18SJames Chapman #include <linux/udp.h> 450d76751fSJames Chapman #include <linux/l2tp.h> 46fd558d18SJames Chapman #include <linux/hash.h> 47fd558d18SJames Chapman #include <linux/sort.h> 48fd558d18SJames Chapman #include <linux/file.h> 49fd558d18SJames Chapman #include <linux/nsproxy.h> 50fd558d18SJames Chapman #include <net/net_namespace.h> 51fd558d18SJames Chapman #include <net/netns/generic.h> 52fd558d18SJames Chapman #include <net/dst.h> 53fd558d18SJames Chapman #include <net/ip.h> 54fd558d18SJames Chapman #include <net/udp.h> 5585644b4dSTom Herbert #include <net/udp_tunnel.h> 56309795f4SJames Chapman #include <net/inet_common.h> 57fd558d18SJames Chapman #include <net/xfrm.h> 580d76751fSJames Chapman #include <net/protocol.h> 59d2cf3361SBenjamin LaHaise #include <net/inet6_connection_sock.h> 60d2cf3361SBenjamin LaHaise #include <net/inet_ecn.h> 61d2cf3361SBenjamin LaHaise #include <net/ip6_route.h> 62d499bd2eSDavid S. Miller #include <net/ip6_checksum.h> 63fd558d18SJames Chapman 64fd558d18SJames Chapman #include <asm/byteorder.h> 6560063497SArun Sharma #include <linux/atomic.h> 66fd558d18SJames Chapman 67fd558d18SJames Chapman #include "l2tp_core.h" 68fd558d18SJames Chapman 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 86fd558d18SJames Chapman #define L2TP_HDR_SIZE_SEQ 10 87fd558d18SJames Chapman #define L2TP_HDR_SIZE_NOSEQ 6 88fd558d18SJames Chapman 89fd558d18SJames Chapman /* Default trace flags */ 90fd558d18SJames Chapman #define L2TP_DEFAULT_DEBUG_FLAGS 0 91fd558d18SJames Chapman 92fd558d18SJames Chapman /* Private data stored for received packets in the skb. 93fd558d18SJames Chapman */ 94fd558d18SJames Chapman struct l2tp_skb_cb { 95f7faffa3SJames Chapman u32 ns; 96fd558d18SJames Chapman u16 has_seq; 97fd558d18SJames Chapman u16 length; 98fd558d18SJames Chapman unsigned long expires; 99fd558d18SJames Chapman }; 100fd558d18SJames Chapman 101fd558d18SJames Chapman #define L2TP_SKB_CB(skb) ((struct l2tp_skb_cb *) &skb->cb[sizeof(struct inet_skb_parm)]) 102fd558d18SJames Chapman 103f8ccac0eSTom Parkin static struct workqueue_struct *l2tp_wq; 104fd558d18SJames Chapman 105fd558d18SJames Chapman /* per-net private data for this module */ 106fd558d18SJames Chapman static unsigned int l2tp_net_id; 107fd558d18SJames Chapman struct l2tp_net { 108fd558d18SJames Chapman struct list_head l2tp_tunnel_list; 109e02d494dSJames Chapman spinlock_t l2tp_tunnel_list_lock; 110f7faffa3SJames Chapman struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2]; 111e02d494dSJames Chapman spinlock_t l2tp_session_hlist_lock; 112fd558d18SJames Chapman }; 113fd558d18SJames Chapman 114b954f940SPaolo Abeni #if IS_ENABLED(CONFIG_IPV6) 115b954f940SPaolo Abeni static bool l2tp_sk_is_v6(struct sock *sk) 116b954f940SPaolo Abeni { 117b954f940SPaolo Abeni return sk->sk_family == PF_INET6 && 118b954f940SPaolo Abeni !ipv6_addr_v4mapped(&sk->sk_v6_daddr); 119b954f940SPaolo Abeni } 120b954f940SPaolo Abeni #endif 121fc130840Sstephen hemminger 1228d8a51e2SDavid S. Miller static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk) 1238d8a51e2SDavid S. Miller { 1248d8a51e2SDavid S. Miller return sk->sk_user_data; 1258d8a51e2SDavid S. Miller } 1268d8a51e2SDavid S. Miller 1279aaef50cSGuillaume Nault static inline struct l2tp_net *l2tp_pernet(const struct net *net) 128fd558d18SJames Chapman { 129fd558d18SJames Chapman BUG_ON(!net); 130fd558d18SJames Chapman 131fd558d18SJames Chapman return net_generic(net, l2tp_net_id); 132fd558d18SJames Chapman } 133fd558d18SJames Chapman 134f7faffa3SJames Chapman /* Session hash global list for L2TPv3. 135f7faffa3SJames Chapman * The session_id SHOULD be random according to RFC3931, but several 136f7faffa3SJames Chapman * L2TP implementations use incrementing session_ids. So we do a real 137f7faffa3SJames Chapman * hash on the session_id, rather than a simple bitmask. 138f7faffa3SJames Chapman */ 139f7faffa3SJames Chapman static inline struct hlist_head * 140f7faffa3SJames Chapman l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id) 141f7faffa3SJames Chapman { 142f7faffa3SJames Chapman return &pn->l2tp_session_hlist[hash_32(session_id, L2TP_HASH_BITS_2)]; 143f7faffa3SJames Chapman 144f7faffa3SJames Chapman } 145f7faffa3SJames Chapman 146fd558d18SJames Chapman /* Session hash list. 147fd558d18SJames Chapman * The session_id SHOULD be random according to RFC2661, but several 148fd558d18SJames Chapman * L2TP implementations (Cisco and Microsoft) use incrementing 149fd558d18SJames Chapman * session_ids. So we do a real hash on the session_id, rather than a 150fd558d18SJames Chapman * simple bitmask. 151fd558d18SJames Chapman */ 152fd558d18SJames Chapman static inline struct hlist_head * 153fd558d18SJames Chapman l2tp_session_id_hash(struct l2tp_tunnel *tunnel, u32 session_id) 154fd558d18SJames Chapman { 155fd558d18SJames Chapman return &tunnel->session_hlist[hash_32(session_id, L2TP_HASH_BITS)]; 156fd558d18SJames Chapman } 157fd558d18SJames Chapman 158d00fa9adSJames Chapman void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) 159d00fa9adSJames Chapman { 160d00fa9adSJames Chapman sock_put(tunnel->sock); 161d00fa9adSJames Chapman /* the tunnel is freed in the socket destructor */ 162d00fa9adSJames Chapman } 163d00fa9adSJames Chapman EXPORT_SYMBOL(l2tp_tunnel_free); 164d00fa9adSJames Chapman 16554652eb1SGuillaume Nault /* Lookup a tunnel. A new reference is held on the returned tunnel. */ 16654652eb1SGuillaume Nault struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, u32 tunnel_id) 16754652eb1SGuillaume Nault { 16854652eb1SGuillaume Nault const struct l2tp_net *pn = l2tp_pernet(net); 16954652eb1SGuillaume Nault struct l2tp_tunnel *tunnel; 17054652eb1SGuillaume Nault 17154652eb1SGuillaume Nault rcu_read_lock_bh(); 17254652eb1SGuillaume Nault list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { 17354652eb1SGuillaume Nault if (tunnel->tunnel_id == tunnel_id) { 17454652eb1SGuillaume Nault l2tp_tunnel_inc_refcount(tunnel); 17554652eb1SGuillaume Nault rcu_read_unlock_bh(); 17654652eb1SGuillaume Nault 17754652eb1SGuillaume Nault return tunnel; 17854652eb1SGuillaume Nault } 17954652eb1SGuillaume Nault } 18054652eb1SGuillaume Nault rcu_read_unlock_bh(); 18154652eb1SGuillaume Nault 18254652eb1SGuillaume Nault return NULL; 18354652eb1SGuillaume Nault } 18454652eb1SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_tunnel_get); 18554652eb1SGuillaume Nault 1865846c131SGuillaume Nault struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth) 1875846c131SGuillaume Nault { 1885846c131SGuillaume Nault const struct l2tp_net *pn = l2tp_pernet(net); 1895846c131SGuillaume Nault struct l2tp_tunnel *tunnel; 1905846c131SGuillaume Nault int count = 0; 1915846c131SGuillaume Nault 1925846c131SGuillaume Nault rcu_read_lock_bh(); 1935846c131SGuillaume Nault list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { 1945846c131SGuillaume Nault if (++count > nth) { 1955846c131SGuillaume Nault l2tp_tunnel_inc_refcount(tunnel); 1965846c131SGuillaume Nault rcu_read_unlock_bh(); 1975846c131SGuillaume Nault return tunnel; 1985846c131SGuillaume Nault } 1995846c131SGuillaume Nault } 2005846c131SGuillaume Nault rcu_read_unlock_bh(); 2015846c131SGuillaume Nault 2025846c131SGuillaume Nault return NULL; 2035846c131SGuillaume Nault } 2045846c131SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_tunnel_get_nth); 2055846c131SGuillaume Nault 206a4346210SGuillaume Nault /* Lookup a session. A new reference is held on the returned session. */ 2079aaef50cSGuillaume Nault struct l2tp_session *l2tp_session_get(const struct net *net, 20861b9a047SGuillaume Nault struct l2tp_tunnel *tunnel, 209a4346210SGuillaume Nault u32 session_id) 21061b9a047SGuillaume Nault { 21161b9a047SGuillaume Nault struct hlist_head *session_list; 21261b9a047SGuillaume Nault struct l2tp_session *session; 21361b9a047SGuillaume Nault 21461b9a047SGuillaume Nault if (!tunnel) { 21561b9a047SGuillaume Nault struct l2tp_net *pn = l2tp_pernet(net); 21661b9a047SGuillaume Nault 21761b9a047SGuillaume Nault session_list = l2tp_session_id_hash_2(pn, session_id); 21861b9a047SGuillaume Nault 21961b9a047SGuillaume Nault rcu_read_lock_bh(); 22061b9a047SGuillaume Nault hlist_for_each_entry_rcu(session, session_list, global_hlist) { 22161b9a047SGuillaume Nault if (session->session_id == session_id) { 22261b9a047SGuillaume Nault l2tp_session_inc_refcount(session); 22361b9a047SGuillaume Nault rcu_read_unlock_bh(); 22461b9a047SGuillaume Nault 22561b9a047SGuillaume Nault return session; 22661b9a047SGuillaume Nault } 22761b9a047SGuillaume Nault } 22861b9a047SGuillaume Nault rcu_read_unlock_bh(); 22961b9a047SGuillaume Nault 23061b9a047SGuillaume Nault return NULL; 23161b9a047SGuillaume Nault } 23261b9a047SGuillaume Nault 23361b9a047SGuillaume Nault session_list = l2tp_session_id_hash(tunnel, session_id); 23461b9a047SGuillaume Nault read_lock_bh(&tunnel->hlist_lock); 23561b9a047SGuillaume Nault hlist_for_each_entry(session, session_list, hlist) { 23661b9a047SGuillaume Nault if (session->session_id == session_id) { 23761b9a047SGuillaume Nault l2tp_session_inc_refcount(session); 23861b9a047SGuillaume Nault read_unlock_bh(&tunnel->hlist_lock); 23961b9a047SGuillaume Nault 24061b9a047SGuillaume Nault return session; 24161b9a047SGuillaume Nault } 24261b9a047SGuillaume Nault } 24361b9a047SGuillaume Nault read_unlock_bh(&tunnel->hlist_lock); 24461b9a047SGuillaume Nault 24561b9a047SGuillaume Nault return NULL; 24661b9a047SGuillaume Nault } 24761b9a047SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_get); 24861b9a047SGuillaume Nault 249a4346210SGuillaume Nault struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth) 250fd558d18SJames Chapman { 251fd558d18SJames Chapman int hash; 252fd558d18SJames Chapman struct l2tp_session *session; 253fd558d18SJames Chapman int count = 0; 254fd558d18SJames Chapman 255fd558d18SJames Chapman read_lock_bh(&tunnel->hlist_lock); 256fd558d18SJames Chapman for (hash = 0; hash < L2TP_HASH_SIZE; hash++) { 257b67bfe0dSSasha Levin hlist_for_each_entry(session, &tunnel->session_hlist[hash], hlist) { 258fd558d18SJames Chapman if (++count > nth) { 259e08293a4SGuillaume Nault l2tp_session_inc_refcount(session); 260fd558d18SJames Chapman read_unlock_bh(&tunnel->hlist_lock); 261fd558d18SJames Chapman return session; 262fd558d18SJames Chapman } 263fd558d18SJames Chapman } 264fd558d18SJames Chapman } 265fd558d18SJames Chapman 266fd558d18SJames Chapman read_unlock_bh(&tunnel->hlist_lock); 267fd558d18SJames Chapman 268fd558d18SJames Chapman return NULL; 269fd558d18SJames Chapman } 270e08293a4SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_get_nth); 271fd558d18SJames Chapman 272309795f4SJames Chapman /* Lookup a session by interface name. 273309795f4SJames Chapman * This is very inefficient but is only used by management interfaces. 274309795f4SJames Chapman */ 2759aaef50cSGuillaume Nault struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net, 276a4346210SGuillaume Nault const char *ifname) 277309795f4SJames Chapman { 278309795f4SJames Chapman struct l2tp_net *pn = l2tp_pernet(net); 279309795f4SJames Chapman int hash; 280309795f4SJames Chapman struct l2tp_session *session; 281309795f4SJames Chapman 282e02d494dSJames Chapman rcu_read_lock_bh(); 283309795f4SJames Chapman for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) { 284b67bfe0dSSasha Levin hlist_for_each_entry_rcu(session, &pn->l2tp_session_hlist[hash], global_hlist) { 285309795f4SJames Chapman if (!strcmp(session->ifname, ifname)) { 2862777e2abSGuillaume Nault l2tp_session_inc_refcount(session); 287e02d494dSJames Chapman rcu_read_unlock_bh(); 2882777e2abSGuillaume Nault 289309795f4SJames Chapman return session; 290309795f4SJames Chapman } 291309795f4SJames Chapman } 292309795f4SJames Chapman } 293309795f4SJames Chapman 294e02d494dSJames Chapman rcu_read_unlock_bh(); 295309795f4SJames Chapman 296309795f4SJames Chapman return NULL; 297309795f4SJames Chapman } 2982777e2abSGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_get_by_ifname); 299309795f4SJames Chapman 3003953ae7bSGuillaume Nault int l2tp_session_register(struct l2tp_session *session, 3013953ae7bSGuillaume Nault struct l2tp_tunnel *tunnel) 302dbdbc73bSGuillaume Nault { 303dbdbc73bSGuillaume Nault struct l2tp_session *session_walk; 304dbdbc73bSGuillaume Nault struct hlist_head *g_head; 305dbdbc73bSGuillaume Nault struct hlist_head *head; 306dbdbc73bSGuillaume Nault struct l2tp_net *pn; 307f3c66d4eSGuillaume Nault int err; 308dbdbc73bSGuillaume Nault 309dbdbc73bSGuillaume Nault head = l2tp_session_id_hash(tunnel, session->session_id); 310dbdbc73bSGuillaume Nault 311dbdbc73bSGuillaume Nault write_lock_bh(&tunnel->hlist_lock); 312f3c66d4eSGuillaume Nault if (!tunnel->acpt_newsess) { 313f3c66d4eSGuillaume Nault err = -ENODEV; 314f3c66d4eSGuillaume Nault goto err_tlock; 315f3c66d4eSGuillaume Nault } 316f3c66d4eSGuillaume Nault 317dbdbc73bSGuillaume Nault hlist_for_each_entry(session_walk, head, hlist) 318f3c66d4eSGuillaume Nault if (session_walk->session_id == session->session_id) { 319f3c66d4eSGuillaume Nault err = -EEXIST; 320f3c66d4eSGuillaume Nault goto err_tlock; 321f3c66d4eSGuillaume Nault } 322dbdbc73bSGuillaume Nault 323dbdbc73bSGuillaume Nault if (tunnel->version == L2TP_HDR_VER_3) { 324dbdbc73bSGuillaume Nault pn = l2tp_pernet(tunnel->l2tp_net); 325363a341dSGuillaume Nault g_head = l2tp_session_id_hash_2(pn, session->session_id); 326dbdbc73bSGuillaume Nault 327dbdbc73bSGuillaume Nault spin_lock_bh(&pn->l2tp_session_hlist_lock); 328dbdbc73bSGuillaume Nault 329f3c66d4eSGuillaume Nault hlist_for_each_entry(session_walk, g_head, global_hlist) 330f3c66d4eSGuillaume Nault if (session_walk->session_id == session->session_id) { 331f3c66d4eSGuillaume Nault err = -EEXIST; 332f3c66d4eSGuillaume Nault goto err_tlock_pnlock; 333f3c66d4eSGuillaume Nault } 334f3c66d4eSGuillaume Nault 335f3c66d4eSGuillaume Nault l2tp_tunnel_inc_refcount(tunnel); 336dbdbc73bSGuillaume Nault hlist_add_head_rcu(&session->global_hlist, g_head); 337f3c66d4eSGuillaume Nault 338dbdbc73bSGuillaume Nault spin_unlock_bh(&pn->l2tp_session_hlist_lock); 339f3c66d4eSGuillaume Nault } else { 340f3c66d4eSGuillaume Nault l2tp_tunnel_inc_refcount(tunnel); 341dbdbc73bSGuillaume Nault } 342dbdbc73bSGuillaume Nault 343dbdbc73bSGuillaume Nault hlist_add_head(&session->hlist, head); 344dbdbc73bSGuillaume Nault write_unlock_bh(&tunnel->hlist_lock); 345dbdbc73bSGuillaume Nault 346dbdbc73bSGuillaume Nault return 0; 347dbdbc73bSGuillaume Nault 348f3c66d4eSGuillaume Nault err_tlock_pnlock: 349dbdbc73bSGuillaume Nault spin_unlock_bh(&pn->l2tp_session_hlist_lock); 350f3c66d4eSGuillaume Nault err_tlock: 351dbdbc73bSGuillaume Nault write_unlock_bh(&tunnel->hlist_lock); 352dbdbc73bSGuillaume Nault 353f3c66d4eSGuillaume Nault return err; 354dbdbc73bSGuillaume Nault } 3553953ae7bSGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_register); 356dbdbc73bSGuillaume Nault 357fd558d18SJames Chapman /***************************************************************************** 358fd558d18SJames Chapman * Receive data handling 359fd558d18SJames Chapman *****************************************************************************/ 360fd558d18SJames Chapman 361fd558d18SJames Chapman /* Queue a skb in order. We come here only if the skb has an L2TP sequence 362fd558d18SJames Chapman * number. 363fd558d18SJames Chapman */ 364fd558d18SJames Chapman static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *skb) 365fd558d18SJames Chapman { 366fd558d18SJames Chapman struct sk_buff *skbp; 367fd558d18SJames Chapman struct sk_buff *tmp; 368f7faffa3SJames Chapman u32 ns = L2TP_SKB_CB(skb)->ns; 369fd558d18SJames Chapman 370fd558d18SJames Chapman spin_lock_bh(&session->reorder_q.lock); 371fd558d18SJames Chapman skb_queue_walk_safe(&session->reorder_q, skbp, tmp) { 372fd558d18SJames Chapman if (L2TP_SKB_CB(skbp)->ns > ns) { 373fd558d18SJames Chapman __skb_queue_before(&session->reorder_q, skbp, skb); 374a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 375fd558d18SJames Chapman "%s: pkt %hu, inserted before %hu, reorder_q len=%d\n", 376fd558d18SJames Chapman session->name, ns, L2TP_SKB_CB(skbp)->ns, 377fd558d18SJames Chapman skb_queue_len(&session->reorder_q)); 3787b7c0719STom Parkin atomic_long_inc(&session->stats.rx_oos_packets); 379fd558d18SJames Chapman goto out; 380fd558d18SJames Chapman } 381fd558d18SJames Chapman } 382fd558d18SJames Chapman 383fd558d18SJames Chapman __skb_queue_tail(&session->reorder_q, skb); 384fd558d18SJames Chapman 385fd558d18SJames Chapman out: 386fd558d18SJames Chapman spin_unlock_bh(&session->reorder_q.lock); 387fd558d18SJames Chapman } 388fd558d18SJames Chapman 389fd558d18SJames Chapman /* Dequeue a single skb. 390fd558d18SJames Chapman */ 391fd558d18SJames Chapman static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff *skb) 392fd558d18SJames Chapman { 393fd558d18SJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 394fd558d18SJames Chapman int length = L2TP_SKB_CB(skb)->length; 395fd558d18SJames Chapman 396fd558d18SJames Chapman /* We're about to requeue the skb, so return resources 397fd558d18SJames Chapman * to its current owner (a socket receive buffer). 398fd558d18SJames Chapman */ 399fd558d18SJames Chapman skb_orphan(skb); 400fd558d18SJames Chapman 4017b7c0719STom Parkin atomic_long_inc(&tunnel->stats.rx_packets); 4027b7c0719STom Parkin atomic_long_add(length, &tunnel->stats.rx_bytes); 4037b7c0719STom Parkin atomic_long_inc(&session->stats.rx_packets); 4047b7c0719STom Parkin atomic_long_add(length, &session->stats.rx_bytes); 405fd558d18SJames Chapman 406fd558d18SJames Chapman if (L2TP_SKB_CB(skb)->has_seq) { 407fd558d18SJames Chapman /* Bump our Nr */ 408fd558d18SJames Chapman session->nr++; 4098a1631d5SJames Chapman session->nr &= session->nr_max; 410f7faffa3SJames Chapman 411a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, "%s: updated nr to %hu\n", 412a4ca44faSJoe Perches session->name, session->nr); 413fd558d18SJames Chapman } 414fd558d18SJames Chapman 415fd558d18SJames Chapman /* call private receive handler */ 416fd558d18SJames Chapman if (session->recv_skb != NULL) 417fd558d18SJames Chapman (*session->recv_skb)(session, skb, L2TP_SKB_CB(skb)->length); 418fd558d18SJames Chapman else 419fd558d18SJames Chapman kfree_skb(skb); 420fd558d18SJames Chapman } 421fd558d18SJames Chapman 422fd558d18SJames Chapman /* Dequeue skbs from the session's reorder_q, subject to packet order. 423fd558d18SJames Chapman * Skbs that have been in the queue for too long are simply discarded. 424fd558d18SJames Chapman */ 425fd558d18SJames Chapman static void l2tp_recv_dequeue(struct l2tp_session *session) 426fd558d18SJames Chapman { 427fd558d18SJames Chapman struct sk_buff *skb; 428fd558d18SJames Chapman struct sk_buff *tmp; 429fd558d18SJames Chapman 430fd558d18SJames Chapman /* If the pkt at the head of the queue has the nr that we 431fd558d18SJames Chapman * expect to send up next, dequeue it and any other 432fd558d18SJames Chapman * in-sequence packets behind it. 433fd558d18SJames Chapman */ 434e2e210c0SEric Dumazet start: 435fd558d18SJames Chapman spin_lock_bh(&session->reorder_q.lock); 436fd558d18SJames Chapman skb_queue_walk_safe(&session->reorder_q, skb, tmp) { 437fd558d18SJames Chapman if (time_after(jiffies, L2TP_SKB_CB(skb)->expires)) { 4387b7c0719STom Parkin atomic_long_inc(&session->stats.rx_seq_discards); 4397b7c0719STom Parkin atomic_long_inc(&session->stats.rx_errors); 440a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 441a4ca44faSJoe Perches "%s: oos pkt %u len %d discarded (too old), waiting for %u, reorder_q_len=%d\n", 442fd558d18SJames Chapman session->name, L2TP_SKB_CB(skb)->ns, 443fd558d18SJames Chapman L2TP_SKB_CB(skb)->length, session->nr, 444fd558d18SJames Chapman skb_queue_len(&session->reorder_q)); 44538d40b3fSJames Chapman session->reorder_skip = 1; 446fd558d18SJames Chapman __skb_unlink(skb, &session->reorder_q); 447fd558d18SJames Chapman kfree_skb(skb); 448fd558d18SJames Chapman continue; 449fd558d18SJames Chapman } 450fd558d18SJames Chapman 451fd558d18SJames Chapman if (L2TP_SKB_CB(skb)->has_seq) { 45238d40b3fSJames Chapman if (session->reorder_skip) { 453a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 45438d40b3fSJames Chapman "%s: advancing nr to next pkt: %u -> %u", 45538d40b3fSJames Chapman session->name, session->nr, 45638d40b3fSJames Chapman L2TP_SKB_CB(skb)->ns); 45738d40b3fSJames Chapman session->reorder_skip = 0; 45838d40b3fSJames Chapman session->nr = L2TP_SKB_CB(skb)->ns; 45938d40b3fSJames Chapman } 460fd558d18SJames Chapman if (L2TP_SKB_CB(skb)->ns != session->nr) { 461a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 462a4ca44faSJoe Perches "%s: holding oos pkt %u len %d, waiting for %u, reorder_q_len=%d\n", 463fd558d18SJames Chapman session->name, L2TP_SKB_CB(skb)->ns, 464fd558d18SJames Chapman L2TP_SKB_CB(skb)->length, session->nr, 465fd558d18SJames Chapman skb_queue_len(&session->reorder_q)); 466fd558d18SJames Chapman goto out; 467fd558d18SJames Chapman } 468fd558d18SJames Chapman } 469fd558d18SJames Chapman __skb_unlink(skb, &session->reorder_q); 470fd558d18SJames Chapman 471fd558d18SJames Chapman /* Process the skb. We release the queue lock while we 472fd558d18SJames Chapman * do so to let other contexts process the queue. 473fd558d18SJames Chapman */ 474fd558d18SJames Chapman spin_unlock_bh(&session->reorder_q.lock); 475fd558d18SJames Chapman l2tp_recv_dequeue_skb(session, skb); 476e2e210c0SEric Dumazet goto start; 477fd558d18SJames Chapman } 478fd558d18SJames Chapman 479fd558d18SJames Chapman out: 480fd558d18SJames Chapman spin_unlock_bh(&session->reorder_q.lock); 481fd558d18SJames Chapman } 482fd558d18SJames Chapman 4838a1631d5SJames Chapman static int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr) 4848a1631d5SJames Chapman { 4858a1631d5SJames Chapman u32 nws; 4868a1631d5SJames Chapman 4878a1631d5SJames Chapman if (nr >= session->nr) 4888a1631d5SJames Chapman nws = nr - session->nr; 4898a1631d5SJames Chapman else 4908a1631d5SJames Chapman nws = (session->nr_max + 1) - (session->nr - nr); 4918a1631d5SJames Chapman 4928a1631d5SJames Chapman return nws < session->nr_window_size; 4938a1631d5SJames Chapman } 4948a1631d5SJames Chapman 495b6dc01a4SJames Chapman /* If packet has sequence numbers, queue it if acceptable. Returns 0 if 496b6dc01a4SJames Chapman * acceptable, else non-zero. 497b6dc01a4SJames Chapman */ 498b6dc01a4SJames Chapman static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb) 499b6dc01a4SJames Chapman { 5008a1631d5SJames Chapman if (!l2tp_seq_check_rx_window(session, L2TP_SKB_CB(skb)->ns)) { 5018a1631d5SJames Chapman /* Packet sequence number is outside allowed window. 5028a1631d5SJames Chapman * Discard it. 5038a1631d5SJames Chapman */ 5048a1631d5SJames Chapman l2tp_dbg(session, L2TP_MSG_SEQ, 5058a1631d5SJames Chapman "%s: pkt %u len %d discarded, outside window, nr=%u\n", 5068a1631d5SJames Chapman session->name, L2TP_SKB_CB(skb)->ns, 5078a1631d5SJames Chapman L2TP_SKB_CB(skb)->length, session->nr); 5088a1631d5SJames Chapman goto discard; 5098a1631d5SJames Chapman } 5108a1631d5SJames Chapman 511b6dc01a4SJames Chapman if (session->reorder_timeout != 0) { 512b6dc01a4SJames Chapman /* Packet reordering enabled. Add skb to session's 513b6dc01a4SJames Chapman * reorder queue, in order of ns. 514b6dc01a4SJames Chapman */ 515b6dc01a4SJames Chapman l2tp_recv_queue_skb(session, skb); 516a0dbd822SJames Chapman goto out; 517a0dbd822SJames Chapman } 518a0dbd822SJames Chapman 519a0dbd822SJames Chapman /* Packet reordering disabled. Discard out-of-sequence packets, while 520a0dbd822SJames Chapman * tracking the number if in-sequence packets after the first OOS packet 521a0dbd822SJames Chapman * is seen. After nr_oos_count_max in-sequence packets, reset the 522a0dbd822SJames Chapman * sequence number to re-enable packet reception. 523b6dc01a4SJames Chapman */ 524a0dbd822SJames Chapman if (L2TP_SKB_CB(skb)->ns == session->nr) { 525a0dbd822SJames Chapman skb_queue_tail(&session->reorder_q, skb); 526a0dbd822SJames Chapman } else { 527a0dbd822SJames Chapman u32 nr_oos = L2TP_SKB_CB(skb)->ns; 528a0dbd822SJames Chapman u32 nr_next = (session->nr_oos + 1) & session->nr_max; 529a0dbd822SJames Chapman 530a0dbd822SJames Chapman if (nr_oos == nr_next) 531a0dbd822SJames Chapman session->nr_oos_count++; 532a0dbd822SJames Chapman else 533a0dbd822SJames Chapman session->nr_oos_count = 0; 534a0dbd822SJames Chapman 535a0dbd822SJames Chapman session->nr_oos = nr_oos; 536a0dbd822SJames Chapman if (session->nr_oos_count > session->nr_oos_count_max) { 537a0dbd822SJames Chapman session->reorder_skip = 1; 538a0dbd822SJames Chapman l2tp_dbg(session, L2TP_MSG_SEQ, 539a0dbd822SJames Chapman "%s: %d oos packets received. Resetting sequence numbers\n", 540a0dbd822SJames Chapman session->name, session->nr_oos_count); 541a0dbd822SJames Chapman } 542a0dbd822SJames Chapman if (!session->reorder_skip) { 543b6dc01a4SJames Chapman atomic_long_inc(&session->stats.rx_seq_discards); 544b6dc01a4SJames Chapman l2tp_dbg(session, L2TP_MSG_SEQ, 545b6dc01a4SJames Chapman "%s: oos pkt %u len %d discarded, waiting for %u, reorder_q_len=%d\n", 546b6dc01a4SJames Chapman session->name, L2TP_SKB_CB(skb)->ns, 547b6dc01a4SJames Chapman L2TP_SKB_CB(skb)->length, session->nr, 548b6dc01a4SJames Chapman skb_queue_len(&session->reorder_q)); 549b6dc01a4SJames Chapman goto discard; 550b6dc01a4SJames Chapman } 551b6dc01a4SJames Chapman skb_queue_tail(&session->reorder_q, skb); 552b6dc01a4SJames Chapman } 553b6dc01a4SJames Chapman 554a0dbd822SJames Chapman out: 555b6dc01a4SJames Chapman return 0; 556b6dc01a4SJames Chapman 557b6dc01a4SJames Chapman discard: 558b6dc01a4SJames Chapman return 1; 559b6dc01a4SJames Chapman } 560b6dc01a4SJames Chapman 561f7faffa3SJames Chapman /* Do receive processing of L2TP data frames. We handle both L2TPv2 562f7faffa3SJames Chapman * and L2TPv3 data frames here. 563f7faffa3SJames Chapman * 564f7faffa3SJames Chapman * L2TPv2 Data Message Header 565f7faffa3SJames Chapman * 566f7faffa3SJames Chapman * 0 1 2 3 567f7faffa3SJames 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 568f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 569f7faffa3SJames Chapman * |T|L|x|x|S|x|O|P|x|x|x|x| Ver | Length (opt) | 570f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 571f7faffa3SJames Chapman * | Tunnel ID | Session ID | 572f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 573f7faffa3SJames Chapman * | Ns (opt) | Nr (opt) | 574f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 575f7faffa3SJames Chapman * | Offset Size (opt) | Offset pad... (opt) 576f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 577f7faffa3SJames Chapman * 578f7faffa3SJames Chapman * Data frames are marked by T=0. All other fields are the same as 579f7faffa3SJames Chapman * those in L2TP control frames. 580f7faffa3SJames Chapman * 581f7faffa3SJames Chapman * L2TPv3 Data Message Header 582f7faffa3SJames Chapman * 583f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 584f7faffa3SJames Chapman * | L2TP Session Header | 585f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 586f7faffa3SJames Chapman * | L2-Specific Sublayer | 587f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 588f7faffa3SJames Chapman * | Tunnel Payload ... 589f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 590f7faffa3SJames Chapman * 591f7faffa3SJames Chapman * L2TPv3 Session Header Over IP 592f7faffa3SJames Chapman * 593f7faffa3SJames Chapman * 0 1 2 3 594f7faffa3SJames 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 595f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 596f7faffa3SJames Chapman * | Session ID | 597f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 598f7faffa3SJames Chapman * | Cookie (optional, maximum 64 bits)... 599f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 600f7faffa3SJames Chapman * | 601f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 602f7faffa3SJames Chapman * 603f7faffa3SJames Chapman * L2TPv3 L2-Specific Sublayer Format 604f7faffa3SJames Chapman * 605f7faffa3SJames Chapman * 0 1 2 3 606f7faffa3SJames 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 607f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 608f7faffa3SJames Chapman * |x|S|x|x|x|x|x|x| Sequence Number | 609f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 610f7faffa3SJames Chapman * 61123fe846fSGuillaume Nault * Cookie value and sublayer format are negotiated with the peer when 61223fe846fSGuillaume Nault * the session is set up. Unlike L2TPv2, we do not need to parse the 61323fe846fSGuillaume Nault * packet header to determine if optional fields are present. 614f7faffa3SJames Chapman * 615f7faffa3SJames Chapman * Caller must already have parsed the frame and determined that it is 616f7faffa3SJames Chapman * a data (not control) frame before coming here. Fields up to the 617f7faffa3SJames Chapman * session-id have already been parsed and ptr points to the data 618f7faffa3SJames Chapman * after the session-id. 619f7faffa3SJames Chapman */ 620f7faffa3SJames Chapman void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, 621f7faffa3SJames Chapman unsigned char *ptr, unsigned char *optr, u16 hdrflags, 6222b139e6bSGuillaume Nault int length) 623f7faffa3SJames Chapman { 624f7faffa3SJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 625f7faffa3SJames Chapman int offset; 626f7faffa3SJames Chapman u32 ns, nr; 627f7faffa3SJames Chapman 628f7faffa3SJames Chapman /* Parse and check optional cookie */ 629f7faffa3SJames Chapman if (session->peer_cookie_len > 0) { 630f7faffa3SJames Chapman if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) { 631a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_DATA, 632f7faffa3SJames Chapman "%s: cookie mismatch (%u/%u). Discarding.\n", 633a4ca44faSJoe Perches tunnel->name, tunnel->tunnel_id, 634a4ca44faSJoe Perches session->session_id); 6357b7c0719STom Parkin atomic_long_inc(&session->stats.rx_cookie_discards); 636f7faffa3SJames Chapman goto discard; 637f7faffa3SJames Chapman } 638f7faffa3SJames Chapman ptr += session->peer_cookie_len; 639f7faffa3SJames Chapman } 640f7faffa3SJames Chapman 641f7faffa3SJames Chapman /* Handle the optional sequence numbers. Sequence numbers are 642f7faffa3SJames Chapman * in different places for L2TPv2 and L2TPv3. 643f7faffa3SJames Chapman * 644f7faffa3SJames Chapman * If we are the LAC, enable/disable sequence numbers under 645f7faffa3SJames Chapman * the control of the LNS. If no sequence numbers present but 646f7faffa3SJames Chapman * we were expecting them, discard frame. 647f7faffa3SJames Chapman */ 648f7faffa3SJames Chapman ns = nr = 0; 649f7faffa3SJames Chapman L2TP_SKB_CB(skb)->has_seq = 0; 650f7faffa3SJames Chapman if (tunnel->version == L2TP_HDR_VER_2) { 651f7faffa3SJames Chapman if (hdrflags & L2TP_HDRFLAG_S) { 652f7faffa3SJames Chapman ns = ntohs(*(__be16 *) ptr); 653f7faffa3SJames Chapman ptr += 2; 654f7faffa3SJames Chapman nr = ntohs(*(__be16 *) ptr); 655f7faffa3SJames Chapman ptr += 2; 656f7faffa3SJames Chapman 657f7faffa3SJames Chapman /* Store L2TP info in the skb */ 658f7faffa3SJames Chapman L2TP_SKB_CB(skb)->ns = ns; 659f7faffa3SJames Chapman L2TP_SKB_CB(skb)->has_seq = 1; 660f7faffa3SJames Chapman 661a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 662f7faffa3SJames Chapman "%s: recv data ns=%u, nr=%u, session nr=%u\n", 663f7faffa3SJames Chapman session->name, ns, nr, session->nr); 664f7faffa3SJames Chapman } 665f7faffa3SJames Chapman } else if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) { 666f7faffa3SJames Chapman u32 l2h = ntohl(*(__be32 *) ptr); 667f7faffa3SJames Chapman 668f7faffa3SJames Chapman if (l2h & 0x40000000) { 669f7faffa3SJames Chapman ns = l2h & 0x00ffffff; 670f7faffa3SJames Chapman 671f7faffa3SJames Chapman /* Store L2TP info in the skb */ 672f7faffa3SJames Chapman L2TP_SKB_CB(skb)->ns = ns; 673f7faffa3SJames Chapman L2TP_SKB_CB(skb)->has_seq = 1; 674f7faffa3SJames Chapman 675a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 676f7faffa3SJames Chapman "%s: recv data ns=%u, session nr=%u\n", 677f7faffa3SJames Chapman session->name, ns, session->nr); 678f7faffa3SJames Chapman } 67962e7b6a5SLorenzo Bianconi ptr += 4; 680f7faffa3SJames Chapman } 681f7faffa3SJames Chapman 682f7faffa3SJames Chapman if (L2TP_SKB_CB(skb)->has_seq) { 683f7faffa3SJames Chapman /* Received a packet with sequence numbers. If we're the LNS, 684f7faffa3SJames Chapman * check if we sre sending sequence numbers and if not, 685f7faffa3SJames Chapman * configure it so. 686f7faffa3SJames Chapman */ 687f7faffa3SJames Chapman if ((!session->lns_mode) && (!session->send_seq)) { 688a4ca44faSJoe Perches l2tp_info(session, L2TP_MSG_SEQ, 689f7faffa3SJames Chapman "%s: requested to enable seq numbers by LNS\n", 690f7faffa3SJames Chapman session->name); 6913f9b9770SAsbjørn Sloth Tønnesen session->send_seq = 1; 692f7faffa3SJames Chapman l2tp_session_set_header_len(session, tunnel->version); 693f7faffa3SJames Chapman } 694f7faffa3SJames Chapman } else { 695f7faffa3SJames Chapman /* No sequence numbers. 696f7faffa3SJames Chapman * If user has configured mandatory sequence numbers, discard. 697f7faffa3SJames Chapman */ 698f7faffa3SJames Chapman if (session->recv_seq) { 699a4ca44faSJoe Perches l2tp_warn(session, L2TP_MSG_SEQ, 700a4ca44faSJoe Perches "%s: recv data has no seq numbers when required. Discarding.\n", 701a4ca44faSJoe Perches session->name); 7027b7c0719STom Parkin atomic_long_inc(&session->stats.rx_seq_discards); 703f7faffa3SJames Chapman goto discard; 704f7faffa3SJames Chapman } 705f7faffa3SJames Chapman 706f7faffa3SJames Chapman /* If we're the LAC and we're sending sequence numbers, the 707f7faffa3SJames Chapman * LNS has requested that we no longer send sequence numbers. 708f7faffa3SJames Chapman * If we're the LNS and we're sending sequence numbers, the 709f7faffa3SJames Chapman * LAC is broken. Discard the frame. 710f7faffa3SJames Chapman */ 711f7faffa3SJames Chapman if ((!session->lns_mode) && (session->send_seq)) { 712a4ca44faSJoe Perches l2tp_info(session, L2TP_MSG_SEQ, 713f7faffa3SJames Chapman "%s: requested to disable seq numbers by LNS\n", 714f7faffa3SJames Chapman session->name); 715f7faffa3SJames Chapman session->send_seq = 0; 716f7faffa3SJames Chapman l2tp_session_set_header_len(session, tunnel->version); 717f7faffa3SJames Chapman } else if (session->send_seq) { 718a4ca44faSJoe Perches l2tp_warn(session, L2TP_MSG_SEQ, 719a4ca44faSJoe Perches "%s: recv data has no seq numbers when required. Discarding.\n", 720a4ca44faSJoe Perches session->name); 7217b7c0719STom Parkin atomic_long_inc(&session->stats.rx_seq_discards); 722f7faffa3SJames Chapman goto discard; 723f7faffa3SJames Chapman } 724f7faffa3SJames Chapman } 725f7faffa3SJames Chapman 726900631eeSJames Chapman /* Session data offset is defined only for L2TPv2 and is 727900631eeSJames Chapman * indicated by an optional 16-bit value in the header. 728f7faffa3SJames Chapman */ 729f7faffa3SJames Chapman if (tunnel->version == L2TP_HDR_VER_2) { 730f7faffa3SJames Chapman /* If offset bit set, skip it. */ 731f7faffa3SJames Chapman if (hdrflags & L2TP_HDRFLAG_O) { 732f7faffa3SJames Chapman offset = ntohs(*(__be16 *)ptr); 733f7faffa3SJames Chapman ptr += 2 + offset; 734f7faffa3SJames Chapman } 735900631eeSJames Chapman } 736f7faffa3SJames Chapman 737f7faffa3SJames Chapman offset = ptr - optr; 738f7faffa3SJames Chapman if (!pskb_may_pull(skb, offset)) 739f7faffa3SJames Chapman goto discard; 740f7faffa3SJames Chapman 741f7faffa3SJames Chapman __skb_pull(skb, offset); 742f7faffa3SJames Chapman 743f7faffa3SJames Chapman /* Prepare skb for adding to the session's reorder_q. Hold 744f7faffa3SJames Chapman * packets for max reorder_timeout or 1 second if not 745f7faffa3SJames Chapman * reordering. 746f7faffa3SJames Chapman */ 747f7faffa3SJames Chapman L2TP_SKB_CB(skb)->length = length; 748f7faffa3SJames Chapman L2TP_SKB_CB(skb)->expires = jiffies + 749f7faffa3SJames Chapman (session->reorder_timeout ? session->reorder_timeout : HZ); 750f7faffa3SJames Chapman 751f7faffa3SJames Chapman /* Add packet to the session's receive queue. Reordering is done here, if 752f7faffa3SJames Chapman * enabled. Saved L2TP protocol info is stored in skb->sb[]. 753f7faffa3SJames Chapman */ 754f7faffa3SJames Chapman if (L2TP_SKB_CB(skb)->has_seq) { 755b6dc01a4SJames Chapman if (l2tp_recv_data_seq(session, skb)) 756f7faffa3SJames Chapman goto discard; 757f7faffa3SJames Chapman } else { 758f7faffa3SJames Chapman /* No sequence numbers. Add the skb to the tail of the 759f7faffa3SJames Chapman * reorder queue. This ensures that it will be 760f7faffa3SJames Chapman * delivered after all previous sequenced skbs. 761f7faffa3SJames Chapman */ 762f7faffa3SJames Chapman skb_queue_tail(&session->reorder_q, skb); 763f7faffa3SJames Chapman } 764f7faffa3SJames Chapman 765f7faffa3SJames Chapman /* Try to dequeue as many skbs from reorder_q as we can. */ 766f7faffa3SJames Chapman l2tp_recv_dequeue(session); 767f7faffa3SJames Chapman 768f7faffa3SJames Chapman return; 769f7faffa3SJames Chapman 770f7faffa3SJames Chapman discard: 7717b7c0719STom Parkin atomic_long_inc(&session->stats.rx_errors); 772f7faffa3SJames Chapman kfree_skb(skb); 773f7faffa3SJames Chapman } 774f7faffa3SJames Chapman EXPORT_SYMBOL(l2tp_recv_common); 775f7faffa3SJames Chapman 77648f72f92STom Parkin /* Drop skbs from the session's reorder_q 77748f72f92STom Parkin */ 7782e67560eSGuillaume Nault static int l2tp_session_queue_purge(struct l2tp_session *session) 77948f72f92STom Parkin { 78048f72f92STom Parkin struct sk_buff *skb = NULL; 78148f72f92STom Parkin BUG_ON(!session); 78248f72f92STom Parkin BUG_ON(session->magic != L2TP_SESSION_MAGIC); 78348f72f92STom Parkin while ((skb = skb_dequeue(&session->reorder_q))) { 78448f72f92STom Parkin atomic_long_inc(&session->stats.rx_errors); 78548f72f92STom Parkin kfree_skb(skb); 78648f72f92STom Parkin } 78748f72f92STom Parkin return 0; 78848f72f92STom Parkin } 78948f72f92STom Parkin 790fd558d18SJames Chapman /* Internal UDP receive frame. Do the real work of receiving an L2TP data frame 791fd558d18SJames Chapman * here. The skb is not on a list when we get here. 792fd558d18SJames Chapman * Returns 0 if the packet was a data packet and was successfully passed on. 793fd558d18SJames Chapman * Returns 1 if the packet was not a good data packet and could not be 794fd558d18SJames Chapman * forwarded. All such packets are passed up to userspace to deal with. 795fd558d18SJames Chapman */ 7962b139e6bSGuillaume Nault static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb) 797fd558d18SJames Chapman { 798fd558d18SJames Chapman struct l2tp_session *session = NULL; 799fd558d18SJames Chapman unsigned char *ptr, *optr; 800fd558d18SJames Chapman u16 hdrflags; 801fd558d18SJames Chapman u32 tunnel_id, session_id; 802fd558d18SJames Chapman u16 version; 803f7faffa3SJames Chapman int length; 804fd558d18SJames Chapman 80558d6085cSTom Herbert /* UDP has verifed checksum */ 806fd558d18SJames Chapman 807fd558d18SJames Chapman /* UDP always verifies the packet length. */ 808fd558d18SJames Chapman __skb_pull(skb, sizeof(struct udphdr)); 809fd558d18SJames Chapman 810fd558d18SJames Chapman /* Short packet? */ 811fd558d18SJames Chapman if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) { 812a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_DATA, 813a4ca44faSJoe Perches "%s: recv short packet (len=%d)\n", 814a4ca44faSJoe Perches tunnel->name, skb->len); 815fd558d18SJames Chapman goto error; 816fd558d18SJames Chapman } 817fd558d18SJames Chapman 818fd558d18SJames Chapman /* Trace packet contents, if enabled */ 819fd558d18SJames Chapman if (tunnel->debug & L2TP_MSG_DATA) { 820fd558d18SJames Chapman length = min(32u, skb->len); 821fd558d18SJames Chapman if (!pskb_may_pull(skb, length)) 822fd558d18SJames Chapman goto error; 823fd558d18SJames Chapman 824a4ca44faSJoe Perches pr_debug("%s: recv\n", tunnel->name); 825a4ca44faSJoe Perches print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, skb->data, length); 826fd558d18SJames Chapman } 827fd558d18SJames Chapman 828e50e705cSEric Dumazet /* Point to L2TP header */ 829e50e705cSEric Dumazet optr = ptr = skb->data; 830e50e705cSEric Dumazet 831fd558d18SJames Chapman /* Get L2TP header flags */ 832fd558d18SJames Chapman hdrflags = ntohs(*(__be16 *) ptr); 833fd558d18SJames Chapman 834fd558d18SJames Chapman /* Check protocol version */ 835fd558d18SJames Chapman version = hdrflags & L2TP_HDR_VER_MASK; 836fd558d18SJames Chapman if (version != tunnel->version) { 837a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_DATA, 838fd558d18SJames Chapman "%s: recv protocol version mismatch: got %d expected %d\n", 839fd558d18SJames Chapman tunnel->name, version, tunnel->version); 840fd558d18SJames Chapman goto error; 841fd558d18SJames Chapman } 842fd558d18SJames Chapman 843fd558d18SJames Chapman /* Get length of L2TP packet */ 844fd558d18SJames Chapman length = skb->len; 845fd558d18SJames Chapman 846fd558d18SJames Chapman /* If type is control packet, it is handled by userspace. */ 847fd558d18SJames Chapman if (hdrflags & L2TP_HDRFLAG_T) { 848a4ca44faSJoe Perches l2tp_dbg(tunnel, L2TP_MSG_DATA, 849a4ca44faSJoe Perches "%s: recv control packet, len=%d\n", 850a4ca44faSJoe Perches tunnel->name, length); 851fd558d18SJames Chapman goto error; 852fd558d18SJames Chapman } 853fd558d18SJames Chapman 854fd558d18SJames Chapman /* Skip flags */ 855fd558d18SJames Chapman ptr += 2; 856fd558d18SJames Chapman 857f7faffa3SJames Chapman if (tunnel->version == L2TP_HDR_VER_2) { 858fd558d18SJames Chapman /* If length is present, skip it */ 859fd558d18SJames Chapman if (hdrflags & L2TP_HDRFLAG_L) 860fd558d18SJames Chapman ptr += 2; 861fd558d18SJames Chapman 862fd558d18SJames Chapman /* Extract tunnel and session ID */ 863fd558d18SJames Chapman tunnel_id = ntohs(*(__be16 *) ptr); 864fd558d18SJames Chapman ptr += 2; 865fd558d18SJames Chapman session_id = ntohs(*(__be16 *) ptr); 866fd558d18SJames Chapman ptr += 2; 867f7faffa3SJames Chapman } else { 868f7faffa3SJames Chapman ptr += 2; /* skip reserved bits */ 869f7faffa3SJames Chapman tunnel_id = tunnel->tunnel_id; 870f7faffa3SJames Chapman session_id = ntohl(*(__be32 *) ptr); 871f7faffa3SJames Chapman ptr += 4; 872f7faffa3SJames Chapman } 873fd558d18SJames Chapman 874fd558d18SJames Chapman /* Find the session context */ 875a4346210SGuillaume Nault session = l2tp_session_get(tunnel->l2tp_net, tunnel, session_id); 876309795f4SJames Chapman if (!session || !session->recv_skb) { 877a4346210SGuillaume Nault if (session) 87861b9a047SGuillaume Nault l2tp_session_dec_refcount(session); 87961b9a047SGuillaume Nault 880fd558d18SJames Chapman /* Not found? Pass to userspace to deal with */ 881a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_DATA, 882f7faffa3SJames Chapman "%s: no session found (%u/%u). Passing up.\n", 883fd558d18SJames Chapman tunnel->name, tunnel_id, session_id); 884fd558d18SJames Chapman goto error; 885fd558d18SJames Chapman } 886fd558d18SJames Chapman 8872b139e6bSGuillaume Nault l2tp_recv_common(session, skb, ptr, optr, hdrflags, length); 88861b9a047SGuillaume Nault l2tp_session_dec_refcount(session); 889fd558d18SJames Chapman 890fd558d18SJames Chapman return 0; 891fd558d18SJames Chapman 892fd558d18SJames Chapman error: 893fd558d18SJames Chapman /* Put UDP header back */ 894fd558d18SJames Chapman __skb_push(skb, sizeof(struct udphdr)); 895fd558d18SJames Chapman 896fd558d18SJames Chapman return 1; 897fd558d18SJames Chapman } 898fd558d18SJames Chapman 899fd558d18SJames Chapman /* UDP encapsulation receive handler. See net/ipv4/udp.c. 900fd558d18SJames Chapman * Return codes: 901fd558d18SJames Chapman * 0 : success. 902fd558d18SJames Chapman * <0: error 903fd558d18SJames Chapman * >0: skb should be passed up to userspace as UDP. 904fd558d18SJames Chapman */ 905fd558d18SJames Chapman int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) 906fd558d18SJames Chapman { 907fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 908fd558d18SJames Chapman 909d00fa9adSJames Chapman tunnel = l2tp_tunnel(sk); 910fd558d18SJames Chapman if (tunnel == NULL) 911fd558d18SJames Chapman goto pass_up; 912fd558d18SJames Chapman 913a4ca44faSJoe Perches l2tp_dbg(tunnel, L2TP_MSG_DATA, "%s: received %d bytes\n", 914a4ca44faSJoe Perches tunnel->name, skb->len); 915fd558d18SJames Chapman 9162b139e6bSGuillaume Nault if (l2tp_udp_recv_core(tunnel, skb)) 917d00fa9adSJames Chapman goto pass_up; 918fd558d18SJames Chapman 919fd558d18SJames Chapman return 0; 920fd558d18SJames Chapman 921fd558d18SJames Chapman pass_up: 922fd558d18SJames Chapman return 1; 923fd558d18SJames Chapman } 924fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_udp_encap_recv); 925fd558d18SJames Chapman 926fd558d18SJames Chapman /************************************************************************ 927fd558d18SJames Chapman * Transmit handling 928fd558d18SJames Chapman ***********************************************************************/ 929fd558d18SJames Chapman 930fd558d18SJames Chapman /* Build an L2TP header for the session into the buffer provided. 931fd558d18SJames Chapman */ 932f7faffa3SJames Chapman static int l2tp_build_l2tpv2_header(struct l2tp_session *session, void *buf) 933fd558d18SJames Chapman { 934f7faffa3SJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 935fd558d18SJames Chapman __be16 *bufp = buf; 936f7faffa3SJames Chapman __be16 *optr = buf; 937fd558d18SJames Chapman u16 flags = L2TP_HDR_VER_2; 938fd558d18SJames Chapman u32 tunnel_id = tunnel->peer_tunnel_id; 939fd558d18SJames Chapman u32 session_id = session->peer_session_id; 940fd558d18SJames Chapman 941fd558d18SJames Chapman if (session->send_seq) 942fd558d18SJames Chapman flags |= L2TP_HDRFLAG_S; 943fd558d18SJames Chapman 944fd558d18SJames Chapman /* Setup L2TP header. */ 945fd558d18SJames Chapman *bufp++ = htons(flags); 946fd558d18SJames Chapman *bufp++ = htons(tunnel_id); 947fd558d18SJames Chapman *bufp++ = htons(session_id); 948fd558d18SJames Chapman if (session->send_seq) { 949fd558d18SJames Chapman *bufp++ = htons(session->ns); 950fd558d18SJames Chapman *bufp++ = 0; 951fd558d18SJames Chapman session->ns++; 952f7faffa3SJames Chapman session->ns &= 0xffff; 953a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, "%s: updated ns to %u\n", 954a4ca44faSJoe Perches session->name, session->ns); 955fd558d18SJames Chapman } 956fd558d18SJames Chapman 957f7faffa3SJames Chapman return bufp - optr; 958f7faffa3SJames Chapman } 959f7faffa3SJames Chapman 960f7faffa3SJames Chapman static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf) 961fd558d18SJames Chapman { 9620d76751fSJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 963f7faffa3SJames Chapman char *bufp = buf; 964f7faffa3SJames Chapman char *optr = bufp; 965fd558d18SJames Chapman 9660d76751fSJames Chapman /* Setup L2TP header. The header differs slightly for UDP and 9670d76751fSJames Chapman * IP encapsulations. For UDP, there is 4 bytes of flags. 9680d76751fSJames Chapman */ 9690d76751fSJames Chapman if (tunnel->encap == L2TP_ENCAPTYPE_UDP) { 9700d76751fSJames Chapman u16 flags = L2TP_HDR_VER_3; 971f7faffa3SJames Chapman *((__be16 *) bufp) = htons(flags); 972f7faffa3SJames Chapman bufp += 2; 973f7faffa3SJames Chapman *((__be16 *) bufp) = 0; 974f7faffa3SJames Chapman bufp += 2; 9750d76751fSJames Chapman } 9760d76751fSJames Chapman 977f7faffa3SJames Chapman *((__be32 *) bufp) = htonl(session->peer_session_id); 978f7faffa3SJames Chapman bufp += 4; 979f7faffa3SJames Chapman if (session->cookie_len) { 980f7faffa3SJames Chapman memcpy(bufp, &session->cookie[0], session->cookie_len); 981f7faffa3SJames Chapman bufp += session->cookie_len; 982fd558d18SJames Chapman } 983f7faffa3SJames Chapman if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) { 984f7faffa3SJames Chapman u32 l2h = 0; 98562e7b6a5SLorenzo Bianconi 986f7faffa3SJames Chapman if (session->send_seq) { 987f7faffa3SJames Chapman l2h = 0x40000000 | session->ns; 988f7faffa3SJames Chapman session->ns++; 989f7faffa3SJames Chapman session->ns &= 0xffffff; 990a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 991a4ca44faSJoe Perches "%s: updated ns to %u\n", 992a4ca44faSJoe Perches session->name, session->ns); 993f7faffa3SJames Chapman } 994f7faffa3SJames Chapman 995f7faffa3SJames Chapman *((__be32 *)bufp) = htonl(l2h); 99662e7b6a5SLorenzo Bianconi bufp += 4; 997f7faffa3SJames Chapman } 998f7faffa3SJames Chapman 999f7faffa3SJames Chapman return bufp - optr; 1000f7faffa3SJames Chapman } 1001fd558d18SJames Chapman 10022685fbb8SGuillaume Nault static void l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, 1003d9d8da80SDavid S. Miller struct flowi *fl, size_t data_len) 1004fd558d18SJames Chapman { 1005fd558d18SJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 1006fd558d18SJames Chapman unsigned int len = skb->len; 1007fd558d18SJames Chapman int error; 1008fd558d18SJames Chapman 1009fd558d18SJames Chapman /* Debug */ 1010fd558d18SJames Chapman if (session->send_seq) 10115b5e0928SAlexey Dobriyan l2tp_dbg(session, L2TP_MSG_DATA, "%s: send %zd bytes, ns=%u\n", 1012a4ca44faSJoe Perches session->name, data_len, session->ns - 1); 1013fd558d18SJames Chapman else 10145b5e0928SAlexey Dobriyan l2tp_dbg(session, L2TP_MSG_DATA, "%s: send %zd bytes\n", 1015a4ca44faSJoe Perches session->name, data_len); 1016fd558d18SJames Chapman 1017fd558d18SJames Chapman if (session->debug & L2TP_MSG_DATA) { 10180d76751fSJames Chapman int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0; 10190d76751fSJames Chapman unsigned char *datap = skb->data + uhlen; 1020fd558d18SJames Chapman 1021a4ca44faSJoe Perches pr_debug("%s: xmit\n", session->name); 1022a4ca44faSJoe Perches print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, 1023a4ca44faSJoe Perches datap, min_t(size_t, 32, len - uhlen)); 1024fd558d18SJames Chapman } 1025fd558d18SJames Chapman 1026fd558d18SJames Chapman /* Queue the packet to IP for output */ 102760ff7467SWANG Cong skb->ignore_df = 1; 1028d2cf3361SBenjamin LaHaise #if IS_ENABLED(CONFIG_IPV6) 1029b954f940SPaolo Abeni if (l2tp_sk_is_v6(tunnel->sock)) 1030b0270e91SEric Dumazet error = inet6_csk_xmit(tunnel->sock, skb, NULL); 1031d2cf3361SBenjamin LaHaise else 1032d2cf3361SBenjamin LaHaise #endif 1033b0270e91SEric Dumazet error = ip_queue_xmit(tunnel->sock, skb, fl); 1034fd558d18SJames Chapman 1035fd558d18SJames Chapman /* Update stats */ 1036fd558d18SJames Chapman if (error >= 0) { 10377b7c0719STom Parkin atomic_long_inc(&tunnel->stats.tx_packets); 10387b7c0719STom Parkin atomic_long_add(len, &tunnel->stats.tx_bytes); 10397b7c0719STom Parkin atomic_long_inc(&session->stats.tx_packets); 10407b7c0719STom Parkin atomic_long_add(len, &session->stats.tx_bytes); 1041fd558d18SJames Chapman } else { 10427b7c0719STom Parkin atomic_long_inc(&tunnel->stats.tx_errors); 10437b7c0719STom Parkin atomic_long_inc(&session->stats.tx_errors); 1044fd558d18SJames Chapman } 1045fd558d18SJames Chapman } 1046fd558d18SJames Chapman 1047fd558d18SJames Chapman /* If caller requires the skb to have a ppp header, the header must be 1048fd558d18SJames Chapman * inserted in the skb data before calling this function. 1049fd558d18SJames Chapman */ 1050fd558d18SJames Chapman int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len) 1051fd558d18SJames Chapman { 1052fd558d18SJames Chapman int data_len = skb->len; 10530d76751fSJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 10540d76751fSJames Chapman struct sock *sk = tunnel->sock; 1055d9d8da80SDavid S. Miller struct flowi *fl; 1056fd558d18SJames Chapman struct udphdr *uh; 1057fd558d18SJames Chapman struct inet_sock *inet; 1058fd558d18SJames Chapman int headroom; 10590d76751fSJames Chapman int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0; 10600d76751fSJames Chapman int udp_len; 1061b8c84307SEric Dumazet int ret = NET_XMIT_SUCCESS; 1062fd558d18SJames Chapman 1063fd558d18SJames Chapman /* Check that there's enough headroom in the skb to insert IP, 1064fd558d18SJames Chapman * UDP and L2TP headers. If not enough, expand it to 1065fd558d18SJames Chapman * make room. Adjust truesize. 1066fd558d18SJames Chapman */ 1067fd558d18SJames Chapman headroom = NET_SKB_PAD + sizeof(struct iphdr) + 10680d76751fSJames Chapman uhlen + hdr_len; 1069835acf5dSEric Dumazet if (skb_cow_head(skb, headroom)) { 1070b8c84307SEric Dumazet kfree_skb(skb); 1071b8c84307SEric Dumazet return NET_XMIT_DROP; 1072835acf5dSEric Dumazet } 1073fd558d18SJames Chapman 1074fd558d18SJames Chapman /* Setup L2TP header */ 1075f7faffa3SJames Chapman session->build_header(session, __skb_push(skb, hdr_len)); 1076fd558d18SJames Chapman 10770d76751fSJames Chapman /* Reset skb netfilter state */ 1078fd558d18SJames Chapman memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 1079fd558d18SJames Chapman IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | 1080fd558d18SJames Chapman IPSKB_REROUTED); 1081fd558d18SJames Chapman nf_reset(skb); 1082fd558d18SJames Chapman 10836af88da1SDavid S. Miller bh_lock_sock(sk); 10846af88da1SDavid S. Miller if (sock_owned_by_user(sk)) { 1085b8c84307SEric Dumazet kfree_skb(skb); 1086b8c84307SEric Dumazet ret = NET_XMIT_DROP; 10876af88da1SDavid S. Miller goto out_unlock; 10886af88da1SDavid S. Miller } 10896af88da1SDavid S. Miller 1090b954f940SPaolo Abeni /* The user-space may change the connection status for the user-space 1091b954f940SPaolo Abeni * provided socket at run time: we must check it under the socket lock 1092b954f940SPaolo Abeni */ 1093b954f940SPaolo Abeni if (tunnel->fd >= 0 && sk->sk_state != TCP_ESTABLISHED) { 1094b954f940SPaolo Abeni kfree_skb(skb); 1095b954f940SPaolo Abeni ret = NET_XMIT_DROP; 1096b954f940SPaolo Abeni goto out_unlock; 1097b954f940SPaolo Abeni } 1098b954f940SPaolo Abeni 1099fd558d18SJames Chapman /* Get routing info from the tunnel socket */ 1100fd558d18SJames Chapman skb_dst_drop(skb); 110171b1391aSFlorian Westphal skb_dst_set(skb, dst_clone(__sk_dst_check(sk, 0))); 11020d76751fSJames Chapman 1103d9d8da80SDavid S. Miller inet = inet_sk(sk); 1104d9d8da80SDavid S. Miller fl = &inet->cork.fl; 11050d76751fSJames Chapman switch (tunnel->encap) { 11060d76751fSJames Chapman case L2TP_ENCAPTYPE_UDP: 11070d76751fSJames Chapman /* Setup UDP header */ 11080d76751fSJames Chapman __skb_push(skb, sizeof(*uh)); 11090d76751fSJames Chapman skb_reset_transport_header(skb); 11100d76751fSJames Chapman uh = udp_hdr(skb); 11110d76751fSJames Chapman uh->source = inet->inet_sport; 11120d76751fSJames Chapman uh->dest = inet->inet_dport; 11130d76751fSJames Chapman udp_len = uhlen + hdr_len + data_len; 11140d76751fSJames Chapman uh->len = htons(udp_len); 1115fd558d18SJames Chapman 1116fd558d18SJames Chapman /* Calculate UDP checksum if configured to do so */ 1117d2cf3361SBenjamin LaHaise #if IS_ENABLED(CONFIG_IPV6) 1118b954f940SPaolo Abeni if (l2tp_sk_is_v6(sk)) 111977157e19STom Herbert udp6_set_csum(udp_get_no_check6_tx(sk), 112077157e19STom Herbert skb, &inet6_sk(sk)->saddr, 112177157e19STom Herbert &sk->sk_v6_daddr, udp_len); 1122d2cf3361SBenjamin LaHaise else 1123d2cf3361SBenjamin LaHaise #endif 112477157e19STom Herbert udp_set_csum(sk->sk_no_check_tx, skb, inet->inet_saddr, 112577157e19STom Herbert inet->inet_daddr, udp_len); 11260d76751fSJames Chapman break; 11270d76751fSJames Chapman 11280d76751fSJames Chapman case L2TP_ENCAPTYPE_IP: 11290d76751fSJames Chapman break; 11300d76751fSJames Chapman } 11310d76751fSJames Chapman 1132d9d8da80SDavid S. Miller l2tp_xmit_core(session, skb, fl, data_len); 11336af88da1SDavid S. Miller out_unlock: 11346af88da1SDavid S. Miller bh_unlock_sock(sk); 1135fd558d18SJames Chapman 1136b8c84307SEric Dumazet return ret; 1137fd558d18SJames Chapman } 1138fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_xmit_skb); 1139fd558d18SJames Chapman 1140fd558d18SJames Chapman /***************************************************************************** 1141fd558d18SJames Chapman * Tinnel and session create/destroy. 1142fd558d18SJames Chapman *****************************************************************************/ 1143fd558d18SJames Chapman 1144fd558d18SJames Chapman /* Tunnel socket destruct hook. 1145fd558d18SJames Chapman * The tunnel context is deleted only when all session sockets have been 1146fd558d18SJames Chapman * closed. 1147fd558d18SJames Chapman */ 1148fc130840Sstephen hemminger static void l2tp_tunnel_destruct(struct sock *sk) 1149fd558d18SJames Chapman { 11508d8a51e2SDavid S. Miller struct l2tp_tunnel *tunnel = l2tp_tunnel(sk); 1151fd558d18SJames Chapman 1152fd558d18SJames Chapman if (tunnel == NULL) 1153fd558d18SJames Chapman goto end; 1154fd558d18SJames Chapman 1155a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: closing...\n", tunnel->name); 1156fd558d18SJames Chapman 1157f8ccac0eSTom Parkin /* Disable udp encapsulation */ 11580d76751fSJames Chapman switch (tunnel->encap) { 11590d76751fSJames Chapman case L2TP_ENCAPTYPE_UDP: 1160fd558d18SJames Chapman /* No longer an encapsulation socket. See net/ipv4/udp.c */ 1161fd558d18SJames Chapman (udp_sk(sk))->encap_type = 0; 1162fd558d18SJames Chapman (udp_sk(sk))->encap_rcv = NULL; 11639980d001STom Parkin (udp_sk(sk))->encap_destroy = NULL; 11640d76751fSJames Chapman break; 11650d76751fSJames Chapman case L2TP_ENCAPTYPE_IP: 11660d76751fSJames Chapman break; 11670d76751fSJames Chapman } 1168fd558d18SJames Chapman 1169fd558d18SJames Chapman /* Remove hooks into tunnel socket */ 1170fd558d18SJames Chapman sk->sk_destruct = tunnel->old_sk_destruct; 1171fd558d18SJames Chapman sk->sk_user_data = NULL; 1172f8ccac0eSTom Parkin 1173fd558d18SJames Chapman /* Call the original destructor */ 1174fd558d18SJames Chapman if (sk->sk_destruct) 1175fd558d18SJames Chapman (*sk->sk_destruct)(sk); 1176d00fa9adSJames Chapman 1177d00fa9adSJames Chapman kfree_rcu(tunnel, rcu); 1178fd558d18SJames Chapman end: 1179fd558d18SJames Chapman return; 1180fd558d18SJames Chapman } 1181fd558d18SJames Chapman 1182fd558d18SJames Chapman /* When the tunnel is closed, all the attached sessions need to go too. 1183fd558d18SJames Chapman */ 1184d08532bbSGuillaume Nault static void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel) 1185fd558d18SJames Chapman { 1186fd558d18SJames Chapman int hash; 1187fd558d18SJames Chapman struct hlist_node *walk; 1188fd558d18SJames Chapman struct hlist_node *tmp; 1189fd558d18SJames Chapman struct l2tp_session *session; 1190fd558d18SJames Chapman 1191fd558d18SJames Chapman BUG_ON(tunnel == NULL); 1192fd558d18SJames Chapman 1193a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: closing all sessions...\n", 1194a4ca44faSJoe Perches tunnel->name); 1195fd558d18SJames Chapman 1196fd558d18SJames Chapman write_lock_bh(&tunnel->hlist_lock); 1197f3c66d4eSGuillaume Nault tunnel->acpt_newsess = false; 1198fd558d18SJames Chapman for (hash = 0; hash < L2TP_HASH_SIZE; hash++) { 1199fd558d18SJames Chapman again: 1200fd558d18SJames Chapman hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) { 1201fd558d18SJames Chapman session = hlist_entry(walk, struct l2tp_session, hlist); 1202fd558d18SJames Chapman 1203a4ca44faSJoe Perches l2tp_info(session, L2TP_MSG_CONTROL, 1204fd558d18SJames Chapman "%s: closing session\n", session->name); 1205fd558d18SJames Chapman 1206fd558d18SJames Chapman hlist_del_init(&session->hlist); 1207fd558d18SJames Chapman 1208b228a940SGuillaume Nault if (test_and_set_bit(0, &session->dead)) 1209b228a940SGuillaume Nault goto again; 1210b228a940SGuillaume Nault 1211fd558d18SJames Chapman write_unlock_bh(&tunnel->hlist_lock); 1212fd558d18SJames Chapman 1213f6e16b29STom Parkin __l2tp_session_unhash(session); 12144c6e2fd3STom Parkin l2tp_session_queue_purge(session); 12154c6e2fd3STom Parkin 1216fd558d18SJames Chapman if (session->session_close != NULL) 1217fd558d18SJames Chapman (*session->session_close)(session); 1218fd558d18SJames Chapman 12199980d001STom Parkin l2tp_session_dec_refcount(session); 12209980d001STom Parkin 1221fd558d18SJames Chapman write_lock_bh(&tunnel->hlist_lock); 1222fd558d18SJames Chapman 1223fd558d18SJames Chapman /* Now restart from the beginning of this hash 1224fd558d18SJames Chapman * chain. We always remove a session from the 1225fd558d18SJames Chapman * list so we are guaranteed to make forward 1226fd558d18SJames Chapman * progress. 1227fd558d18SJames Chapman */ 1228fd558d18SJames Chapman goto again; 1229fd558d18SJames Chapman } 1230fd558d18SJames Chapman } 1231fd558d18SJames Chapman write_unlock_bh(&tunnel->hlist_lock); 1232fd558d18SJames Chapman } 1233fd558d18SJames Chapman 12349980d001STom Parkin /* Tunnel socket destroy hook for UDP encapsulation */ 12359980d001STom Parkin static void l2tp_udp_encap_destroy(struct sock *sk) 12369980d001STom Parkin { 1237d00fa9adSJames Chapman struct l2tp_tunnel *tunnel = l2tp_tunnel(sk); 1238d00fa9adSJames Chapman 1239d00fa9adSJames Chapman if (tunnel) 1240d00fa9adSJames Chapman l2tp_tunnel_delete(tunnel); 12419980d001STom Parkin } 12429980d001STom Parkin 1243f8ccac0eSTom Parkin /* Workqueue tunnel deletion function */ 1244f8ccac0eSTom Parkin static void l2tp_tunnel_del_work(struct work_struct *work) 1245f8ccac0eSTom Parkin { 1246d00fa9adSJames Chapman struct l2tp_tunnel *tunnel = container_of(work, struct l2tp_tunnel, 1247d00fa9adSJames Chapman del_work); 1248d00fa9adSJames Chapman struct sock *sk = tunnel->sock; 1249d00fa9adSJames Chapman struct socket *sock = sk->sk_socket; 125028f5bfb8SJames Chapman struct l2tp_net *pn; 125112d656afSRidge Kennedy 125212d656afSRidge Kennedy l2tp_tunnel_closeall(tunnel); 125312d656afSRidge Kennedy 125476a6abdbSJames Chapman /* If the tunnel socket was created within the kernel, use 125502d13ed5STom Parkin * the sk API to release it here. 1256f8ccac0eSTom Parkin */ 125776a6abdbSJames Chapman if (tunnel->fd < 0) { 125826abe143SEric W. Biederman if (sock) { 1259167eb17eSTom Parkin kernel_sock_shutdown(sock, SHUT_RDWR); 126026abe143SEric W. Biederman sock_release(sock); 126126abe143SEric W. Biederman } 1262167eb17eSTom Parkin } 1263f8ccac0eSTom Parkin 126428f5bfb8SJames Chapman /* Remove the tunnel struct from the tunnel list */ 126528f5bfb8SJames Chapman pn = l2tp_pernet(tunnel->l2tp_net); 126628f5bfb8SJames Chapman spin_lock_bh(&pn->l2tp_tunnel_list_lock); 126728f5bfb8SJames Chapman list_del_rcu(&tunnel->list); 126828f5bfb8SJames Chapman spin_unlock_bh(&pn->l2tp_tunnel_list_lock); 126928f5bfb8SJames Chapman 1270d00fa9adSJames Chapman /* drop initial ref */ 1271d00fa9adSJames Chapman l2tp_tunnel_dec_refcount(tunnel); 1272d00fa9adSJames Chapman 1273d00fa9adSJames Chapman /* drop workqueue ref */ 127406a15f51SAlexander Couzens l2tp_tunnel_dec_refcount(tunnel); 1275fd558d18SJames Chapman } 1276fd558d18SJames Chapman 1277789a4a2cSJames Chapman /* Create a socket for the tunnel, if one isn't set up by 1278789a4a2cSJames Chapman * userspace. This is used for static tunnels where there is no 1279789a4a2cSJames Chapman * managing L2TP daemon. 1280167eb17eSTom Parkin * 1281167eb17eSTom Parkin * Since we don't want these sockets to keep a namespace alive by 1282167eb17eSTom Parkin * themselves, we drop the socket's namespace refcount after creation. 1283167eb17eSTom Parkin * These sockets are freed when the namespace exits using the pernet 1284167eb17eSTom Parkin * exit hook. 1285789a4a2cSJames Chapman */ 1286167eb17eSTom Parkin static int l2tp_tunnel_sock_create(struct net *net, 1287167eb17eSTom Parkin u32 tunnel_id, 1288167eb17eSTom Parkin u32 peer_tunnel_id, 1289167eb17eSTom Parkin struct l2tp_tunnel_cfg *cfg, 1290167eb17eSTom Parkin struct socket **sockp) 1291789a4a2cSJames Chapman { 1292789a4a2cSJames Chapman int err = -EINVAL; 12937bddd0dbSEric Dumazet struct socket *sock = NULL; 129485644b4dSTom Herbert struct udp_port_cfg udp_conf; 1295789a4a2cSJames Chapman 1296789a4a2cSJames Chapman switch (cfg->encap) { 1297789a4a2cSJames Chapman case L2TP_ENCAPTYPE_UDP: 129885644b4dSTom Herbert memset(&udp_conf, 0, sizeof(udp_conf)); 129985644b4dSTom Herbert 1300f9bac8dfSChris Elston #if IS_ENABLED(CONFIG_IPV6) 1301f9bac8dfSChris Elston if (cfg->local_ip6 && cfg->peer_ip6) { 130285644b4dSTom Herbert udp_conf.family = AF_INET6; 130385644b4dSTom Herbert memcpy(&udp_conf.local_ip6, cfg->local_ip6, 130485644b4dSTom Herbert sizeof(udp_conf.local_ip6)); 130585644b4dSTom Herbert memcpy(&udp_conf.peer_ip6, cfg->peer_ip6, 130685644b4dSTom Herbert sizeof(udp_conf.peer_ip6)); 130785644b4dSTom Herbert udp_conf.use_udp6_tx_checksums = 1308018f8258SWang Shanker ! cfg->udp6_zero_tx_checksums; 130985644b4dSTom Herbert udp_conf.use_udp6_rx_checksums = 1310018f8258SWang Shanker ! cfg->udp6_zero_rx_checksums; 1311f9bac8dfSChris Elston } else 1312f9bac8dfSChris Elston #endif 1313f9bac8dfSChris Elston { 131485644b4dSTom Herbert udp_conf.family = AF_INET; 131585644b4dSTom Herbert udp_conf.local_ip = cfg->local_ip; 131685644b4dSTom Herbert udp_conf.peer_ip = cfg->peer_ip; 131785644b4dSTom Herbert udp_conf.use_udp_checksums = cfg->use_udp_checksums; 1318f9bac8dfSChris Elston } 1319789a4a2cSJames Chapman 132085644b4dSTom Herbert udp_conf.local_udp_port = htons(cfg->local_udp_port); 132185644b4dSTom Herbert udp_conf.peer_udp_port = htons(cfg->peer_udp_port); 132285644b4dSTom Herbert 132385644b4dSTom Herbert err = udp_sock_create(net, &udp_conf, &sock); 132485644b4dSTom Herbert if (err < 0) 132585644b4dSTom Herbert goto out; 1326789a4a2cSJames Chapman 1327789a4a2cSJames Chapman break; 1328789a4a2cSJames Chapman 1329789a4a2cSJames Chapman case L2TP_ENCAPTYPE_IP: 1330f9bac8dfSChris Elston #if IS_ENABLED(CONFIG_IPV6) 1331f9bac8dfSChris Elston if (cfg->local_ip6 && cfg->peer_ip6) { 133285644b4dSTom Herbert struct sockaddr_l2tpip6 ip6_addr = {0}; 133385644b4dSTom Herbert 133426abe143SEric W. Biederman err = sock_create_kern(net, AF_INET6, SOCK_DGRAM, 1335167eb17eSTom Parkin IPPROTO_L2TP, &sock); 13365dac94e1SJames Chapman if (err < 0) 1337f9bac8dfSChris Elston goto out; 13385dac94e1SJames Chapman 13395dac94e1SJames Chapman ip6_addr.l2tp_family = AF_INET6; 13405dac94e1SJames Chapman memcpy(&ip6_addr.l2tp_addr, cfg->local_ip6, 13415dac94e1SJames Chapman sizeof(ip6_addr.l2tp_addr)); 13425dac94e1SJames Chapman ip6_addr.l2tp_conn_id = tunnel_id; 13435dac94e1SJames Chapman err = kernel_bind(sock, (struct sockaddr *) &ip6_addr, 13445dac94e1SJames Chapman sizeof(ip6_addr)); 13455dac94e1SJames Chapman if (err < 0) 13465dac94e1SJames Chapman goto out; 13475dac94e1SJames Chapman 13485dac94e1SJames Chapman ip6_addr.l2tp_family = AF_INET6; 13495dac94e1SJames Chapman memcpy(&ip6_addr.l2tp_addr, cfg->peer_ip6, 13505dac94e1SJames Chapman sizeof(ip6_addr.l2tp_addr)); 13515dac94e1SJames Chapman ip6_addr.l2tp_conn_id = peer_tunnel_id; 13525dac94e1SJames Chapman err = kernel_connect(sock, 13535dac94e1SJames Chapman (struct sockaddr *) &ip6_addr, 13545dac94e1SJames Chapman sizeof(ip6_addr), 0); 13555dac94e1SJames Chapman if (err < 0) 13565dac94e1SJames Chapman goto out; 13575dac94e1SJames Chapman } else 1358f9bac8dfSChris Elston #endif 13595dac94e1SJames Chapman { 136085644b4dSTom Herbert struct sockaddr_l2tpip ip_addr = {0}; 136185644b4dSTom Herbert 136226abe143SEric W. Biederman err = sock_create_kern(net, AF_INET, SOCK_DGRAM, 1363167eb17eSTom Parkin IPPROTO_L2TP, &sock); 1364789a4a2cSJames Chapman if (err < 0) 1365789a4a2cSJames Chapman goto out; 1366789a4a2cSJames Chapman 1367789a4a2cSJames Chapman ip_addr.l2tp_family = AF_INET; 1368789a4a2cSJames Chapman ip_addr.l2tp_addr = cfg->local_ip; 1369789a4a2cSJames Chapman ip_addr.l2tp_conn_id = tunnel_id; 13705dac94e1SJames Chapman err = kernel_bind(sock, (struct sockaddr *) &ip_addr, 13715dac94e1SJames Chapman sizeof(ip_addr)); 1372789a4a2cSJames Chapman if (err < 0) 1373789a4a2cSJames Chapman goto out; 1374789a4a2cSJames Chapman 1375789a4a2cSJames Chapman ip_addr.l2tp_family = AF_INET; 1376789a4a2cSJames Chapman ip_addr.l2tp_addr = cfg->peer_ip; 1377789a4a2cSJames Chapman ip_addr.l2tp_conn_id = peer_tunnel_id; 13785dac94e1SJames Chapman err = kernel_connect(sock, (struct sockaddr *) &ip_addr, 13795dac94e1SJames Chapman sizeof(ip_addr), 0); 1380789a4a2cSJames Chapman if (err < 0) 1381789a4a2cSJames Chapman goto out; 13825dac94e1SJames Chapman } 1383789a4a2cSJames Chapman break; 1384789a4a2cSJames Chapman 1385789a4a2cSJames Chapman default: 1386789a4a2cSJames Chapman goto out; 1387789a4a2cSJames Chapman } 1388789a4a2cSJames Chapman 1389789a4a2cSJames Chapman out: 1390167eb17eSTom Parkin *sockp = sock; 1391789a4a2cSJames Chapman if ((err < 0) && sock) { 1392167eb17eSTom Parkin kernel_sock_shutdown(sock, SHUT_RDWR); 139326abe143SEric W. Biederman sock_release(sock); 1394789a4a2cSJames Chapman *sockp = NULL; 1395789a4a2cSJames Chapman } 1396789a4a2cSJames Chapman 1397789a4a2cSJames Chapman return err; 1398789a4a2cSJames Chapman } 1399789a4a2cSJames Chapman 140037159ef2SEric Dumazet static struct lock_class_key l2tp_socket_class; 140137159ef2SEric Dumazet 1402fd558d18SJames Chapman int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp) 1403fd558d18SJames Chapman { 1404fd558d18SJames Chapman struct l2tp_tunnel *tunnel = NULL; 1405fd558d18SJames Chapman int err; 14060d76751fSJames Chapman enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP; 1407fd558d18SJames Chapman 14080d76751fSJames Chapman if (cfg != NULL) 14090d76751fSJames Chapman encap = cfg->encap; 14100d76751fSJames Chapman 1411fd558d18SJames Chapman tunnel = kzalloc(sizeof(struct l2tp_tunnel), GFP_KERNEL); 1412fd558d18SJames Chapman if (tunnel == NULL) { 1413fd558d18SJames Chapman err = -ENOMEM; 1414fd558d18SJames Chapman goto err; 1415fd558d18SJames Chapman } 1416fd558d18SJames Chapman 1417fd558d18SJames Chapman tunnel->version = version; 1418fd558d18SJames Chapman tunnel->tunnel_id = tunnel_id; 1419fd558d18SJames Chapman tunnel->peer_tunnel_id = peer_tunnel_id; 1420fd558d18SJames Chapman tunnel->debug = L2TP_DEFAULT_DEBUG_FLAGS; 1421fd558d18SJames Chapman 1422fd558d18SJames Chapman tunnel->magic = L2TP_TUNNEL_MAGIC; 1423fd558d18SJames Chapman sprintf(&tunnel->name[0], "tunl %u", tunnel_id); 1424fd558d18SJames Chapman rwlock_init(&tunnel->hlist_lock); 1425f3c66d4eSGuillaume Nault tunnel->acpt_newsess = true; 1426fd558d18SJames Chapman 14270d76751fSJames Chapman if (cfg != NULL) 1428fd558d18SJames Chapman tunnel->debug = cfg->debug; 1429fd558d18SJames Chapman 14300d76751fSJames Chapman tunnel->encap = encap; 1431fd558d18SJames Chapman 1432d00fa9adSJames Chapman refcount_set(&tunnel->ref_count, 1); 1433d00fa9adSJames Chapman tunnel->fd = fd; 1434d00fa9adSJames Chapman 1435f8ccac0eSTom Parkin /* Init delete workqueue struct */ 1436f8ccac0eSTom Parkin INIT_WORK(&tunnel->del_work, l2tp_tunnel_del_work); 1437f8ccac0eSTom Parkin 1438fd558d18SJames Chapman INIT_LIST_HEAD(&tunnel->list); 1439fd558d18SJames Chapman 1440fd558d18SJames Chapman err = 0; 1441fd558d18SJames Chapman err: 1442fd558d18SJames Chapman if (tunnelp) 1443fd558d18SJames Chapman *tunnelp = tunnel; 1444fd558d18SJames Chapman 1445fd558d18SJames Chapman return err; 1446fd558d18SJames Chapman } 1447fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_tunnel_create); 1448fd558d18SJames Chapman 14496b9f3423SGuillaume Nault static int l2tp_validate_socket(const struct sock *sk, const struct net *net, 14506b9f3423SGuillaume Nault enum l2tp_encap_type encap) 14516b9f3423SGuillaume Nault { 14526b9f3423SGuillaume Nault if (!net_eq(sock_net(sk), net)) 14536b9f3423SGuillaume Nault return -EINVAL; 14546b9f3423SGuillaume Nault 14556b9f3423SGuillaume Nault if (sk->sk_type != SOCK_DGRAM) 14566b9f3423SGuillaume Nault return -EPROTONOSUPPORT; 14576b9f3423SGuillaume Nault 14586b9f3423SGuillaume Nault if ((encap == L2TP_ENCAPTYPE_UDP && sk->sk_protocol != IPPROTO_UDP) || 14596b9f3423SGuillaume Nault (encap == L2TP_ENCAPTYPE_IP && sk->sk_protocol != IPPROTO_L2TP)) 14606b9f3423SGuillaume Nault return -EPROTONOSUPPORT; 14616b9f3423SGuillaume Nault 14626b9f3423SGuillaume Nault if (sk->sk_user_data) 14636b9f3423SGuillaume Nault return -EBUSY; 14646b9f3423SGuillaume Nault 14656b9f3423SGuillaume Nault return 0; 14666b9f3423SGuillaume Nault } 14676b9f3423SGuillaume Nault 14686b9f3423SGuillaume Nault int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, 14696b9f3423SGuillaume Nault struct l2tp_tunnel_cfg *cfg) 14706b9f3423SGuillaume Nault { 1471f6cd651bSGuillaume Nault struct l2tp_tunnel *tunnel_walk; 14726b9f3423SGuillaume Nault struct l2tp_net *pn; 14736b9f3423SGuillaume Nault struct socket *sock; 14746b9f3423SGuillaume Nault struct sock *sk; 14756b9f3423SGuillaume Nault int ret; 14766b9f3423SGuillaume Nault 14776b9f3423SGuillaume Nault if (tunnel->fd < 0) { 14786b9f3423SGuillaume Nault ret = l2tp_tunnel_sock_create(net, tunnel->tunnel_id, 14796b9f3423SGuillaume Nault tunnel->peer_tunnel_id, cfg, 14806b9f3423SGuillaume Nault &sock); 14816b9f3423SGuillaume Nault if (ret < 0) 14826b9f3423SGuillaume Nault goto err; 14836b9f3423SGuillaume Nault } else { 14846b9f3423SGuillaume Nault sock = sockfd_lookup(tunnel->fd, &ret); 14856b9f3423SGuillaume Nault if (!sock) 14866b9f3423SGuillaume Nault goto err; 14876b9f3423SGuillaume Nault 14886b9f3423SGuillaume Nault ret = l2tp_validate_socket(sock->sk, net, tunnel->encap); 14896b9f3423SGuillaume Nault if (ret < 0) 14906b9f3423SGuillaume Nault goto err_sock; 14916b9f3423SGuillaume Nault } 14926b9f3423SGuillaume Nault 14936b9f3423SGuillaume Nault sk = sock->sk; 14946b9f3423SGuillaume Nault 14956b9f3423SGuillaume Nault sock_hold(sk); 14966b9f3423SGuillaume Nault tunnel->sock = sk; 14976b9f3423SGuillaume Nault tunnel->l2tp_net = net; 14986b9f3423SGuillaume Nault 14996b9f3423SGuillaume Nault pn = l2tp_pernet(net); 1500f6cd651bSGuillaume Nault 15016b9f3423SGuillaume Nault spin_lock_bh(&pn->l2tp_tunnel_list_lock); 1502f6cd651bSGuillaume Nault list_for_each_entry(tunnel_walk, &pn->l2tp_tunnel_list, list) { 1503f6cd651bSGuillaume Nault if (tunnel_walk->tunnel_id == tunnel->tunnel_id) { 1504f6cd651bSGuillaume Nault spin_unlock_bh(&pn->l2tp_tunnel_list_lock); 1505f6cd651bSGuillaume Nault 1506f6cd651bSGuillaume Nault ret = -EEXIST; 1507f6cd651bSGuillaume Nault goto err_sock; 1508f6cd651bSGuillaume Nault } 1509f6cd651bSGuillaume Nault } 15106b9f3423SGuillaume Nault list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); 15116b9f3423SGuillaume Nault spin_unlock_bh(&pn->l2tp_tunnel_list_lock); 15126b9f3423SGuillaume Nault 15136b9f3423SGuillaume Nault if (tunnel->encap == L2TP_ENCAPTYPE_UDP) { 15146b9f3423SGuillaume Nault struct udp_tunnel_sock_cfg udp_cfg = { 15156b9f3423SGuillaume Nault .sk_user_data = tunnel, 15166b9f3423SGuillaume Nault .encap_type = UDP_ENCAP_L2TPINUDP, 15176b9f3423SGuillaume Nault .encap_rcv = l2tp_udp_encap_recv, 15186b9f3423SGuillaume Nault .encap_destroy = l2tp_udp_encap_destroy, 15196b9f3423SGuillaume Nault }; 15206b9f3423SGuillaume Nault 15216b9f3423SGuillaume Nault setup_udp_tunnel_sock(net, sock, &udp_cfg); 15226b9f3423SGuillaume Nault } else { 15236b9f3423SGuillaume Nault sk->sk_user_data = tunnel; 15246b9f3423SGuillaume Nault } 15256b9f3423SGuillaume Nault 15266b9f3423SGuillaume Nault tunnel->old_sk_destruct = sk->sk_destruct; 15276b9f3423SGuillaume Nault sk->sk_destruct = &l2tp_tunnel_destruct; 15286b9f3423SGuillaume Nault lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, 15296b9f3423SGuillaume Nault "l2tp_sock"); 15306b9f3423SGuillaume Nault sk->sk_allocation = GFP_ATOMIC; 15316b9f3423SGuillaume Nault 15326b9f3423SGuillaume Nault if (tunnel->fd >= 0) 15336b9f3423SGuillaume Nault sockfd_put(sock); 15346b9f3423SGuillaume Nault 15356b9f3423SGuillaume Nault return 0; 15366b9f3423SGuillaume Nault 15376b9f3423SGuillaume Nault err_sock: 1538f6cd651bSGuillaume Nault if (tunnel->fd < 0) 1539f6cd651bSGuillaume Nault sock_release(sock); 1540f6cd651bSGuillaume Nault else 15416b9f3423SGuillaume Nault sockfd_put(sock); 15426b9f3423SGuillaume Nault err: 15436b9f3423SGuillaume Nault return ret; 15446b9f3423SGuillaume Nault } 15456b9f3423SGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_tunnel_register); 15466b9f3423SGuillaume Nault 1547309795f4SJames Chapman /* This function is used by the netlink TUNNEL_DELETE command. 1548309795f4SJames Chapman */ 154962b982eeSSabrina Dubroca void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) 1550309795f4SJames Chapman { 155162b982eeSSabrina Dubroca if (!test_and_set_bit(0, &tunnel->dead)) { 155206a15f51SAlexander Couzens l2tp_tunnel_inc_refcount(tunnel); 155362b982eeSSabrina Dubroca queue_work(l2tp_wq, &tunnel->del_work); 155406a15f51SAlexander Couzens } 1555309795f4SJames Chapman } 1556309795f4SJames Chapman EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); 1557309795f4SJames Chapman 1558fd558d18SJames Chapman /* Really kill the session. 1559fd558d18SJames Chapman */ 1560fd558d18SJames Chapman void l2tp_session_free(struct l2tp_session *session) 1561fd558d18SJames Chapman { 1562f6e16b29STom Parkin struct l2tp_tunnel *tunnel = session->tunnel; 1563fd558d18SJames Chapman 1564fbea9e07SReshetova, Elena BUG_ON(refcount_read(&session->ref_count) != 0); 1565fd558d18SJames Chapman 1566f6e16b29STom Parkin if (tunnel) { 1567fd558d18SJames Chapman BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); 1568fd558d18SJames Chapman l2tp_tunnel_dec_refcount(tunnel); 1569fd558d18SJames Chapman } 1570fd558d18SJames Chapman 1571fd558d18SJames Chapman kfree(session); 1572fd558d18SJames Chapman } 1573fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_free); 1574fd558d18SJames Chapman 1575f6e16b29STom Parkin /* Remove an l2tp session from l2tp_core's hash lists. 1576f6e16b29STom Parkin * Provides a tidyup interface for pseudowire code which can't just route all 1577f6e16b29STom Parkin * shutdown via. l2tp_session_delete and a pseudowire-specific session_close 1578f6e16b29STom Parkin * callback. 1579f6e16b29STom Parkin */ 1580f6e16b29STom Parkin void __l2tp_session_unhash(struct l2tp_session *session) 1581f6e16b29STom Parkin { 1582f6e16b29STom Parkin struct l2tp_tunnel *tunnel = session->tunnel; 1583f6e16b29STom Parkin 1584f6e16b29STom Parkin /* Remove the session from core hashes */ 1585f6e16b29STom Parkin if (tunnel) { 1586f6e16b29STom Parkin /* Remove from the per-tunnel hash */ 1587f6e16b29STom Parkin write_lock_bh(&tunnel->hlist_lock); 1588f6e16b29STom Parkin hlist_del_init(&session->hlist); 1589f6e16b29STom Parkin write_unlock_bh(&tunnel->hlist_lock); 1590f6e16b29STom Parkin 1591f6e16b29STom Parkin /* For L2TPv3 we have a per-net hash: remove from there, too */ 1592f6e16b29STom Parkin if (tunnel->version != L2TP_HDR_VER_2) { 1593f6e16b29STom Parkin struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); 1594f6e16b29STom Parkin spin_lock_bh(&pn->l2tp_session_hlist_lock); 1595f6e16b29STom Parkin hlist_del_init_rcu(&session->global_hlist); 1596f6e16b29STom Parkin spin_unlock_bh(&pn->l2tp_session_hlist_lock); 1597f6e16b29STom Parkin synchronize_rcu(); 1598f6e16b29STom Parkin } 1599f6e16b29STom Parkin } 1600f6e16b29STom Parkin } 1601f6e16b29STom Parkin EXPORT_SYMBOL_GPL(__l2tp_session_unhash); 1602f6e16b29STom Parkin 1603309795f4SJames Chapman /* This function is used by the netlink SESSION_DELETE command and by 1604309795f4SJames Chapman pseudowire modules. 1605309795f4SJames Chapman */ 1606309795f4SJames Chapman int l2tp_session_delete(struct l2tp_session *session) 1607309795f4SJames Chapman { 1608b228a940SGuillaume Nault if (test_and_set_bit(0, &session->dead)) 1609b228a940SGuillaume Nault return 0; 1610b228a940SGuillaume Nault 1611f6e16b29STom Parkin __l2tp_session_unhash(session); 16124c6e2fd3STom Parkin l2tp_session_queue_purge(session); 1613309795f4SJames Chapman if (session->session_close != NULL) 1614309795f4SJames Chapman (*session->session_close)(session); 1615a4346210SGuillaume Nault 1616309795f4SJames Chapman l2tp_session_dec_refcount(session); 1617a4346210SGuillaume Nault 1618309795f4SJames Chapman return 0; 1619309795f4SJames Chapman } 1620309795f4SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_delete); 1621309795f4SJames Chapman 1622f7faffa3SJames Chapman /* We come here whenever a session's send_seq, cookie_len or 162362e7b6a5SLorenzo Bianconi * l2specific_type parameters are set. 1624f7faffa3SJames Chapman */ 1625bb5016eaSGuillaume Nault void l2tp_session_set_header_len(struct l2tp_session *session, int version) 1626f7faffa3SJames Chapman { 1627f7faffa3SJames Chapman if (version == L2TP_HDR_VER_2) { 1628f7faffa3SJames Chapman session->hdr_len = 6; 1629f7faffa3SJames Chapman if (session->send_seq) 1630f7faffa3SJames Chapman session->hdr_len += 4; 1631f7faffa3SJames Chapman } else { 163262e7b6a5SLorenzo Bianconi session->hdr_len = 4 + session->cookie_len; 163362e7b6a5SLorenzo Bianconi session->hdr_len += l2tp_get_l2specific_len(session); 16340d76751fSJames Chapman if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP) 16350d76751fSJames Chapman session->hdr_len += 4; 1636f7faffa3SJames Chapman } 1637f7faffa3SJames Chapman 1638f7faffa3SJames Chapman } 1639bb5016eaSGuillaume Nault EXPORT_SYMBOL_GPL(l2tp_session_set_header_len); 1640f7faffa3SJames Chapman 1641fd558d18SJames Chapman struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) 1642fd558d18SJames Chapman { 1643fd558d18SJames Chapman struct l2tp_session *session; 1644fd558d18SJames Chapman 1645fd558d18SJames Chapman session = kzalloc(sizeof(struct l2tp_session) + priv_size, GFP_KERNEL); 1646fd558d18SJames Chapman if (session != NULL) { 1647fd558d18SJames Chapman session->magic = L2TP_SESSION_MAGIC; 1648fd558d18SJames Chapman session->tunnel = tunnel; 1649fd558d18SJames Chapman 1650fd558d18SJames Chapman session->session_id = session_id; 1651fd558d18SJames Chapman session->peer_session_id = peer_session_id; 1652d301e325SJames Chapman session->nr = 0; 16538a1631d5SJames Chapman if (tunnel->version == L2TP_HDR_VER_2) 16548a1631d5SJames Chapman session->nr_max = 0xffff; 16558a1631d5SJames Chapman else 16568a1631d5SJames Chapman session->nr_max = 0xffffff; 16578a1631d5SJames Chapman session->nr_window_size = session->nr_max / 2; 1658a0dbd822SJames Chapman session->nr_oos_count_max = 4; 1659a0dbd822SJames Chapman 1660a0dbd822SJames Chapman /* Use NR of first received packet */ 1661a0dbd822SJames Chapman session->reorder_skip = 1; 1662fd558d18SJames Chapman 1663fd558d18SJames Chapman sprintf(&session->name[0], "sess %u/%u", 1664fd558d18SJames Chapman tunnel->tunnel_id, session->session_id); 1665fd558d18SJames Chapman 1666fd558d18SJames Chapman skb_queue_head_init(&session->reorder_q); 1667fd558d18SJames Chapman 1668fd558d18SJames Chapman INIT_HLIST_NODE(&session->hlist); 1669f7faffa3SJames Chapman INIT_HLIST_NODE(&session->global_hlist); 1670fd558d18SJames Chapman 1671fd558d18SJames Chapman /* Inherit debug options from tunnel */ 1672fd558d18SJames Chapman session->debug = tunnel->debug; 1673fd558d18SJames Chapman 1674fd558d18SJames Chapman if (cfg) { 1675f7faffa3SJames Chapman session->pwtype = cfg->pw_type; 1676fd558d18SJames Chapman session->debug = cfg->debug; 1677fd558d18SJames Chapman session->mtu = cfg->mtu; 1678fd558d18SJames Chapman session->mru = cfg->mru; 1679fd558d18SJames Chapman session->send_seq = cfg->send_seq; 1680fd558d18SJames Chapman session->recv_seq = cfg->recv_seq; 1681fd558d18SJames Chapman session->lns_mode = cfg->lns_mode; 1682f7faffa3SJames Chapman session->reorder_timeout = cfg->reorder_timeout; 1683f7faffa3SJames Chapman session->l2specific_type = cfg->l2specific_type; 1684f7faffa3SJames Chapman session->cookie_len = cfg->cookie_len; 1685f7faffa3SJames Chapman memcpy(&session->cookie[0], &cfg->cookie[0], cfg->cookie_len); 1686f7faffa3SJames Chapman session->peer_cookie_len = cfg->peer_cookie_len; 1687f7faffa3SJames Chapman memcpy(&session->peer_cookie[0], &cfg->peer_cookie[0], cfg->peer_cookie_len); 1688fd558d18SJames Chapman } 1689fd558d18SJames Chapman 1690f7faffa3SJames Chapman if (tunnel->version == L2TP_HDR_VER_2) 1691f7faffa3SJames Chapman session->build_header = l2tp_build_l2tpv2_header; 1692f7faffa3SJames Chapman else 1693f7faffa3SJames Chapman session->build_header = l2tp_build_l2tpv3_header; 1694f7faffa3SJames Chapman 1695f7faffa3SJames Chapman l2tp_session_set_header_len(session, tunnel->version); 1696f7faffa3SJames Chapman 16979ee369a4SGuillaume Nault refcount_set(&session->ref_count, 1); 16989ee369a4SGuillaume Nault 1699fd558d18SJames Chapman return session; 1700fd558d18SJames Chapman } 1701dbdbc73bSGuillaume Nault 1702dbdbc73bSGuillaume Nault return ERR_PTR(-ENOMEM); 1703dbdbc73bSGuillaume Nault } 1704fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_create); 1705fd558d18SJames Chapman 1706fd558d18SJames Chapman /***************************************************************************** 1707fd558d18SJames Chapman * Init and cleanup 1708fd558d18SJames Chapman *****************************************************************************/ 1709fd558d18SJames Chapman 1710fd558d18SJames Chapman static __net_init int l2tp_init_net(struct net *net) 1711fd558d18SJames Chapman { 1712e773aaffSJiri Pirko struct l2tp_net *pn = net_generic(net, l2tp_net_id); 1713f7faffa3SJames Chapman int hash; 1714fd558d18SJames Chapman 1715fd558d18SJames Chapman INIT_LIST_HEAD(&pn->l2tp_tunnel_list); 1716e02d494dSJames Chapman spin_lock_init(&pn->l2tp_tunnel_list_lock); 1717fd558d18SJames Chapman 1718f7faffa3SJames Chapman for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) 1719f7faffa3SJames Chapman INIT_HLIST_HEAD(&pn->l2tp_session_hlist[hash]); 1720f7faffa3SJames Chapman 1721e02d494dSJames Chapman spin_lock_init(&pn->l2tp_session_hlist_lock); 1722f7faffa3SJames Chapman 1723fd558d18SJames Chapman return 0; 1724fd558d18SJames Chapman } 1725fd558d18SJames Chapman 1726167eb17eSTom Parkin static __net_exit void l2tp_exit_net(struct net *net) 1727167eb17eSTom Parkin { 1728167eb17eSTom Parkin struct l2tp_net *pn = l2tp_pernet(net); 1729167eb17eSTom Parkin struct l2tp_tunnel *tunnel = NULL; 17301e7af3b2SVasily Averin int hash; 1731167eb17eSTom Parkin 1732167eb17eSTom Parkin rcu_read_lock_bh(); 1733167eb17eSTom Parkin list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { 17344dc12ffeSJiri Slaby l2tp_tunnel_delete(tunnel); 1735167eb17eSTom Parkin } 1736167eb17eSTom Parkin rcu_read_unlock_bh(); 17372f86953eSSabrina Dubroca 17382f86953eSSabrina Dubroca flush_workqueue(l2tp_wq); 17392f86953eSSabrina Dubroca rcu_barrier(); 17401e7af3b2SVasily Averin 17411e7af3b2SVasily Averin for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) 17421e7af3b2SVasily Averin WARN_ON_ONCE(!hlist_empty(&pn->l2tp_session_hlist[hash])); 1743167eb17eSTom Parkin } 1744167eb17eSTom Parkin 1745fd558d18SJames Chapman static struct pernet_operations l2tp_net_ops = { 1746fd558d18SJames Chapman .init = l2tp_init_net, 1747167eb17eSTom Parkin .exit = l2tp_exit_net, 1748fd558d18SJames Chapman .id = &l2tp_net_id, 1749fd558d18SJames Chapman .size = sizeof(struct l2tp_net), 1750fd558d18SJames Chapman }; 1751fd558d18SJames Chapman 1752fd558d18SJames Chapman static int __init l2tp_init(void) 1753fd558d18SJames Chapman { 1754fd558d18SJames Chapman int rc = 0; 1755fd558d18SJames Chapman 1756fd558d18SJames Chapman rc = register_pernet_device(&l2tp_net_ops); 1757fd558d18SJames Chapman if (rc) 1758fd558d18SJames Chapman goto out; 1759fd558d18SJames Chapman 176059ff3eb6SZhangZhen l2tp_wq = alloc_workqueue("l2tp", WQ_UNBOUND, 0); 1761f8ccac0eSTom Parkin if (!l2tp_wq) { 1762f8ccac0eSTom Parkin pr_err("alloc_workqueue failed\n"); 176367e04c29SWANG Cong unregister_pernet_device(&l2tp_net_ops); 1764f8ccac0eSTom Parkin rc = -ENOMEM; 1765f8ccac0eSTom Parkin goto out; 1766f8ccac0eSTom Parkin } 1767f8ccac0eSTom Parkin 1768a4ca44faSJoe Perches pr_info("L2TP core driver, %s\n", L2TP_DRV_VERSION); 1769fd558d18SJames Chapman 1770fd558d18SJames Chapman out: 1771fd558d18SJames Chapman return rc; 1772fd558d18SJames Chapman } 1773fd558d18SJames Chapman 1774fd558d18SJames Chapman static void __exit l2tp_exit(void) 1775fd558d18SJames Chapman { 1776fd558d18SJames Chapman unregister_pernet_device(&l2tp_net_ops); 1777f8ccac0eSTom Parkin if (l2tp_wq) { 1778f8ccac0eSTom Parkin destroy_workqueue(l2tp_wq); 1779f8ccac0eSTom Parkin l2tp_wq = NULL; 1780f8ccac0eSTom Parkin } 1781fd558d18SJames Chapman } 1782fd558d18SJames Chapman 1783fd558d18SJames Chapman module_init(l2tp_init); 1784fd558d18SJames Chapman module_exit(l2tp_exit); 1785fd558d18SJames Chapman 1786fd558d18SJames Chapman MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); 1787fd558d18SJames Chapman MODULE_DESCRIPTION("L2TP core"); 1788fd558d18SJames Chapman MODULE_LICENSE("GPL"); 1789fd558d18SJames Chapman MODULE_VERSION(L2TP_DRV_VERSION); 1790