aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/pppol2tp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/pppol2tp.c')
-rw-r--r--drivers/net/pppol2tp.c44
1 files changed, 24 insertions, 20 deletions
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index ed8ead432d77..440e190778a1 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -491,44 +491,46 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
491 u16 hdrflags; 491 u16 hdrflags;
492 u16 tunnel_id, session_id; 492 u16 tunnel_id, session_id;
493 int length; 493 int length;
494 struct udphdr *uh; 494 int offset;
495 495
496 tunnel = pppol2tp_sock_to_tunnel(sock); 496 tunnel = pppol2tp_sock_to_tunnel(sock);
497 if (tunnel == NULL) 497 if (tunnel == NULL)
498 goto error; 498 goto error;
499 499
500 /* UDP always verifies the packet length. */
501 __skb_pull(skb, sizeof(struct udphdr));
502
500 /* Short packet? */ 503 /* Short packet? */
501 if (skb->len < sizeof(struct udphdr)) { 504 if (!pskb_may_pull(skb, 12)) {
502 PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO, 505 PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
503 "%s: recv short packet (len=%d)\n", tunnel->name, skb->len); 506 "%s: recv short packet (len=%d)\n", tunnel->name, skb->len);
504 goto error; 507 goto error;
505 } 508 }
506 509
507 /* Point to L2TP header */ 510 /* Point to L2TP header */
508 ptr = skb->data + sizeof(struct udphdr); 511 ptr = skb->data;
509 512
510 /* Get L2TP header flags */ 513 /* Get L2TP header flags */
511 hdrflags = ntohs(*(__be16*)ptr); 514 hdrflags = ntohs(*(__be16*)ptr);
512 515
513 /* Trace packet contents, if enabled */ 516 /* Trace packet contents, if enabled */
514 if (tunnel->debug & PPPOL2TP_MSG_DATA) { 517 if (tunnel->debug & PPPOL2TP_MSG_DATA) {
518 length = min(16u, skb->len);
519 if (!pskb_may_pull(skb, length))
520 goto error;
521
515 printk(KERN_DEBUG "%s: recv: ", tunnel->name); 522 printk(KERN_DEBUG "%s: recv: ", tunnel->name);
516 523
517 for (length = 0; length < 16; length++) 524 offset = 0;
518 printk(" %02X", ptr[length]); 525 do {
526 printk(" %02X", ptr[offset]);
527 } while (++offset < length);
528
519 printk("\n"); 529 printk("\n");
520 } 530 }
521 531
522 /* Get length of L2TP packet */ 532 /* Get length of L2TP packet */
523 uh = (struct udphdr *) skb_transport_header(skb); 533 length = skb->len;
524 length = ntohs(uh->len) - sizeof(struct udphdr);
525
526 /* Too short? */
527 if (length < 12) {
528 PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
529 "%s: recv short L2TP packet (len=%d)\n", tunnel->name, length);
530 goto error;
531 }
532 534
533 /* If type is control packet, it is handled by userspace. */ 535 /* If type is control packet, it is handled by userspace. */
534 if (hdrflags & L2TP_HDRFLAG_T) { 536 if (hdrflags & L2TP_HDRFLAG_T) {
@@ -606,7 +608,6 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
606 "%s: recv data has no seq numbers when required. " 608 "%s: recv data has no seq numbers when required. "
607 "Discarding\n", session->name); 609 "Discarding\n", session->name);
608 session->stats.rx_seq_discards++; 610 session->stats.rx_seq_discards++;
609 session->stats.rx_errors++;
610 goto discard; 611 goto discard;
611 } 612 }
612 613
@@ -625,7 +626,6 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
625 "%s: recv data has no seq numbers when required. " 626 "%s: recv data has no seq numbers when required. "
626 "Discarding\n", session->name); 627 "Discarding\n", session->name);
627 session->stats.rx_seq_discards++; 628 session->stats.rx_seq_discards++;
628 session->stats.rx_errors++;
629 goto discard; 629 goto discard;
630 } 630 }
631 631
@@ -634,10 +634,14 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
634 } 634 }
635 635
636 /* If offset bit set, skip it. */ 636 /* If offset bit set, skip it. */
637 if (hdrflags & L2TP_HDRFLAG_O) 637 if (hdrflags & L2TP_HDRFLAG_O) {
638 ptr += 2 + ntohs(*(__be16 *) ptr); 638 offset = ntohs(*(__be16 *)ptr);
639 skb->transport_header += 2 + offset;
640 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 2))
641 goto discard;
642 }
639 643
640 skb_pull(skb, ptr - skb->data); 644 __skb_pull(skb, skb_transport_offset(skb));
641 645
642 /* Skip PPP header, if present. In testing, Microsoft L2TP clients 646 /* Skip PPP header, if present. In testing, Microsoft L2TP clients
643 * don't send the PPP header (PPP header compression enabled), but 647 * don't send the PPP header (PPP header compression enabled), but
@@ -673,7 +677,6 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
673 */ 677 */
674 if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) { 678 if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) {
675 session->stats.rx_seq_discards++; 679 session->stats.rx_seq_discards++;
676 session->stats.rx_errors++;
677 PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, 680 PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
678 "%s: oos pkt %hu len %d discarded, " 681 "%s: oos pkt %hu len %d discarded, "
679 "waiting for %hu, reorder_q_len=%d\n", 682 "waiting for %hu, reorder_q_len=%d\n",
@@ -698,6 +701,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
698 return 0; 701 return 0;
699 702
700discard: 703discard:
704 session->stats.rx_errors++;
701 kfree_skb(skb); 705 kfree_skb(skb);
702 sock_put(session->sock); 706 sock_put(session->sock);
703 707