1fd558d18SJames Chapman /* 2fd558d18SJames Chapman * L2TP internal definitions. 3fd558d18SJames Chapman * 4fd558d18SJames Chapman * Copyright (c) 2008,2009 Katalix Systems Ltd 5fd558d18SJames Chapman * 6fd558d18SJames Chapman * This program is free software; you can redistribute it and/or modify 7fd558d18SJames Chapman * it under the terms of the GNU General Public License version 2 as 8fd558d18SJames Chapman * published by the Free Software Foundation. 9fd558d18SJames Chapman */ 10fd558d18SJames Chapman 11fd558d18SJames Chapman #ifndef _L2TP_CORE_H_ 12fd558d18SJames Chapman #define _L2TP_CORE_H_ 13fd558d18SJames Chapman 14fd558d18SJames Chapman /* Just some random numbers */ 15fd558d18SJames Chapman #define L2TP_TUNNEL_MAGIC 0x42114DDA 16fd558d18SJames Chapman #define L2TP_SESSION_MAGIC 0x0C04EB7D 17fd558d18SJames Chapman 18f7faffa3SJames Chapman /* Per tunnel, session hash table size */ 19fd558d18SJames Chapman #define L2TP_HASH_BITS 4 20fd558d18SJames Chapman #define L2TP_HASH_SIZE (1 << L2TP_HASH_BITS) 21fd558d18SJames Chapman 22f7faffa3SJames Chapman /* System-wide, session hash table size */ 23f7faffa3SJames Chapman #define L2TP_HASH_BITS_2 8 24f7faffa3SJames Chapman #define L2TP_HASH_SIZE_2 (1 << L2TP_HASH_BITS_2) 25f7faffa3SJames Chapman 26fd558d18SJames Chapman /* Debug message categories for the DEBUG socket option */ 27fd558d18SJames Chapman enum { 28fd558d18SJames Chapman L2TP_MSG_DEBUG = (1 << 0), /* verbose debug (if 29fd558d18SJames Chapman * compiled in) */ 30fd558d18SJames Chapman L2TP_MSG_CONTROL = (1 << 1), /* userspace - kernel 31fd558d18SJames Chapman * interface */ 32fd558d18SJames Chapman L2TP_MSG_SEQ = (1 << 2), /* sequence numbers */ 33fd558d18SJames Chapman L2TP_MSG_DATA = (1 << 3), /* data packets */ 34fd558d18SJames Chapman }; 35fd558d18SJames Chapman 36fd558d18SJames Chapman struct sk_buff; 37fd558d18SJames Chapman 38fd558d18SJames Chapman struct l2tp_stats { 397b7c0719STom Parkin atomic_long_t tx_packets; 407b7c0719STom Parkin atomic_long_t tx_bytes; 417b7c0719STom Parkin atomic_long_t tx_errors; 427b7c0719STom Parkin atomic_long_t rx_packets; 437b7c0719STom Parkin atomic_long_t rx_bytes; 447b7c0719STom Parkin atomic_long_t rx_seq_discards; 457b7c0719STom Parkin atomic_long_t rx_oos_packets; 467b7c0719STom Parkin atomic_long_t rx_errors; 477b7c0719STom Parkin atomic_long_t rx_cookie_discards; 48fd558d18SJames Chapman }; 49fd558d18SJames Chapman 50fd558d18SJames Chapman struct l2tp_tunnel; 51fd558d18SJames Chapman 52fd558d18SJames Chapman /* Describes a session. Contains information to determine incoming 53fd558d18SJames Chapman * packets and transmit outgoing ones. 54fd558d18SJames Chapman */ 55fd558d18SJames Chapman struct l2tp_session_cfg { 56f7faffa3SJames Chapman enum l2tp_pwtype pw_type; 5795c96174SEric Dumazet unsigned int data_seq:2; /* data sequencing level 58fd558d18SJames Chapman * 0 => none, 1 => IP only, 59fd558d18SJames Chapman * 2 => all 60fd558d18SJames Chapman */ 6195c96174SEric Dumazet unsigned int recv_seq:1; /* expect receive packets with 62fd558d18SJames Chapman * sequence numbers? */ 6395c96174SEric Dumazet unsigned int send_seq:1; /* send packets with sequence 64fd558d18SJames Chapman * numbers? */ 6595c96174SEric Dumazet unsigned int lns_mode:1; /* behave as LNS? LAC enables 66fd558d18SJames Chapman * sequence numbers under 67fd558d18SJames Chapman * control of LNS. */ 68fd558d18SJames Chapman int debug; /* bitmask of debug message 69fd558d18SJames Chapman * categories */ 70309795f4SJames Chapman u16 vlan_id; /* VLAN pseudowire only */ 71f7faffa3SJames Chapman u16 offset; /* offset to payload */ 72f7faffa3SJames Chapman u16 l2specific_len; /* Layer 2 specific length */ 73f7faffa3SJames Chapman u16 l2specific_type; /* Layer 2 specific type */ 74f7faffa3SJames Chapman u8 cookie[8]; /* optional cookie */ 75f7faffa3SJames Chapman int cookie_len; /* 0, 4 or 8 bytes */ 76f7faffa3SJames Chapman u8 peer_cookie[8]; /* peer's cookie */ 77f7faffa3SJames Chapman int peer_cookie_len; /* 0, 4 or 8 bytes */ 78fd558d18SJames Chapman int reorder_timeout; /* configured reorder timeout 79fd558d18SJames Chapman * (in jiffies) */ 80fd558d18SJames Chapman int mtu; 81fd558d18SJames Chapman int mru; 82309795f4SJames Chapman char *ifname; 83fd558d18SJames Chapman }; 84fd558d18SJames Chapman 85fd558d18SJames Chapman struct l2tp_session { 86fd558d18SJames Chapman int magic; /* should be 87fd558d18SJames Chapman * L2TP_SESSION_MAGIC */ 88fd558d18SJames Chapman 89fd558d18SJames Chapman struct l2tp_tunnel *tunnel; /* back pointer to tunnel 90fd558d18SJames Chapman * context */ 91fd558d18SJames Chapman u32 session_id; 92fd558d18SJames Chapman u32 peer_session_id; 93f7faffa3SJames Chapman u8 cookie[8]; 94f7faffa3SJames Chapman int cookie_len; 95f7faffa3SJames Chapman u8 peer_cookie[8]; 96f7faffa3SJames Chapman int peer_cookie_len; 97f7faffa3SJames Chapman u16 offset; /* offset from end of L2TP header 98f7faffa3SJames Chapman to beginning of data */ 99f7faffa3SJames Chapman u16 l2specific_len; 100f7faffa3SJames Chapman u16 l2specific_type; 101f7faffa3SJames Chapman u16 hdr_len; 102f7faffa3SJames Chapman u32 nr; /* session NR state (receive) */ 103f7faffa3SJames Chapman u32 ns; /* session NR state (send) */ 104fd558d18SJames Chapman struct sk_buff_head reorder_q; /* receive reorder queue */ 1058a1631d5SJames Chapman u32 nr_max; /* max NR. Depends on tunnel */ 1068a1631d5SJames Chapman u32 nr_window_size; /* NR window size */ 107fd558d18SJames Chapman struct hlist_node hlist; /* Hash list node */ 108fd558d18SJames Chapman atomic_t ref_count; 109fd558d18SJames Chapman 110fd558d18SJames Chapman char name[32]; /* for logging */ 111309795f4SJames Chapman char ifname[IFNAMSIZ]; 11295c96174SEric Dumazet unsigned int data_seq:2; /* data sequencing level 113fd558d18SJames Chapman * 0 => none, 1 => IP only, 114fd558d18SJames Chapman * 2 => all 115fd558d18SJames Chapman */ 11695c96174SEric Dumazet unsigned int recv_seq:1; /* expect receive packets with 117fd558d18SJames Chapman * sequence numbers? */ 11895c96174SEric Dumazet unsigned int send_seq:1; /* send packets with sequence 119fd558d18SJames Chapman * numbers? */ 12095c96174SEric Dumazet unsigned int lns_mode:1; /* behave as LNS? LAC enables 121fd558d18SJames Chapman * sequence numbers under 122fd558d18SJames Chapman * control of LNS. */ 123fd558d18SJames Chapman int debug; /* bitmask of debug message 124fd558d18SJames Chapman * categories */ 125fd558d18SJames Chapman int reorder_timeout; /* configured reorder timeout 126fd558d18SJames Chapman * (in jiffies) */ 12738d40b3fSJames Chapman int reorder_skip; /* set if skip to next nr */ 128fd558d18SJames Chapman int mtu; 129fd558d18SJames Chapman int mru; 130f7faffa3SJames Chapman enum l2tp_pwtype pwtype; 131fd558d18SJames Chapman struct l2tp_stats stats; 132f7faffa3SJames Chapman struct hlist_node global_hlist; /* Global hash list node */ 133fd558d18SJames Chapman 134f7faffa3SJames Chapman int (*build_header)(struct l2tp_session *session, void *buf); 135fd558d18SJames Chapman void (*recv_skb)(struct l2tp_session *session, struct sk_buff *skb, int data_len); 136fd558d18SJames Chapman void (*session_close)(struct l2tp_session *session); 137fd558d18SJames Chapman void (*ref)(struct l2tp_session *session); 138fd558d18SJames Chapman void (*deref)(struct l2tp_session *session); 139f66ef2d0SDavid S. Miller #if defined(CONFIG_L2TP_DEBUGFS) || defined(CONFIG_L2TP_DEBUGFS_MODULE) 1400ad66140SJames Chapman void (*show)(struct seq_file *m, void *priv); 1410ad66140SJames Chapman #endif 142fd558d18SJames Chapman uint8_t priv[0]; /* private data */ 143fd558d18SJames Chapman }; 144fd558d18SJames Chapman 145fd558d18SJames Chapman /* Describes the tunnel. It contains info to track all the associated 146fd558d18SJames Chapman * sessions so incoming packets can be sorted out 147fd558d18SJames Chapman */ 148fd558d18SJames Chapman struct l2tp_tunnel_cfg { 149fd558d18SJames Chapman int debug; /* bitmask of debug message 150fd558d18SJames Chapman * categories */ 1510d76751fSJames Chapman enum l2tp_encap_type encap; 152789a4a2cSJames Chapman 153789a4a2cSJames Chapman /* Used only for kernel-created sockets */ 154789a4a2cSJames Chapman struct in_addr local_ip; 155789a4a2cSJames Chapman struct in_addr peer_ip; 156f9bac8dfSChris Elston #if IS_ENABLED(CONFIG_IPV6) 157f9bac8dfSChris Elston struct in6_addr *local_ip6; 158f9bac8dfSChris Elston struct in6_addr *peer_ip6; 159f9bac8dfSChris Elston #endif 160789a4a2cSJames Chapman u16 local_udp_port; 161789a4a2cSJames Chapman u16 peer_udp_port; 1627bddd0dbSEric Dumazet unsigned int use_udp_checksums:1; 163fd558d18SJames Chapman }; 164fd558d18SJames Chapman 165fd558d18SJames Chapman struct l2tp_tunnel { 166fd558d18SJames Chapman int magic; /* Should be L2TP_TUNNEL_MAGIC */ 16799469c32Sxeb@mail.ru struct rcu_head rcu; 168fd558d18SJames Chapman rwlock_t hlist_lock; /* protect session_hlist */ 169fd558d18SJames Chapman struct hlist_head session_hlist[L2TP_HASH_SIZE]; 170fd558d18SJames Chapman /* hashed list of sessions, 171fd558d18SJames Chapman * hashed by id */ 172fd558d18SJames Chapman u32 tunnel_id; 173fd558d18SJames Chapman u32 peer_tunnel_id; 174fd558d18SJames Chapman int version; /* 2=>L2TPv2, 3=>L2TPv3 */ 175fd558d18SJames Chapman 176fd558d18SJames Chapman char name[20]; /* for logging */ 177fd558d18SJames Chapman int debug; /* bitmask of debug message 178fd558d18SJames Chapman * categories */ 1790d76751fSJames Chapman enum l2tp_encap_type encap; 180fd558d18SJames Chapman struct l2tp_stats stats; 181fd558d18SJames Chapman 182fd558d18SJames Chapman struct list_head list; /* Keep a list of all tunnels */ 183fd558d18SJames Chapman struct net *l2tp_net; /* the net we belong to */ 184fd558d18SJames Chapman 185fd558d18SJames Chapman atomic_t ref_count; 1860ad66140SJames Chapman #ifdef CONFIG_DEBUG_FS 1870ad66140SJames Chapman void (*show)(struct seq_file *m, void *arg); 1880ad66140SJames Chapman #endif 189fd558d18SJames Chapman int (*recv_payload_hook)(struct sk_buff *skb); 190fd558d18SJames Chapman void (*old_sk_destruct)(struct sock *); 191fd558d18SJames Chapman struct sock *sock; /* Parent socket */ 19280d84ef3STom Parkin int fd; /* Parent fd, if tunnel socket 19380d84ef3STom Parkin * was created by userspace */ 194fd558d18SJames Chapman 195f8ccac0eSTom Parkin struct work_struct del_work; 196f8ccac0eSTom Parkin 197fd558d18SJames Chapman uint8_t priv[0]; /* private data */ 198fd558d18SJames Chapman }; 199fd558d18SJames Chapman 200309795f4SJames Chapman struct l2tp_nl_cmd_ops { 201309795f4SJames Chapman int (*session_create)(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg); 202309795f4SJames Chapman int (*session_delete)(struct l2tp_session *session); 203309795f4SJames Chapman }; 204309795f4SJames Chapman 205fd558d18SJames Chapman static inline void *l2tp_tunnel_priv(struct l2tp_tunnel *tunnel) 206fd558d18SJames Chapman { 207fd558d18SJames Chapman return &tunnel->priv[0]; 208fd558d18SJames Chapman } 209fd558d18SJames Chapman 210fd558d18SJames Chapman static inline void *l2tp_session_priv(struct l2tp_session *session) 211fd558d18SJames Chapman { 212fd558d18SJames Chapman return &session->priv[0]; 213fd558d18SJames Chapman } 214fd558d18SJames Chapman 215fd558d18SJames Chapman static inline struct l2tp_tunnel *l2tp_sock_to_tunnel(struct sock *sk) 216fd558d18SJames Chapman { 217fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 218fd558d18SJames Chapman 219fd558d18SJames Chapman if (sk == NULL) 220fd558d18SJames Chapman return NULL; 221fd558d18SJames Chapman 222fd558d18SJames Chapman sock_hold(sk); 223fd558d18SJames Chapman tunnel = (struct l2tp_tunnel *)(sk->sk_user_data); 224fd558d18SJames Chapman if (tunnel == NULL) { 225fd558d18SJames Chapman sock_put(sk); 226fd558d18SJames Chapman goto out; 227fd558d18SJames Chapman } 228fd558d18SJames Chapman 229fd558d18SJames Chapman BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); 230fd558d18SJames Chapman 231fd558d18SJames Chapman out: 232fd558d18SJames Chapman return tunnel; 233fd558d18SJames Chapman } 234fd558d18SJames Chapman 23580d84ef3STom Parkin extern struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel); 23680d84ef3STom Parkin extern void l2tp_tunnel_sock_put(struct sock *sk); 237f7faffa3SJames Chapman extern struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id); 238fd558d18SJames Chapman extern struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth); 239309795f4SJames Chapman extern struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname); 240fd558d18SJames Chapman extern struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id); 241fd558d18SJames Chapman extern struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth); 242fd558d18SJames Chapman 243fd558d18SJames Chapman extern 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); 244e34f4c70STom Parkin extern void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); 245309795f4SJames Chapman extern int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); 246fd558d18SJames Chapman extern 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); 247f6e16b29STom Parkin extern void __l2tp_session_unhash(struct l2tp_session *session); 248309795f4SJames Chapman extern int l2tp_session_delete(struct l2tp_session *session); 249fd558d18SJames Chapman extern void l2tp_session_free(struct l2tp_session *session); 250f7faffa3SJames Chapman extern void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, unsigned char *ptr, unsigned char *optr, u16 hdrflags, int length, int (*payload_hook)(struct sk_buff *skb)); 25148f72f92STom Parkin extern int l2tp_session_queue_purge(struct l2tp_session *session); 252fd558d18SJames Chapman extern int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb); 253fd558d18SJames Chapman 254fd558d18SJames Chapman extern int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len); 255fd558d18SJames Chapman 256309795f4SJames Chapman extern int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops); 257309795f4SJames Chapman extern void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type); 258309795f4SJames Chapman 259fd558d18SJames Chapman /* Session reference counts. Incremented when code obtains a reference 260fd558d18SJames Chapman * to a session. 261fd558d18SJames Chapman */ 262fd558d18SJames Chapman static inline void l2tp_session_inc_refcount_1(struct l2tp_session *session) 263fd558d18SJames Chapman { 264fd558d18SJames Chapman atomic_inc(&session->ref_count); 265fd558d18SJames Chapman } 266fd558d18SJames Chapman 267fd558d18SJames Chapman static inline void l2tp_session_dec_refcount_1(struct l2tp_session *session) 268fd558d18SJames Chapman { 269fd558d18SJames Chapman if (atomic_dec_and_test(&session->ref_count)) 270fd558d18SJames Chapman l2tp_session_free(session); 271fd558d18SJames Chapman } 272fd558d18SJames Chapman 273fd558d18SJames Chapman #ifdef L2TP_REFCNT_DEBUG 274a4ca44faSJoe Perches #define l2tp_session_inc_refcount(_s) \ 275a4ca44faSJoe Perches do { \ 276a4ca44faSJoe Perches pr_debug("l2tp_session_inc_refcount: %s:%d %s: cnt=%d\n", \ 277a4ca44faSJoe Perches __func__, __LINE__, (_s)->name, \ 278a4ca44faSJoe Perches atomic_read(&_s->ref_count)); \ 279fd558d18SJames Chapman l2tp_session_inc_refcount_1(_s); \ 280fd558d18SJames Chapman } while (0) 281a4ca44faSJoe Perches #define l2tp_session_dec_refcount(_s) \ 282a4ca44faSJoe Perches do { \ 283a4ca44faSJoe Perches pr_debug("l2tp_session_dec_refcount: %s:%d %s: cnt=%d\n", \ 284a4ca44faSJoe Perches __func__, __LINE__, (_s)->name, \ 285a4ca44faSJoe Perches atomic_read(&_s->ref_count)); \ 286fd558d18SJames Chapman l2tp_session_dec_refcount_1(_s); \ 287fd558d18SJames Chapman } while (0) 288fd558d18SJames Chapman #else 289fd558d18SJames Chapman #define l2tp_session_inc_refcount(s) l2tp_session_inc_refcount_1(s) 290fd558d18SJames Chapman #define l2tp_session_dec_refcount(s) l2tp_session_dec_refcount_1(s) 291fd558d18SJames Chapman #endif 292fd558d18SJames Chapman 293a4ca44faSJoe Perches #define l2tp_printk(ptr, type, func, fmt, ...) \ 294a4ca44faSJoe Perches do { \ 295a4ca44faSJoe Perches if (((ptr)->debug) & (type)) \ 296a4ca44faSJoe Perches func(fmt, ##__VA_ARGS__); \ 297a4ca44faSJoe Perches } while (0) 298a4ca44faSJoe Perches 299a4ca44faSJoe Perches #define l2tp_warn(ptr, type, fmt, ...) \ 300a4ca44faSJoe Perches l2tp_printk(ptr, type, pr_warn, fmt, ##__VA_ARGS__) 301a4ca44faSJoe Perches #define l2tp_info(ptr, type, fmt, ...) \ 302a4ca44faSJoe Perches l2tp_printk(ptr, type, pr_info, fmt, ##__VA_ARGS__) 303a4ca44faSJoe Perches #define l2tp_dbg(ptr, type, fmt, ...) \ 304a4ca44faSJoe Perches l2tp_printk(ptr, type, pr_debug, fmt, ##__VA_ARGS__) 305a4ca44faSJoe Perches 306fd558d18SJames Chapman #endif /* _L2TP_CORE_H_ */ 307