[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:
Patrick McHardy 2006-04-06 14:19:24 -07:00 committed by David S. Miller
parent 422c346fad
commit 96f6bf82ea
8 changed files with 25 additions and 153 deletions

View file

@ -224,25 +224,14 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
} }
/* See ip_conntrack_proto_tcp.c */ /* See ip_conntrack_proto_tcp.c */
if (hooknum != NF_IP_PRE_ROUTING) if (hooknum == NF_IP_PRE_ROUTING &&
goto checksum_skipped; nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
if (LOG_INVALID(IPPROTO_ICMP))
switch (skb->ip_summed) { nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
case CHECKSUM_HW: "ip_ct_icmp: bad ICMP checksum ");
if (!(u16)csum_fold(skb->csum)) return -NF_ACCEPT;
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;
}
} }
checksum_skipped:
/* /*
* 18 is the highest 'known' ICMP type. Anything else is a mystery * 18 is the highest 'known' ICMP type. Anything else is a mystery
* *

View file

@ -870,11 +870,8 @@ static int tcp_error(struct sk_buff *skb,
* and moreover root might send raw packets. * and moreover root might send raw packets.
*/ */
/* FIXME: Source route IP option packets --RR */ /* FIXME: Source route IP option packets --RR */
if (hooknum == NF_IP_PRE_ROUTING if (hooknum == NF_IP_PRE_ROUTING &&
&& skb->ip_summed != CHECKSUM_UNNECESSARY nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
&& 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 (LOG_INVALID(IPPROTO_TCP)) if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: bad TCP checksum "); "ip_ct_tcp: bad TCP checksum ");

View file

@ -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 * because the semantic of CHECKSUM_HW is different there
* and moreover root might send raw packets. * and moreover root might send raw packets.
* FIXME: Source route IP option packets --RR */ * FIXME: Source route IP option packets --RR */
if (hooknum == NF_IP_PRE_ROUTING if (hooknum == NF_IP_PRE_ROUTING &&
&& skb->ip_summed != CHECKSUM_UNNECESSARY nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
&& 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 (LOG_INVALID(IPPROTO_UDP)) if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_udp: bad UDP checksum "); "ip_ct_udp: bad UDP checksum ");

View file

@ -106,7 +106,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
struct rtable *rt; struct rtable *rt;
u_int16_t tmp_port; u_int16_t tmp_port;
u_int32_t tmp_addr; u_int32_t tmp_addr;
unsigned int tcplen;
int needs_ack; int needs_ack;
int hh_len; int hh_len;
@ -124,13 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
return; return;
/* Check checksum */ /* Check checksum */
tcplen = oldskb->len - iph->ihl * 4; if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
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)))
return; return;
if ((rt = route_reverse(oldskb, oth, hook)) == NULL) if ((rt = route_reverse(oldskb, oth, hook)) == NULL)

View file

@ -235,30 +235,14 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
} }
/* See ip_conntrack_proto_tcp.c */ /* See ip_conntrack_proto_tcp.c */
if (hooknum != NF_IP_PRE_ROUTING) if (hooknum == NF_IP_PRE_ROUTING &&
goto checksum_skipped; nf_ip_checksum(skb, hooknum, dataoff, 0)) {
switch (skb->ip_summed) {
case CHECKSUM_HW:
if (!(u16)csum_fold(skb->csum))
break;
if (LOG_INVALID(IPPROTO_ICMP)) if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"nf_ct_icmp: bad HW ICMP checksum "); "nf_ct_icmp: bad HW ICMP checksum ");
return -NF_ACCEPT; 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 * 18 is the highest 'known' ICMP type. Anything else is a mystery
* *

View file

@ -233,21 +233,13 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff,
return -NF_ACCEPT; return -NF_ACCEPT;
} }
if (hooknum != NF_IP6_PRE_ROUTING) if (hooknum == NF_IP6_PRE_ROUTING &&
goto skipped; nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
/* Ignore it if the checksum's bogus. */
if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
skb->len - dataoff, IPPROTO_ICMPV6,
skb_checksum(skb, dataoff,
skb->len - dataoff, 0))) {
nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
"nf_ct_icmpv6: ICMPv6 checksum failed\n"); "nf_ct_icmpv6: ICMPv6 checksum failed\n");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
skipped:
/* is not error message ? */ /* is not error message ? */
if (icmp6h->icmp6_type >= 128) if (icmp6h->icmp6_type >= 128)
return NF_ACCEPT; return NF_ACCEPT;

View file

@ -799,8 +799,7 @@ static int tcp_error(struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info *ctinfo, enum ip_conntrack_info *ctinfo,
int pf, int pf,
unsigned int hooknum, unsigned int hooknum)
int(*csum)(const struct sk_buff *,unsigned int))
{ {
struct tcphdr _tcph, *th; struct tcphdr _tcph, *th;
unsigned int tcplen = skb->len - dataoff; unsigned int tcplen = skb->len - dataoff;
@ -830,9 +829,8 @@ static int tcp_error(struct sk_buff *skb,
*/ */
/* FIXME: Source route IP option packets --RR */ /* FIXME: Source route IP option packets --RR */
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
(pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
&& skb->ip_summed != CHECKSUM_UNNECESSARY nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
&& csum(skb, dataoff)) {
if (LOG_INVALID(IPPROTO_TCP)) if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL, nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: bad TCP checksum "); "nf_ct_tcp: bad TCP checksum ");
@ -851,44 +849,6 @@ static int tcp_error(struct sk_buff *skb,
return NF_ACCEPT; return NF_ACCEPT;
} }
static int csum4(const struct sk_buff *skb, unsigned int dataoff)
{
return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
skb->len - dataoff, IPPROTO_TCP,
skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, dataoff,
skb->len - dataoff, 0));
}
static int csum6(const struct sk_buff *skb, unsigned int dataoff)
{
return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
skb->len - dataoff, IPPROTO_TCP,
skb->ip_summed == CHECKSUM_HW
? csum_sub(skb->csum,
skb_checksum(skb, 0, dataoff, 0))
: skb_checksum(skb, dataoff, skb->len - dataoff,
0));
}
static int tcp_error4(struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
unsigned int hooknum)
{
return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
}
static int tcp_error6(struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
unsigned int hooknum)
{
return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
}
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
static int tcp_packet(struct nf_conn *conntrack, static int tcp_packet(struct nf_conn *conntrack,
const struct sk_buff *skb, const struct sk_buff *skb,
@ -1218,7 +1178,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
.print_conntrack = tcp_print_conntrack, .print_conntrack = tcp_print_conntrack,
.packet = tcp_packet, .packet = tcp_packet,
.new = tcp_new, .new = tcp_new,
.error = tcp_error4, .error = tcp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \ #if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE) defined(CONFIG_NF_CT_NETLINK_MODULE)
.to_nfattr = tcp_to_nfattr, .to_nfattr = tcp_to_nfattr,
@ -1239,7 +1199,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
.print_conntrack = tcp_print_conntrack, .print_conntrack = tcp_print_conntrack,
.packet = tcp_packet, .packet = tcp_packet,
.new = tcp_new, .new = tcp_new,
.error = tcp_error6, .error = tcp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \ #if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE) defined(CONFIG_NF_CT_NETLINK_MODULE)
.to_nfattr = tcp_to_nfattr, .to_nfattr = tcp_to_nfattr,

View file

@ -103,8 +103,7 @@ static int udp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
static int udp_error(struct sk_buff *skb, unsigned int dataoff, static int udp_error(struct sk_buff *skb, unsigned int dataoff,
enum ip_conntrack_info *ctinfo, enum ip_conntrack_info *ctinfo,
int pf, int pf,
unsigned int hooknum, unsigned int hooknum)
int (*csum)(const struct sk_buff *, unsigned int))
{ {
unsigned int udplen = skb->len - dataoff; unsigned int udplen = skb->len - dataoff;
struct udphdr _hdr, *hdr; struct udphdr _hdr, *hdr;
@ -136,9 +135,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
* and moreover root might send raw packets. * and moreover root might send raw packets.
* FIXME: Source route IP option packets --RR */ * FIXME: Source route IP option packets --RR */
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
(pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
&& skb->ip_summed != CHECKSUM_UNNECESSARY nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
&& csum(skb, dataoff)) {
if (LOG_INVALID(IPPROTO_UDP)) if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL, nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_udp: bad UDP checksum "); "nf_ct_udp: bad UDP checksum ");
@ -148,44 +146,6 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
return NF_ACCEPT; return NF_ACCEPT;
} }
static int csum4(const struct sk_buff *skb, unsigned int dataoff)
{
return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
skb->len - dataoff, IPPROTO_UDP,
skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, dataoff,
skb->len - dataoff, 0));
}
static int csum6(const struct sk_buff *skb, unsigned int dataoff)
{
return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
skb->len - dataoff, IPPROTO_UDP,
skb->ip_summed == CHECKSUM_HW
? csum_sub(skb->csum,
skb_checksum(skb, 0, dataoff, 0))
: skb_checksum(skb, dataoff, skb->len - dataoff,
0));
}
static int udp_error4(struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
unsigned int hooknum)
{
return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
}
static int udp_error6(struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
unsigned int hooknum)
{
return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
}
struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
{ {
.l3proto = PF_INET, .l3proto = PF_INET,
@ -197,7 +157,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
.print_conntrack = udp_print_conntrack, .print_conntrack = udp_print_conntrack,
.packet = udp_packet, .packet = udp_packet,
.new = udp_new, .new = udp_new,
.error = udp_error4, .error = udp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \ #if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE) defined(CONFIG_NF_CT_NETLINK_MODULE)
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
@ -216,7 +176,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
.print_conntrack = udp_print_conntrack, .print_conntrack = udp_print_conntrack,
.packet = udp_packet, .packet = udp_packet,
.new = udp_new, .new = udp_new,
.error = udp_error6, .error = udp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \ #if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE) defined(CONFIG_NF_CT_NETLINK_MODULE)
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,