diff options
Diffstat (limited to 'net/dccp/ipv4.c')
-rw-r--r-- | net/dccp/ipv4.c | 39 |
1 files changed, 19 insertions, 20 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 61c09014dade..34d6d197c3b2 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -518,7 +518,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) | |||
518 | sizeof(struct dccp_hdr_reset); | 518 | sizeof(struct dccp_hdr_reset); |
519 | struct sk_buff *skb; | 519 | struct sk_buff *skb; |
520 | struct dst_entry *dst; | 520 | struct dst_entry *dst; |
521 | u64 seqno; | 521 | u64 seqno = 0; |
522 | 522 | ||
523 | /* Never send a reset in response to a reset. */ | 523 | /* Never send a reset in response to a reset. */ |
524 | if (rxdh->dccph_type == DCCP_PKT_RESET) | 524 | if (rxdh->dccph_type == DCCP_PKT_RESET) |
@@ -552,13 +552,11 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) | |||
552 | DCCP_SKB_CB(rxskb)->dccpd_reset_code; | 552 | DCCP_SKB_CB(rxskb)->dccpd_reset_code; |
553 | 553 | ||
554 | /* See "8.3.1. Abnormal Termination" in RFC 4340 */ | 554 | /* See "8.3.1. Abnormal Termination" in RFC 4340 */ |
555 | seqno = 0; | ||
556 | if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) | 555 | if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) |
557 | dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1); | 556 | dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1); |
558 | 557 | ||
559 | dccp_hdr_set_seq(dh, seqno); | 558 | dccp_hdr_set_seq(dh, seqno); |
560 | dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), | 559 | dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq); |
561 | DCCP_SKB_CB(rxskb)->dccpd_seq); | ||
562 | 560 | ||
563 | dccp_csum_outgoing(skb); | 561 | dccp_csum_outgoing(skb); |
564 | dh->dccph_checksum = dccp_v4_csum_finish(skb, rxskb->nh.iph->saddr, | 562 | dh->dccph_checksum = dccp_v4_csum_finish(skb, rxskb->nh.iph->saddr, |
@@ -734,6 +732,11 @@ discard: | |||
734 | 732 | ||
735 | EXPORT_SYMBOL_GPL(dccp_v4_do_rcv); | 733 | EXPORT_SYMBOL_GPL(dccp_v4_do_rcv); |
736 | 734 | ||
735 | /** | ||
736 | * dccp_invalid_packet - check for malformed packets | ||
737 | * Implements RFC 4340, 8.5: Step 1: Check header basics | ||
738 | * Packets that fail these checks are ignored and do not receive Resets. | ||
739 | */ | ||
737 | int dccp_invalid_packet(struct sk_buff *skb) | 740 | int dccp_invalid_packet(struct sk_buff *skb) |
738 | { | 741 | { |
739 | const struct dccp_hdr *dh; | 742 | const struct dccp_hdr *dh; |
@@ -742,6 +745,7 @@ int dccp_invalid_packet(struct sk_buff *skb) | |||
742 | if (skb->pkt_type != PACKET_HOST) | 745 | if (skb->pkt_type != PACKET_HOST) |
743 | return 1; | 746 | return 1; |
744 | 747 | ||
748 | /* If the packet is shorter than 12 bytes, drop packet and return */ | ||
745 | if (!pskb_may_pull(skb, sizeof(struct dccp_hdr))) { | 749 | if (!pskb_may_pull(skb, sizeof(struct dccp_hdr))) { |
746 | LIMIT_NETDEBUG(KERN_WARNING "DCCP: pskb_may_pull failed\n"); | 750 | LIMIT_NETDEBUG(KERN_WARNING "DCCP: pskb_may_pull failed\n"); |
747 | return 1; | 751 | return 1; |
@@ -749,42 +753,37 @@ int dccp_invalid_packet(struct sk_buff *skb) | |||
749 | 753 | ||
750 | dh = dccp_hdr(skb); | 754 | dh = dccp_hdr(skb); |
751 | 755 | ||
752 | /* If the packet type is not understood, drop packet and return */ | 756 | /* If P.type is not understood, drop packet and return */ |
753 | if (dh->dccph_type >= DCCP_PKT_INVALID) { | 757 | if (dh->dccph_type >= DCCP_PKT_INVALID) { |
754 | LIMIT_NETDEBUG(KERN_WARNING "DCCP: invalid packet type\n"); | 758 | LIMIT_NETDEBUG(KERN_WARNING "DCCP: invalid packet type\n"); |
755 | return 1; | 759 | return 1; |
756 | } | 760 | } |
757 | 761 | ||
758 | /* | 762 | /* |
759 | * If P.Data Offset is too small for packet type, or too large for | 763 | * If P.Data Offset is too small for packet type, drop packet and return |
760 | * packet, drop packet and return | ||
761 | */ | 764 | */ |
762 | if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) { | 765 | if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) { |
763 | LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) " | 766 | LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) " |
764 | "too small 1\n", | 767 | "too small\n", dh->dccph_doff); |
765 | dh->dccph_doff); | ||
766 | return 1; | 768 | return 1; |
767 | } | 769 | } |
768 | 770 | /* | |
771 | * If P.Data Offset is too too large for packet, drop packet and return | ||
772 | */ | ||
769 | if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) { | 773 | if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) { |
770 | LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) " | 774 | LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) " |
771 | "too small 2\n", | 775 | "too large\n", dh->dccph_doff); |
772 | dh->dccph_doff); | ||
773 | return 1; | 776 | return 1; |
774 | } | 777 | } |
775 | 778 | ||
776 | dh = dccp_hdr(skb); | ||
777 | |||
778 | /* | 779 | /* |
779 | * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet | 780 | * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet |
780 | * has short sequence numbers), drop packet and return | 781 | * has short sequence numbers), drop packet and return |
781 | */ | 782 | */ |
782 | if (dh->dccph_x == 0 && | 783 | if (dh->dccph_type >= DCCP_PKT_DATA && |
783 | dh->dccph_type != DCCP_PKT_DATA && | 784 | dh->dccph_type <= DCCP_PKT_DATAACK && dh->dccph_x == 0) { |
784 | dh->dccph_type != DCCP_PKT_ACK && | 785 | LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.type (%s) not Data||Ack||" |
785 | dh->dccph_type != DCCP_PKT_DATAACK) { | 786 | "DataAck, while P.X == 0\n", |
786 | LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.type (%s) not Data, Ack " | ||
787 | "nor DataAck and P.X == 0\n", | ||
788 | dccp_packet_name(dh->dccph_type)); | 787 | dccp_packet_name(dh->dccph_type)); |
789 | return 1; | 788 | return 1; |
790 | } | 789 | } |