aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ipv4.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/ipv4.c')
-rw-r--r--net/dccp/ipv4.c105
1 files changed, 52 insertions, 53 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 91bffaa761a6..496112080f3d 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -349,13 +349,19 @@ out:
349 sock_put(sk); 349 sock_put(sk);
350} 350}
351 351
352/* This routine computes an IPv4 DCCP checksum. */ 352static inline u16 dccp_v4_csum_finish(struct sk_buff *skb,
353void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) 353 __be32 src, __be32 dst)
354{
355 return csum_tcpudp_magic(src, dst, skb->len, IPPROTO_DCCP, skb->csum);
356}
357
358void dccp_v4_send_check(struct sock *sk, int unused, struct sk_buff *skb)
354{ 359{
355 const struct inet_sock *inet = inet_sk(sk); 360 const struct inet_sock *inet = inet_sk(sk);
356 struct dccp_hdr *dh = dccp_hdr(skb); 361 struct dccp_hdr *dh = dccp_hdr(skb);
357 362
358 dh->dccph_checksum = dccp_v4_checksum(skb, inet->saddr, inet->daddr); 363 dccp_csum_outgoing(skb);
364 dh->dccph_checksum = dccp_v4_csum_finish(skb, inet->saddr, inet->daddr);
359} 365}
360 366
361EXPORT_SYMBOL_GPL(dccp_v4_send_check); 367EXPORT_SYMBOL_GPL(dccp_v4_send_check);
@@ -454,47 +460,6 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
454 return sk; 460 return sk;
455} 461}
456 462
457int dccp_v4_checksum(const struct sk_buff *skb, const __be32 saddr,
458 const __be32 daddr)
459{
460 const struct dccp_hdr* dh = dccp_hdr(skb);
461 int checksum_len;
462 u32 tmp;
463
464 if (dh->dccph_cscov == 0)
465 checksum_len = skb->len;
466 else {
467 checksum_len = (dh->dccph_cscov + dh->dccph_x) * sizeof(u32);
468 checksum_len = checksum_len < skb->len ? checksum_len :
469 skb->len;
470 }
471
472 tmp = csum_partial((unsigned char *)dh, checksum_len, 0);
473 return csum_tcpudp_magic(saddr, daddr, checksum_len,
474 IPPROTO_DCCP, tmp);
475}
476
477EXPORT_SYMBOL_GPL(dccp_v4_checksum);
478
479static int dccp_v4_verify_checksum(struct sk_buff *skb,
480 const __be32 saddr, const __be32 daddr)
481{
482 struct dccp_hdr *dh = dccp_hdr(skb);
483 int checksum_len;
484 u32 tmp;
485
486 if (dh->dccph_cscov == 0)
487 checksum_len = skb->len;
488 else {
489 checksum_len = (dh->dccph_cscov + dh->dccph_x) * sizeof(u32);
490 checksum_len = checksum_len < skb->len ? checksum_len :
491 skb->len;
492 }
493 tmp = csum_partial((unsigned char *)dh, checksum_len, 0);
494 return csum_tcpudp_magic(saddr, daddr, checksum_len,
495 IPPROTO_DCCP, tmp) == 0 ? 0 : -1;
496}
497
498static struct dst_entry* dccp_v4_route_skb(struct sock *sk, 463static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
499 struct sk_buff *skb) 464 struct sk_buff *skb)
500{ 465{
@@ -536,8 +501,8 @@ static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
536 const struct inet_request_sock *ireq = inet_rsk(req); 501 const struct inet_request_sock *ireq = inet_rsk(req);
537 struct dccp_hdr *dh = dccp_hdr(skb); 502 struct dccp_hdr *dh = dccp_hdr(skb);
538 503
539 dh->dccph_checksum = dccp_v4_checksum(skb, ireq->loc_addr, 504 dh->dccph_checksum = dccp_v4_csum_finish(skb, ireq->loc_addr,
540 ireq->rmt_addr); 505 ireq->rmt_addr);
541 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 506 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
542 err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, 507 err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
543 ireq->rmt_addr, 508 ireq->rmt_addr,
@@ -602,8 +567,9 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
602 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), 567 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
603 DCCP_SKB_CB(rxskb)->dccpd_seq); 568 DCCP_SKB_CB(rxskb)->dccpd_seq);
604 569
605 dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr, 570 dccp_csum_outgoing(skb);
606 rxskb->nh.iph->daddr); 571 dh->dccph_checksum = dccp_v4_csum_finish(skb, rxskb->nh.iph->saddr,
572 rxskb->nh.iph->daddr);
607 573
608 bh_lock_sock(dccp_v4_ctl_socket->sk); 574 bh_lock_sock(dccp_v4_ctl_socket->sk);
609 err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk, 575 err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
@@ -779,6 +745,7 @@ EXPORT_SYMBOL_GPL(dccp_v4_do_rcv);
779int dccp_invalid_packet(struct sk_buff *skb) 745int dccp_invalid_packet(struct sk_buff *skb)
780{ 746{
781 const struct dccp_hdr *dh; 747 const struct dccp_hdr *dh;
748 unsigned int cscov;
782 749
783 if (skb->pkt_type != PACKET_HOST) 750 if (skb->pkt_type != PACKET_HOST)
784 return 1; 751 return 1;
@@ -830,6 +797,22 @@ int dccp_invalid_packet(struct sk_buff *skb)
830 return 1; 797 return 1;
831 } 798 }
832 799
800 /*
801 * If P.CsCov is too large for the packet size, drop packet and return.
802 * This must come _before_ checksumming (not as RFC 4340 suggests).
803 */
804 cscov = dccp_csum_coverage(skb);
805 if (cscov > skb->len) {
806 LIMIT_NETDEBUG(KERN_WARNING
807 "DCCP: P.CsCov %u exceeds packet length %d\n",
808 dh->dccph_cscov, skb->len);
809 return 1;
810 }
811
812 /* If header checksum is incorrect, drop packet and return.
813 * (This step is completed in the AF-dependent functions.) */
814 skb->csum = skb_checksum(skb, 0, cscov, 0);
815
833 return 0; 816 return 0;
834} 817}
835 818
@@ -840,16 +823,17 @@ static int dccp_v4_rcv(struct sk_buff *skb)
840{ 823{
841 const struct dccp_hdr *dh; 824 const struct dccp_hdr *dh;
842 struct sock *sk; 825 struct sock *sk;
826 int min_cov;
843 827
844 /* Step 1: Check header basics: */ 828 /* Step 1: Check header basics */
845 829
846 if (dccp_invalid_packet(skb)) 830 if (dccp_invalid_packet(skb))
847 goto discard_it; 831 goto discard_it;
848 832
849 /* If the header checksum is incorrect, drop packet and return */ 833 /* Step 1: If header checksum is incorrect, drop packet and return */
850 if (dccp_v4_verify_checksum(skb, skb->nh.iph->saddr, 834 if (dccp_v4_csum_finish(skb, skb->nh.iph->saddr, skb->nh.iph->daddr)) {
851 skb->nh.iph->daddr) < 0) { 835 LIMIT_NETDEBUG(KERN_WARNING
852 LIMIT_NETDEBUG(KERN_WARNING "%s: incorrect header checksum\n", 836 "%s: dropped packet with invalid checksum\n",
853 __FUNCTION__); 837 __FUNCTION__);
854 goto discard_it; 838 goto discard_it;
855 } 839 }
@@ -905,6 +889,21 @@ static int dccp_v4_rcv(struct sk_buff *skb)
905 goto no_dccp_socket; 889 goto no_dccp_socket;
906 } 890 }
907 891
892 /*
893 * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
894 * o if MinCsCov = 0, only packets with CsCov = 0 are accepted
895 * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
896 */
897 min_cov = dccp_sk(sk)->dccps_pcrlen;
898 if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov)) {
899 dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d\n",
900 dh->dccph_cscov, min_cov);
901 /* FIXME: "Such packets SHOULD be reported using Data Dropped
902 * options (Section 11.7) with Drop Code 0, Protocol
903 * Constraints." */
904 goto discard_and_relse;
905 }
906
908 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) 907 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
909 goto discard_and_relse; 908 goto discard_and_relse;
910 nf_reset(skb); 909 nf_reset(skb);