diff options
author | James Chapman <jchapman@katalix.com> | 2010-04-02 02:18:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-03 17:56:03 -0400 |
commit | f7faffa3ff8ef6ae712ef16312b8a2aa7a1c95fe (patch) | |
tree | 2b9d1bd7ed08767a02cd282a876970b34241f7af /net/l2tp | |
parent | 9345471bca96d00d4196b3dcc4a5625f1bfae247 (diff) |
l2tp: Add L2TPv3 protocol support
The L2TPv3 protocol changes the layout of the L2TP packet
header. Tunnel and session ids change from 16-bit to 32-bit values,
data sequence numbers change from 16-bit to 24-bit values and PPP-specific
fields are moved into protocol-specific subheaders.
Although this patch introduces L2TPv3 protocol support, there are no
userspace interfaces to create L2TPv3 sessions yet.
Signed-off-by: James Chapman <jchapman@katalix.com>
Reviewed-by: Randy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/l2tp')
-rw-r--r-- | net/l2tp/Kconfig | 25 | ||||
-rw-r--r-- | net/l2tp/l2tp_core.c | 532 | ||||
-rw-r--r-- | net/l2tp/l2tp_core.h | 54 | ||||
-rw-r--r-- | net/l2tp/l2tp_ppp.c | 21 |
4 files changed, 484 insertions, 148 deletions
diff --git a/net/l2tp/Kconfig b/net/l2tp/Kconfig index ec88c5cdc39..d60758d6047 100644 --- a/net/l2tp/Kconfig +++ b/net/l2tp/Kconfig | |||
@@ -19,6 +19,10 @@ menuconfig L2TP | |||
19 | connections. L2TP is also used as a VPN protocol, popular | 19 | connections. L2TP is also used as a VPN protocol, popular |
20 | with home workers to connect to their offices. | 20 | with home workers to connect to their offices. |
21 | 21 | ||
22 | L2TPv3 allows other protocols as well as PPP to be carried | ||
23 | over L2TP tunnels. L2TPv3 is defined in RFC 3931 | ||
24 | <http://www.ietf.org/rfc/rfc3931.txt>. | ||
25 | |||
22 | The kernel component handles only L2TP data packets: a | 26 | The kernel component handles only L2TP data packets: a |
23 | userland daemon handles L2TP the control protocol (tunnel | 27 | userland daemon handles L2TP the control protocol (tunnel |
24 | and session setup). One such daemon is OpenL2TP | 28 | and session setup). One such daemon is OpenL2TP |
@@ -26,3 +30,24 @@ menuconfig L2TP | |||
26 | 30 | ||
27 | If you don't need L2TP, say N. To compile all L2TP code as | 31 | If you don't need L2TP, say N. To compile all L2TP code as |
28 | modules, choose M here. | 32 | modules, choose M here. |
33 | |||
34 | config L2TP_V3 | ||
35 | bool "L2TPv3 support (EXPERIMENTAL)" | ||
36 | depends on EXPERIMENTAL && L2TP | ||
37 | help | ||
38 | Layer Two Tunneling Protocol Version 3 | ||
39 | |||
40 | From RFC 3931 <http://www.ietf.org/rfc/rfc3931.txt>. | ||
41 | |||
42 | The Layer Two Tunneling Protocol (L2TP) provides a dynamic | ||
43 | mechanism for tunneling Layer 2 (L2) "circuits" across a | ||
44 | packet-oriented data network (e.g., over IP). L2TP, as | ||
45 | originally defined in RFC 2661, is a standard method for | ||
46 | tunneling Point-to-Point Protocol (PPP) [RFC1661] sessions. | ||
47 | L2TP has since been adopted for tunneling a number of other | ||
48 | L2 protocols, including ATM, Frame Relay, HDLC and even raw | ||
49 | ethernet frames. | ||
50 | |||
51 | If you are connecting to L2TPv3 equipment, or you want to | ||
52 | tunnel raw ethernet frames using L2TP, say Y here. If | ||
53 | unsure, say N. | ||
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 4b6da368989..0eee1a65f1b 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -65,6 +65,7 @@ | |||
65 | 65 | ||
66 | #define L2TP_HDR_VER_MASK 0x000F | 66 | #define L2TP_HDR_VER_MASK 0x000F |
67 | #define L2TP_HDR_VER_2 0x0002 | 67 | #define L2TP_HDR_VER_2 0x0002 |
68 | #define L2TP_HDR_VER_3 0x0003 | ||
68 | 69 | ||
69 | /* L2TPv3 default L2-specific sublayer */ | 70 | /* L2TPv3 default L2-specific sublayer */ |
70 | #define L2TP_SLFLAG_S 0x40000000 | 71 | #define L2TP_SLFLAG_S 0x40000000 |
@@ -85,7 +86,7 @@ | |||
85 | /* Private data stored for received packets in the skb. | 86 | /* Private data stored for received packets in the skb. |
86 | */ | 87 | */ |
87 | struct l2tp_skb_cb { | 88 | struct l2tp_skb_cb { |
88 | u16 ns; | 89 | u32 ns; |
89 | u16 has_seq; | 90 | u16 has_seq; |
90 | u16 length; | 91 | u16 length; |
91 | unsigned long expires; | 92 | unsigned long expires; |
@@ -101,6 +102,8 @@ static unsigned int l2tp_net_id; | |||
101 | struct l2tp_net { | 102 | struct l2tp_net { |
102 | struct list_head l2tp_tunnel_list; | 103 | struct list_head l2tp_tunnel_list; |
103 | rwlock_t l2tp_tunnel_list_lock; | 104 | rwlock_t l2tp_tunnel_list_lock; |
105 | struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2]; | ||
106 | rwlock_t l2tp_session_hlist_lock; | ||
104 | }; | 107 | }; |
105 | 108 | ||
106 | static inline struct l2tp_net *l2tp_pernet(struct net *net) | 109 | static inline struct l2tp_net *l2tp_pernet(struct net *net) |
@@ -110,6 +113,40 @@ static inline struct l2tp_net *l2tp_pernet(struct net *net) | |||
110 | return net_generic(net, l2tp_net_id); | 113 | return net_generic(net, l2tp_net_id); |
111 | } | 114 | } |
112 | 115 | ||
116 | /* Session hash global list for L2TPv3. | ||
117 | * The session_id SHOULD be random according to RFC3931, but several | ||
118 | * L2TP implementations use incrementing session_ids. So we do a real | ||
119 | * hash on the session_id, rather than a simple bitmask. | ||
120 | */ | ||
121 | static inline struct hlist_head * | ||
122 | l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id) | ||
123 | { | ||
124 | return &pn->l2tp_session_hlist[hash_32(session_id, L2TP_HASH_BITS_2)]; | ||
125 | |||
126 | } | ||
127 | |||
128 | /* Lookup a session by id in the global session list | ||
129 | */ | ||
130 | static struct l2tp_session *l2tp_session_find_2(struct net *net, u32 session_id) | ||
131 | { | ||
132 | struct l2tp_net *pn = l2tp_pernet(net); | ||
133 | struct hlist_head *session_list = | ||
134 | l2tp_session_id_hash_2(pn, session_id); | ||
135 | struct l2tp_session *session; | ||
136 | struct hlist_node *walk; | ||
137 | |||
138 | read_lock_bh(&pn->l2tp_session_hlist_lock); | ||
139 | hlist_for_each_entry(session, walk, session_list, global_hlist) { | ||
140 | if (session->session_id == session_id) { | ||
141 | read_unlock_bh(&pn->l2tp_session_hlist_lock); | ||
142 | return session; | ||
143 | } | ||
144 | } | ||
145 | read_unlock_bh(&pn->l2tp_session_hlist_lock); | ||
146 | |||
147 | return NULL; | ||
148 | } | ||
149 | |||
113 | /* Session hash list. | 150 | /* Session hash list. |
114 | * The session_id SHOULD be random according to RFC2661, but several | 151 | * The session_id SHOULD be random according to RFC2661, but several |
115 | * L2TP implementations (Cisco and Microsoft) use incrementing | 152 | * L2TP implementations (Cisco and Microsoft) use incrementing |
@@ -124,13 +161,20 @@ l2tp_session_id_hash(struct l2tp_tunnel *tunnel, u32 session_id) | |||
124 | 161 | ||
125 | /* Lookup a session by id | 162 | /* Lookup a session by id |
126 | */ | 163 | */ |
127 | struct l2tp_session *l2tp_session_find(struct l2tp_tunnel *tunnel, u32 session_id) | 164 | struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id) |
128 | { | 165 | { |
129 | struct hlist_head *session_list = | 166 | struct hlist_head *session_list; |
130 | l2tp_session_id_hash(tunnel, session_id); | ||
131 | struct l2tp_session *session; | 167 | struct l2tp_session *session; |
132 | struct hlist_node *walk; | 168 | struct hlist_node *walk; |
133 | 169 | ||
170 | /* In L2TPv3, session_ids are unique over all tunnels and we | ||
171 | * sometimes need to look them up before we know the | ||
172 | * tunnel. | ||
173 | */ | ||
174 | if (tunnel == NULL) | ||
175 | return l2tp_session_find_2(net, session_id); | ||
176 | |||
177 | session_list = l2tp_session_id_hash(tunnel, session_id); | ||
134 | read_lock_bh(&tunnel->hlist_lock); | 178 | read_lock_bh(&tunnel->hlist_lock); |
135 | hlist_for_each_entry(session, walk, session_list, hlist) { | 179 | hlist_for_each_entry(session, walk, session_list, hlist) { |
136 | if (session->session_id == session_id) { | 180 | if (session->session_id == session_id) { |
@@ -218,7 +262,7 @@ static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *sk | |||
218 | { | 262 | { |
219 | struct sk_buff *skbp; | 263 | struct sk_buff *skbp; |
220 | struct sk_buff *tmp; | 264 | struct sk_buff *tmp; |
221 | u16 ns = L2TP_SKB_CB(skb)->ns; | 265 | u32 ns = L2TP_SKB_CB(skb)->ns; |
222 | 266 | ||
223 | spin_lock_bh(&session->reorder_q.lock); | 267 | spin_lock_bh(&session->reorder_q.lock); |
224 | skb_queue_walk_safe(&session->reorder_q, skbp, tmp) { | 268 | skb_queue_walk_safe(&session->reorder_q, skbp, tmp) { |
@@ -259,6 +303,11 @@ static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff * | |||
259 | if (L2TP_SKB_CB(skb)->has_seq) { | 303 | if (L2TP_SKB_CB(skb)->has_seq) { |
260 | /* Bump our Nr */ | 304 | /* Bump our Nr */ |
261 | session->nr++; | 305 | session->nr++; |
306 | if (tunnel->version == L2TP_HDR_VER_2) | ||
307 | session->nr &= 0xffff; | ||
308 | else | ||
309 | session->nr &= 0xffffff; | ||
310 | |||
262 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | 311 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, |
263 | "%s: updated nr to %hu\n", session->name, session->nr); | 312 | "%s: updated nr to %hu\n", session->name, session->nr); |
264 | } | 313 | } |
@@ -291,8 +340,8 @@ static void l2tp_recv_dequeue(struct l2tp_session *session) | |||
291 | session->stats.rx_seq_discards++; | 340 | session->stats.rx_seq_discards++; |
292 | session->stats.rx_errors++; | 341 | session->stats.rx_errors++; |
293 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | 342 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, |
294 | "%s: oos pkt %hu len %d discarded (too old), " | 343 | "%s: oos pkt %u len %d discarded (too old), " |
295 | "waiting for %hu, reorder_q_len=%d\n", | 344 | "waiting for %u, reorder_q_len=%d\n", |
296 | session->name, L2TP_SKB_CB(skb)->ns, | 345 | session->name, L2TP_SKB_CB(skb)->ns, |
297 | L2TP_SKB_CB(skb)->length, session->nr, | 346 | L2TP_SKB_CB(skb)->length, session->nr, |
298 | skb_queue_len(&session->reorder_q)); | 347 | skb_queue_len(&session->reorder_q)); |
@@ -306,8 +355,8 @@ static void l2tp_recv_dequeue(struct l2tp_session *session) | |||
306 | if (L2TP_SKB_CB(skb)->has_seq) { | 355 | if (L2TP_SKB_CB(skb)->has_seq) { |
307 | if (L2TP_SKB_CB(skb)->ns != session->nr) { | 356 | if (L2TP_SKB_CB(skb)->ns != session->nr) { |
308 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | 357 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, |
309 | "%s: holding oos pkt %hu len %d, " | 358 | "%s: holding oos pkt %u len %d, " |
310 | "waiting for %hu, reorder_q_len=%d\n", | 359 | "waiting for %u, reorder_q_len=%d\n", |
311 | session->name, L2TP_SKB_CB(skb)->ns, | 360 | session->name, L2TP_SKB_CB(skb)->ns, |
312 | L2TP_SKB_CB(skb)->length, session->nr, | 361 | L2TP_SKB_CB(skb)->length, session->nr, |
313 | skb_queue_len(&session->reorder_q)); | 362 | skb_queue_len(&session->reorder_q)); |
@@ -352,100 +401,73 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk, | |||
352 | return __skb_checksum_complete(skb); | 401 | return __skb_checksum_complete(skb); |
353 | } | 402 | } |
354 | 403 | ||
355 | /* Internal UDP receive frame. Do the real work of receiving an L2TP data frame | 404 | /* Do receive processing of L2TP data frames. We handle both L2TPv2 |
356 | * here. The skb is not on a list when we get here. | 405 | * and L2TPv3 data frames here. |
357 | * Returns 0 if the packet was a data packet and was successfully passed on. | 406 | * |
358 | * Returns 1 if the packet was not a good data packet and could not be | 407 | * L2TPv2 Data Message Header |
359 | * forwarded. All such packets are passed up to userspace to deal with. | 408 | * |
409 | * 0 1 2 3 | ||
410 | * 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 | ||
411 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
412 | * |T|L|x|x|S|x|O|P|x|x|x|x| Ver | Length (opt) | | ||
413 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
414 | * | Tunnel ID | Session ID | | ||
415 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
416 | * | Ns (opt) | Nr (opt) | | ||
417 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
418 | * | Offset Size (opt) | Offset pad... (opt) | ||
419 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
420 | * | ||
421 | * Data frames are marked by T=0. All other fields are the same as | ||
422 | * those in L2TP control frames. | ||
423 | * | ||
424 | * L2TPv3 Data Message Header | ||
425 | * | ||
426 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
427 | * | L2TP Session Header | | ||
428 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
429 | * | L2-Specific Sublayer | | ||
430 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
431 | * | Tunnel Payload ... | ||
432 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
433 | * | ||
434 | * L2TPv3 Session Header Over IP | ||
435 | * | ||
436 | * 0 1 2 3 | ||
437 | * 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 | ||
438 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
439 | * | Session ID | | ||
440 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
441 | * | Cookie (optional, maximum 64 bits)... | ||
442 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
443 | * | | ||
444 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
445 | * | ||
446 | * L2TPv3 L2-Specific Sublayer Format | ||
447 | * | ||
448 | * 0 1 2 3 | ||
449 | * 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 | ||
450 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
451 | * |x|S|x|x|x|x|x|x| Sequence Number | | ||
452 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
453 | * | ||
454 | * Cookie value, sublayer format and offset (pad) are negotiated with | ||
455 | * the peer when the session is set up. Unlike L2TPv2, we do not need | ||
456 | * to parse the packet header to determine if optional fields are | ||
457 | * present. | ||
458 | * | ||
459 | * Caller must already have parsed the frame and determined that it is | ||
460 | * a data (not control) frame before coming here. Fields up to the | ||
461 | * session-id have already been parsed and ptr points to the data | ||
462 | * after the session-id. | ||
360 | */ | 463 | */ |
361 | int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | 464 | void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, |
362 | int (*payload_hook)(struct sk_buff *skb)) | 465 | unsigned char *ptr, unsigned char *optr, u16 hdrflags, |
466 | int length, int (*payload_hook)(struct sk_buff *skb)) | ||
363 | { | 467 | { |
364 | struct l2tp_session *session = NULL; | 468 | struct l2tp_tunnel *tunnel = session->tunnel; |
365 | unsigned char *ptr, *optr; | ||
366 | u16 hdrflags; | ||
367 | u32 tunnel_id, session_id; | ||
368 | int length; | ||
369 | int offset; | 469 | int offset; |
370 | u16 version; | 470 | u32 ns, nr; |
371 | u16 ns, nr; | ||
372 | |||
373 | if (tunnel->sock && l2tp_verify_udp_checksum(tunnel->sock, skb)) | ||
374 | goto discard_bad_csum; | ||
375 | |||
376 | /* UDP always verifies the packet length. */ | ||
377 | __skb_pull(skb, sizeof(struct udphdr)); | ||
378 | |||
379 | /* Short packet? */ | ||
380 | if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) { | ||
381 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO, | ||
382 | "%s: recv short packet (len=%d)\n", tunnel->name, skb->len); | ||
383 | goto error; | ||
384 | } | ||
385 | |||
386 | /* Point to L2TP header */ | ||
387 | optr = ptr = skb->data; | ||
388 | |||
389 | /* Trace packet contents, if enabled */ | ||
390 | if (tunnel->debug & L2TP_MSG_DATA) { | ||
391 | length = min(32u, skb->len); | ||
392 | if (!pskb_may_pull(skb, length)) | ||
393 | goto error; | ||
394 | |||
395 | printk(KERN_DEBUG "%s: recv: ", tunnel->name); | ||
396 | |||
397 | offset = 0; | ||
398 | do { | ||
399 | printk(" %02X", ptr[offset]); | ||
400 | } while (++offset < length); | ||
401 | |||
402 | printk("\n"); | ||
403 | } | ||
404 | |||
405 | /* Get L2TP header flags */ | ||
406 | hdrflags = ntohs(*(__be16 *)ptr); | ||
407 | |||
408 | /* Check protocol version */ | ||
409 | version = hdrflags & L2TP_HDR_VER_MASK; | ||
410 | if (version != tunnel->version) { | ||
411 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO, | ||
412 | "%s: recv protocol version mismatch: got %d expected %d\n", | ||
413 | tunnel->name, version, tunnel->version); | ||
414 | goto error; | ||
415 | } | ||
416 | |||
417 | /* Get length of L2TP packet */ | ||
418 | length = skb->len; | ||
419 | |||
420 | /* If type is control packet, it is handled by userspace. */ | ||
421 | if (hdrflags & L2TP_HDRFLAG_T) { | ||
422 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_DEBUG, | ||
423 | "%s: recv control packet, len=%d\n", tunnel->name, length); | ||
424 | goto error; | ||
425 | } | ||
426 | |||
427 | /* Skip flags */ | ||
428 | ptr += 2; | ||
429 | |||
430 | /* If length is present, skip it */ | ||
431 | if (hdrflags & L2TP_HDRFLAG_L) | ||
432 | ptr += 2; | ||
433 | |||
434 | /* Extract tunnel and session ID */ | ||
435 | tunnel_id = ntohs(*(__be16 *) ptr); | ||
436 | ptr += 2; | ||
437 | session_id = ntohs(*(__be16 *) ptr); | ||
438 | ptr += 2; | ||
439 | |||
440 | /* Find the session context */ | ||
441 | session = l2tp_session_find(tunnel, session_id); | ||
442 | if (!session) { | ||
443 | /* Not found? Pass to userspace to deal with */ | ||
444 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO, | ||
445 | "%s: no session found (%hu/%hu). Passing up.\n", | ||
446 | tunnel->name, tunnel_id, session_id); | ||
447 | goto error; | ||
448 | } | ||
449 | 471 | ||
450 | /* The ref count is increased since we now hold a pointer to | 472 | /* The ref count is increased since we now hold a pointer to |
451 | * the session. Take care to decrement the refcnt when exiting | 473 | * the session. Take care to decrement the refcnt when exiting |
@@ -455,6 +477,18 @@ int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | |||
455 | if (session->ref) | 477 | if (session->ref) |
456 | (*session->ref)(session); | 478 | (*session->ref)(session); |
457 | 479 | ||
480 | /* Parse and check optional cookie */ | ||
481 | if (session->peer_cookie_len > 0) { | ||
482 | if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) { | ||
483 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO, | ||
484 | "%s: cookie mismatch (%u/%u). Discarding.\n", | ||
485 | tunnel->name, tunnel->tunnel_id, session->session_id); | ||
486 | session->stats.rx_cookie_discards++; | ||
487 | goto discard; | ||
488 | } | ||
489 | ptr += session->peer_cookie_len; | ||
490 | } | ||
491 | |||
458 | /* Handle the optional sequence numbers. Sequence numbers are | 492 | /* Handle the optional sequence numbers. Sequence numbers are |
459 | * in different places for L2TPv2 and L2TPv3. | 493 | * in different places for L2TPv2 and L2TPv3. |
460 | * | 494 | * |
@@ -464,21 +498,40 @@ int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | |||
464 | */ | 498 | */ |
465 | ns = nr = 0; | 499 | ns = nr = 0; |
466 | L2TP_SKB_CB(skb)->has_seq = 0; | 500 | L2TP_SKB_CB(skb)->has_seq = 0; |
467 | if (hdrflags & L2TP_HDRFLAG_S) { | 501 | if (tunnel->version == L2TP_HDR_VER_2) { |
468 | ns = (u16) ntohs(*(__be16 *) ptr); | 502 | if (hdrflags & L2TP_HDRFLAG_S) { |
469 | ptr += 2; | 503 | ns = ntohs(*(__be16 *) ptr); |
470 | nr = ntohs(*(__be16 *) ptr); | 504 | ptr += 2; |
471 | ptr += 2; | 505 | nr = ntohs(*(__be16 *) ptr); |
506 | ptr += 2; | ||
472 | 507 | ||
473 | /* Store L2TP info in the skb */ | 508 | /* Store L2TP info in the skb */ |
474 | L2TP_SKB_CB(skb)->ns = ns; | 509 | L2TP_SKB_CB(skb)->ns = ns; |
475 | L2TP_SKB_CB(skb)->has_seq = 1; | 510 | L2TP_SKB_CB(skb)->has_seq = 1; |
476 | 511 | ||
477 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | 512 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, |
478 | "%s: recv data ns=%hu, nr=%hu, session nr=%hu\n", | 513 | "%s: recv data ns=%u, nr=%u, session nr=%u\n", |
479 | session->name, ns, nr, session->nr); | 514 | session->name, ns, nr, session->nr); |
515 | } | ||
516 | } else if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) { | ||
517 | u32 l2h = ntohl(*(__be32 *) ptr); | ||
518 | |||
519 | if (l2h & 0x40000000) { | ||
520 | ns = l2h & 0x00ffffff; | ||
521 | |||
522 | /* Store L2TP info in the skb */ | ||
523 | L2TP_SKB_CB(skb)->ns = ns; | ||
524 | L2TP_SKB_CB(skb)->has_seq = 1; | ||
525 | |||
526 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | ||
527 | "%s: recv data ns=%u, session nr=%u\n", | ||
528 | session->name, ns, session->nr); | ||
529 | } | ||
480 | } | 530 | } |
481 | 531 | ||
532 | /* Advance past L2-specific header, if present */ | ||
533 | ptr += session->l2specific_len; | ||
534 | |||
482 | if (L2TP_SKB_CB(skb)->has_seq) { | 535 | if (L2TP_SKB_CB(skb)->has_seq) { |
483 | /* Received a packet with sequence numbers. If we're the LNS, | 536 | /* Received a packet with sequence numbers. If we're the LNS, |
484 | * check if we sre sending sequence numbers and if not, | 537 | * check if we sre sending sequence numbers and if not, |
@@ -489,6 +542,7 @@ int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | |||
489 | "%s: requested to enable seq numbers by LNS\n", | 542 | "%s: requested to enable seq numbers by LNS\n", |
490 | session->name); | 543 | session->name); |
491 | session->send_seq = -1; | 544 | session->send_seq = -1; |
545 | l2tp_session_set_header_len(session, tunnel->version); | ||
492 | } | 546 | } |
493 | } else { | 547 | } else { |
494 | /* No sequence numbers. | 548 | /* No sequence numbers. |
@@ -512,6 +566,7 @@ int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | |||
512 | "%s: requested to disable seq numbers by LNS\n", | 566 | "%s: requested to disable seq numbers by LNS\n", |
513 | session->name); | 567 | session->name); |
514 | session->send_seq = 0; | 568 | session->send_seq = 0; |
569 | l2tp_session_set_header_len(session, tunnel->version); | ||
515 | } else if (session->send_seq) { | 570 | } else if (session->send_seq) { |
516 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_WARNING, | 571 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_WARNING, |
517 | "%s: recv data has no seq numbers when required. " | 572 | "%s: recv data has no seq numbers when required. " |
@@ -521,11 +576,19 @@ int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | |||
521 | } | 576 | } |
522 | } | 577 | } |
523 | 578 | ||
524 | /* If offset bit set, skip it. */ | 579 | /* Session data offset is handled differently for L2TPv2 and |
525 | if (hdrflags & L2TP_HDRFLAG_O) { | 580 | * L2TPv3. For L2TPv2, there is an optional 16-bit value in |
526 | offset = ntohs(*(__be16 *)ptr); | 581 | * the header. For L2TPv3, the offset is negotiated using AVPs |
527 | ptr += 2 + offset; | 582 | * in the session setup control protocol. |
528 | } | 583 | */ |
584 | if (tunnel->version == L2TP_HDR_VER_2) { | ||
585 | /* If offset bit set, skip it. */ | ||
586 | if (hdrflags & L2TP_HDRFLAG_O) { | ||
587 | offset = ntohs(*(__be16 *)ptr); | ||
588 | ptr += 2 + offset; | ||
589 | } | ||
590 | } else | ||
591 | ptr += session->offset; | ||
529 | 592 | ||
530 | offset = ptr - optr; | 593 | offset = ptr - optr; |
531 | if (!pskb_may_pull(skb, offset)) | 594 | if (!pskb_may_pull(skb, offset)) |
@@ -564,8 +627,8 @@ int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | |||
564 | if (L2TP_SKB_CB(skb)->ns != session->nr) { | 627 | if (L2TP_SKB_CB(skb)->ns != session->nr) { |
565 | session->stats.rx_seq_discards++; | 628 | session->stats.rx_seq_discards++; |
566 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | 629 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, |
567 | "%s: oos pkt %hu len %d discarded, " | 630 | "%s: oos pkt %u len %d discarded, " |
568 | "waiting for %hu, reorder_q_len=%d\n", | 631 | "waiting for %u, reorder_q_len=%d\n", |
569 | session->name, L2TP_SKB_CB(skb)->ns, | 632 | session->name, L2TP_SKB_CB(skb)->ns, |
570 | L2TP_SKB_CB(skb)->length, session->nr, | 633 | L2TP_SKB_CB(skb)->length, session->nr, |
571 | skb_queue_len(&session->reorder_q)); | 634 | skb_queue_len(&session->reorder_q)); |
@@ -586,7 +649,7 @@ int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | |||
586 | 649 | ||
587 | l2tp_session_dec_refcount(session); | 650 | l2tp_session_dec_refcount(session); |
588 | 651 | ||
589 | return 0; | 652 | return; |
590 | 653 | ||
591 | discard: | 654 | discard: |
592 | session->stats.rx_errors++; | 655 | session->stats.rx_errors++; |
@@ -596,6 +659,111 @@ discard: | |||
596 | (*session->deref)(session); | 659 | (*session->deref)(session); |
597 | 660 | ||
598 | l2tp_session_dec_refcount(session); | 661 | l2tp_session_dec_refcount(session); |
662 | } | ||
663 | EXPORT_SYMBOL(l2tp_recv_common); | ||
664 | |||
665 | /* Internal UDP receive frame. Do the real work of receiving an L2TP data frame | ||
666 | * here. The skb is not on a list when we get here. | ||
667 | * Returns 0 if the packet was a data packet and was successfully passed on. | ||
668 | * Returns 1 if the packet was not a good data packet and could not be | ||
669 | * forwarded. All such packets are passed up to userspace to deal with. | ||
670 | */ | ||
671 | int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | ||
672 | int (*payload_hook)(struct sk_buff *skb)) | ||
673 | { | ||
674 | struct l2tp_session *session = NULL; | ||
675 | unsigned char *ptr, *optr; | ||
676 | u16 hdrflags; | ||
677 | u32 tunnel_id, session_id; | ||
678 | int offset; | ||
679 | u16 version; | ||
680 | int length; | ||
681 | |||
682 | if (tunnel->sock && l2tp_verify_udp_checksum(tunnel->sock, skb)) | ||
683 | goto discard_bad_csum; | ||
684 | |||
685 | /* UDP always verifies the packet length. */ | ||
686 | __skb_pull(skb, sizeof(struct udphdr)); | ||
687 | |||
688 | /* Short packet? */ | ||
689 | if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) { | ||
690 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO, | ||
691 | "%s: recv short packet (len=%d)\n", tunnel->name, skb->len); | ||
692 | goto error; | ||
693 | } | ||
694 | |||
695 | /* Point to L2TP header */ | ||
696 | optr = ptr = skb->data; | ||
697 | |||
698 | /* Trace packet contents, if enabled */ | ||
699 | if (tunnel->debug & L2TP_MSG_DATA) { | ||
700 | length = min(32u, skb->len); | ||
701 | if (!pskb_may_pull(skb, length)) | ||
702 | goto error; | ||
703 | |||
704 | printk(KERN_DEBUG "%s: recv: ", tunnel->name); | ||
705 | |||
706 | offset = 0; | ||
707 | do { | ||
708 | printk(" %02X", ptr[offset]); | ||
709 | } while (++offset < length); | ||
710 | |||
711 | printk("\n"); | ||
712 | } | ||
713 | |||
714 | /* Get L2TP header flags */ | ||
715 | hdrflags = ntohs(*(__be16 *) ptr); | ||
716 | |||
717 | /* Check protocol version */ | ||
718 | version = hdrflags & L2TP_HDR_VER_MASK; | ||
719 | if (version != tunnel->version) { | ||
720 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO, | ||
721 | "%s: recv protocol version mismatch: got %d expected %d\n", | ||
722 | tunnel->name, version, tunnel->version); | ||
723 | goto error; | ||
724 | } | ||
725 | |||
726 | /* Get length of L2TP packet */ | ||
727 | length = skb->len; | ||
728 | |||
729 | /* If type is control packet, it is handled by userspace. */ | ||
730 | if (hdrflags & L2TP_HDRFLAG_T) { | ||
731 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_DEBUG, | ||
732 | "%s: recv control packet, len=%d\n", tunnel->name, length); | ||
733 | goto error; | ||
734 | } | ||
735 | |||
736 | /* Skip flags */ | ||
737 | ptr += 2; | ||
738 | |||
739 | if (tunnel->version == L2TP_HDR_VER_2) { | ||
740 | /* If length is present, skip it */ | ||
741 | if (hdrflags & L2TP_HDRFLAG_L) | ||
742 | ptr += 2; | ||
743 | |||
744 | /* Extract tunnel and session ID */ | ||
745 | tunnel_id = ntohs(*(__be16 *) ptr); | ||
746 | ptr += 2; | ||
747 | session_id = ntohs(*(__be16 *) ptr); | ||
748 | ptr += 2; | ||
749 | } else { | ||
750 | ptr += 2; /* skip reserved bits */ | ||
751 | tunnel_id = tunnel->tunnel_id; | ||
752 | session_id = ntohl(*(__be32 *) ptr); | ||
753 | ptr += 4; | ||
754 | } | ||
755 | |||
756 | /* Find the session context */ | ||
757 | session = l2tp_session_find(tunnel->l2tp_net, tunnel, session_id); | ||
758 | if (!session) { | ||
759 | /* Not found? Pass to userspace to deal with */ | ||
760 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO, | ||
761 | "%s: no session found (%u/%u). Passing up.\n", | ||
762 | tunnel->name, tunnel_id, session_id); | ||
763 | goto error; | ||
764 | } | ||
765 | |||
766 | l2tp_recv_common(session, skb, ptr, optr, hdrflags, length, payload_hook); | ||
599 | 767 | ||
600 | return 0; | 768 | return 0; |
601 | 769 | ||
@@ -651,11 +819,11 @@ EXPORT_SYMBOL_GPL(l2tp_udp_encap_recv); | |||
651 | 819 | ||
652 | /* Build an L2TP header for the session into the buffer provided. | 820 | /* Build an L2TP header for the session into the buffer provided. |
653 | */ | 821 | */ |
654 | static void l2tp_build_l2tpv2_header(struct l2tp_tunnel *tunnel, | 822 | static int l2tp_build_l2tpv2_header(struct l2tp_session *session, void *buf) |
655 | struct l2tp_session *session, | ||
656 | void *buf) | ||
657 | { | 823 | { |
824 | struct l2tp_tunnel *tunnel = session->tunnel; | ||
658 | __be16 *bufp = buf; | 825 | __be16 *bufp = buf; |
826 | __be16 *optr = buf; | ||
659 | u16 flags = L2TP_HDR_VER_2; | 827 | u16 flags = L2TP_HDR_VER_2; |
660 | u32 tunnel_id = tunnel->peer_tunnel_id; | 828 | u32 tunnel_id = tunnel->peer_tunnel_id; |
661 | u32 session_id = session->peer_session_id; | 829 | u32 session_id = session->peer_session_id; |
@@ -671,19 +839,51 @@ static void l2tp_build_l2tpv2_header(struct l2tp_tunnel *tunnel, | |||
671 | *bufp++ = htons(session->ns); | 839 | *bufp++ = htons(session->ns); |
672 | *bufp++ = 0; | 840 | *bufp++ = 0; |
673 | session->ns++; | 841 | session->ns++; |
842 | session->ns &= 0xffff; | ||
674 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | 843 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, |
675 | "%s: updated ns to %hu\n", session->name, session->ns); | 844 | "%s: updated ns to %u\n", session->name, session->ns); |
676 | } | 845 | } |
846 | |||
847 | return bufp - optr; | ||
677 | } | 848 | } |
678 | 849 | ||
679 | void l2tp_build_l2tp_header(struct l2tp_session *session, void *buf) | 850 | static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf) |
680 | { | 851 | { |
681 | struct l2tp_tunnel *tunnel = session->tunnel; | 852 | char *bufp = buf; |
853 | char *optr = bufp; | ||
854 | u16 flags = L2TP_HDR_VER_3; | ||
855 | |||
856 | /* Setup L2TP header. */ | ||
857 | *((__be16 *) bufp) = htons(flags); | ||
858 | bufp += 2; | ||
859 | *((__be16 *) bufp) = 0; | ||
860 | bufp += 2; | ||
861 | *((__be32 *) bufp) = htonl(session->peer_session_id); | ||
862 | bufp += 4; | ||
863 | if (session->cookie_len) { | ||
864 | memcpy(bufp, &session->cookie[0], session->cookie_len); | ||
865 | bufp += session->cookie_len; | ||
866 | } | ||
867 | if (session->l2specific_len) { | ||
868 | if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) { | ||
869 | u32 l2h = 0; | ||
870 | if (session->send_seq) { | ||
871 | l2h = 0x40000000 | session->ns; | ||
872 | session->ns++; | ||
873 | session->ns &= 0xffffff; | ||
874 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | ||
875 | "%s: updated ns to %u\n", session->name, session->ns); | ||
876 | } | ||
877 | |||
878 | *((__be32 *) bufp) = htonl(l2h); | ||
879 | } | ||
880 | bufp += session->l2specific_len; | ||
881 | } | ||
882 | if (session->offset) | ||
883 | bufp += session->offset; | ||
682 | 884 | ||
683 | BUG_ON(tunnel->version != L2TP_HDR_VER_2); | 885 | return bufp - optr; |
684 | l2tp_build_l2tpv2_header(tunnel, session, buf); | ||
685 | } | 886 | } |
686 | EXPORT_SYMBOL_GPL(l2tp_build_l2tp_header); | ||
687 | 887 | ||
688 | int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, size_t data_len) | 888 | int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, size_t data_len) |
689 | { | 889 | { |
@@ -694,7 +894,7 @@ int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, size_t dat | |||
694 | /* Debug */ | 894 | /* Debug */ |
695 | if (session->send_seq) | 895 | if (session->send_seq) |
696 | PRINTK(session->debug, L2TP_MSG_DATA, KERN_DEBUG, | 896 | PRINTK(session->debug, L2TP_MSG_DATA, KERN_DEBUG, |
697 | "%s: send %Zd bytes, ns=%hu\n", session->name, | 897 | "%s: send %Zd bytes, ns=%u\n", session->name, |
698 | data_len, session->ns - 1); | 898 | data_len, session->ns - 1); |
699 | else | 899 | else |
700 | PRINTK(session->debug, L2TP_MSG_DATA, KERN_DEBUG, | 900 | PRINTK(session->debug, L2TP_MSG_DATA, KERN_DEBUG, |
@@ -780,7 +980,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
780 | skb->truesize += new_headroom - old_headroom; | 980 | skb->truesize += new_headroom - old_headroom; |
781 | 981 | ||
782 | /* Setup L2TP header */ | 982 | /* Setup L2TP header */ |
783 | l2tp_build_l2tp_header(session, __skb_push(skb, hdr_len)); | 983 | session->build_header(session, __skb_push(skb, hdr_len)); |
784 | udp_len = sizeof(struct udphdr) + hdr_len + data_len; | 984 | udp_len = sizeof(struct udphdr) + hdr_len + data_len; |
785 | 985 | ||
786 | /* Setup UDP header */ | 986 | /* Setup UDP header */ |
@@ -791,7 +991,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
791 | uh->source = inet->inet_sport; | 991 | uh->source = inet->inet_sport; |
792 | uh->dest = inet->inet_dport; | 992 | uh->dest = inet->inet_dport; |
793 | uh->len = htons(udp_len); | 993 | uh->len = htons(udp_len); |
794 | |||
795 | uh->check = 0; | 994 | uh->check = 0; |
796 | 995 | ||
797 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 996 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
@@ -911,6 +1110,14 @@ again: | |||
911 | 1110 | ||
912 | write_unlock_bh(&tunnel->hlist_lock); | 1111 | write_unlock_bh(&tunnel->hlist_lock); |
913 | 1112 | ||
1113 | if (tunnel->version != L2TP_HDR_VER_2) { | ||
1114 | struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); | ||
1115 | |||
1116 | write_lock_bh(&pn->l2tp_session_hlist_lock); | ||
1117 | hlist_del_init(&session->global_hlist); | ||
1118 | write_unlock_bh(&pn->l2tp_session_hlist_lock); | ||
1119 | } | ||
1120 | |||
914 | if (session->session_close != NULL) | 1121 | if (session->session_close != NULL) |
915 | (*session->session_close)(session); | 1122 | (*session->session_close)(session); |
916 | 1123 | ||
@@ -997,9 +1204,6 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 | |||
997 | goto err; | 1204 | goto err; |
998 | } | 1205 | } |
999 | 1206 | ||
1000 | if (version != L2TP_HDR_VER_2) | ||
1001 | goto err; | ||
1002 | |||
1003 | tunnel = kzalloc(sizeof(struct l2tp_tunnel), GFP_KERNEL); | 1207 | tunnel = kzalloc(sizeof(struct l2tp_tunnel), GFP_KERNEL); |
1004 | if (tunnel == NULL) { | 1208 | if (tunnel == NULL) { |
1005 | err = -ENOMEM; | 1209 | err = -ENOMEM; |
@@ -1077,6 +1281,15 @@ void l2tp_session_free(struct l2tp_session *session) | |||
1077 | hlist_del_init(&session->hlist); | 1281 | hlist_del_init(&session->hlist); |
1078 | write_unlock_bh(&tunnel->hlist_lock); | 1282 | write_unlock_bh(&tunnel->hlist_lock); |
1079 | 1283 | ||
1284 | /* Unlink from the global hash if not L2TPv2 */ | ||
1285 | if (tunnel->version != L2TP_HDR_VER_2) { | ||
1286 | struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); | ||
1287 | |||
1288 | write_lock_bh(&pn->l2tp_session_hlist_lock); | ||
1289 | hlist_del_init(&session->global_hlist); | ||
1290 | write_unlock_bh(&pn->l2tp_session_hlist_lock); | ||
1291 | } | ||
1292 | |||
1080 | if (session->session_id != 0) | 1293 | if (session->session_id != 0) |
1081 | atomic_dec(&l2tp_session_count); | 1294 | atomic_dec(&l2tp_session_count); |
1082 | 1295 | ||
@@ -1095,6 +1308,22 @@ void l2tp_session_free(struct l2tp_session *session) | |||
1095 | } | 1308 | } |
1096 | EXPORT_SYMBOL_GPL(l2tp_session_free); | 1309 | EXPORT_SYMBOL_GPL(l2tp_session_free); |
1097 | 1310 | ||
1311 | /* We come here whenever a session's send_seq, cookie_len or | ||
1312 | * l2specific_len parameters are set. | ||
1313 | */ | ||
1314 | void l2tp_session_set_header_len(struct l2tp_session *session, int version) | ||
1315 | { | ||
1316 | if (version == L2TP_HDR_VER_2) { | ||
1317 | session->hdr_len = 6; | ||
1318 | if (session->send_seq) | ||
1319 | session->hdr_len += 4; | ||
1320 | } else { | ||
1321 | session->hdr_len = 8 + session->cookie_len + session->l2specific_len + session->offset; | ||
1322 | } | ||
1323 | |||
1324 | } | ||
1325 | EXPORT_SYMBOL_GPL(l2tp_session_set_header_len); | ||
1326 | |||
1098 | 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) | 1327 | 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) |
1099 | { | 1328 | { |
1100 | struct l2tp_session *session; | 1329 | struct l2tp_session *session; |
@@ -1106,6 +1335,7 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn | |||
1106 | 1335 | ||
1107 | session->session_id = session_id; | 1336 | session->session_id = session_id; |
1108 | session->peer_session_id = peer_session_id; | 1337 | session->peer_session_id = peer_session_id; |
1338 | session->nr = 1; | ||
1109 | 1339 | ||
1110 | sprintf(&session->name[0], "sess %u/%u", | 1340 | sprintf(&session->name[0], "sess %u/%u", |
1111 | tunnel->tunnel_id, session->session_id); | 1341 | tunnel->tunnel_id, session->session_id); |
@@ -1113,20 +1343,36 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn | |||
1113 | skb_queue_head_init(&session->reorder_q); | 1343 | skb_queue_head_init(&session->reorder_q); |
1114 | 1344 | ||
1115 | INIT_HLIST_NODE(&session->hlist); | 1345 | INIT_HLIST_NODE(&session->hlist); |
1346 | INIT_HLIST_NODE(&session->global_hlist); | ||
1116 | 1347 | ||
1117 | /* Inherit debug options from tunnel */ | 1348 | /* Inherit debug options from tunnel */ |
1118 | session->debug = tunnel->debug; | 1349 | session->debug = tunnel->debug; |
1119 | 1350 | ||
1120 | if (cfg) { | 1351 | if (cfg) { |
1352 | session->pwtype = cfg->pw_type; | ||
1121 | session->debug = cfg->debug; | 1353 | session->debug = cfg->debug; |
1122 | session->hdr_len = cfg->hdr_len; | ||
1123 | session->mtu = cfg->mtu; | 1354 | session->mtu = cfg->mtu; |
1124 | session->mru = cfg->mru; | 1355 | session->mru = cfg->mru; |
1125 | session->send_seq = cfg->send_seq; | 1356 | session->send_seq = cfg->send_seq; |
1126 | session->recv_seq = cfg->recv_seq; | 1357 | session->recv_seq = cfg->recv_seq; |
1127 | session->lns_mode = cfg->lns_mode; | 1358 | session->lns_mode = cfg->lns_mode; |
1359 | session->reorder_timeout = cfg->reorder_timeout; | ||
1360 | session->offset = cfg->offset; | ||
1361 | session->l2specific_type = cfg->l2specific_type; | ||
1362 | session->l2specific_len = cfg->l2specific_len; | ||
1363 | session->cookie_len = cfg->cookie_len; | ||
1364 | memcpy(&session->cookie[0], &cfg->cookie[0], cfg->cookie_len); | ||
1365 | session->peer_cookie_len = cfg->peer_cookie_len; | ||
1366 | memcpy(&session->peer_cookie[0], &cfg->peer_cookie[0], cfg->peer_cookie_len); | ||
1128 | } | 1367 | } |
1129 | 1368 | ||
1369 | if (tunnel->version == L2TP_HDR_VER_2) | ||
1370 | session->build_header = l2tp_build_l2tpv2_header; | ||
1371 | else | ||
1372 | session->build_header = l2tp_build_l2tpv3_header; | ||
1373 | |||
1374 | l2tp_session_set_header_len(session, tunnel->version); | ||
1375 | |||
1130 | /* Bump the reference count. The session context is deleted | 1376 | /* Bump the reference count. The session context is deleted |
1131 | * only when this drops to zero. | 1377 | * only when this drops to zero. |
1132 | */ | 1378 | */ |
@@ -1142,6 +1388,16 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn | |||
1142 | l2tp_session_id_hash(tunnel, session_id)); | 1388 | l2tp_session_id_hash(tunnel, session_id)); |
1143 | write_unlock_bh(&tunnel->hlist_lock); | 1389 | write_unlock_bh(&tunnel->hlist_lock); |
1144 | 1390 | ||
1391 | /* And to the global session list if L2TPv3 */ | ||
1392 | if (tunnel->version != L2TP_HDR_VER_2) { | ||
1393 | struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); | ||
1394 | |||
1395 | write_lock_bh(&pn->l2tp_session_hlist_lock); | ||
1396 | hlist_add_head(&session->global_hlist, | ||
1397 | l2tp_session_id_hash_2(pn, session_id)); | ||
1398 | write_unlock_bh(&pn->l2tp_session_hlist_lock); | ||
1399 | } | ||
1400 | |||
1145 | /* Ignore management session in session count value */ | 1401 | /* Ignore management session in session count value */ |
1146 | if (session->session_id != 0) | 1402 | if (session->session_id != 0) |
1147 | atomic_inc(&l2tp_session_count); | 1403 | atomic_inc(&l2tp_session_count); |
@@ -1159,6 +1415,7 @@ static __net_init int l2tp_init_net(struct net *net) | |||
1159 | { | 1415 | { |
1160 | struct l2tp_net *pn; | 1416 | struct l2tp_net *pn; |
1161 | int err; | 1417 | int err; |
1418 | int hash; | ||
1162 | 1419 | ||
1163 | pn = kzalloc(sizeof(*pn), GFP_KERNEL); | 1420 | pn = kzalloc(sizeof(*pn), GFP_KERNEL); |
1164 | if (!pn) | 1421 | if (!pn) |
@@ -1167,6 +1424,11 @@ static __net_init int l2tp_init_net(struct net *net) | |||
1167 | INIT_LIST_HEAD(&pn->l2tp_tunnel_list); | 1424 | INIT_LIST_HEAD(&pn->l2tp_tunnel_list); |
1168 | rwlock_init(&pn->l2tp_tunnel_list_lock); | 1425 | rwlock_init(&pn->l2tp_tunnel_list_lock); |
1169 | 1426 | ||
1427 | for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) | ||
1428 | INIT_HLIST_HEAD(&pn->l2tp_session_hlist[hash]); | ||
1429 | |||
1430 | rwlock_init(&pn->l2tp_session_hlist_lock); | ||
1431 | |||
1170 | err = net_assign_generic(net, l2tp_net_id, pn); | 1432 | err = net_assign_generic(net, l2tp_net_id, pn); |
1171 | if (err) | 1433 | if (err) |
1172 | goto out; | 1434 | goto out; |
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 2efe1a3ada9..5c53eb2a8ad 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h | |||
@@ -15,9 +15,14 @@ | |||
15 | #define L2TP_TUNNEL_MAGIC 0x42114DDA | 15 | #define L2TP_TUNNEL_MAGIC 0x42114DDA |
16 | #define L2TP_SESSION_MAGIC 0x0C04EB7D | 16 | #define L2TP_SESSION_MAGIC 0x0C04EB7D |
17 | 17 | ||
18 | /* Per tunnel, session hash table size */ | ||
18 | #define L2TP_HASH_BITS 4 | 19 | #define L2TP_HASH_BITS 4 |
19 | #define L2TP_HASH_SIZE (1 << L2TP_HASH_BITS) | 20 | #define L2TP_HASH_SIZE (1 << L2TP_HASH_BITS) |
20 | 21 | ||
22 | /* System-wide, session hash table size */ | ||
23 | #define L2TP_HASH_BITS_2 8 | ||
24 | #define L2TP_HASH_SIZE_2 (1 << L2TP_HASH_BITS_2) | ||
25 | |||
21 | /* Debug message categories for the DEBUG socket option */ | 26 | /* Debug message categories for the DEBUG socket option */ |
22 | enum { | 27 | enum { |
23 | L2TP_MSG_DEBUG = (1 << 0), /* verbose debug (if | 28 | L2TP_MSG_DEBUG = (1 << 0), /* verbose debug (if |
@@ -28,6 +33,21 @@ enum { | |||
28 | L2TP_MSG_DATA = (1 << 3), /* data packets */ | 33 | L2TP_MSG_DATA = (1 << 3), /* data packets */ |
29 | }; | 34 | }; |
30 | 35 | ||
36 | enum l2tp_pwtype { | ||
37 | L2TP_PWTYPE_NONE = 0x0000, | ||
38 | L2TP_PWTYPE_ETH_VLAN = 0x0004, | ||
39 | L2TP_PWTYPE_ETH = 0x0005, | ||
40 | L2TP_PWTYPE_PPP = 0x0007, | ||
41 | L2TP_PWTYPE_PPP_AC = 0x0008, | ||
42 | L2TP_PWTYPE_IP = 0x000b, | ||
43 | __L2TP_PWTYPE_MAX | ||
44 | }; | ||
45 | |||
46 | enum l2tp_l2spec_type { | ||
47 | L2TP_L2SPECTYPE_NONE, | ||
48 | L2TP_L2SPECTYPE_DEFAULT, | ||
49 | }; | ||
50 | |||
31 | struct sk_buff; | 51 | struct sk_buff; |
32 | 52 | ||
33 | struct l2tp_stats { | 53 | struct l2tp_stats { |
@@ -39,6 +59,7 @@ struct l2tp_stats { | |||
39 | u64 rx_seq_discards; | 59 | u64 rx_seq_discards; |
40 | u64 rx_oos_packets; | 60 | u64 rx_oos_packets; |
41 | u64 rx_errors; | 61 | u64 rx_errors; |
62 | u64 rx_cookie_discards; | ||
42 | }; | 63 | }; |
43 | 64 | ||
44 | struct l2tp_tunnel; | 65 | struct l2tp_tunnel; |
@@ -47,6 +68,7 @@ struct l2tp_tunnel; | |||
47 | * packets and transmit outgoing ones. | 68 | * packets and transmit outgoing ones. |
48 | */ | 69 | */ |
49 | struct l2tp_session_cfg { | 70 | struct l2tp_session_cfg { |
71 | enum l2tp_pwtype pw_type; | ||
50 | unsigned data_seq:2; /* data sequencing level | 72 | unsigned data_seq:2; /* data sequencing level |
51 | * 0 => none, 1 => IP only, | 73 | * 0 => none, 1 => IP only, |
52 | * 2 => all | 74 | * 2 => all |
@@ -60,12 +82,17 @@ struct l2tp_session_cfg { | |||
60 | * control of LNS. */ | 82 | * control of LNS. */ |
61 | int debug; /* bitmask of debug message | 83 | int debug; /* bitmask of debug message |
62 | * categories */ | 84 | * categories */ |
63 | int offset; /* offset to payload */ | 85 | u16 offset; /* offset to payload */ |
86 | u16 l2specific_len; /* Layer 2 specific length */ | ||
87 | u16 l2specific_type; /* Layer 2 specific type */ | ||
88 | u8 cookie[8]; /* optional cookie */ | ||
89 | int cookie_len; /* 0, 4 or 8 bytes */ | ||
90 | u8 peer_cookie[8]; /* peer's cookie */ | ||
91 | int peer_cookie_len; /* 0, 4 or 8 bytes */ | ||
64 | int reorder_timeout; /* configured reorder timeout | 92 | int reorder_timeout; /* configured reorder timeout |
65 | * (in jiffies) */ | 93 | * (in jiffies) */ |
66 | int mtu; | 94 | int mtu; |
67 | int mru; | 95 | int mru; |
68 | int hdr_len; | ||
69 | }; | 96 | }; |
70 | 97 | ||
71 | struct l2tp_session { | 98 | struct l2tp_session { |
@@ -76,8 +103,17 @@ struct l2tp_session { | |||
76 | * context */ | 103 | * context */ |
77 | u32 session_id; | 104 | u32 session_id; |
78 | u32 peer_session_id; | 105 | u32 peer_session_id; |
79 | u16 nr; /* session NR state (receive) */ | 106 | u8 cookie[8]; |
80 | u16 ns; /* session NR state (send) */ | 107 | int cookie_len; |
108 | u8 peer_cookie[8]; | ||
109 | int peer_cookie_len; | ||
110 | u16 offset; /* offset from end of L2TP header | ||
111 | to beginning of data */ | ||
112 | u16 l2specific_len; | ||
113 | u16 l2specific_type; | ||
114 | u16 hdr_len; | ||
115 | u32 nr; /* session NR state (receive) */ | ||
116 | u32 ns; /* session NR state (send) */ | ||
81 | struct sk_buff_head reorder_q; /* receive reorder queue */ | 117 | struct sk_buff_head reorder_q; /* receive reorder queue */ |
82 | struct hlist_node hlist; /* Hash list node */ | 118 | struct hlist_node hlist; /* Hash list node */ |
83 | atomic_t ref_count; | 119 | atomic_t ref_count; |
@@ -100,9 +136,11 @@ struct l2tp_session { | |||
100 | * (in jiffies) */ | 136 | * (in jiffies) */ |
101 | int mtu; | 137 | int mtu; |
102 | int mru; | 138 | int mru; |
103 | int hdr_len; | 139 | enum l2tp_pwtype pwtype; |
104 | struct l2tp_stats stats; | 140 | struct l2tp_stats stats; |
141 | struct hlist_node global_hlist; /* Global hash list node */ | ||
105 | 142 | ||
143 | int (*build_header)(struct l2tp_session *session, void *buf); | ||
106 | void (*recv_skb)(struct l2tp_session *session, struct sk_buff *skb, int data_len); | 144 | void (*recv_skb)(struct l2tp_session *session, struct sk_buff *skb, int data_len); |
107 | void (*session_close)(struct l2tp_session *session); | 145 | void (*session_close)(struct l2tp_session *session); |
108 | void (*ref)(struct l2tp_session *session); | 146 | void (*ref)(struct l2tp_session *session); |
@@ -132,7 +170,6 @@ struct l2tp_tunnel { | |||
132 | char name[20]; /* for logging */ | 170 | char name[20]; /* for logging */ |
133 | int debug; /* bitmask of debug message | 171 | int debug; /* bitmask of debug message |
134 | * categories */ | 172 | * categories */ |
135 | int hdr_len; | ||
136 | struct l2tp_stats stats; | 173 | struct l2tp_stats stats; |
137 | 174 | ||
138 | struct list_head list; /* Keep a list of all tunnels */ | 175 | struct list_head list; /* Keep a list of all tunnels */ |
@@ -178,7 +215,7 @@ out: | |||
178 | return tunnel; | 215 | return tunnel; |
179 | } | 216 | } |
180 | 217 | ||
181 | extern struct l2tp_session *l2tp_session_find(struct l2tp_tunnel *tunnel, u32 session_id); | 218 | extern struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id); |
182 | extern struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth); | 219 | extern struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth); |
183 | extern struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id); | 220 | extern struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id); |
184 | extern struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth); | 221 | extern struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth); |
@@ -187,14 +224,15 @@ extern int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_i | |||
187 | 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); | 224 | 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); |
188 | extern void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); | 225 | extern void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); |
189 | extern void l2tp_session_free(struct l2tp_session *session); | 226 | extern void l2tp_session_free(struct l2tp_session *session); |
227 | 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)); | ||
190 | extern int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, int (*payload_hook)(struct sk_buff *skb)); | 228 | extern int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, int (*payload_hook)(struct sk_buff *skb)); |
191 | extern int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb); | 229 | extern int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb); |
192 | 230 | ||
193 | extern void l2tp_build_l2tp_header(struct l2tp_session *session, void *buf); | ||
194 | extern int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, size_t data_len); | 231 | extern int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, size_t data_len); |
195 | extern int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len); | 232 | extern int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len); |
196 | extern void l2tp_tunnel_destruct(struct sock *sk); | 233 | extern void l2tp_tunnel_destruct(struct sock *sk); |
197 | extern void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); | 234 | extern void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); |
235 | extern void l2tp_session_set_header_len(struct l2tp_session *session, int version); | ||
198 | 236 | ||
199 | /* Tunnel reference counts. Incremented per session that is added to | 237 | /* Tunnel reference counts. Incremented per session that is added to |
200 | * the tunnel. | 238 | * the tunnel. |
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 3ad290dd830..bee5b1413ec 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
@@ -670,7 +670,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
670 | 670 | ||
671 | /* Check that this session doesn't already exist */ | 671 | /* Check that this session doesn't already exist */ |
672 | error = -EEXIST; | 672 | error = -EEXIST; |
673 | session = l2tp_session_find(tunnel, sp->pppol2tp.s_session); | 673 | session = l2tp_session_find(sock_net(sk), tunnel, sp->pppol2tp.s_session); |
674 | if (session != NULL) | 674 | if (session != NULL) |
675 | goto end; | 675 | goto end; |
676 | 676 | ||
@@ -678,7 +678,6 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
678 | * headers. | 678 | * headers. |
679 | */ | 679 | */ |
680 | cfg.mtu = cfg.mru = 1500 - PPPOL2TP_HEADER_OVERHEAD; | 680 | cfg.mtu = cfg.mru = 1500 - PPPOL2TP_HEADER_OVERHEAD; |
681 | cfg.hdr_len = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; | ||
682 | cfg.debug = tunnel->debug; | 681 | cfg.debug = tunnel->debug; |
683 | 682 | ||
684 | /* Allocate and initialize a new session context. */ | 683 | /* Allocate and initialize a new session context. */ |
@@ -999,7 +998,7 @@ static int pppol2tp_tunnel_ioctl(struct l2tp_tunnel *tunnel, | |||
999 | if (stats.session_id != 0) { | 998 | if (stats.session_id != 0) { |
1000 | /* resend to session ioctl handler */ | 999 | /* resend to session ioctl handler */ |
1001 | struct l2tp_session *session = | 1000 | struct l2tp_session *session = |
1002 | l2tp_session_find(tunnel, stats.session_id); | 1001 | l2tp_session_find(sock_net(sk), tunnel, stats.session_id); |
1003 | if (session != NULL) | 1002 | if (session != NULL) |
1004 | err = pppol2tp_session_ioctl(session, cmd, arg); | 1003 | err = pppol2tp_session_ioctl(session, cmd, arg); |
1005 | else | 1004 | else |
@@ -1375,6 +1374,8 @@ end: | |||
1375 | 1374 | ||
1376 | /***************************************************************************** | 1375 | /***************************************************************************** |
1377 | * /proc filesystem for debug | 1376 | * /proc filesystem for debug |
1377 | * Since the original pppol2tp driver provided /proc/net/pppol2tp for | ||
1378 | * L2TPv2, we dump only L2TPv2 tunnels and sessions here. | ||
1378 | *****************************************************************************/ | 1379 | *****************************************************************************/ |
1379 | 1380 | ||
1380 | static unsigned int pppol2tp_net_id; | 1381 | static unsigned int pppol2tp_net_id; |
@@ -1391,14 +1392,24 @@ struct pppol2tp_seq_data { | |||
1391 | 1392 | ||
1392 | static void pppol2tp_next_tunnel(struct net *net, struct pppol2tp_seq_data *pd) | 1393 | static void pppol2tp_next_tunnel(struct net *net, struct pppol2tp_seq_data *pd) |
1393 | { | 1394 | { |
1394 | pd->tunnel = l2tp_tunnel_find_nth(net, pd->tunnel_idx); | 1395 | for (;;) { |
1395 | pd->tunnel_idx++; | 1396 | pd->tunnel = l2tp_tunnel_find_nth(net, pd->tunnel_idx); |
1397 | pd->tunnel_idx++; | ||
1398 | |||
1399 | if (pd->tunnel == NULL) | ||
1400 | break; | ||
1401 | |||
1402 | /* Ignore L2TPv3 tunnels */ | ||
1403 | if (pd->tunnel->version < 3) | ||
1404 | break; | ||
1405 | } | ||
1396 | } | 1406 | } |
1397 | 1407 | ||
1398 | static void pppol2tp_next_session(struct net *net, struct pppol2tp_seq_data *pd) | 1408 | static void pppol2tp_next_session(struct net *net, struct pppol2tp_seq_data *pd) |
1399 | { | 1409 | { |
1400 | pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx); | 1410 | pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx); |
1401 | pd->session_idx++; | 1411 | pd->session_idx++; |
1412 | |||
1402 | if (pd->session == NULL) { | 1413 | if (pd->session == NULL) { |
1403 | pd->session_idx = 0; | 1414 | pd->session_idx = 0; |
1404 | pppol2tp_next_tunnel(net, pd); | 1415 | pppol2tp_next_tunnel(net, pd); |