Commit 96f6bf82 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[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: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 422c346f
...@@ -224,25 +224,14 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, ...@@ -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
* *
......
...@@ -870,11 +870,8 @@ static int tcp_error(struct sk_buff *skb, ...@@ -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 ");
......
...@@ -120,11 +120,8 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, ...@@ -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 ");
......
...@@ -106,7 +106,6 @@ static void send_reset(struct sk_buff *oldskb, int hook) ...@@ -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) ...@@ -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)
......
...@@ -235,30 +235,14 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff, ...@@ -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
* *
......
...@@ -233,21 +233,13 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff, ...@@ -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;
......
...@@ -799,8 +799,7 @@ static int tcp_error(struct sk_buff *skb, ...@@ -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, ...@@ -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, ...@@ -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 = ...@@ -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 = ...@@ -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,
......
...@@ -103,8 +103,7 @@ static int udp_new(struct nf_conn *conntrack, const struct sk_buff *skb, ...@@ -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, ...@@ -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, ...@@ -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 = ...@@ -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 = ...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment