[NETFILTER]: Convert conntrack/ipt_REJECT to new checksumming functions
Besides removing lots of duplicate code, all converted users benefit from improved HW checksum error handling. Tested with and without HW checksums in almost all combinations. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
422c346fad
commit
96f6bf82ea
@@ -224,25 +224,14 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
|
||||
}
|
||||
|
||||
/* See ip_conntrack_proto_tcp.c */
|
||||
if (hooknum != NF_IP_PRE_ROUTING)
|
||||
goto checksum_skipped;
|
||||
|
||||
switch (skb->ip_summed) {
|
||||
case CHECKSUM_HW:
|
||||
if (!(u16)csum_fold(skb->csum))
|
||||
break;
|
||||
/* fall through */
|
||||
case CHECKSUM_NONE:
|
||||
skb->csum = 0;
|
||||
if (__skb_checksum_complete(skb)) {
|
||||
if (LOG_INVALID(IPPROTO_ICMP))
|
||||
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
||||
"ip_ct_icmp: bad ICMP checksum ");
|
||||
return -NF_ACCEPT;
|
||||
}
|
||||
if (hooknum == NF_IP_PRE_ROUTING &&
|
||||
nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
|
||||
if (LOG_INVALID(IPPROTO_ICMP))
|
||||
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
||||
"ip_ct_icmp: bad ICMP checksum ");
|
||||
return -NF_ACCEPT;
|
||||
}
|
||||
|
||||
checksum_skipped:
|
||||
/*
|
||||
* 18 is the highest 'known' ICMP type. Anything else is a mystery
|
||||
*
|
||||
|
@@ -870,11 +870,8 @@ static int tcp_error(struct sk_buff *skb,
|
||||
* and moreover root might send raw packets.
|
||||
*/
|
||||
/* FIXME: Source route IP option packets --RR */
|
||||
if (hooknum == NF_IP_PRE_ROUTING
|
||||
&& skb->ip_summed != CHECKSUM_UNNECESSARY
|
||||
&& csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
|
||||
skb->ip_summed == CHECKSUM_HW ? skb->csum
|
||||
: skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
|
||||
if (hooknum == NF_IP_PRE_ROUTING &&
|
||||
nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
|
||||
if (LOG_INVALID(IPPROTO_TCP))
|
||||
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
||||
"ip_ct_tcp: bad TCP checksum ");
|
||||
|
@@ -120,11 +120,8 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
|
||||
* because the semantic of CHECKSUM_HW is different there
|
||||
* and moreover root might send raw packets.
|
||||
* FIXME: Source route IP option packets --RR */
|
||||
if (hooknum == NF_IP_PRE_ROUTING
|
||||
&& skb->ip_summed != CHECKSUM_UNNECESSARY
|
||||
&& csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
|
||||
skb->ip_summed == CHECKSUM_HW ? skb->csum
|
||||
: skb_checksum(skb, iph->ihl*4, udplen, 0))) {
|
||||
if (hooknum == NF_IP_PRE_ROUTING &&
|
||||
nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
|
||||
if (LOG_INVALID(IPPROTO_UDP))
|
||||
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
||||
"ip_ct_udp: bad UDP checksum ");
|
||||
|
@@ -106,7 +106,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
|
||||
struct rtable *rt;
|
||||
u_int16_t tmp_port;
|
||||
u_int32_t tmp_addr;
|
||||
unsigned int tcplen;
|
||||
int needs_ack;
|
||||
int hh_len;
|
||||
|
||||
@@ -124,13 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
|
||||
return;
|
||||
|
||||
/* Check checksum */
|
||||
tcplen = oldskb->len - iph->ihl * 4;
|
||||
if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) ||
|
||||
(hook == NF_IP_LOCAL_IN &&
|
||||
oldskb->ip_summed != CHECKSUM_UNNECESSARY)) &&
|
||||
csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
|
||||
oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum :
|
||||
skb_checksum(oldskb, iph->ihl * 4, tcplen, 0)))
|
||||
if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
|
||||
return;
|
||||
|
||||
if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
|
||||
|
@@ -235,30 +235,14 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
|
||||
}
|
||||
|
||||
/* See ip_conntrack_proto_tcp.c */
|
||||
if (hooknum != NF_IP_PRE_ROUTING)
|
||||
goto checksum_skipped;
|
||||
|
||||
switch (skb->ip_summed) {
|
||||
case CHECKSUM_HW:
|
||||
if (!(u16)csum_fold(skb->csum))
|
||||
break;
|
||||
if (hooknum == NF_IP_PRE_ROUTING &&
|
||||
nf_ip_checksum(skb, hooknum, dataoff, 0)) {
|
||||
if (LOG_INVALID(IPPROTO_ICMP))
|
||||
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
|
||||
"nf_ct_icmp: bad HW ICMP checksum ");
|
||||
return -NF_ACCEPT;
|
||||
case CHECKSUM_NONE:
|
||||
if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
|
||||
if (LOG_INVALID(IPPROTO_ICMP))
|
||||
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
|
||||
NULL,
|
||||
"nf_ct_icmp: bad ICMP checksum ");
|
||||
return -NF_ACCEPT;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
checksum_skipped:
|
||||
/*
|
||||
* 18 is the highest 'known' ICMP type. Anything else is a mystery
|
||||
*
|
||||
|
Reference in New Issue
Block a user