Commit 95b81ef7 authored by Yoshifumi Nishida's avatar Yoshifumi Nishida Committed by David S. Miller
Browse files

[DCCP]: Fix checksum routines

parent a019d6fe
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -242,7 +242,8 @@ extern int dccp_setsockopt(struct sock *sk, int level, int optname,
				   char *optval, int optlen);
extern void	   dccp_shutdown(struct sock *sk, int how);

extern int	   dccp_v4_checksum(struct sk_buff *skb);
extern int	   dccp_v4_checksum(const struct sk_buff *skb,
				    const u32 saddr, const u32 daddr);

extern int	   dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code);
extern void	   dccp_send_close(struct sock *sk);
+20 −18
Original line number Diff line number Diff line
@@ -802,9 +802,9 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
	return sk;
}

int dccp_v4_checksum(struct sk_buff *skb)
int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr, const u32 daddr)
{
	struct dccp_hdr* dh = dccp_hdr(skb);
	const struct dccp_hdr* dh = dccp_hdr(skb);
	int checksum_len;
	u32 tmp;

@@ -816,24 +816,24 @@ int dccp_v4_checksum(struct sk_buff *skb)
	}

	tmp = csum_partial((unsigned char *)dh, checksum_len, 0);
	return csum_fold(tmp);
	return csum_tcpudp_magic(saddr, daddr, checksum_len, IPPROTO_DCCP, tmp);
}

static int dccp_v4_verify_checksum(struct sk_buff *skb)
static int dccp_v4_verify_checksum(struct sk_buff *skb,
				   const u32 saddr, const u32 daddr)
{
	struct dccp_hdr *th = dccp_hdr(skb);
	const u16 remote_checksum = th->dccph_checksum;
	u16 local_checksum;

	/* FIXME: don't mess with skb payload */
	th->dccph_checksum = 0; /* zero it for computation */

	local_checksum = dccp_v4_checksum(skb);

	/* FIXME: don't mess with skb payload */
	th->dccph_checksum = remote_checksum; /* put it back */
	struct dccp_hdr *dh = dccp_hdr(skb);
	int checksum_len;
	u32 tmp;

	return remote_checksum == local_checksum ? 0 : -1;
	if (dh->dccph_cscov == 0)
		checksum_len = skb->len;
	else {
		checksum_len = (dh->dccph_cscov + dh->dccph_x) * sizeof(u32);
		checksum_len = checksum_len < skb->len ? checksum_len : skb->len;
	}
	tmp = csum_partial((unsigned char *)dh, checksum_len, 0);
	return csum_tcpudp_magic(saddr, daddr, checksum_len, IPPROTO_DCCP, tmp) == 0 ? 0 : -1;
}

static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
@@ -902,7 +902,8 @@ void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
	dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq);
	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq);

	dh->dccph_checksum = dccp_v4_checksum(skb);
	dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr,
					      rxskb->nh.iph->daddr);

	bh_lock_sock(dccp_ctl_socket->sk);
	err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk,
@@ -1024,7 +1025,8 @@ static inline int dccp_invalid_packet(struct sk_buff *skb)
	}

	/* If the header checksum is incorrect, drop packet and return */
	if (dccp_v4_verify_checksum(skb) < 0) {
	if (dccp_v4_verify_checksum(skb, skb->nh.iph->saddr,
				    skb->nh.iph->daddr) < 0) {
		dccp_pr_debug("header checksum is incorrect\n");
		return 1;
	}
+6 −3
Original line number Diff line number Diff line
@@ -93,7 +93,8 @@ int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
			break;
		}

		dh->dccph_checksum = dccp_v4_checksum(skb);
		dh->dccph_checksum = dccp_v4_checksum(skb, inet->saddr,
						      inet->daddr);

		if (dcb->dccpd_type == DCCP_PKT_ACK ||
		    dcb->dccpd_type == DCCP_PKT_DATAACK)
@@ -193,7 +194,8 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
	dccp_hdr_set_seq(dh, dccp_rsk(req)->dreq_iss);
	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dccp_rsk(req)->dreq_isr);

	dh->dccph_checksum = dccp_v4_checksum(skb);
	dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr,
					      inet_rsk(req)->rmt_addr);

	DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
	return skb;
@@ -242,7 +244,8 @@ struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,

	dccp_hdr_reset(skb)->dccph_reset_code = code;

	dh->dccph_checksum = dccp_v4_checksum(skb);
	dh->dccph_checksum = dccp_v4_checksum(skb, inet_sk(sk)->saddr,
					      inet_sk(sk)->daddr);

	DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
	return skb;