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/l2tp_core.c | |
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/l2tp_core.c')
-rw-r--r-- | net/l2tp/l2tp_core.c | 532 |
1 files changed, 397 insertions, 135 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 4b6da3689893..0eee1a65f1b1 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; |