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> 55309795f4SJames Chapman #include <net/inet_common.h> 56fd558d18SJames Chapman #include <net/xfrm.h> 570d76751fSJames Chapman #include <net/protocol.h> 58d2cf3361SBenjamin LaHaise #include <net/inet6_connection_sock.h> 59d2cf3361SBenjamin LaHaise #include <net/inet_ecn.h> 60d2cf3361SBenjamin LaHaise #include <net/ip6_route.h> 61d499bd2eSDavid S. Miller #include <net/ip6_checksum.h> 62fd558d18SJames Chapman 63fd558d18SJames Chapman #include <asm/byteorder.h> 6460063497SArun Sharma #include <linux/atomic.h> 65fd558d18SJames Chapman 66fd558d18SJames Chapman #include "l2tp_core.h" 67fd558d18SJames Chapman 68fd558d18SJames Chapman #define L2TP_DRV_VERSION "V2.0" 69fd558d18SJames Chapman 70fd558d18SJames Chapman /* L2TP header constants */ 71fd558d18SJames Chapman #define L2TP_HDRFLAG_T 0x8000 72fd558d18SJames Chapman #define L2TP_HDRFLAG_L 0x4000 73fd558d18SJames Chapman #define L2TP_HDRFLAG_S 0x0800 74fd558d18SJames Chapman #define L2TP_HDRFLAG_O 0x0200 75fd558d18SJames Chapman #define L2TP_HDRFLAG_P 0x0100 76fd558d18SJames Chapman 77fd558d18SJames Chapman #define L2TP_HDR_VER_MASK 0x000F 78fd558d18SJames Chapman #define L2TP_HDR_VER_2 0x0002 79f7faffa3SJames Chapman #define L2TP_HDR_VER_3 0x0003 80fd558d18SJames Chapman 81fd558d18SJames Chapman /* L2TPv3 default L2-specific sublayer */ 82fd558d18SJames Chapman #define L2TP_SLFLAG_S 0x40000000 83fd558d18SJames Chapman #define L2TP_SL_SEQ_MASK 0x00ffffff 84fd558d18SJames Chapman 85fd558d18SJames Chapman #define L2TP_HDR_SIZE_SEQ 10 86fd558d18SJames Chapman #define L2TP_HDR_SIZE_NOSEQ 6 87fd558d18SJames Chapman 88fd558d18SJames Chapman /* Default trace flags */ 89fd558d18SJames Chapman #define L2TP_DEFAULT_DEBUG_FLAGS 0 90fd558d18SJames Chapman 91fd558d18SJames Chapman /* Private data stored for received packets in the skb. 92fd558d18SJames Chapman */ 93fd558d18SJames Chapman struct l2tp_skb_cb { 94f7faffa3SJames Chapman u32 ns; 95fd558d18SJames Chapman u16 has_seq; 96fd558d18SJames Chapman u16 length; 97fd558d18SJames Chapman unsigned long expires; 98fd558d18SJames Chapman }; 99fd558d18SJames Chapman 100fd558d18SJames Chapman #define L2TP_SKB_CB(skb) ((struct l2tp_skb_cb *) &skb->cb[sizeof(struct inet_skb_parm)]) 101fd558d18SJames Chapman 102fd558d18SJames Chapman static atomic_t l2tp_tunnel_count; 103fd558d18SJames Chapman static atomic_t l2tp_session_count; 104f8ccac0eSTom Parkin static struct workqueue_struct *l2tp_wq; 105fd558d18SJames Chapman 106fd558d18SJames Chapman /* per-net private data for this module */ 107fd558d18SJames Chapman static unsigned int l2tp_net_id; 108fd558d18SJames Chapman struct l2tp_net { 109fd558d18SJames Chapman struct list_head l2tp_tunnel_list; 110e02d494dSJames Chapman spinlock_t l2tp_tunnel_list_lock; 111f7faffa3SJames Chapman struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2]; 112e02d494dSJames Chapman spinlock_t l2tp_session_hlist_lock; 113fd558d18SJames Chapman }; 114fd558d18SJames Chapman 115fc130840Sstephen hemminger static void l2tp_session_set_header_len(struct l2tp_session *session, int version); 116fc130840Sstephen hemminger static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); 117fc130840Sstephen hemminger static void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); 118fc130840Sstephen hemminger 119fd558d18SJames Chapman static inline struct l2tp_net *l2tp_pernet(struct net *net) 120fd558d18SJames Chapman { 121fd558d18SJames Chapman BUG_ON(!net); 122fd558d18SJames Chapman 123fd558d18SJames Chapman return net_generic(net, l2tp_net_id); 124fd558d18SJames Chapman } 125fd558d18SJames Chapman 126fc130840Sstephen hemminger /* Tunnel reference counts. Incremented per session that is added to 127fc130840Sstephen hemminger * the tunnel. 128fc130840Sstephen hemminger */ 129fc130840Sstephen hemminger static inline void l2tp_tunnel_inc_refcount_1(struct l2tp_tunnel *tunnel) 130fc130840Sstephen hemminger { 131fc130840Sstephen hemminger atomic_inc(&tunnel->ref_count); 132fc130840Sstephen hemminger } 133fc130840Sstephen hemminger 134fc130840Sstephen hemminger static inline void l2tp_tunnel_dec_refcount_1(struct l2tp_tunnel *tunnel) 135fc130840Sstephen hemminger { 136fc130840Sstephen hemminger if (atomic_dec_and_test(&tunnel->ref_count)) 137fc130840Sstephen hemminger l2tp_tunnel_free(tunnel); 138fc130840Sstephen hemminger } 139fc130840Sstephen hemminger #ifdef L2TP_REFCNT_DEBUG 140a4ca44faSJoe Perches #define l2tp_tunnel_inc_refcount(_t) \ 141a4ca44faSJoe Perches do { \ 142a4ca44faSJoe Perches pr_debug("l2tp_tunnel_inc_refcount: %s:%d %s: cnt=%d\n", \ 143a4ca44faSJoe Perches __func__, __LINE__, (_t)->name, \ 144a4ca44faSJoe Perches atomic_read(&_t->ref_count)); \ 145fc130840Sstephen hemminger l2tp_tunnel_inc_refcount_1(_t); \ 146fc130840Sstephen hemminger } while (0) 147a4ca44faSJoe Perches #define l2tp_tunnel_dec_refcount(_t) 148a4ca44faSJoe Perches do { \ 149a4ca44faSJoe Perches pr_debug("l2tp_tunnel_dec_refcount: %s:%d %s: cnt=%d\n", \ 150a4ca44faSJoe Perches __func__, __LINE__, (_t)->name, \ 151a4ca44faSJoe Perches atomic_read(&_t->ref_count)); \ 152fc130840Sstephen hemminger l2tp_tunnel_dec_refcount_1(_t); \ 153fc130840Sstephen hemminger } while (0) 154fc130840Sstephen hemminger #else 155fc130840Sstephen hemminger #define l2tp_tunnel_inc_refcount(t) l2tp_tunnel_inc_refcount_1(t) 156fc130840Sstephen hemminger #define l2tp_tunnel_dec_refcount(t) l2tp_tunnel_dec_refcount_1(t) 157fc130840Sstephen hemminger #endif 158fc130840Sstephen hemminger 159f7faffa3SJames Chapman /* Session hash global list for L2TPv3. 160f7faffa3SJames Chapman * The session_id SHOULD be random according to RFC3931, but several 161f7faffa3SJames Chapman * L2TP implementations use incrementing session_ids. So we do a real 162f7faffa3SJames Chapman * hash on the session_id, rather than a simple bitmask. 163f7faffa3SJames Chapman */ 164f7faffa3SJames Chapman static inline struct hlist_head * 165f7faffa3SJames Chapman l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id) 166f7faffa3SJames Chapman { 167f7faffa3SJames Chapman return &pn->l2tp_session_hlist[hash_32(session_id, L2TP_HASH_BITS_2)]; 168f7faffa3SJames Chapman 169f7faffa3SJames Chapman } 170f7faffa3SJames Chapman 17180d84ef3STom Parkin /* Lookup the tunnel socket, possibly involving the fs code if the socket is 17280d84ef3STom Parkin * owned by userspace. A struct sock returned from this function must be 17380d84ef3STom Parkin * released using l2tp_tunnel_sock_put once you're done with it. 17480d84ef3STom Parkin */ 17580d84ef3STom Parkin struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel) 17680d84ef3STom Parkin { 17780d84ef3STom Parkin int err = 0; 17880d84ef3STom Parkin struct socket *sock = NULL; 17980d84ef3STom Parkin struct sock *sk = NULL; 18080d84ef3STom Parkin 18180d84ef3STom Parkin if (!tunnel) 18280d84ef3STom Parkin goto out; 18380d84ef3STom Parkin 18480d84ef3STom Parkin if (tunnel->fd >= 0) { 18580d84ef3STom Parkin /* Socket is owned by userspace, who might be in the process 18680d84ef3STom Parkin * of closing it. Look the socket up using the fd to ensure 18780d84ef3STom Parkin * consistency. 18880d84ef3STom Parkin */ 18980d84ef3STom Parkin sock = sockfd_lookup(tunnel->fd, &err); 19080d84ef3STom Parkin if (sock) 19180d84ef3STom Parkin sk = sock->sk; 19280d84ef3STom Parkin } else { 19380d84ef3STom Parkin /* Socket is owned by kernelspace */ 19480d84ef3STom Parkin sk = tunnel->sock; 19580d84ef3STom Parkin } 19680d84ef3STom Parkin 19780d84ef3STom Parkin out: 19880d84ef3STom Parkin return sk; 19980d84ef3STom Parkin } 20080d84ef3STom Parkin EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_lookup); 20180d84ef3STom Parkin 20280d84ef3STom Parkin /* Drop a reference to a tunnel socket obtained via. l2tp_tunnel_sock_put */ 20380d84ef3STom Parkin void l2tp_tunnel_sock_put(struct sock *sk) 20480d84ef3STom Parkin { 20580d84ef3STom Parkin struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk); 20680d84ef3STom Parkin if (tunnel) { 20780d84ef3STom Parkin if (tunnel->fd >= 0) { 20880d84ef3STom Parkin /* Socket is owned by userspace */ 20980d84ef3STom Parkin sockfd_put(sk->sk_socket); 21080d84ef3STom Parkin } 21180d84ef3STom Parkin sock_put(sk); 21280d84ef3STom Parkin } 21380d84ef3STom Parkin } 21480d84ef3STom Parkin EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_put); 21580d84ef3STom Parkin 216f7faffa3SJames Chapman /* Lookup a session by id in the global session list 217f7faffa3SJames Chapman */ 218f7faffa3SJames Chapman static struct l2tp_session *l2tp_session_find_2(struct net *net, u32 session_id) 219f7faffa3SJames Chapman { 220f7faffa3SJames Chapman struct l2tp_net *pn = l2tp_pernet(net); 221f7faffa3SJames Chapman struct hlist_head *session_list = 222f7faffa3SJames Chapman l2tp_session_id_hash_2(pn, session_id); 223f7faffa3SJames Chapman struct l2tp_session *session; 224f7faffa3SJames Chapman 225e02d494dSJames Chapman rcu_read_lock_bh(); 226b67bfe0dSSasha Levin hlist_for_each_entry_rcu(session, session_list, global_hlist) { 227f7faffa3SJames Chapman if (session->session_id == session_id) { 228e02d494dSJames Chapman rcu_read_unlock_bh(); 229f7faffa3SJames Chapman return session; 230f7faffa3SJames Chapman } 231f7faffa3SJames Chapman } 232e02d494dSJames Chapman rcu_read_unlock_bh(); 233f7faffa3SJames Chapman 234f7faffa3SJames Chapman return NULL; 235f7faffa3SJames Chapman } 236f7faffa3SJames Chapman 237fd558d18SJames Chapman /* Session hash list. 238fd558d18SJames Chapman * The session_id SHOULD be random according to RFC2661, but several 239fd558d18SJames Chapman * L2TP implementations (Cisco and Microsoft) use incrementing 240fd558d18SJames Chapman * session_ids. So we do a real hash on the session_id, rather than a 241fd558d18SJames Chapman * simple bitmask. 242fd558d18SJames Chapman */ 243fd558d18SJames Chapman static inline struct hlist_head * 244fd558d18SJames Chapman l2tp_session_id_hash(struct l2tp_tunnel *tunnel, u32 session_id) 245fd558d18SJames Chapman { 246fd558d18SJames Chapman return &tunnel->session_hlist[hash_32(session_id, L2TP_HASH_BITS)]; 247fd558d18SJames Chapman } 248fd558d18SJames Chapman 249fd558d18SJames Chapman /* Lookup a session by id 250fd558d18SJames Chapman */ 251f7faffa3SJames Chapman struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id) 252fd558d18SJames Chapman { 253f7faffa3SJames Chapman struct hlist_head *session_list; 254fd558d18SJames Chapman struct l2tp_session *session; 255fd558d18SJames Chapman 256f7faffa3SJames Chapman /* In L2TPv3, session_ids are unique over all tunnels and we 257f7faffa3SJames Chapman * sometimes need to look them up before we know the 258f7faffa3SJames Chapman * tunnel. 259f7faffa3SJames Chapman */ 260f7faffa3SJames Chapman if (tunnel == NULL) 261f7faffa3SJames Chapman return l2tp_session_find_2(net, session_id); 262f7faffa3SJames Chapman 263f7faffa3SJames Chapman session_list = l2tp_session_id_hash(tunnel, session_id); 264fd558d18SJames Chapman read_lock_bh(&tunnel->hlist_lock); 265b67bfe0dSSasha Levin hlist_for_each_entry(session, session_list, hlist) { 266fd558d18SJames Chapman if (session->session_id == session_id) { 267fd558d18SJames Chapman read_unlock_bh(&tunnel->hlist_lock); 268fd558d18SJames Chapman return session; 269fd558d18SJames Chapman } 270fd558d18SJames Chapman } 271fd558d18SJames Chapman read_unlock_bh(&tunnel->hlist_lock); 272fd558d18SJames Chapman 273fd558d18SJames Chapman return NULL; 274fd558d18SJames Chapman } 275fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_find); 276fd558d18SJames Chapman 277fd558d18SJames Chapman struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth) 278fd558d18SJames Chapman { 279fd558d18SJames Chapman int hash; 280fd558d18SJames Chapman struct l2tp_session *session; 281fd558d18SJames Chapman int count = 0; 282fd558d18SJames Chapman 283fd558d18SJames Chapman read_lock_bh(&tunnel->hlist_lock); 284fd558d18SJames Chapman for (hash = 0; hash < L2TP_HASH_SIZE; hash++) { 285b67bfe0dSSasha Levin hlist_for_each_entry(session, &tunnel->session_hlist[hash], hlist) { 286fd558d18SJames Chapman if (++count > nth) { 287fd558d18SJames Chapman read_unlock_bh(&tunnel->hlist_lock); 288fd558d18SJames Chapman return session; 289fd558d18SJames Chapman } 290fd558d18SJames Chapman } 291fd558d18SJames Chapman } 292fd558d18SJames Chapman 293fd558d18SJames Chapman read_unlock_bh(&tunnel->hlist_lock); 294fd558d18SJames Chapman 295fd558d18SJames Chapman return NULL; 296fd558d18SJames Chapman } 297fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_find_nth); 298fd558d18SJames Chapman 299309795f4SJames Chapman /* Lookup a session by interface name. 300309795f4SJames Chapman * This is very inefficient but is only used by management interfaces. 301309795f4SJames Chapman */ 302309795f4SJames Chapman struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname) 303309795f4SJames Chapman { 304309795f4SJames Chapman struct l2tp_net *pn = l2tp_pernet(net); 305309795f4SJames Chapman int hash; 306309795f4SJames Chapman struct l2tp_session *session; 307309795f4SJames Chapman 308e02d494dSJames Chapman rcu_read_lock_bh(); 309309795f4SJames Chapman for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) { 310b67bfe0dSSasha Levin hlist_for_each_entry_rcu(session, &pn->l2tp_session_hlist[hash], global_hlist) { 311309795f4SJames Chapman if (!strcmp(session->ifname, ifname)) { 312e02d494dSJames Chapman rcu_read_unlock_bh(); 313309795f4SJames Chapman return session; 314309795f4SJames Chapman } 315309795f4SJames Chapman } 316309795f4SJames Chapman } 317309795f4SJames Chapman 318e02d494dSJames Chapman rcu_read_unlock_bh(); 319309795f4SJames Chapman 320309795f4SJames Chapman return NULL; 321309795f4SJames Chapman } 322309795f4SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_find_by_ifname); 323309795f4SJames Chapman 324fd558d18SJames Chapman /* Lookup a tunnel by id 325fd558d18SJames Chapman */ 326fd558d18SJames Chapman struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id) 327fd558d18SJames Chapman { 328fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 329fd558d18SJames Chapman struct l2tp_net *pn = l2tp_pernet(net); 330fd558d18SJames Chapman 331e02d494dSJames Chapman rcu_read_lock_bh(); 332e02d494dSJames Chapman list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { 333fd558d18SJames Chapman if (tunnel->tunnel_id == tunnel_id) { 334e02d494dSJames Chapman rcu_read_unlock_bh(); 335fd558d18SJames Chapman return tunnel; 336fd558d18SJames Chapman } 337fd558d18SJames Chapman } 338e02d494dSJames Chapman rcu_read_unlock_bh(); 339fd558d18SJames Chapman 340fd558d18SJames Chapman return NULL; 341fd558d18SJames Chapman } 342fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_tunnel_find); 343fd558d18SJames Chapman 344fd558d18SJames Chapman struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth) 345fd558d18SJames Chapman { 346fd558d18SJames Chapman struct l2tp_net *pn = l2tp_pernet(net); 347fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 348fd558d18SJames Chapman int count = 0; 349fd558d18SJames Chapman 350e02d494dSJames Chapman rcu_read_lock_bh(); 351e02d494dSJames Chapman list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { 352fd558d18SJames Chapman if (++count > nth) { 353e02d494dSJames Chapman rcu_read_unlock_bh(); 354fd558d18SJames Chapman return tunnel; 355fd558d18SJames Chapman } 356fd558d18SJames Chapman } 357fd558d18SJames Chapman 358e02d494dSJames Chapman rcu_read_unlock_bh(); 359fd558d18SJames Chapman 360fd558d18SJames Chapman return NULL; 361fd558d18SJames Chapman } 362fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_tunnel_find_nth); 363fd558d18SJames Chapman 364fd558d18SJames Chapman /***************************************************************************** 365fd558d18SJames Chapman * Receive data handling 366fd558d18SJames Chapman *****************************************************************************/ 367fd558d18SJames Chapman 368fd558d18SJames Chapman /* Queue a skb in order. We come here only if the skb has an L2TP sequence 369fd558d18SJames Chapman * number. 370fd558d18SJames Chapman */ 371fd558d18SJames Chapman static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *skb) 372fd558d18SJames Chapman { 373fd558d18SJames Chapman struct sk_buff *skbp; 374fd558d18SJames Chapman struct sk_buff *tmp; 375f7faffa3SJames Chapman u32 ns = L2TP_SKB_CB(skb)->ns; 3765de7aee5SJames Chapman struct l2tp_stats *sstats; 377fd558d18SJames Chapman 378fd558d18SJames Chapman spin_lock_bh(&session->reorder_q.lock); 3795de7aee5SJames Chapman sstats = &session->stats; 380fd558d18SJames Chapman skb_queue_walk_safe(&session->reorder_q, skbp, tmp) { 381fd558d18SJames Chapman if (L2TP_SKB_CB(skbp)->ns > ns) { 382fd558d18SJames Chapman __skb_queue_before(&session->reorder_q, skbp, skb); 383a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 384fd558d18SJames Chapman "%s: pkt %hu, inserted before %hu, reorder_q len=%d\n", 385fd558d18SJames Chapman session->name, ns, L2TP_SKB_CB(skbp)->ns, 386fd558d18SJames Chapman skb_queue_len(&session->reorder_q)); 3875de7aee5SJames Chapman u64_stats_update_begin(&sstats->syncp); 3885de7aee5SJames Chapman sstats->rx_oos_packets++; 3895de7aee5SJames Chapman u64_stats_update_end(&sstats->syncp); 390fd558d18SJames Chapman goto out; 391fd558d18SJames Chapman } 392fd558d18SJames Chapman } 393fd558d18SJames Chapman 394fd558d18SJames Chapman __skb_queue_tail(&session->reorder_q, skb); 395fd558d18SJames Chapman 396fd558d18SJames Chapman out: 397fd558d18SJames Chapman spin_unlock_bh(&session->reorder_q.lock); 398fd558d18SJames Chapman } 399fd558d18SJames Chapman 400fd558d18SJames Chapman /* Dequeue a single skb. 401fd558d18SJames Chapman */ 402fd558d18SJames Chapman static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff *skb) 403fd558d18SJames Chapman { 404fd558d18SJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 405fd558d18SJames Chapman int length = L2TP_SKB_CB(skb)->length; 4065de7aee5SJames Chapman struct l2tp_stats *tstats, *sstats; 407fd558d18SJames Chapman 408fd558d18SJames Chapman /* We're about to requeue the skb, so return resources 409fd558d18SJames Chapman * to its current owner (a socket receive buffer). 410fd558d18SJames Chapman */ 411fd558d18SJames Chapman skb_orphan(skb); 412fd558d18SJames Chapman 4135de7aee5SJames Chapman tstats = &tunnel->stats; 4145de7aee5SJames Chapman u64_stats_update_begin(&tstats->syncp); 4155de7aee5SJames Chapman sstats = &session->stats; 4165de7aee5SJames Chapman u64_stats_update_begin(&sstats->syncp); 4175de7aee5SJames Chapman tstats->rx_packets++; 4185de7aee5SJames Chapman tstats->rx_bytes += length; 4195de7aee5SJames Chapman sstats->rx_packets++; 4205de7aee5SJames Chapman sstats->rx_bytes += length; 4215de7aee5SJames Chapman u64_stats_update_end(&tstats->syncp); 4225de7aee5SJames Chapman u64_stats_update_end(&sstats->syncp); 423fd558d18SJames Chapman 424fd558d18SJames Chapman if (L2TP_SKB_CB(skb)->has_seq) { 425fd558d18SJames Chapman /* Bump our Nr */ 426fd558d18SJames Chapman session->nr++; 427f7faffa3SJames Chapman if (tunnel->version == L2TP_HDR_VER_2) 428f7faffa3SJames Chapman session->nr &= 0xffff; 429f7faffa3SJames Chapman else 430f7faffa3SJames Chapman session->nr &= 0xffffff; 431f7faffa3SJames Chapman 432a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, "%s: updated nr to %hu\n", 433a4ca44faSJoe Perches session->name, session->nr); 434fd558d18SJames Chapman } 435fd558d18SJames Chapman 436fd558d18SJames Chapman /* call private receive handler */ 437fd558d18SJames Chapman if (session->recv_skb != NULL) 438fd558d18SJames Chapman (*session->recv_skb)(session, skb, L2TP_SKB_CB(skb)->length); 439fd558d18SJames Chapman else 440fd558d18SJames Chapman kfree_skb(skb); 441fd558d18SJames Chapman 442fd558d18SJames Chapman if (session->deref) 443fd558d18SJames Chapman (*session->deref)(session); 444fd558d18SJames Chapman } 445fd558d18SJames Chapman 446fd558d18SJames Chapman /* Dequeue skbs from the session's reorder_q, subject to packet order. 447fd558d18SJames Chapman * Skbs that have been in the queue for too long are simply discarded. 448fd558d18SJames Chapman */ 449fd558d18SJames Chapman static void l2tp_recv_dequeue(struct l2tp_session *session) 450fd558d18SJames Chapman { 451fd558d18SJames Chapman struct sk_buff *skb; 452fd558d18SJames Chapman struct sk_buff *tmp; 4535de7aee5SJames Chapman struct l2tp_stats *sstats; 454fd558d18SJames Chapman 455fd558d18SJames Chapman /* If the pkt at the head of the queue has the nr that we 456fd558d18SJames Chapman * expect to send up next, dequeue it and any other 457fd558d18SJames Chapman * in-sequence packets behind it. 458fd558d18SJames Chapman */ 459e2e210c0SEric Dumazet start: 460fd558d18SJames Chapman spin_lock_bh(&session->reorder_q.lock); 4615de7aee5SJames Chapman sstats = &session->stats; 462fd558d18SJames Chapman skb_queue_walk_safe(&session->reorder_q, skb, tmp) { 463fd558d18SJames Chapman if (time_after(jiffies, L2TP_SKB_CB(skb)->expires)) { 4645de7aee5SJames Chapman u64_stats_update_begin(&sstats->syncp); 4655de7aee5SJames Chapman sstats->rx_seq_discards++; 4665de7aee5SJames Chapman sstats->rx_errors++; 4675de7aee5SJames Chapman u64_stats_update_end(&sstats->syncp); 468a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 469a4ca44faSJoe Perches "%s: oos pkt %u len %d discarded (too old), waiting for %u, reorder_q_len=%d\n", 470fd558d18SJames Chapman session->name, L2TP_SKB_CB(skb)->ns, 471fd558d18SJames Chapman L2TP_SKB_CB(skb)->length, session->nr, 472fd558d18SJames Chapman skb_queue_len(&session->reorder_q)); 47338d40b3fSJames Chapman session->reorder_skip = 1; 474fd558d18SJames Chapman __skb_unlink(skb, &session->reorder_q); 475fd558d18SJames Chapman kfree_skb(skb); 476fd558d18SJames Chapman if (session->deref) 477fd558d18SJames Chapman (*session->deref)(session); 478fd558d18SJames Chapman continue; 479fd558d18SJames Chapman } 480fd558d18SJames Chapman 481fd558d18SJames Chapman if (L2TP_SKB_CB(skb)->has_seq) { 48238d40b3fSJames Chapman if (session->reorder_skip) { 483a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 48438d40b3fSJames Chapman "%s: advancing nr to next pkt: %u -> %u", 48538d40b3fSJames Chapman session->name, session->nr, 48638d40b3fSJames Chapman L2TP_SKB_CB(skb)->ns); 48738d40b3fSJames Chapman session->reorder_skip = 0; 48838d40b3fSJames Chapman session->nr = L2TP_SKB_CB(skb)->ns; 48938d40b3fSJames Chapman } 490fd558d18SJames Chapman if (L2TP_SKB_CB(skb)->ns != session->nr) { 491a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 492a4ca44faSJoe Perches "%s: holding oos pkt %u len %d, waiting for %u, reorder_q_len=%d\n", 493fd558d18SJames Chapman session->name, L2TP_SKB_CB(skb)->ns, 494fd558d18SJames Chapman L2TP_SKB_CB(skb)->length, session->nr, 495fd558d18SJames Chapman skb_queue_len(&session->reorder_q)); 496fd558d18SJames Chapman goto out; 497fd558d18SJames Chapman } 498fd558d18SJames Chapman } 499fd558d18SJames Chapman __skb_unlink(skb, &session->reorder_q); 500fd558d18SJames Chapman 501fd558d18SJames Chapman /* Process the skb. We release the queue lock while we 502fd558d18SJames Chapman * do so to let other contexts process the queue. 503fd558d18SJames Chapman */ 504fd558d18SJames Chapman spin_unlock_bh(&session->reorder_q.lock); 505fd558d18SJames Chapman l2tp_recv_dequeue_skb(session, skb); 506e2e210c0SEric Dumazet goto start; 507fd558d18SJames Chapman } 508fd558d18SJames Chapman 509fd558d18SJames Chapman out: 510fd558d18SJames Chapman spin_unlock_bh(&session->reorder_q.lock); 511fd558d18SJames Chapman } 512fd558d18SJames Chapman 513fd558d18SJames Chapman static inline int l2tp_verify_udp_checksum(struct sock *sk, 514fd558d18SJames Chapman struct sk_buff *skb) 515fd558d18SJames Chapman { 516fd558d18SJames Chapman struct udphdr *uh = udp_hdr(skb); 517fd558d18SJames Chapman u16 ulen = ntohs(uh->len); 518fd558d18SJames Chapman __wsum psum; 519fd558d18SJames Chapman 520d2cf3361SBenjamin LaHaise if (sk->sk_no_check || skb_csum_unnecessary(skb)) 521fd558d18SJames Chapman return 0; 522fd558d18SJames Chapman 523d2cf3361SBenjamin LaHaise #if IS_ENABLED(CONFIG_IPV6) 524d2cf3361SBenjamin LaHaise if (sk->sk_family == PF_INET6) { 525d2cf3361SBenjamin LaHaise if (!uh->check) { 526d2cf3361SBenjamin LaHaise LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n"); 527d2cf3361SBenjamin LaHaise return 1; 528d2cf3361SBenjamin LaHaise } 529d2cf3361SBenjamin LaHaise if ((skb->ip_summed == CHECKSUM_COMPLETE) && 530d2cf3361SBenjamin LaHaise !csum_ipv6_magic(&ipv6_hdr(skb)->saddr, 531d2cf3361SBenjamin LaHaise &ipv6_hdr(skb)->daddr, ulen, 532d2cf3361SBenjamin LaHaise IPPROTO_UDP, skb->csum)) { 533d2cf3361SBenjamin LaHaise skb->ip_summed = CHECKSUM_UNNECESSARY; 534d2cf3361SBenjamin LaHaise return 0; 535d2cf3361SBenjamin LaHaise } 536d2cf3361SBenjamin LaHaise skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr, 537d2cf3361SBenjamin LaHaise &ipv6_hdr(skb)->daddr, 538d2cf3361SBenjamin LaHaise skb->len, IPPROTO_UDP, 539d2cf3361SBenjamin LaHaise 0)); 540d2cf3361SBenjamin LaHaise } else 541d2cf3361SBenjamin LaHaise #endif 542d2cf3361SBenjamin LaHaise { 543d2cf3361SBenjamin LaHaise struct inet_sock *inet; 544d2cf3361SBenjamin LaHaise if (!uh->check) 545d2cf3361SBenjamin LaHaise return 0; 546fd558d18SJames Chapman inet = inet_sk(sk); 547d2cf3361SBenjamin LaHaise psum = csum_tcpudp_nofold(inet->inet_saddr, inet->inet_daddr, 548d2cf3361SBenjamin LaHaise ulen, IPPROTO_UDP, 0); 549fd558d18SJames Chapman 550fd558d18SJames Chapman if ((skb->ip_summed == CHECKSUM_COMPLETE) && 551fd558d18SJames Chapman !csum_fold(csum_add(psum, skb->csum))) 552fd558d18SJames Chapman return 0; 553fd558d18SJames Chapman skb->csum = psum; 554d2cf3361SBenjamin LaHaise } 555fd558d18SJames Chapman 556fd558d18SJames Chapman return __skb_checksum_complete(skb); 557fd558d18SJames Chapman } 558fd558d18SJames Chapman 559f7faffa3SJames Chapman /* Do receive processing of L2TP data frames. We handle both L2TPv2 560f7faffa3SJames Chapman * and L2TPv3 data frames here. 561f7faffa3SJames Chapman * 562f7faffa3SJames Chapman * L2TPv2 Data Message Header 563f7faffa3SJames Chapman * 564f7faffa3SJames Chapman * 0 1 2 3 565f7faffa3SJames 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 566f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 567f7faffa3SJames Chapman * |T|L|x|x|S|x|O|P|x|x|x|x| Ver | Length (opt) | 568f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 569f7faffa3SJames Chapman * | Tunnel ID | Session ID | 570f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 571f7faffa3SJames Chapman * | Ns (opt) | Nr (opt) | 572f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 573f7faffa3SJames Chapman * | Offset Size (opt) | Offset pad... (opt) 574f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 575f7faffa3SJames Chapman * 576f7faffa3SJames Chapman * Data frames are marked by T=0. All other fields are the same as 577f7faffa3SJames Chapman * those in L2TP control frames. 578f7faffa3SJames Chapman * 579f7faffa3SJames Chapman * L2TPv3 Data Message Header 580f7faffa3SJames Chapman * 581f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 582f7faffa3SJames Chapman * | L2TP Session Header | 583f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 584f7faffa3SJames Chapman * | L2-Specific Sublayer | 585f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 586f7faffa3SJames Chapman * | Tunnel Payload ... 587f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 588f7faffa3SJames Chapman * 589f7faffa3SJames Chapman * L2TPv3 Session Header Over IP 590f7faffa3SJames Chapman * 591f7faffa3SJames Chapman * 0 1 2 3 592f7faffa3SJames 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 593f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 594f7faffa3SJames Chapman * | Session ID | 595f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 596f7faffa3SJames Chapman * | Cookie (optional, maximum 64 bits)... 597f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 598f7faffa3SJames Chapman * | 599f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 600f7faffa3SJames Chapman * 601f7faffa3SJames Chapman * L2TPv3 L2-Specific Sublayer Format 602f7faffa3SJames Chapman * 603f7faffa3SJames Chapman * 0 1 2 3 604f7faffa3SJames 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 605f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 606f7faffa3SJames Chapman * |x|S|x|x|x|x|x|x| Sequence Number | 607f7faffa3SJames Chapman * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 608f7faffa3SJames Chapman * 609f7faffa3SJames Chapman * Cookie value, sublayer format and offset (pad) are negotiated with 610f7faffa3SJames Chapman * the peer when the session is set up. Unlike L2TPv2, we do not need 611f7faffa3SJames Chapman * to parse the packet header to determine if optional fields are 612f7faffa3SJames Chapman * present. 613f7faffa3SJames Chapman * 614f7faffa3SJames Chapman * Caller must already have parsed the frame and determined that it is 615f7faffa3SJames Chapman * a data (not control) frame before coming here. Fields up to the 616f7faffa3SJames Chapman * session-id have already been parsed and ptr points to the data 617f7faffa3SJames Chapman * after the session-id. 618f7faffa3SJames Chapman */ 619f7faffa3SJames Chapman void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, 620f7faffa3SJames Chapman unsigned char *ptr, unsigned char *optr, u16 hdrflags, 621f7faffa3SJames Chapman int length, int (*payload_hook)(struct sk_buff *skb)) 622f7faffa3SJames Chapman { 623f7faffa3SJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 624f7faffa3SJames Chapman int offset; 625f7faffa3SJames Chapman u32 ns, nr; 6265de7aee5SJames Chapman struct l2tp_stats *sstats = &session->stats; 627f7faffa3SJames Chapman 628f7faffa3SJames Chapman /* The ref count is increased since we now hold a pointer to 629f7faffa3SJames Chapman * the session. Take care to decrement the refcnt when exiting 630f7faffa3SJames Chapman * this function from now on... 631f7faffa3SJames Chapman */ 632f7faffa3SJames Chapman l2tp_session_inc_refcount(session); 633f7faffa3SJames Chapman if (session->ref) 634f7faffa3SJames Chapman (*session->ref)(session); 635f7faffa3SJames Chapman 636f7faffa3SJames Chapman /* Parse and check optional cookie */ 637f7faffa3SJames Chapman if (session->peer_cookie_len > 0) { 638f7faffa3SJames Chapman if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) { 639a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_DATA, 640f7faffa3SJames Chapman "%s: cookie mismatch (%u/%u). Discarding.\n", 641a4ca44faSJoe Perches tunnel->name, tunnel->tunnel_id, 642a4ca44faSJoe Perches session->session_id); 6435de7aee5SJames Chapman u64_stats_update_begin(&sstats->syncp); 6445de7aee5SJames Chapman sstats->rx_cookie_discards++; 6455de7aee5SJames Chapman u64_stats_update_end(&sstats->syncp); 646f7faffa3SJames Chapman goto discard; 647f7faffa3SJames Chapman } 648f7faffa3SJames Chapman ptr += session->peer_cookie_len; 649f7faffa3SJames Chapman } 650f7faffa3SJames Chapman 651f7faffa3SJames Chapman /* Handle the optional sequence numbers. Sequence numbers are 652f7faffa3SJames Chapman * in different places for L2TPv2 and L2TPv3. 653f7faffa3SJames Chapman * 654f7faffa3SJames Chapman * If we are the LAC, enable/disable sequence numbers under 655f7faffa3SJames Chapman * the control of the LNS. If no sequence numbers present but 656f7faffa3SJames Chapman * we were expecting them, discard frame. 657f7faffa3SJames Chapman */ 658f7faffa3SJames Chapman ns = nr = 0; 659f7faffa3SJames Chapman L2TP_SKB_CB(skb)->has_seq = 0; 660f7faffa3SJames Chapman if (tunnel->version == L2TP_HDR_VER_2) { 661f7faffa3SJames Chapman if (hdrflags & L2TP_HDRFLAG_S) { 662f7faffa3SJames Chapman ns = ntohs(*(__be16 *) ptr); 663f7faffa3SJames Chapman ptr += 2; 664f7faffa3SJames Chapman nr = ntohs(*(__be16 *) ptr); 665f7faffa3SJames Chapman ptr += 2; 666f7faffa3SJames Chapman 667f7faffa3SJames Chapman /* Store L2TP info in the skb */ 668f7faffa3SJames Chapman L2TP_SKB_CB(skb)->ns = ns; 669f7faffa3SJames Chapman L2TP_SKB_CB(skb)->has_seq = 1; 670f7faffa3SJames Chapman 671a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 672f7faffa3SJames Chapman "%s: recv data ns=%u, nr=%u, session nr=%u\n", 673f7faffa3SJames Chapman session->name, ns, nr, session->nr); 674f7faffa3SJames Chapman } 675f7faffa3SJames Chapman } else if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) { 676f7faffa3SJames Chapman u32 l2h = ntohl(*(__be32 *) ptr); 677f7faffa3SJames Chapman 678f7faffa3SJames Chapman if (l2h & 0x40000000) { 679f7faffa3SJames Chapman ns = l2h & 0x00ffffff; 680f7faffa3SJames Chapman 681f7faffa3SJames Chapman /* Store L2TP info in the skb */ 682f7faffa3SJames Chapman L2TP_SKB_CB(skb)->ns = ns; 683f7faffa3SJames Chapman L2TP_SKB_CB(skb)->has_seq = 1; 684f7faffa3SJames Chapman 685a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 686f7faffa3SJames Chapman "%s: recv data ns=%u, session nr=%u\n", 687f7faffa3SJames Chapman session->name, ns, session->nr); 688f7faffa3SJames Chapman } 689f7faffa3SJames Chapman } 690f7faffa3SJames Chapman 691f7faffa3SJames Chapman /* Advance past L2-specific header, if present */ 692f7faffa3SJames Chapman ptr += session->l2specific_len; 693f7faffa3SJames Chapman 694f7faffa3SJames Chapman if (L2TP_SKB_CB(skb)->has_seq) { 695f7faffa3SJames Chapman /* Received a packet with sequence numbers. If we're the LNS, 696f7faffa3SJames Chapman * check if we sre sending sequence numbers and if not, 697f7faffa3SJames Chapman * configure it so. 698f7faffa3SJames Chapman */ 699f7faffa3SJames Chapman if ((!session->lns_mode) && (!session->send_seq)) { 700a4ca44faSJoe Perches l2tp_info(session, L2TP_MSG_SEQ, 701f7faffa3SJames Chapman "%s: requested to enable seq numbers by LNS\n", 702f7faffa3SJames Chapman session->name); 703f7faffa3SJames Chapman session->send_seq = -1; 704f7faffa3SJames Chapman l2tp_session_set_header_len(session, tunnel->version); 705f7faffa3SJames Chapman } 706f7faffa3SJames Chapman } else { 707f7faffa3SJames Chapman /* No sequence numbers. 708f7faffa3SJames Chapman * If user has configured mandatory sequence numbers, discard. 709f7faffa3SJames Chapman */ 710f7faffa3SJames Chapman if (session->recv_seq) { 711a4ca44faSJoe Perches l2tp_warn(session, L2TP_MSG_SEQ, 712a4ca44faSJoe Perches "%s: recv data has no seq numbers when required. Discarding.\n", 713a4ca44faSJoe Perches session->name); 7145de7aee5SJames Chapman u64_stats_update_begin(&sstats->syncp); 7155de7aee5SJames Chapman sstats->rx_seq_discards++; 7165de7aee5SJames Chapman u64_stats_update_end(&sstats->syncp); 717f7faffa3SJames Chapman goto discard; 718f7faffa3SJames Chapman } 719f7faffa3SJames Chapman 720f7faffa3SJames Chapman /* If we're the LAC and we're sending sequence numbers, the 721f7faffa3SJames Chapman * LNS has requested that we no longer send sequence numbers. 722f7faffa3SJames Chapman * If we're the LNS and we're sending sequence numbers, the 723f7faffa3SJames Chapman * LAC is broken. Discard the frame. 724f7faffa3SJames Chapman */ 725f7faffa3SJames Chapman if ((!session->lns_mode) && (session->send_seq)) { 726a4ca44faSJoe Perches l2tp_info(session, L2TP_MSG_SEQ, 727f7faffa3SJames Chapman "%s: requested to disable seq numbers by LNS\n", 728f7faffa3SJames Chapman session->name); 729f7faffa3SJames Chapman session->send_seq = 0; 730f7faffa3SJames Chapman l2tp_session_set_header_len(session, tunnel->version); 731f7faffa3SJames Chapman } else if (session->send_seq) { 732a4ca44faSJoe Perches l2tp_warn(session, L2TP_MSG_SEQ, 733a4ca44faSJoe Perches "%s: recv data has no seq numbers when required. Discarding.\n", 734a4ca44faSJoe Perches session->name); 7355de7aee5SJames Chapman u64_stats_update_begin(&sstats->syncp); 7365de7aee5SJames Chapman sstats->rx_seq_discards++; 7375de7aee5SJames Chapman u64_stats_update_end(&sstats->syncp); 738f7faffa3SJames Chapman goto discard; 739f7faffa3SJames Chapman } 740f7faffa3SJames Chapman } 741f7faffa3SJames Chapman 742f7faffa3SJames Chapman /* Session data offset is handled differently for L2TPv2 and 743f7faffa3SJames Chapman * L2TPv3. For L2TPv2, there is an optional 16-bit value in 744f7faffa3SJames Chapman * the header. For L2TPv3, the offset is negotiated using AVPs 745f7faffa3SJames Chapman * in the session setup control protocol. 746f7faffa3SJames Chapman */ 747f7faffa3SJames Chapman if (tunnel->version == L2TP_HDR_VER_2) { 748f7faffa3SJames Chapman /* If offset bit set, skip it. */ 749f7faffa3SJames Chapman if (hdrflags & L2TP_HDRFLAG_O) { 750f7faffa3SJames Chapman offset = ntohs(*(__be16 *)ptr); 751f7faffa3SJames Chapman ptr += 2 + offset; 752f7faffa3SJames Chapman } 753f7faffa3SJames Chapman } else 754f7faffa3SJames Chapman ptr += session->offset; 755f7faffa3SJames Chapman 756f7faffa3SJames Chapman offset = ptr - optr; 757f7faffa3SJames Chapman if (!pskb_may_pull(skb, offset)) 758f7faffa3SJames Chapman goto discard; 759f7faffa3SJames Chapman 760f7faffa3SJames Chapman __skb_pull(skb, offset); 761f7faffa3SJames Chapman 762f7faffa3SJames Chapman /* If caller wants to process the payload before we queue the 763f7faffa3SJames Chapman * packet, do so now. 764f7faffa3SJames Chapman */ 765f7faffa3SJames Chapman if (payload_hook) 766f7faffa3SJames Chapman if ((*payload_hook)(skb)) 767f7faffa3SJames Chapman goto discard; 768f7faffa3SJames Chapman 769f7faffa3SJames Chapman /* Prepare skb for adding to the session's reorder_q. Hold 770f7faffa3SJames Chapman * packets for max reorder_timeout or 1 second if not 771f7faffa3SJames Chapman * reordering. 772f7faffa3SJames Chapman */ 773f7faffa3SJames Chapman L2TP_SKB_CB(skb)->length = length; 774f7faffa3SJames Chapman L2TP_SKB_CB(skb)->expires = jiffies + 775f7faffa3SJames Chapman (session->reorder_timeout ? session->reorder_timeout : HZ); 776f7faffa3SJames Chapman 777f7faffa3SJames Chapman /* Add packet to the session's receive queue. Reordering is done here, if 778f7faffa3SJames Chapman * enabled. Saved L2TP protocol info is stored in skb->sb[]. 779f7faffa3SJames Chapman */ 780f7faffa3SJames Chapman if (L2TP_SKB_CB(skb)->has_seq) { 781f7faffa3SJames Chapman if (session->reorder_timeout != 0) { 782f7faffa3SJames Chapman /* Packet reordering enabled. Add skb to session's 783f7faffa3SJames Chapman * reorder queue, in order of ns. 784f7faffa3SJames Chapman */ 785f7faffa3SJames Chapman l2tp_recv_queue_skb(session, skb); 786f7faffa3SJames Chapman } else { 787f7faffa3SJames Chapman /* Packet reordering disabled. Discard out-of-sequence 788f7faffa3SJames Chapman * packets 789f7faffa3SJames Chapman */ 790f7faffa3SJames Chapman if (L2TP_SKB_CB(skb)->ns != session->nr) { 7915de7aee5SJames Chapman u64_stats_update_begin(&sstats->syncp); 7925de7aee5SJames Chapman sstats->rx_seq_discards++; 7935de7aee5SJames Chapman u64_stats_update_end(&sstats->syncp); 794a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 795a4ca44faSJoe Perches "%s: oos pkt %u len %d discarded, waiting for %u, reorder_q_len=%d\n", 796f7faffa3SJames Chapman session->name, L2TP_SKB_CB(skb)->ns, 797f7faffa3SJames Chapman L2TP_SKB_CB(skb)->length, session->nr, 798f7faffa3SJames Chapman skb_queue_len(&session->reorder_q)); 799f7faffa3SJames Chapman goto discard; 800f7faffa3SJames Chapman } 801f7faffa3SJames Chapman skb_queue_tail(&session->reorder_q, skb); 802f7faffa3SJames Chapman } 803f7faffa3SJames Chapman } else { 804f7faffa3SJames Chapman /* No sequence numbers. Add the skb to the tail of the 805f7faffa3SJames Chapman * reorder queue. This ensures that it will be 806f7faffa3SJames Chapman * delivered after all previous sequenced skbs. 807f7faffa3SJames Chapman */ 808f7faffa3SJames Chapman skb_queue_tail(&session->reorder_q, skb); 809f7faffa3SJames Chapman } 810f7faffa3SJames Chapman 811f7faffa3SJames Chapman /* Try to dequeue as many skbs from reorder_q as we can. */ 812f7faffa3SJames Chapman l2tp_recv_dequeue(session); 813f7faffa3SJames Chapman 814f7faffa3SJames Chapman l2tp_session_dec_refcount(session); 815f7faffa3SJames Chapman 816f7faffa3SJames Chapman return; 817f7faffa3SJames Chapman 818f7faffa3SJames Chapman discard: 8195de7aee5SJames Chapman u64_stats_update_begin(&sstats->syncp); 8205de7aee5SJames Chapman sstats->rx_errors++; 8215de7aee5SJames Chapman u64_stats_update_end(&sstats->syncp); 822f7faffa3SJames Chapman kfree_skb(skb); 823f7faffa3SJames Chapman 824f7faffa3SJames Chapman if (session->deref) 825f7faffa3SJames Chapman (*session->deref)(session); 826f7faffa3SJames Chapman 827f7faffa3SJames Chapman l2tp_session_dec_refcount(session); 828f7faffa3SJames Chapman } 829f7faffa3SJames Chapman EXPORT_SYMBOL(l2tp_recv_common); 830f7faffa3SJames Chapman 831fd558d18SJames Chapman /* Internal UDP receive frame. Do the real work of receiving an L2TP data frame 832fd558d18SJames Chapman * here. The skb is not on a list when we get here. 833fd558d18SJames Chapman * Returns 0 if the packet was a data packet and was successfully passed on. 834fd558d18SJames Chapman * Returns 1 if the packet was not a good data packet and could not be 835fd558d18SJames Chapman * forwarded. All such packets are passed up to userspace to deal with. 836fd558d18SJames Chapman */ 837fc130840Sstephen hemminger static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, 838fd558d18SJames Chapman int (*payload_hook)(struct sk_buff *skb)) 839fd558d18SJames Chapman { 840fd558d18SJames Chapman struct l2tp_session *session = NULL; 841fd558d18SJames Chapman unsigned char *ptr, *optr; 842fd558d18SJames Chapman u16 hdrflags; 843fd558d18SJames Chapman u32 tunnel_id, session_id; 844fd558d18SJames Chapman u16 version; 845f7faffa3SJames Chapman int length; 8465de7aee5SJames Chapman struct l2tp_stats *tstats; 847fd558d18SJames Chapman 848fd558d18SJames Chapman if (tunnel->sock && l2tp_verify_udp_checksum(tunnel->sock, skb)) 849fd558d18SJames Chapman goto discard_bad_csum; 850fd558d18SJames Chapman 851fd558d18SJames Chapman /* UDP always verifies the packet length. */ 852fd558d18SJames Chapman __skb_pull(skb, sizeof(struct udphdr)); 853fd558d18SJames Chapman 854fd558d18SJames Chapman /* Short packet? */ 855fd558d18SJames Chapman if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) { 856a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_DATA, 857a4ca44faSJoe Perches "%s: recv short packet (len=%d)\n", 858a4ca44faSJoe Perches tunnel->name, skb->len); 859fd558d18SJames Chapman goto error; 860fd558d18SJames Chapman } 861fd558d18SJames Chapman 862fd558d18SJames Chapman /* Trace packet contents, if enabled */ 863fd558d18SJames Chapman if (tunnel->debug & L2TP_MSG_DATA) { 864fd558d18SJames Chapman length = min(32u, skb->len); 865fd558d18SJames Chapman if (!pskb_may_pull(skb, length)) 866fd558d18SJames Chapman goto error; 867fd558d18SJames Chapman 868a4ca44faSJoe Perches pr_debug("%s: recv\n", tunnel->name); 869a4ca44faSJoe Perches print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, skb->data, length); 870fd558d18SJames Chapman } 871fd558d18SJames Chapman 872e50e705cSEric Dumazet /* Point to L2TP header */ 873e50e705cSEric Dumazet optr = ptr = skb->data; 874e50e705cSEric Dumazet 875fd558d18SJames Chapman /* Get L2TP header flags */ 876fd558d18SJames Chapman hdrflags = ntohs(*(__be16 *) ptr); 877fd558d18SJames Chapman 878fd558d18SJames Chapman /* Check protocol version */ 879fd558d18SJames Chapman version = hdrflags & L2TP_HDR_VER_MASK; 880fd558d18SJames Chapman if (version != tunnel->version) { 881a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_DATA, 882fd558d18SJames Chapman "%s: recv protocol version mismatch: got %d expected %d\n", 883fd558d18SJames Chapman tunnel->name, version, tunnel->version); 884fd558d18SJames Chapman goto error; 885fd558d18SJames Chapman } 886fd558d18SJames Chapman 887fd558d18SJames Chapman /* Get length of L2TP packet */ 888fd558d18SJames Chapman length = skb->len; 889fd558d18SJames Chapman 890fd558d18SJames Chapman /* If type is control packet, it is handled by userspace. */ 891fd558d18SJames Chapman if (hdrflags & L2TP_HDRFLAG_T) { 892a4ca44faSJoe Perches l2tp_dbg(tunnel, L2TP_MSG_DATA, 893a4ca44faSJoe Perches "%s: recv control packet, len=%d\n", 894a4ca44faSJoe Perches tunnel->name, length); 895fd558d18SJames Chapman goto error; 896fd558d18SJames Chapman } 897fd558d18SJames Chapman 898fd558d18SJames Chapman /* Skip flags */ 899fd558d18SJames Chapman ptr += 2; 900fd558d18SJames Chapman 901f7faffa3SJames Chapman if (tunnel->version == L2TP_HDR_VER_2) { 902fd558d18SJames Chapman /* If length is present, skip it */ 903fd558d18SJames Chapman if (hdrflags & L2TP_HDRFLAG_L) 904fd558d18SJames Chapman ptr += 2; 905fd558d18SJames Chapman 906fd558d18SJames Chapman /* Extract tunnel and session ID */ 907fd558d18SJames Chapman tunnel_id = ntohs(*(__be16 *) ptr); 908fd558d18SJames Chapman ptr += 2; 909fd558d18SJames Chapman session_id = ntohs(*(__be16 *) ptr); 910fd558d18SJames Chapman ptr += 2; 911f7faffa3SJames Chapman } else { 912f7faffa3SJames Chapman ptr += 2; /* skip reserved bits */ 913f7faffa3SJames Chapman tunnel_id = tunnel->tunnel_id; 914f7faffa3SJames Chapman session_id = ntohl(*(__be32 *) ptr); 915f7faffa3SJames Chapman ptr += 4; 916f7faffa3SJames Chapman } 917fd558d18SJames Chapman 918fd558d18SJames Chapman /* Find the session context */ 919f7faffa3SJames Chapman session = l2tp_session_find(tunnel->l2tp_net, tunnel, session_id); 920309795f4SJames Chapman if (!session || !session->recv_skb) { 921fd558d18SJames Chapman /* Not found? Pass to userspace to deal with */ 922a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_DATA, 923f7faffa3SJames Chapman "%s: no session found (%u/%u). Passing up.\n", 924fd558d18SJames Chapman tunnel->name, tunnel_id, session_id); 925fd558d18SJames Chapman goto error; 926fd558d18SJames Chapman } 927fd558d18SJames Chapman 928f7faffa3SJames Chapman l2tp_recv_common(session, skb, ptr, optr, hdrflags, length, payload_hook); 929fd558d18SJames Chapman 930fd558d18SJames Chapman return 0; 931fd558d18SJames Chapman 932fd558d18SJames Chapman discard_bad_csum: 933fd558d18SJames Chapman LIMIT_NETDEBUG("%s: UDP: bad checksum\n", tunnel->name); 934fd558d18SJames Chapman UDP_INC_STATS_USER(tunnel->l2tp_net, UDP_MIB_INERRORS, 0); 9355de7aee5SJames Chapman tstats = &tunnel->stats; 9365de7aee5SJames Chapman u64_stats_update_begin(&tstats->syncp); 9375de7aee5SJames Chapman tstats->rx_errors++; 9385de7aee5SJames Chapman u64_stats_update_end(&tstats->syncp); 939fd558d18SJames Chapman kfree_skb(skb); 940fd558d18SJames Chapman 941fd558d18SJames Chapman return 0; 942fd558d18SJames Chapman 943fd558d18SJames Chapman error: 944fd558d18SJames Chapman /* Put UDP header back */ 945fd558d18SJames Chapman __skb_push(skb, sizeof(struct udphdr)); 946fd558d18SJames Chapman 947fd558d18SJames Chapman return 1; 948fd558d18SJames Chapman } 949fd558d18SJames Chapman 950fd558d18SJames Chapman /* UDP encapsulation receive handler. See net/ipv4/udp.c. 951fd558d18SJames Chapman * Return codes: 952fd558d18SJames Chapman * 0 : success. 953fd558d18SJames Chapman * <0: error 954fd558d18SJames Chapman * >0: skb should be passed up to userspace as UDP. 955fd558d18SJames Chapman */ 956fd558d18SJames Chapman int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) 957fd558d18SJames Chapman { 958fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 959fd558d18SJames Chapman 960fd558d18SJames Chapman tunnel = l2tp_sock_to_tunnel(sk); 961fd558d18SJames Chapman if (tunnel == NULL) 962fd558d18SJames Chapman goto pass_up; 963fd558d18SJames Chapman 964a4ca44faSJoe Perches l2tp_dbg(tunnel, L2TP_MSG_DATA, "%s: received %d bytes\n", 965a4ca44faSJoe Perches tunnel->name, skb->len); 966fd558d18SJames Chapman 967fd558d18SJames Chapman if (l2tp_udp_recv_core(tunnel, skb, tunnel->recv_payload_hook)) 968fd558d18SJames Chapman goto pass_up_put; 969fd558d18SJames Chapman 970fd558d18SJames Chapman sock_put(sk); 971fd558d18SJames Chapman return 0; 972fd558d18SJames Chapman 973fd558d18SJames Chapman pass_up_put: 974fd558d18SJames Chapman sock_put(sk); 975fd558d18SJames Chapman pass_up: 976fd558d18SJames Chapman return 1; 977fd558d18SJames Chapman } 978fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_udp_encap_recv); 979fd558d18SJames Chapman 980fd558d18SJames Chapman /************************************************************************ 981fd558d18SJames Chapman * Transmit handling 982fd558d18SJames Chapman ***********************************************************************/ 983fd558d18SJames Chapman 984fd558d18SJames Chapman /* Build an L2TP header for the session into the buffer provided. 985fd558d18SJames Chapman */ 986f7faffa3SJames Chapman static int l2tp_build_l2tpv2_header(struct l2tp_session *session, void *buf) 987fd558d18SJames Chapman { 988f7faffa3SJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 989fd558d18SJames Chapman __be16 *bufp = buf; 990f7faffa3SJames Chapman __be16 *optr = buf; 991fd558d18SJames Chapman u16 flags = L2TP_HDR_VER_2; 992fd558d18SJames Chapman u32 tunnel_id = tunnel->peer_tunnel_id; 993fd558d18SJames Chapman u32 session_id = session->peer_session_id; 994fd558d18SJames Chapman 995fd558d18SJames Chapman if (session->send_seq) 996fd558d18SJames Chapman flags |= L2TP_HDRFLAG_S; 997fd558d18SJames Chapman 998fd558d18SJames Chapman /* Setup L2TP header. */ 999fd558d18SJames Chapman *bufp++ = htons(flags); 1000fd558d18SJames Chapman *bufp++ = htons(tunnel_id); 1001fd558d18SJames Chapman *bufp++ = htons(session_id); 1002fd558d18SJames Chapman if (session->send_seq) { 1003fd558d18SJames Chapman *bufp++ = htons(session->ns); 1004fd558d18SJames Chapman *bufp++ = 0; 1005fd558d18SJames Chapman session->ns++; 1006f7faffa3SJames Chapman session->ns &= 0xffff; 1007a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, "%s: updated ns to %u\n", 1008a4ca44faSJoe Perches session->name, session->ns); 1009fd558d18SJames Chapman } 1010fd558d18SJames Chapman 1011f7faffa3SJames Chapman return bufp - optr; 1012f7faffa3SJames Chapman } 1013f7faffa3SJames Chapman 1014f7faffa3SJames Chapman static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf) 1015fd558d18SJames Chapman { 10160d76751fSJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 1017f7faffa3SJames Chapman char *bufp = buf; 1018f7faffa3SJames Chapman char *optr = bufp; 1019fd558d18SJames Chapman 10200d76751fSJames Chapman /* Setup L2TP header. The header differs slightly for UDP and 10210d76751fSJames Chapman * IP encapsulations. For UDP, there is 4 bytes of flags. 10220d76751fSJames Chapman */ 10230d76751fSJames Chapman if (tunnel->encap == L2TP_ENCAPTYPE_UDP) { 10240d76751fSJames Chapman u16 flags = L2TP_HDR_VER_3; 1025f7faffa3SJames Chapman *((__be16 *) bufp) = htons(flags); 1026f7faffa3SJames Chapman bufp += 2; 1027f7faffa3SJames Chapman *((__be16 *) bufp) = 0; 1028f7faffa3SJames Chapman bufp += 2; 10290d76751fSJames Chapman } 10300d76751fSJames Chapman 1031f7faffa3SJames Chapman *((__be32 *) bufp) = htonl(session->peer_session_id); 1032f7faffa3SJames Chapman bufp += 4; 1033f7faffa3SJames Chapman if (session->cookie_len) { 1034f7faffa3SJames Chapman memcpy(bufp, &session->cookie[0], session->cookie_len); 1035f7faffa3SJames Chapman bufp += session->cookie_len; 1036fd558d18SJames Chapman } 1037f7faffa3SJames Chapman if (session->l2specific_len) { 1038f7faffa3SJames Chapman if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) { 1039f7faffa3SJames Chapman u32 l2h = 0; 1040f7faffa3SJames Chapman if (session->send_seq) { 1041f7faffa3SJames Chapman l2h = 0x40000000 | session->ns; 1042f7faffa3SJames Chapman session->ns++; 1043f7faffa3SJames Chapman session->ns &= 0xffffff; 1044a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_SEQ, 1045a4ca44faSJoe Perches "%s: updated ns to %u\n", 1046a4ca44faSJoe Perches session->name, session->ns); 1047f7faffa3SJames Chapman } 1048f7faffa3SJames Chapman 1049f7faffa3SJames Chapman *((__be32 *) bufp) = htonl(l2h); 1050f7faffa3SJames Chapman } 1051f7faffa3SJames Chapman bufp += session->l2specific_len; 1052f7faffa3SJames Chapman } 1053f7faffa3SJames Chapman if (session->offset) 1054f7faffa3SJames Chapman bufp += session->offset; 1055f7faffa3SJames Chapman 1056f7faffa3SJames Chapman return bufp - optr; 1057f7faffa3SJames Chapman } 1058fd558d18SJames Chapman 1059fc130840Sstephen hemminger static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, 1060d9d8da80SDavid S. Miller struct flowi *fl, size_t data_len) 1061fd558d18SJames Chapman { 1062fd558d18SJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 1063fd558d18SJames Chapman unsigned int len = skb->len; 1064fd558d18SJames Chapman int error; 10655de7aee5SJames Chapman struct l2tp_stats *tstats, *sstats; 1066fd558d18SJames Chapman 1067fd558d18SJames Chapman /* Debug */ 1068fd558d18SJames Chapman if (session->send_seq) 1069a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_DATA, "%s: send %Zd bytes, ns=%u\n", 1070a4ca44faSJoe Perches session->name, data_len, session->ns - 1); 1071fd558d18SJames Chapman else 1072a4ca44faSJoe Perches l2tp_dbg(session, L2TP_MSG_DATA, "%s: send %Zd bytes\n", 1073a4ca44faSJoe Perches session->name, data_len); 1074fd558d18SJames Chapman 1075fd558d18SJames Chapman if (session->debug & L2TP_MSG_DATA) { 10760d76751fSJames Chapman int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0; 10770d76751fSJames Chapman unsigned char *datap = skb->data + uhlen; 1078fd558d18SJames Chapman 1079a4ca44faSJoe Perches pr_debug("%s: xmit\n", session->name); 1080a4ca44faSJoe Perches print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, 1081a4ca44faSJoe Perches datap, min_t(size_t, 32, len - uhlen)); 1082fd558d18SJames Chapman } 1083fd558d18SJames Chapman 1084fd558d18SJames Chapman /* Queue the packet to IP for output */ 10854e15ed4dSShan Wei skb->local_df = 1; 1086d2cf3361SBenjamin LaHaise #if IS_ENABLED(CONFIG_IPV6) 1087d2cf3361SBenjamin LaHaise if (skb->sk->sk_family == PF_INET6) 1088d2cf3361SBenjamin LaHaise error = inet6_csk_xmit(skb, NULL); 1089d2cf3361SBenjamin LaHaise else 1090d2cf3361SBenjamin LaHaise #endif 1091d9d8da80SDavid S. Miller error = ip_queue_xmit(skb, fl); 1092fd558d18SJames Chapman 1093fd558d18SJames Chapman /* Update stats */ 10945de7aee5SJames Chapman tstats = &tunnel->stats; 10955de7aee5SJames Chapman u64_stats_update_begin(&tstats->syncp); 10965de7aee5SJames Chapman sstats = &session->stats; 10975de7aee5SJames Chapman u64_stats_update_begin(&sstats->syncp); 1098fd558d18SJames Chapman if (error >= 0) { 10995de7aee5SJames Chapman tstats->tx_packets++; 11005de7aee5SJames Chapman tstats->tx_bytes += len; 11015de7aee5SJames Chapman sstats->tx_packets++; 11025de7aee5SJames Chapman sstats->tx_bytes += len; 1103fd558d18SJames Chapman } else { 11045de7aee5SJames Chapman tstats->tx_errors++; 11055de7aee5SJames Chapman sstats->tx_errors++; 1106fd558d18SJames Chapman } 11075de7aee5SJames Chapman u64_stats_update_end(&tstats->syncp); 11085de7aee5SJames Chapman u64_stats_update_end(&sstats->syncp); 1109fd558d18SJames Chapman 1110fd558d18SJames Chapman return 0; 1111fd558d18SJames Chapman } 1112fd558d18SJames Chapman 1113fd558d18SJames Chapman /* Automatically called when the skb is freed. 1114fd558d18SJames Chapman */ 1115fd558d18SJames Chapman static void l2tp_sock_wfree(struct sk_buff *skb) 1116fd558d18SJames Chapman { 1117fd558d18SJames Chapman sock_put(skb->sk); 1118fd558d18SJames Chapman } 1119fd558d18SJames Chapman 1120fd558d18SJames Chapman /* For data skbs that we transmit, we associate with the tunnel socket 1121fd558d18SJames Chapman * but don't do accounting. 1122fd558d18SJames Chapman */ 1123fd558d18SJames Chapman static inline void l2tp_skb_set_owner_w(struct sk_buff *skb, struct sock *sk) 1124fd558d18SJames Chapman { 1125fd558d18SJames Chapman sock_hold(sk); 1126fd558d18SJames Chapman skb->sk = sk; 1127fd558d18SJames Chapman skb->destructor = l2tp_sock_wfree; 1128fd558d18SJames Chapman } 1129fd558d18SJames Chapman 1130d2cf3361SBenjamin LaHaise #if IS_ENABLED(CONFIG_IPV6) 1131d2cf3361SBenjamin LaHaise static void l2tp_xmit_ipv6_csum(struct sock *sk, struct sk_buff *skb, 1132d2cf3361SBenjamin LaHaise int udp_len) 1133d2cf3361SBenjamin LaHaise { 1134d2cf3361SBenjamin LaHaise struct ipv6_pinfo *np = inet6_sk(sk); 1135d2cf3361SBenjamin LaHaise struct udphdr *uh = udp_hdr(skb); 1136d2cf3361SBenjamin LaHaise 1137d2cf3361SBenjamin LaHaise if (!skb_dst(skb) || !skb_dst(skb)->dev || 1138d2cf3361SBenjamin LaHaise !(skb_dst(skb)->dev->features & NETIF_F_IPV6_CSUM)) { 1139d2cf3361SBenjamin LaHaise __wsum csum = skb_checksum(skb, 0, udp_len, 0); 1140d2cf3361SBenjamin LaHaise skb->ip_summed = CHECKSUM_UNNECESSARY; 1141d2cf3361SBenjamin LaHaise uh->check = csum_ipv6_magic(&np->saddr, &np->daddr, udp_len, 1142d2cf3361SBenjamin LaHaise IPPROTO_UDP, csum); 1143d2cf3361SBenjamin LaHaise if (uh->check == 0) 1144d2cf3361SBenjamin LaHaise uh->check = CSUM_MANGLED_0; 1145d2cf3361SBenjamin LaHaise } else { 1146d2cf3361SBenjamin LaHaise skb->ip_summed = CHECKSUM_PARTIAL; 1147d2cf3361SBenjamin LaHaise skb->csum_start = skb_transport_header(skb) - skb->head; 1148d2cf3361SBenjamin LaHaise skb->csum_offset = offsetof(struct udphdr, check); 1149d2cf3361SBenjamin LaHaise uh->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, 1150d2cf3361SBenjamin LaHaise udp_len, IPPROTO_UDP, 0); 1151d2cf3361SBenjamin LaHaise } 1152d2cf3361SBenjamin LaHaise } 1153d2cf3361SBenjamin LaHaise #endif 1154d2cf3361SBenjamin LaHaise 1155fd558d18SJames Chapman /* If caller requires the skb to have a ppp header, the header must be 1156fd558d18SJames Chapman * inserted in the skb data before calling this function. 1157fd558d18SJames Chapman */ 1158fd558d18SJames Chapman int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len) 1159fd558d18SJames Chapman { 1160fd558d18SJames Chapman int data_len = skb->len; 11610d76751fSJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 11620d76751fSJames Chapman struct sock *sk = tunnel->sock; 1163d9d8da80SDavid S. Miller struct flowi *fl; 1164fd558d18SJames Chapman struct udphdr *uh; 1165fd558d18SJames Chapman struct inet_sock *inet; 1166fd558d18SJames Chapman __wsum csum; 1167fd558d18SJames Chapman int headroom; 11680d76751fSJames Chapman int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0; 11690d76751fSJames Chapman int udp_len; 1170b8c84307SEric Dumazet int ret = NET_XMIT_SUCCESS; 1171fd558d18SJames Chapman 1172fd558d18SJames Chapman /* Check that there's enough headroom in the skb to insert IP, 1173fd558d18SJames Chapman * UDP and L2TP headers. If not enough, expand it to 1174fd558d18SJames Chapman * make room. Adjust truesize. 1175fd558d18SJames Chapman */ 1176fd558d18SJames Chapman headroom = NET_SKB_PAD + sizeof(struct iphdr) + 11770d76751fSJames Chapman uhlen + hdr_len; 1178835acf5dSEric Dumazet if (skb_cow_head(skb, headroom)) { 1179b8c84307SEric Dumazet kfree_skb(skb); 1180b8c84307SEric Dumazet return NET_XMIT_DROP; 1181835acf5dSEric Dumazet } 1182fd558d18SJames Chapman 1183fd558d18SJames Chapman skb_orphan(skb); 1184fd558d18SJames Chapman /* Setup L2TP header */ 1185f7faffa3SJames Chapman session->build_header(session, __skb_push(skb, hdr_len)); 1186fd558d18SJames Chapman 11870d76751fSJames Chapman /* Reset skb netfilter state */ 1188fd558d18SJames Chapman memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 1189fd558d18SJames Chapman IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | 1190fd558d18SJames Chapman IPSKB_REROUTED); 1191fd558d18SJames Chapman nf_reset(skb); 1192fd558d18SJames Chapman 11936af88da1SDavid S. Miller bh_lock_sock(sk); 11946af88da1SDavid S. Miller if (sock_owned_by_user(sk)) { 1195b8c84307SEric Dumazet kfree_skb(skb); 1196b8c84307SEric Dumazet ret = NET_XMIT_DROP; 11976af88da1SDavid S. Miller goto out_unlock; 11986af88da1SDavid S. Miller } 11996af88da1SDavid S. Miller 1200fd558d18SJames Chapman /* Get routing info from the tunnel socket */ 1201fd558d18SJames Chapman skb_dst_drop(skb); 120271b1391aSFlorian Westphal skb_dst_set(skb, dst_clone(__sk_dst_check(sk, 0))); 12030d76751fSJames Chapman 1204d9d8da80SDavid S. Miller inet = inet_sk(sk); 1205d9d8da80SDavid S. Miller fl = &inet->cork.fl; 12060d76751fSJames Chapman switch (tunnel->encap) { 12070d76751fSJames Chapman case L2TP_ENCAPTYPE_UDP: 12080d76751fSJames Chapman /* Setup UDP header */ 12090d76751fSJames Chapman __skb_push(skb, sizeof(*uh)); 12100d76751fSJames Chapman skb_reset_transport_header(skb); 12110d76751fSJames Chapman uh = udp_hdr(skb); 12120d76751fSJames Chapman uh->source = inet->inet_sport; 12130d76751fSJames Chapman uh->dest = inet->inet_dport; 12140d76751fSJames Chapman udp_len = uhlen + hdr_len + data_len; 12150d76751fSJames Chapman uh->len = htons(udp_len); 12160d76751fSJames Chapman uh->check = 0; 1217fd558d18SJames Chapman 1218fd558d18SJames Chapman /* Calculate UDP checksum if configured to do so */ 1219d2cf3361SBenjamin LaHaise #if IS_ENABLED(CONFIG_IPV6) 1220d2cf3361SBenjamin LaHaise if (sk->sk_family == PF_INET6) 1221d2cf3361SBenjamin LaHaise l2tp_xmit_ipv6_csum(sk, skb, udp_len); 1222d2cf3361SBenjamin LaHaise else 1223d2cf3361SBenjamin LaHaise #endif 1224fd558d18SJames Chapman if (sk->sk_no_check == UDP_CSUM_NOXMIT) 1225fd558d18SJames Chapman skb->ip_summed = CHECKSUM_NONE; 1226fd558d18SJames Chapman else if ((skb_dst(skb) && skb_dst(skb)->dev) && 1227fd558d18SJames Chapman (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM))) { 1228fd558d18SJames Chapman skb->ip_summed = CHECKSUM_COMPLETE; 1229fd558d18SJames Chapman csum = skb_checksum(skb, 0, udp_len, 0); 1230fd558d18SJames Chapman uh->check = csum_tcpudp_magic(inet->inet_saddr, 1231fd558d18SJames Chapman inet->inet_daddr, 1232fd558d18SJames Chapman udp_len, IPPROTO_UDP, csum); 1233fd558d18SJames Chapman if (uh->check == 0) 1234fd558d18SJames Chapman uh->check = CSUM_MANGLED_0; 1235fd558d18SJames Chapman } else { 1236fd558d18SJames Chapman skb->ip_summed = CHECKSUM_PARTIAL; 1237fd558d18SJames Chapman skb->csum_start = skb_transport_header(skb) - skb->head; 1238fd558d18SJames Chapman skb->csum_offset = offsetof(struct udphdr, check); 1239fd558d18SJames Chapman uh->check = ~csum_tcpudp_magic(inet->inet_saddr, 1240fd558d18SJames Chapman inet->inet_daddr, 1241fd558d18SJames Chapman udp_len, IPPROTO_UDP, 0); 1242fd558d18SJames Chapman } 12430d76751fSJames Chapman break; 12440d76751fSJames Chapman 12450d76751fSJames Chapman case L2TP_ENCAPTYPE_IP: 12460d76751fSJames Chapman break; 12470d76751fSJames Chapman } 12480d76751fSJames Chapman 12490d76751fSJames Chapman l2tp_skb_set_owner_w(skb, sk); 1250fd558d18SJames Chapman 1251d9d8da80SDavid S. Miller l2tp_xmit_core(session, skb, fl, data_len); 12526af88da1SDavid S. Miller out_unlock: 12536af88da1SDavid S. Miller bh_unlock_sock(sk); 1254fd558d18SJames Chapman 1255b8c84307SEric Dumazet return ret; 1256fd558d18SJames Chapman } 1257fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_xmit_skb); 1258fd558d18SJames Chapman 1259fd558d18SJames Chapman /***************************************************************************** 1260fd558d18SJames Chapman * Tinnel and session create/destroy. 1261fd558d18SJames Chapman *****************************************************************************/ 1262fd558d18SJames Chapman 1263fd558d18SJames Chapman /* Tunnel socket destruct hook. 1264fd558d18SJames Chapman * The tunnel context is deleted only when all session sockets have been 1265fd558d18SJames Chapman * closed. 1266fd558d18SJames Chapman */ 1267fc130840Sstephen hemminger static void l2tp_tunnel_destruct(struct sock *sk) 1268fd558d18SJames Chapman { 1269fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 1270f8ccac0eSTom Parkin struct l2tp_net *pn; 1271fd558d18SJames Chapman 1272fd558d18SJames Chapman tunnel = sk->sk_user_data; 1273fd558d18SJames Chapman if (tunnel == NULL) 1274fd558d18SJames Chapman goto end; 1275fd558d18SJames Chapman 1276a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: closing...\n", tunnel->name); 1277fd558d18SJames Chapman 1278fd558d18SJames Chapman 1279f8ccac0eSTom Parkin /* Disable udp encapsulation */ 12800d76751fSJames Chapman switch (tunnel->encap) { 12810d76751fSJames Chapman case L2TP_ENCAPTYPE_UDP: 1282fd558d18SJames Chapman /* No longer an encapsulation socket. See net/ipv4/udp.c */ 1283fd558d18SJames Chapman (udp_sk(sk))->encap_type = 0; 1284fd558d18SJames Chapman (udp_sk(sk))->encap_rcv = NULL; 12859980d001STom Parkin (udp_sk(sk))->encap_destroy = NULL; 12860d76751fSJames Chapman break; 12870d76751fSJames Chapman case L2TP_ENCAPTYPE_IP: 12880d76751fSJames Chapman break; 12890d76751fSJames Chapman } 1290fd558d18SJames Chapman 1291fd558d18SJames Chapman /* Remove hooks into tunnel socket */ 1292fd558d18SJames Chapman sk->sk_destruct = tunnel->old_sk_destruct; 1293fd558d18SJames Chapman sk->sk_user_data = NULL; 1294f8ccac0eSTom Parkin tunnel->sock = NULL; 1295f8ccac0eSTom Parkin 1296f8ccac0eSTom Parkin /* Remove the tunnel struct from the tunnel list */ 1297f8ccac0eSTom Parkin pn = l2tp_pernet(tunnel->l2tp_net); 1298f8ccac0eSTom Parkin spin_lock_bh(&pn->l2tp_tunnel_list_lock); 1299f8ccac0eSTom Parkin list_del_rcu(&tunnel->list); 1300f8ccac0eSTom Parkin spin_unlock_bh(&pn->l2tp_tunnel_list_lock); 1301f8ccac0eSTom Parkin atomic_dec(&l2tp_tunnel_count); 1302f8ccac0eSTom Parkin 1303f8ccac0eSTom Parkin l2tp_tunnel_closeall(tunnel); 1304f8ccac0eSTom Parkin l2tp_tunnel_dec_refcount(tunnel); 1305fd558d18SJames Chapman 1306fd558d18SJames Chapman /* Call the original destructor */ 1307fd558d18SJames Chapman if (sk->sk_destruct) 1308fd558d18SJames Chapman (*sk->sk_destruct)(sk); 1309fd558d18SJames Chapman end: 1310fd558d18SJames Chapman return; 1311fd558d18SJames Chapman } 1312fd558d18SJames Chapman 1313fd558d18SJames Chapman /* When the tunnel is closed, all the attached sessions need to go too. 1314fd558d18SJames Chapman */ 1315fc130840Sstephen hemminger static void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel) 1316fd558d18SJames Chapman { 1317fd558d18SJames Chapman int hash; 1318fd558d18SJames Chapman struct hlist_node *walk; 1319fd558d18SJames Chapman struct hlist_node *tmp; 1320fd558d18SJames Chapman struct l2tp_session *session; 1321fd558d18SJames Chapman 1322fd558d18SJames Chapman BUG_ON(tunnel == NULL); 1323fd558d18SJames Chapman 1324a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: closing all sessions...\n", 1325a4ca44faSJoe Perches tunnel->name); 1326fd558d18SJames Chapman 1327fd558d18SJames Chapman write_lock_bh(&tunnel->hlist_lock); 1328fd558d18SJames Chapman for (hash = 0; hash < L2TP_HASH_SIZE; hash++) { 1329fd558d18SJames Chapman again: 1330fd558d18SJames Chapman hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) { 1331fd558d18SJames Chapman session = hlist_entry(walk, struct l2tp_session, hlist); 1332fd558d18SJames Chapman 1333a4ca44faSJoe Perches l2tp_info(session, L2TP_MSG_CONTROL, 1334fd558d18SJames Chapman "%s: closing session\n", session->name); 1335fd558d18SJames Chapman 1336fd558d18SJames Chapman hlist_del_init(&session->hlist); 1337fd558d18SJames Chapman 1338fd558d18SJames Chapman /* Since we should hold the sock lock while 1339fd558d18SJames Chapman * doing any unbinding, we need to release the 1340fd558d18SJames Chapman * lock we're holding before taking that lock. 1341fd558d18SJames Chapman * Hold a reference to the sock so it doesn't 1342fd558d18SJames Chapman * disappear as we're jumping between locks. 1343fd558d18SJames Chapman */ 1344fd558d18SJames Chapman if (session->ref != NULL) 1345fd558d18SJames Chapman (*session->ref)(session); 1346fd558d18SJames Chapman 1347fd558d18SJames Chapman write_unlock_bh(&tunnel->hlist_lock); 1348fd558d18SJames Chapman 1349f7faffa3SJames Chapman if (tunnel->version != L2TP_HDR_VER_2) { 1350f7faffa3SJames Chapman struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); 1351f7faffa3SJames Chapman 1352e02d494dSJames Chapman spin_lock_bh(&pn->l2tp_session_hlist_lock); 1353e02d494dSJames Chapman hlist_del_init_rcu(&session->global_hlist); 1354e02d494dSJames Chapman spin_unlock_bh(&pn->l2tp_session_hlist_lock); 1355e02d494dSJames Chapman synchronize_rcu(); 1356f7faffa3SJames Chapman } 1357f7faffa3SJames Chapman 1358fd558d18SJames Chapman if (session->session_close != NULL) 1359fd558d18SJames Chapman (*session->session_close)(session); 1360fd558d18SJames Chapman 1361fd558d18SJames Chapman if (session->deref != NULL) 1362fd558d18SJames Chapman (*session->deref)(session); 1363fd558d18SJames Chapman 13649980d001STom Parkin l2tp_session_dec_refcount(session); 13659980d001STom Parkin 1366fd558d18SJames Chapman write_lock_bh(&tunnel->hlist_lock); 1367fd558d18SJames Chapman 1368fd558d18SJames Chapman /* Now restart from the beginning of this hash 1369fd558d18SJames Chapman * chain. We always remove a session from the 1370fd558d18SJames Chapman * list so we are guaranteed to make forward 1371fd558d18SJames Chapman * progress. 1372fd558d18SJames Chapman */ 1373fd558d18SJames Chapman goto again; 1374fd558d18SJames Chapman } 1375fd558d18SJames Chapman } 1376fd558d18SJames Chapman write_unlock_bh(&tunnel->hlist_lock); 1377fd558d18SJames Chapman } 1378fd558d18SJames Chapman 13799980d001STom Parkin /* Tunnel socket destroy hook for UDP encapsulation */ 13809980d001STom Parkin static void l2tp_udp_encap_destroy(struct sock *sk) 13819980d001STom Parkin { 13829980d001STom Parkin struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk); 13839980d001STom Parkin if (tunnel) { 13849980d001STom Parkin l2tp_tunnel_closeall(tunnel); 13859980d001STom Parkin sock_put(sk); 13869980d001STom Parkin } 13879980d001STom Parkin } 13889980d001STom Parkin 1389fd558d18SJames Chapman /* Really kill the tunnel. 1390fd558d18SJames Chapman * Come here only when all sessions have been cleared from the tunnel. 1391fd558d18SJames Chapman */ 1392fc130840Sstephen hemminger static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) 1393fd558d18SJames Chapman { 1394fd558d18SJames Chapman BUG_ON(atomic_read(&tunnel->ref_count) != 0); 1395fd558d18SJames Chapman BUG_ON(tunnel->sock != NULL); 1396a4ca44faSJoe Perches l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: free...\n", tunnel->name); 139799469c32Sxeb@mail.ru kfree_rcu(tunnel, rcu); 1398f8ccac0eSTom Parkin } 1399fd558d18SJames Chapman 1400f8ccac0eSTom Parkin /* Workqueue tunnel deletion function */ 1401f8ccac0eSTom Parkin static void l2tp_tunnel_del_work(struct work_struct *work) 1402f8ccac0eSTom Parkin { 1403f8ccac0eSTom Parkin struct l2tp_tunnel *tunnel = NULL; 1404f8ccac0eSTom Parkin struct socket *sock = NULL; 1405f8ccac0eSTom Parkin struct sock *sk = NULL; 1406f8ccac0eSTom Parkin 1407f8ccac0eSTom Parkin tunnel = container_of(work, struct l2tp_tunnel, del_work); 1408f8ccac0eSTom Parkin sk = l2tp_tunnel_sock_lookup(tunnel); 1409f8ccac0eSTom Parkin if (!sk) 1410f8ccac0eSTom Parkin return; 1411f8ccac0eSTom Parkin 1412f8ccac0eSTom Parkin sock = sk->sk_socket; 1413f8ccac0eSTom Parkin BUG_ON(!sock); 1414f8ccac0eSTom Parkin 1415167eb17eSTom Parkin /* If the tunnel socket was created directly by the kernel, use the 1416167eb17eSTom Parkin * sk_* API to release the socket now. Otherwise go through the 1417167eb17eSTom Parkin * inet_* layer to shut the socket down, and let userspace close it. 1418167eb17eSTom Parkin * In either case the tunnel resources are freed in the socket 1419167eb17eSTom Parkin * destructor when the tunnel socket goes away. 1420f8ccac0eSTom Parkin */ 1421167eb17eSTom Parkin if (sock->file == NULL) { 1422167eb17eSTom Parkin kernel_sock_shutdown(sock, SHUT_RDWR); 1423167eb17eSTom Parkin sk_release_kernel(sk); 1424167eb17eSTom Parkin } else { 1425f8ccac0eSTom Parkin inet_shutdown(sock, 2); 1426167eb17eSTom Parkin } 1427f8ccac0eSTom Parkin 1428f8ccac0eSTom Parkin l2tp_tunnel_sock_put(sk); 1429fd558d18SJames Chapman } 1430fd558d18SJames Chapman 1431789a4a2cSJames Chapman /* Create a socket for the tunnel, if one isn't set up by 1432789a4a2cSJames Chapman * userspace. This is used for static tunnels where there is no 1433789a4a2cSJames Chapman * managing L2TP daemon. 1434167eb17eSTom Parkin * 1435167eb17eSTom Parkin * Since we don't want these sockets to keep a namespace alive by 1436167eb17eSTom Parkin * themselves, we drop the socket's namespace refcount after creation. 1437167eb17eSTom Parkin * These sockets are freed when the namespace exits using the pernet 1438167eb17eSTom Parkin * exit hook. 1439789a4a2cSJames Chapman */ 1440167eb17eSTom Parkin static int l2tp_tunnel_sock_create(struct net *net, 1441167eb17eSTom Parkin u32 tunnel_id, 1442167eb17eSTom Parkin u32 peer_tunnel_id, 1443167eb17eSTom Parkin struct l2tp_tunnel_cfg *cfg, 1444167eb17eSTom Parkin struct socket **sockp) 1445789a4a2cSJames Chapman { 1446789a4a2cSJames Chapman int err = -EINVAL; 14477bddd0dbSEric Dumazet struct socket *sock = NULL; 1448167eb17eSTom Parkin struct sockaddr_in udp_addr = {0}; 1449167eb17eSTom Parkin struct sockaddr_l2tpip ip_addr = {0}; 1450167eb17eSTom Parkin #if IS_ENABLED(CONFIG_IPV6) 1451167eb17eSTom Parkin struct sockaddr_in6 udp6_addr = {0}; 1452167eb17eSTom Parkin struct sockaddr_l2tpip6 ip6_addr = {0}; 1453167eb17eSTom Parkin #endif 1454789a4a2cSJames Chapman 1455789a4a2cSJames Chapman switch (cfg->encap) { 1456789a4a2cSJames Chapman case L2TP_ENCAPTYPE_UDP: 1457f9bac8dfSChris Elston #if IS_ENABLED(CONFIG_IPV6) 1458f9bac8dfSChris Elston if (cfg->local_ip6 && cfg->peer_ip6) { 1459167eb17eSTom Parkin err = sock_create_kern(AF_INET6, SOCK_DGRAM, 0, &sock); 1460f9bac8dfSChris Elston if (err < 0) 1461f9bac8dfSChris Elston goto out; 1462f9bac8dfSChris Elston 1463167eb17eSTom Parkin sk_change_net(sock->sk, net); 1464f9bac8dfSChris Elston 1465f9bac8dfSChris Elston udp6_addr.sin6_family = AF_INET6; 1466f9bac8dfSChris Elston memcpy(&udp6_addr.sin6_addr, cfg->local_ip6, 1467f9bac8dfSChris Elston sizeof(udp6_addr.sin6_addr)); 1468f9bac8dfSChris Elston udp6_addr.sin6_port = htons(cfg->local_udp_port); 1469f9bac8dfSChris Elston err = kernel_bind(sock, (struct sockaddr *) &udp6_addr, 1470f9bac8dfSChris Elston sizeof(udp6_addr)); 1471f9bac8dfSChris Elston if (err < 0) 1472f9bac8dfSChris Elston goto out; 1473f9bac8dfSChris Elston 1474f9bac8dfSChris Elston udp6_addr.sin6_family = AF_INET6; 1475f9bac8dfSChris Elston memcpy(&udp6_addr.sin6_addr, cfg->peer_ip6, 1476f9bac8dfSChris Elston sizeof(udp6_addr.sin6_addr)); 1477f9bac8dfSChris Elston udp6_addr.sin6_port = htons(cfg->peer_udp_port); 1478f9bac8dfSChris Elston err = kernel_connect(sock, 1479f9bac8dfSChris Elston (struct sockaddr *) &udp6_addr, 1480f9bac8dfSChris Elston sizeof(udp6_addr), 0); 1481f9bac8dfSChris Elston if (err < 0) 1482f9bac8dfSChris Elston goto out; 1483f9bac8dfSChris Elston } else 1484f9bac8dfSChris Elston #endif 1485f9bac8dfSChris Elston { 1486167eb17eSTom Parkin err = sock_create_kern(AF_INET, SOCK_DGRAM, 0, &sock); 1487789a4a2cSJames Chapman if (err < 0) 1488789a4a2cSJames Chapman goto out; 1489789a4a2cSJames Chapman 1490167eb17eSTom Parkin sk_change_net(sock->sk, net); 1491789a4a2cSJames Chapman 1492789a4a2cSJames Chapman udp_addr.sin_family = AF_INET; 1493789a4a2cSJames Chapman udp_addr.sin_addr = cfg->local_ip; 1494789a4a2cSJames Chapman udp_addr.sin_port = htons(cfg->local_udp_port); 1495f9bac8dfSChris Elston err = kernel_bind(sock, (struct sockaddr *) &udp_addr, 1496f9bac8dfSChris Elston sizeof(udp_addr)); 1497789a4a2cSJames Chapman if (err < 0) 1498789a4a2cSJames Chapman goto out; 1499789a4a2cSJames Chapman 1500789a4a2cSJames Chapman udp_addr.sin_family = AF_INET; 1501789a4a2cSJames Chapman udp_addr.sin_addr = cfg->peer_ip; 1502789a4a2cSJames Chapman udp_addr.sin_port = htons(cfg->peer_udp_port); 1503f9bac8dfSChris Elston err = kernel_connect(sock, 1504f9bac8dfSChris Elston (struct sockaddr *) &udp_addr, 1505f9bac8dfSChris Elston sizeof(udp_addr), 0); 1506789a4a2cSJames Chapman if (err < 0) 1507789a4a2cSJames Chapman goto out; 1508f9bac8dfSChris Elston } 1509789a4a2cSJames Chapman 1510789a4a2cSJames Chapman if (!cfg->use_udp_checksums) 1511789a4a2cSJames Chapman sock->sk->sk_no_check = UDP_CSUM_NOXMIT; 1512789a4a2cSJames Chapman 1513789a4a2cSJames Chapman break; 1514789a4a2cSJames Chapman 1515789a4a2cSJames Chapman case L2TP_ENCAPTYPE_IP: 1516f9bac8dfSChris Elston #if IS_ENABLED(CONFIG_IPV6) 1517f9bac8dfSChris Elston if (cfg->local_ip6 && cfg->peer_ip6) { 1518167eb17eSTom Parkin err = sock_create_kern(AF_INET6, SOCK_DGRAM, 1519167eb17eSTom Parkin IPPROTO_L2TP, &sock); 15205dac94e1SJames Chapman if (err < 0) 1521f9bac8dfSChris Elston goto out; 15225dac94e1SJames Chapman 1523167eb17eSTom Parkin sk_change_net(sock->sk, net); 15245dac94e1SJames Chapman 15255dac94e1SJames Chapman ip6_addr.l2tp_family = AF_INET6; 15265dac94e1SJames Chapman memcpy(&ip6_addr.l2tp_addr, cfg->local_ip6, 15275dac94e1SJames Chapman sizeof(ip6_addr.l2tp_addr)); 15285dac94e1SJames Chapman ip6_addr.l2tp_conn_id = tunnel_id; 15295dac94e1SJames Chapman err = kernel_bind(sock, (struct sockaddr *) &ip6_addr, 15305dac94e1SJames Chapman sizeof(ip6_addr)); 15315dac94e1SJames Chapman if (err < 0) 15325dac94e1SJames Chapman goto out; 15335dac94e1SJames Chapman 15345dac94e1SJames Chapman ip6_addr.l2tp_family = AF_INET6; 15355dac94e1SJames Chapman memcpy(&ip6_addr.l2tp_addr, cfg->peer_ip6, 15365dac94e1SJames Chapman sizeof(ip6_addr.l2tp_addr)); 15375dac94e1SJames Chapman ip6_addr.l2tp_conn_id = peer_tunnel_id; 15385dac94e1SJames Chapman err = kernel_connect(sock, 15395dac94e1SJames Chapman (struct sockaddr *) &ip6_addr, 15405dac94e1SJames Chapman sizeof(ip6_addr), 0); 15415dac94e1SJames Chapman if (err < 0) 15425dac94e1SJames Chapman goto out; 15435dac94e1SJames Chapman } else 1544f9bac8dfSChris Elston #endif 15455dac94e1SJames Chapman { 1546167eb17eSTom Parkin err = sock_create_kern(AF_INET, SOCK_DGRAM, 1547167eb17eSTom Parkin IPPROTO_L2TP, &sock); 1548789a4a2cSJames Chapman if (err < 0) 1549789a4a2cSJames Chapman goto out; 1550789a4a2cSJames Chapman 1551167eb17eSTom Parkin sk_change_net(sock->sk, net); 1552789a4a2cSJames Chapman 1553789a4a2cSJames Chapman ip_addr.l2tp_family = AF_INET; 1554789a4a2cSJames Chapman ip_addr.l2tp_addr = cfg->local_ip; 1555789a4a2cSJames Chapman ip_addr.l2tp_conn_id = tunnel_id; 15565dac94e1SJames Chapman err = kernel_bind(sock, (struct sockaddr *) &ip_addr, 15575dac94e1SJames Chapman sizeof(ip_addr)); 1558789a4a2cSJames Chapman if (err < 0) 1559789a4a2cSJames Chapman goto out; 1560789a4a2cSJames Chapman 1561789a4a2cSJames Chapman ip_addr.l2tp_family = AF_INET; 1562789a4a2cSJames Chapman ip_addr.l2tp_addr = cfg->peer_ip; 1563789a4a2cSJames Chapman ip_addr.l2tp_conn_id = peer_tunnel_id; 15645dac94e1SJames Chapman err = kernel_connect(sock, (struct sockaddr *) &ip_addr, 15655dac94e1SJames Chapman sizeof(ip_addr), 0); 1566789a4a2cSJames Chapman if (err < 0) 1567789a4a2cSJames Chapman goto out; 15685dac94e1SJames Chapman } 1569789a4a2cSJames Chapman break; 1570789a4a2cSJames Chapman 1571789a4a2cSJames Chapman default: 1572789a4a2cSJames Chapman goto out; 1573789a4a2cSJames Chapman } 1574789a4a2cSJames Chapman 1575789a4a2cSJames Chapman out: 1576167eb17eSTom Parkin *sockp = sock; 1577789a4a2cSJames Chapman if ((err < 0) && sock) { 1578167eb17eSTom Parkin kernel_sock_shutdown(sock, SHUT_RDWR); 1579167eb17eSTom Parkin sk_release_kernel(sock->sk); 1580789a4a2cSJames Chapman *sockp = NULL; 1581789a4a2cSJames Chapman } 1582789a4a2cSJames Chapman 1583789a4a2cSJames Chapman return err; 1584789a4a2cSJames Chapman } 1585789a4a2cSJames Chapman 158637159ef2SEric Dumazet static struct lock_class_key l2tp_socket_class; 158737159ef2SEric Dumazet 1588fd558d18SJames 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) 1589fd558d18SJames Chapman { 1590fd558d18SJames Chapman struct l2tp_tunnel *tunnel = NULL; 1591fd558d18SJames Chapman int err; 1592fd558d18SJames Chapman struct socket *sock = NULL; 1593fd558d18SJames Chapman struct sock *sk = NULL; 1594fd558d18SJames Chapman struct l2tp_net *pn; 15950d76751fSJames Chapman enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP; 1596fd558d18SJames Chapman 1597fd558d18SJames Chapman /* Get the tunnel socket from the fd, which was opened by 1598789a4a2cSJames Chapman * the userspace L2TP daemon. If not specified, create a 1599789a4a2cSJames Chapman * kernel socket. 1600fd558d18SJames Chapman */ 1601789a4a2cSJames Chapman if (fd < 0) { 1602167eb17eSTom Parkin err = l2tp_tunnel_sock_create(net, tunnel_id, peer_tunnel_id, 1603167eb17eSTom Parkin cfg, &sock); 1604789a4a2cSJames Chapman if (err < 0) 1605789a4a2cSJames Chapman goto err; 1606789a4a2cSJames Chapman } else { 1607fd558d18SJames Chapman sock = sockfd_lookup(fd, &err); 1608fd558d18SJames Chapman if (!sock) { 1609cbb95e0cSTom Parkin pr_err("tunl %u: sockfd_lookup(fd=%d) returned %d\n", 1610fd558d18SJames Chapman tunnel_id, fd, err); 1611cbb95e0cSTom Parkin err = -EBADF; 1612cbb95e0cSTom Parkin goto err; 1613cbb95e0cSTom Parkin } 1614cbb95e0cSTom Parkin 1615cbb95e0cSTom Parkin /* Reject namespace mismatches */ 1616cbb95e0cSTom Parkin if (!net_eq(sock_net(sock->sk), net)) { 1617cbb95e0cSTom Parkin pr_err("tunl %u: netns mismatch\n", tunnel_id); 1618cbb95e0cSTom Parkin err = -EINVAL; 1619fd558d18SJames Chapman goto err; 1620fd558d18SJames Chapman } 1621789a4a2cSJames Chapman } 1622fd558d18SJames Chapman 1623fd558d18SJames Chapman sk = sock->sk; 1624fd558d18SJames Chapman 16250d76751fSJames Chapman if (cfg != NULL) 16260d76751fSJames Chapman encap = cfg->encap; 16270d76751fSJames Chapman 1628fd558d18SJames Chapman /* Quick sanity checks */ 16290d76751fSJames Chapman switch (encap) { 16300d76751fSJames Chapman case L2TP_ENCAPTYPE_UDP: 1631fd558d18SJames Chapman err = -EPROTONOSUPPORT; 1632fd558d18SJames Chapman if (sk->sk_protocol != IPPROTO_UDP) { 1633a4ca44faSJoe Perches pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n", 1634fd558d18SJames Chapman tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP); 1635fd558d18SJames Chapman goto err; 1636fd558d18SJames Chapman } 16370d76751fSJames Chapman break; 16380d76751fSJames Chapman case L2TP_ENCAPTYPE_IP: 16390d76751fSJames Chapman err = -EPROTONOSUPPORT; 16400d76751fSJames Chapman if (sk->sk_protocol != IPPROTO_L2TP) { 1641a4ca44faSJoe Perches pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n", 16420d76751fSJames Chapman tunnel_id, fd, sk->sk_protocol, IPPROTO_L2TP); 1643fd558d18SJames Chapman goto err; 1644fd558d18SJames Chapman } 16450d76751fSJames Chapman break; 16460d76751fSJames Chapman } 1647fd558d18SJames Chapman 1648fd558d18SJames Chapman /* Check if this socket has already been prepped */ 1649fd558d18SJames Chapman tunnel = (struct l2tp_tunnel *)sk->sk_user_data; 1650fd558d18SJames Chapman if (tunnel != NULL) { 1651fd558d18SJames Chapman /* This socket has already been prepped */ 1652fd558d18SJames Chapman err = -EBUSY; 1653fd558d18SJames Chapman goto err; 1654fd558d18SJames Chapman } 1655fd558d18SJames Chapman 1656fd558d18SJames Chapman tunnel = kzalloc(sizeof(struct l2tp_tunnel), GFP_KERNEL); 1657fd558d18SJames Chapman if (tunnel == NULL) { 1658fd558d18SJames Chapman err = -ENOMEM; 1659fd558d18SJames Chapman goto err; 1660fd558d18SJames Chapman } 1661fd558d18SJames Chapman 1662fd558d18SJames Chapman tunnel->version = version; 1663fd558d18SJames Chapman tunnel->tunnel_id = tunnel_id; 1664fd558d18SJames Chapman tunnel->peer_tunnel_id = peer_tunnel_id; 1665fd558d18SJames Chapman tunnel->debug = L2TP_DEFAULT_DEBUG_FLAGS; 1666fd558d18SJames Chapman 1667fd558d18SJames Chapman tunnel->magic = L2TP_TUNNEL_MAGIC; 1668fd558d18SJames Chapman sprintf(&tunnel->name[0], "tunl %u", tunnel_id); 1669fd558d18SJames Chapman rwlock_init(&tunnel->hlist_lock); 1670fd558d18SJames Chapman 1671fd558d18SJames Chapman /* The net we belong to */ 1672fd558d18SJames Chapman tunnel->l2tp_net = net; 1673fd558d18SJames Chapman pn = l2tp_pernet(net); 1674fd558d18SJames Chapman 16750d76751fSJames Chapman if (cfg != NULL) 1676fd558d18SJames Chapman tunnel->debug = cfg->debug; 1677fd558d18SJames Chapman 1678fd558d18SJames Chapman /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ 16790d76751fSJames Chapman tunnel->encap = encap; 16800d76751fSJames Chapman if (encap == L2TP_ENCAPTYPE_UDP) { 16810d76751fSJames Chapman /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ 1682fd558d18SJames Chapman udp_sk(sk)->encap_type = UDP_ENCAP_L2TPINUDP; 1683fd558d18SJames Chapman udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv; 16849980d001STom Parkin udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy; 1685d2cf3361SBenjamin LaHaise #if IS_ENABLED(CONFIG_IPV6) 1686d2cf3361SBenjamin LaHaise if (sk->sk_family == PF_INET6) 1687d2cf3361SBenjamin LaHaise udpv6_encap_enable(); 1688d2cf3361SBenjamin LaHaise else 1689d2cf3361SBenjamin LaHaise #endif 1690447167bfSEric Dumazet udp_encap_enable(); 16910d76751fSJames Chapman } 1692fd558d18SJames Chapman 1693fd558d18SJames Chapman sk->sk_user_data = tunnel; 1694fd558d18SJames Chapman 1695fd558d18SJames Chapman /* Hook on the tunnel socket destructor so that we can cleanup 1696fd558d18SJames Chapman * if the tunnel socket goes away. 1697fd558d18SJames Chapman */ 1698fd558d18SJames Chapman tunnel->old_sk_destruct = sk->sk_destruct; 1699fd558d18SJames Chapman sk->sk_destruct = &l2tp_tunnel_destruct; 1700fd558d18SJames Chapman tunnel->sock = sk; 170180d84ef3STom Parkin tunnel->fd = fd; 170237159ef2SEric Dumazet lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock"); 170337159ef2SEric Dumazet 1704fd558d18SJames Chapman sk->sk_allocation = GFP_ATOMIC; 1705fd558d18SJames Chapman 1706f8ccac0eSTom Parkin /* Init delete workqueue struct */ 1707f8ccac0eSTom Parkin INIT_WORK(&tunnel->del_work, l2tp_tunnel_del_work); 1708f8ccac0eSTom Parkin 1709fd558d18SJames Chapman /* Add tunnel to our list */ 1710fd558d18SJames Chapman INIT_LIST_HEAD(&tunnel->list); 1711fd558d18SJames Chapman atomic_inc(&l2tp_tunnel_count); 1712fd558d18SJames Chapman 1713fd558d18SJames Chapman /* Bump the reference count. The tunnel context is deleted 17141769192aSEric Dumazet * only when this drops to zero. Must be done before list insertion 1715fd558d18SJames Chapman */ 1716fd558d18SJames Chapman l2tp_tunnel_inc_refcount(tunnel); 17171769192aSEric Dumazet spin_lock_bh(&pn->l2tp_tunnel_list_lock); 17181769192aSEric Dumazet list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); 17191769192aSEric Dumazet spin_unlock_bh(&pn->l2tp_tunnel_list_lock); 1720fd558d18SJames Chapman 1721fd558d18SJames Chapman err = 0; 1722fd558d18SJames Chapman err: 1723fd558d18SJames Chapman if (tunnelp) 1724fd558d18SJames Chapman *tunnelp = tunnel; 1725fd558d18SJames Chapman 1726789a4a2cSJames Chapman /* If tunnel's socket was created by the kernel, it doesn't 1727789a4a2cSJames Chapman * have a file. 1728789a4a2cSJames Chapman */ 1729789a4a2cSJames Chapman if (sock && sock->file) 1730fd558d18SJames Chapman sockfd_put(sock); 1731fd558d18SJames Chapman 1732fd558d18SJames Chapman return err; 1733fd558d18SJames Chapman } 1734fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_tunnel_create); 1735fd558d18SJames Chapman 1736309795f4SJames Chapman /* This function is used by the netlink TUNNEL_DELETE command. 1737309795f4SJames Chapman */ 1738309795f4SJames Chapman int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) 1739309795f4SJames Chapman { 1740f8ccac0eSTom Parkin return (false == queue_work(l2tp_wq, &tunnel->del_work)); 1741309795f4SJames Chapman } 1742309795f4SJames Chapman EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); 1743309795f4SJames Chapman 1744fd558d18SJames Chapman /* Really kill the session. 1745fd558d18SJames Chapman */ 1746fd558d18SJames Chapman void l2tp_session_free(struct l2tp_session *session) 1747fd558d18SJames Chapman { 1748fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 1749fd558d18SJames Chapman 1750fd558d18SJames Chapman BUG_ON(atomic_read(&session->ref_count) != 0); 1751fd558d18SJames Chapman 1752fd558d18SJames Chapman tunnel = session->tunnel; 1753fd558d18SJames Chapman if (tunnel != NULL) { 1754fd558d18SJames Chapman BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); 1755fd558d18SJames Chapman 1756fd558d18SJames Chapman /* Delete the session from the hash */ 1757fd558d18SJames Chapman write_lock_bh(&tunnel->hlist_lock); 1758fd558d18SJames Chapman hlist_del_init(&session->hlist); 1759fd558d18SJames Chapman write_unlock_bh(&tunnel->hlist_lock); 1760fd558d18SJames Chapman 1761f7faffa3SJames Chapman /* Unlink from the global hash if not L2TPv2 */ 1762f7faffa3SJames Chapman if (tunnel->version != L2TP_HDR_VER_2) { 1763f7faffa3SJames Chapman struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); 1764f7faffa3SJames Chapman 1765e02d494dSJames Chapman spin_lock_bh(&pn->l2tp_session_hlist_lock); 1766e02d494dSJames Chapman hlist_del_init_rcu(&session->global_hlist); 1767e02d494dSJames Chapman spin_unlock_bh(&pn->l2tp_session_hlist_lock); 1768e02d494dSJames Chapman synchronize_rcu(); 1769f7faffa3SJames Chapman } 1770f7faffa3SJames Chapman 1771fd558d18SJames Chapman if (session->session_id != 0) 1772fd558d18SJames Chapman atomic_dec(&l2tp_session_count); 1773fd558d18SJames Chapman 1774fd558d18SJames Chapman sock_put(tunnel->sock); 1775fd558d18SJames Chapman 1776fd558d18SJames Chapman /* This will delete the tunnel context if this 1777fd558d18SJames Chapman * is the last session on the tunnel. 1778fd558d18SJames Chapman */ 1779fd558d18SJames Chapman session->tunnel = NULL; 1780fd558d18SJames Chapman l2tp_tunnel_dec_refcount(tunnel); 1781fd558d18SJames Chapman } 1782fd558d18SJames Chapman 1783fd558d18SJames Chapman kfree(session); 1784fd558d18SJames Chapman 1785fd558d18SJames Chapman return; 1786fd558d18SJames Chapman } 1787fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_free); 1788fd558d18SJames Chapman 1789309795f4SJames Chapman /* This function is used by the netlink SESSION_DELETE command and by 1790309795f4SJames Chapman pseudowire modules. 1791309795f4SJames Chapman */ 1792309795f4SJames Chapman int l2tp_session_delete(struct l2tp_session *session) 1793309795f4SJames Chapman { 1794309795f4SJames Chapman if (session->session_close != NULL) 1795309795f4SJames Chapman (*session->session_close)(session); 1796309795f4SJames Chapman 1797309795f4SJames Chapman l2tp_session_dec_refcount(session); 1798309795f4SJames Chapman 1799309795f4SJames Chapman return 0; 1800309795f4SJames Chapman } 1801309795f4SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_delete); 1802309795f4SJames Chapman 1803309795f4SJames Chapman 1804f7faffa3SJames Chapman /* We come here whenever a session's send_seq, cookie_len or 1805f7faffa3SJames Chapman * l2specific_len parameters are set. 1806f7faffa3SJames Chapman */ 1807fc130840Sstephen hemminger static void l2tp_session_set_header_len(struct l2tp_session *session, int version) 1808f7faffa3SJames Chapman { 1809f7faffa3SJames Chapman if (version == L2TP_HDR_VER_2) { 1810f7faffa3SJames Chapman session->hdr_len = 6; 1811f7faffa3SJames Chapman if (session->send_seq) 1812f7faffa3SJames Chapman session->hdr_len += 4; 1813f7faffa3SJames Chapman } else { 18140d76751fSJames Chapman session->hdr_len = 4 + session->cookie_len + session->l2specific_len + session->offset; 18150d76751fSJames Chapman if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP) 18160d76751fSJames Chapman session->hdr_len += 4; 1817f7faffa3SJames Chapman } 1818f7faffa3SJames Chapman 1819f7faffa3SJames Chapman } 1820f7faffa3SJames Chapman 1821fd558d18SJames 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) 1822fd558d18SJames Chapman { 1823fd558d18SJames Chapman struct l2tp_session *session; 1824fd558d18SJames Chapman 1825fd558d18SJames Chapman session = kzalloc(sizeof(struct l2tp_session) + priv_size, GFP_KERNEL); 1826fd558d18SJames Chapman if (session != NULL) { 1827fd558d18SJames Chapman session->magic = L2TP_SESSION_MAGIC; 1828fd558d18SJames Chapman session->tunnel = tunnel; 1829fd558d18SJames Chapman 1830fd558d18SJames Chapman session->session_id = session_id; 1831fd558d18SJames Chapman session->peer_session_id = peer_session_id; 1832d301e325SJames Chapman session->nr = 0; 1833fd558d18SJames Chapman 1834fd558d18SJames Chapman sprintf(&session->name[0], "sess %u/%u", 1835fd558d18SJames Chapman tunnel->tunnel_id, session->session_id); 1836fd558d18SJames Chapman 1837fd558d18SJames Chapman skb_queue_head_init(&session->reorder_q); 1838fd558d18SJames Chapman 1839fd558d18SJames Chapman INIT_HLIST_NODE(&session->hlist); 1840f7faffa3SJames Chapman INIT_HLIST_NODE(&session->global_hlist); 1841fd558d18SJames Chapman 1842fd558d18SJames Chapman /* Inherit debug options from tunnel */ 1843fd558d18SJames Chapman session->debug = tunnel->debug; 1844fd558d18SJames Chapman 1845fd558d18SJames Chapman if (cfg) { 1846f7faffa3SJames Chapman session->pwtype = cfg->pw_type; 1847fd558d18SJames Chapman session->debug = cfg->debug; 1848fd558d18SJames Chapman session->mtu = cfg->mtu; 1849fd558d18SJames Chapman session->mru = cfg->mru; 1850fd558d18SJames Chapman session->send_seq = cfg->send_seq; 1851fd558d18SJames Chapman session->recv_seq = cfg->recv_seq; 1852fd558d18SJames Chapman session->lns_mode = cfg->lns_mode; 1853f7faffa3SJames Chapman session->reorder_timeout = cfg->reorder_timeout; 1854f7faffa3SJames Chapman session->offset = cfg->offset; 1855f7faffa3SJames Chapman session->l2specific_type = cfg->l2specific_type; 1856f7faffa3SJames Chapman session->l2specific_len = cfg->l2specific_len; 1857f7faffa3SJames Chapman session->cookie_len = cfg->cookie_len; 1858f7faffa3SJames Chapman memcpy(&session->cookie[0], &cfg->cookie[0], cfg->cookie_len); 1859f7faffa3SJames Chapman session->peer_cookie_len = cfg->peer_cookie_len; 1860f7faffa3SJames Chapman memcpy(&session->peer_cookie[0], &cfg->peer_cookie[0], cfg->peer_cookie_len); 1861fd558d18SJames Chapman } 1862fd558d18SJames Chapman 1863f7faffa3SJames Chapman if (tunnel->version == L2TP_HDR_VER_2) 1864f7faffa3SJames Chapman session->build_header = l2tp_build_l2tpv2_header; 1865f7faffa3SJames Chapman else 1866f7faffa3SJames Chapman session->build_header = l2tp_build_l2tpv3_header; 1867f7faffa3SJames Chapman 1868f7faffa3SJames Chapman l2tp_session_set_header_len(session, tunnel->version); 1869f7faffa3SJames Chapman 1870fd558d18SJames Chapman /* Bump the reference count. The session context is deleted 1871fd558d18SJames Chapman * only when this drops to zero. 1872fd558d18SJames Chapman */ 1873fd558d18SJames Chapman l2tp_session_inc_refcount(session); 1874fd558d18SJames Chapman l2tp_tunnel_inc_refcount(tunnel); 1875fd558d18SJames Chapman 1876fd558d18SJames Chapman /* Ensure tunnel socket isn't deleted */ 1877fd558d18SJames Chapman sock_hold(tunnel->sock); 1878fd558d18SJames Chapman 1879fd558d18SJames Chapman /* Add session to the tunnel's hash list */ 1880fd558d18SJames Chapman write_lock_bh(&tunnel->hlist_lock); 1881fd558d18SJames Chapman hlist_add_head(&session->hlist, 1882fd558d18SJames Chapman l2tp_session_id_hash(tunnel, session_id)); 1883fd558d18SJames Chapman write_unlock_bh(&tunnel->hlist_lock); 1884fd558d18SJames Chapman 1885f7faffa3SJames Chapman /* And to the global session list if L2TPv3 */ 1886f7faffa3SJames Chapman if (tunnel->version != L2TP_HDR_VER_2) { 1887f7faffa3SJames Chapman struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); 1888f7faffa3SJames Chapman 1889e02d494dSJames Chapman spin_lock_bh(&pn->l2tp_session_hlist_lock); 1890e02d494dSJames Chapman hlist_add_head_rcu(&session->global_hlist, 1891f7faffa3SJames Chapman l2tp_session_id_hash_2(pn, session_id)); 1892e02d494dSJames Chapman spin_unlock_bh(&pn->l2tp_session_hlist_lock); 1893f7faffa3SJames Chapman } 1894f7faffa3SJames Chapman 1895fd558d18SJames Chapman /* Ignore management session in session count value */ 1896fd558d18SJames Chapman if (session->session_id != 0) 1897fd558d18SJames Chapman atomic_inc(&l2tp_session_count); 1898fd558d18SJames Chapman } 1899fd558d18SJames Chapman 1900fd558d18SJames Chapman return session; 1901fd558d18SJames Chapman } 1902fd558d18SJames Chapman EXPORT_SYMBOL_GPL(l2tp_session_create); 1903fd558d18SJames Chapman 1904fd558d18SJames Chapman /***************************************************************************** 1905fd558d18SJames Chapman * Init and cleanup 1906fd558d18SJames Chapman *****************************************************************************/ 1907fd558d18SJames Chapman 1908fd558d18SJames Chapman static __net_init int l2tp_init_net(struct net *net) 1909fd558d18SJames Chapman { 1910e773aaffSJiri Pirko struct l2tp_net *pn = net_generic(net, l2tp_net_id); 1911f7faffa3SJames Chapman int hash; 1912fd558d18SJames Chapman 1913fd558d18SJames Chapman INIT_LIST_HEAD(&pn->l2tp_tunnel_list); 1914e02d494dSJames Chapman spin_lock_init(&pn->l2tp_tunnel_list_lock); 1915fd558d18SJames Chapman 1916f7faffa3SJames Chapman for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) 1917f7faffa3SJames Chapman INIT_HLIST_HEAD(&pn->l2tp_session_hlist[hash]); 1918f7faffa3SJames Chapman 1919e02d494dSJames Chapman spin_lock_init(&pn->l2tp_session_hlist_lock); 1920f7faffa3SJames Chapman 1921fd558d18SJames Chapman return 0; 1922fd558d18SJames Chapman } 1923fd558d18SJames Chapman 1924167eb17eSTom Parkin static __net_exit void l2tp_exit_net(struct net *net) 1925167eb17eSTom Parkin { 1926167eb17eSTom Parkin struct l2tp_net *pn = l2tp_pernet(net); 1927167eb17eSTom Parkin struct l2tp_tunnel *tunnel = NULL; 1928167eb17eSTom Parkin 1929167eb17eSTom Parkin rcu_read_lock_bh(); 1930167eb17eSTom Parkin list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { 1931167eb17eSTom Parkin (void)l2tp_tunnel_delete(tunnel); 1932167eb17eSTom Parkin } 1933167eb17eSTom Parkin rcu_read_unlock_bh(); 1934167eb17eSTom Parkin } 1935167eb17eSTom Parkin 1936fd558d18SJames Chapman static struct pernet_operations l2tp_net_ops = { 1937fd558d18SJames Chapman .init = l2tp_init_net, 1938167eb17eSTom Parkin .exit = l2tp_exit_net, 1939fd558d18SJames Chapman .id = &l2tp_net_id, 1940fd558d18SJames Chapman .size = sizeof(struct l2tp_net), 1941fd558d18SJames Chapman }; 1942fd558d18SJames Chapman 1943fd558d18SJames Chapman static int __init l2tp_init(void) 1944fd558d18SJames Chapman { 1945fd558d18SJames Chapman int rc = 0; 1946fd558d18SJames Chapman 1947fd558d18SJames Chapman rc = register_pernet_device(&l2tp_net_ops); 1948fd558d18SJames Chapman if (rc) 1949fd558d18SJames Chapman goto out; 1950fd558d18SJames Chapman 1951f8ccac0eSTom Parkin l2tp_wq = alloc_workqueue("l2tp", WQ_NON_REENTRANT | WQ_UNBOUND, 0); 1952f8ccac0eSTom Parkin if (!l2tp_wq) { 1953f8ccac0eSTom Parkin pr_err("alloc_workqueue failed\n"); 1954f8ccac0eSTom Parkin rc = -ENOMEM; 1955f8ccac0eSTom Parkin goto out; 1956f8ccac0eSTom Parkin } 1957f8ccac0eSTom Parkin 1958a4ca44faSJoe Perches pr_info("L2TP core driver, %s\n", L2TP_DRV_VERSION); 1959fd558d18SJames Chapman 1960fd558d18SJames Chapman out: 1961fd558d18SJames Chapman return rc; 1962fd558d18SJames Chapman } 1963fd558d18SJames Chapman 1964fd558d18SJames Chapman static void __exit l2tp_exit(void) 1965fd558d18SJames Chapman { 1966fd558d18SJames Chapman unregister_pernet_device(&l2tp_net_ops); 1967f8ccac0eSTom Parkin if (l2tp_wq) { 1968f8ccac0eSTom Parkin destroy_workqueue(l2tp_wq); 1969f8ccac0eSTom Parkin l2tp_wq = NULL; 1970f8ccac0eSTom Parkin } 1971fd558d18SJames Chapman } 1972fd558d18SJames Chapman 1973fd558d18SJames Chapman module_init(l2tp_init); 1974fd558d18SJames Chapman module_exit(l2tp_exit); 1975fd558d18SJames Chapman 1976fd558d18SJames Chapman MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); 1977fd558d18SJames Chapman MODULE_DESCRIPTION("L2TP core"); 1978fd558d18SJames Chapman MODULE_LICENSE("GPL"); 1979fd558d18SJames Chapman MODULE_VERSION(L2TP_DRV_VERSION); 1980fd558d18SJames Chapman 1981