aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-04-06 17:19:24 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-04-10 01:25:42 -0400
commit96f6bf82ea3abc77d255d5d554df5f349651f6de (patch)
tree7050071415f6e0ab56ee6d9a51680b30c3876a94 /net
parent422c346fad806e2abaeffac686860ebc98dfe33e (diff)
[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>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c23
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_udp.c7
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c9
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c20
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c12
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c50
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c50
8 files changed, 25 insertions, 153 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 3021af0910f1..d8b14a9010a6 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -224,25 +224,14 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
224 } 224 }
225 225
226 /* See ip_conntrack_proto_tcp.c */ 226 /* See ip_conntrack_proto_tcp.c */
227 if (hooknum != NF_IP_PRE_ROUTING) 227 if (hooknum == NF_IP_PRE_ROUTING &&
228 goto checksum_skipped; 228 nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
229 229 if (LOG_INVALID(IPPROTO_ICMP))
230 switch (skb->ip_summed) { 230 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
231 case CHECKSUM_HW: 231 "ip_ct_icmp: bad ICMP checksum ");
232 if (!(u16)csum_fold(skb->csum)) 232 return -NF_ACCEPT;
233 break;
234 /* fall through */
235 case CHECKSUM_NONE:
236 skb->csum = 0;
237 if (__skb_checksum_complete(skb)) {
238 if (LOG_INVALID(IPPROTO_ICMP))
239 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
240 "ip_ct_icmp: bad ICMP checksum ");
241 return -NF_ACCEPT;
242 }
243 } 233 }
244 234
245checksum_skipped:
246 /* 235 /*
247 * 18 is the highest 'known' ICMP type. Anything else is a mystery 236 * 18 is the highest 'known' ICMP type. Anything else is a mystery
248 * 237 *
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index e0dc37063545..062b252b58ad 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -870,11 +870,8 @@ static int tcp_error(struct sk_buff *skb,
870 * and moreover root might send raw packets. 870 * and moreover root might send raw packets.
871 */ 871 */
872 /* FIXME: Source route IP option packets --RR */ 872 /* FIXME: Source route IP option packets --RR */
873 if (hooknum == NF_IP_PRE_ROUTING 873 if (hooknum == NF_IP_PRE_ROUTING &&
874 && skb->ip_summed != CHECKSUM_UNNECESSARY 874 nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
875 && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
876 skb->ip_summed == CHECKSUM_HW ? skb->csum
877 : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
878 if (LOG_INVALID(IPPROTO_TCP)) 875 if (LOG_INVALID(IPPROTO_TCP))
879 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 876 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
880 "ip_ct_tcp: bad TCP checksum "); 877 "ip_ct_tcp: bad TCP checksum ");
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index 55b7d3210adf..70899868783b 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -120,11 +120,8 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
120 * because the semantic of CHECKSUM_HW is different there 120 * because the semantic of CHECKSUM_HW is different there
121 * and moreover root might send raw packets. 121 * and moreover root might send raw packets.
122 * FIXME: Source route IP option packets --RR */ 122 * FIXME: Source route IP option packets --RR */
123 if (hooknum == NF_IP_PRE_ROUTING 123 if (hooknum == NF_IP_PRE_ROUTING &&
124 && skb->ip_summed != CHECKSUM_UNNECESSARY 124 nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
125 && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
126 skb->ip_summed == CHECKSUM_HW ? skb->csum
127 : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
128 if (LOG_INVALID(IPPROTO_UDP)) 125 if (LOG_INVALID(IPPROTO_UDP))
129 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 126 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
130 "ip_ct_udp: bad UDP checksum "); 127 "ip_ct_udp: bad UDP checksum ");
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 4269a5440d43..0bba3c2bb786 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -106,7 +106,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
106 struct rtable *rt; 106 struct rtable *rt;
107 u_int16_t tmp_port; 107 u_int16_t tmp_port;
108 u_int32_t tmp_addr; 108 u_int32_t tmp_addr;
109 unsigned int tcplen;
110 int needs_ack; 109 int needs_ack;
111 int hh_len; 110 int hh_len;
112 111
@@ -124,13 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
124 return; 123 return;
125 124
126 /* Check checksum */ 125 /* Check checksum */
127 tcplen = oldskb->len - iph->ihl * 4; 126 if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
128 if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) ||
129 (hook == NF_IP_LOCAL_IN &&
130 oldskb->ip_summed != CHECKSUM_UNNECESSARY)) &&
131 csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
132 oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum :
133 skb_checksum(oldskb, iph->ihl * 4, tcplen, 0)))
134 return; 127 return;
135 128
136 if ((rt = route_reverse(oldskb, oth, hook)) == NULL) 129 if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 52dc175be39a..4b0d361cc6e6 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -235,30 +235,14 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
235 } 235 }
236 236
237 /* See ip_conntrack_proto_tcp.c */ 237 /* See ip_conntrack_proto_tcp.c */
238 if (hooknum != NF_IP_PRE_ROUTING) 238 if (hooknum == NF_IP_PRE_ROUTING &&
239 goto checksum_skipped; 239 nf_ip_checksum(skb, hooknum, dataoff, 0)) {
240
241 switch (skb->ip_summed) {
242 case CHECKSUM_HW:
243 if (!(u16)csum_fold(skb->csum))
244 break;
245 if (LOG_INVALID(IPPROTO_ICMP)) 240 if (LOG_INVALID(IPPROTO_ICMP))
246 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 241 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
247 "nf_ct_icmp: bad HW ICMP checksum "); 242 "nf_ct_icmp: bad HW ICMP checksum ");
248 return -NF_ACCEPT; 243 return -NF_ACCEPT;
249 case CHECKSUM_NONE:
250 if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
251 if (LOG_INVALID(IPPROTO_ICMP))
252 nf_log_packet(PF_INET, 0, skb, NULL, NULL,
253 NULL,
254 "nf_ct_icmp: bad ICMP checksum ");
255 return -NF_ACCEPT;
256 }
257 default:
258 break;
259 } 244 }
260 245
261checksum_skipped:
262 /* 246 /*
263 * 18 is the highest 'known' ICMP type. Anything else is a mystery 247 * 18 is the highest 'known' ICMP type. Anything else is a mystery
264 * 248 *
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 09945c333055..86c6703265d0 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -233,21 +233,13 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff,
233 return -NF_ACCEPT; 233 return -NF_ACCEPT;
234 } 234 }
235 235
236 if (hooknum != NF_IP6_PRE_ROUTING) 236 if (hooknum == NF_IP6_PRE_ROUTING &&
237 goto skipped; 237 nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
238
239 /* Ignore it if the checksum's bogus. */
240 if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
241 skb->len - dataoff, IPPROTO_ICMPV6,
242 skb_checksum(skb, dataoff,
243 skb->len - dataoff, 0))) {
244 nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, 238 nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
245 "nf_ct_icmpv6: ICMPv6 checksum failed\n"); 239 "nf_ct_icmpv6: ICMPv6 checksum failed\n");
246 return -NF_ACCEPT; 240 return -NF_ACCEPT;
247 } 241 }
248 242
249skipped:
250
251 /* is not error message ? */ 243 /* is not error message ? */
252 if (icmp6h->icmp6_type >= 128) 244 if (icmp6h->icmp6_type >= 128)
253 return NF_ACCEPT; 245 return NF_ACCEPT;
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 6492ed66fb3c..69899f27d26a 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -799,8 +799,7 @@ static int tcp_error(struct sk_buff *skb,
799 unsigned int dataoff, 799 unsigned int dataoff,
800 enum ip_conntrack_info *ctinfo, 800 enum ip_conntrack_info *ctinfo,
801 int pf, 801 int pf,
802 unsigned int hooknum, 802 unsigned int hooknum)
803 int(*csum)(const struct sk_buff *,unsigned int))
804{ 803{
805 struct tcphdr _tcph, *th; 804 struct tcphdr _tcph, *th;
806 unsigned int tcplen = skb->len - dataoff; 805 unsigned int tcplen = skb->len - dataoff;
@@ -830,9 +829,8 @@ static int tcp_error(struct sk_buff *skb,
830 */ 829 */
831 /* FIXME: Source route IP option packets --RR */ 830 /* FIXME: Source route IP option packets --RR */
832 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || 831 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
833 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) 832 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
834 && skb->ip_summed != CHECKSUM_UNNECESSARY 833 nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
835 && csum(skb, dataoff)) {
836 if (LOG_INVALID(IPPROTO_TCP)) 834 if (LOG_INVALID(IPPROTO_TCP))
837 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 835 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
838 "nf_ct_tcp: bad TCP checksum "); 836 "nf_ct_tcp: bad TCP checksum ");
@@ -851,44 +849,6 @@ static int tcp_error(struct sk_buff *skb,
851 return NF_ACCEPT; 849 return NF_ACCEPT;
852} 850}
853 851
854static int csum4(const struct sk_buff *skb, unsigned int dataoff)
855{
856 return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
857 skb->len - dataoff, IPPROTO_TCP,
858 skb->ip_summed == CHECKSUM_HW ? skb->csum
859 : skb_checksum(skb, dataoff,
860 skb->len - dataoff, 0));
861}
862
863static int csum6(const struct sk_buff *skb, unsigned int dataoff)
864{
865 return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
866 skb->len - dataoff, IPPROTO_TCP,
867 skb->ip_summed == CHECKSUM_HW
868 ? csum_sub(skb->csum,
869 skb_checksum(skb, 0, dataoff, 0))
870 : skb_checksum(skb, dataoff, skb->len - dataoff,
871 0));
872}
873
874static int tcp_error4(struct sk_buff *skb,
875 unsigned int dataoff,
876 enum ip_conntrack_info *ctinfo,
877 int pf,
878 unsigned int hooknum)
879{
880 return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
881}
882
883static int tcp_error6(struct sk_buff *skb,
884 unsigned int dataoff,
885 enum ip_conntrack_info *ctinfo,
886 int pf,
887 unsigned int hooknum)
888{
889 return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
890}
891
892/* Returns verdict for packet, or -1 for invalid. */ 852/* Returns verdict for packet, or -1 for invalid. */
893static int tcp_packet(struct nf_conn *conntrack, 853static int tcp_packet(struct nf_conn *conntrack,
894 const struct sk_buff *skb, 854 const struct sk_buff *skb,
@@ -1218,7 +1178,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
1218 .print_conntrack = tcp_print_conntrack, 1178 .print_conntrack = tcp_print_conntrack,
1219 .packet = tcp_packet, 1179 .packet = tcp_packet,
1220 .new = tcp_new, 1180 .new = tcp_new,
1221 .error = tcp_error4, 1181 .error = tcp_error,
1222#if defined(CONFIG_NF_CT_NETLINK) || \ 1182#if defined(CONFIG_NF_CT_NETLINK) || \
1223 defined(CONFIG_NF_CT_NETLINK_MODULE) 1183 defined(CONFIG_NF_CT_NETLINK_MODULE)
1224 .to_nfattr = tcp_to_nfattr, 1184 .to_nfattr = tcp_to_nfattr,
@@ -1239,7 +1199,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
1239 .print_conntrack = tcp_print_conntrack, 1199 .print_conntrack = tcp_print_conntrack,
1240 .packet = tcp_packet, 1200 .packet = tcp_packet,
1241 .new = tcp_new, 1201 .new = tcp_new,
1242 .error = tcp_error6, 1202 .error = tcp_error,
1243#if defined(CONFIG_NF_CT_NETLINK) || \ 1203#if defined(CONFIG_NF_CT_NETLINK) || \
1244 defined(CONFIG_NF_CT_NETLINK_MODULE) 1204 defined(CONFIG_NF_CT_NETLINK_MODULE)
1245 .to_nfattr = tcp_to_nfattr, 1205 .to_nfattr = tcp_to_nfattr,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 831d206344e0..d93edbfde9e3 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -103,8 +103,7 @@ static int udp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
103static int udp_error(struct sk_buff *skb, unsigned int dataoff, 103static int udp_error(struct sk_buff *skb, unsigned int dataoff,
104 enum ip_conntrack_info *ctinfo, 104 enum ip_conntrack_info *ctinfo,
105 int pf, 105 int pf,
106 unsigned int hooknum, 106 unsigned int hooknum)
107 int (*csum)(const struct sk_buff *, unsigned int))
108{ 107{
109 unsigned int udplen = skb->len - dataoff; 108 unsigned int udplen = skb->len - dataoff;
110 struct udphdr _hdr, *hdr; 109 struct udphdr _hdr, *hdr;
@@ -136,9 +135,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
136 * and moreover root might send raw packets. 135 * and moreover root might send raw packets.
137 * FIXME: Source route IP option packets --RR */ 136 * FIXME: Source route IP option packets --RR */
138 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || 137 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
139 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) 138 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
140 && skb->ip_summed != CHECKSUM_UNNECESSARY 139 nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
141 && csum(skb, dataoff)) {
142 if (LOG_INVALID(IPPROTO_UDP)) 140 if (LOG_INVALID(IPPROTO_UDP))
143 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 141 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
144 "nf_ct_udp: bad UDP checksum "); 142 "nf_ct_udp: bad UDP checksum ");
@@ -148,44 +146,6 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
148 return NF_ACCEPT; 146 return NF_ACCEPT;
149} 147}
150 148
151static int csum4(const struct sk_buff *skb, unsigned int dataoff)
152{
153 return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
154 skb->len - dataoff, IPPROTO_UDP,
155 skb->ip_summed == CHECKSUM_HW ? skb->csum
156 : skb_checksum(skb, dataoff,
157 skb->len - dataoff, 0));
158}
159
160static int csum6(const struct sk_buff *skb, unsigned int dataoff)
161{
162 return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
163 skb->len - dataoff, IPPROTO_UDP,
164 skb->ip_summed == CHECKSUM_HW
165 ? csum_sub(skb->csum,
166 skb_checksum(skb, 0, dataoff, 0))
167 : skb_checksum(skb, dataoff, skb->len - dataoff,
168 0));
169}
170
171static int udp_error4(struct sk_buff *skb,
172 unsigned int dataoff,
173 enum ip_conntrack_info *ctinfo,
174 int pf,
175 unsigned int hooknum)
176{
177 return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
178}
179
180static int udp_error6(struct sk_buff *skb,
181 unsigned int dataoff,
182 enum ip_conntrack_info *ctinfo,
183 int pf,
184 unsigned int hooknum)
185{
186 return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
187}
188
189struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = 149struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
190{ 150{
191 .l3proto = PF_INET, 151 .l3proto = PF_INET,
@@ -197,7 +157,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
197 .print_conntrack = udp_print_conntrack, 157 .print_conntrack = udp_print_conntrack,
198 .packet = udp_packet, 158 .packet = udp_packet,
199 .new = udp_new, 159 .new = udp_new,
200 .error = udp_error4, 160 .error = udp_error,
201#if defined(CONFIG_NF_CT_NETLINK) || \ 161#if defined(CONFIG_NF_CT_NETLINK) || \
202 defined(CONFIG_NF_CT_NETLINK_MODULE) 162 defined(CONFIG_NF_CT_NETLINK_MODULE)
203 .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, 163 .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
@@ -216,7 +176,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
216 .print_conntrack = udp_print_conntrack, 176 .print_conntrack = udp_print_conntrack,
217 .packet = udp_packet, 177 .packet = udp_packet,
218 .new = udp_new, 178 .new = udp_new,
219 .error = udp_error6, 179 .error = udp_error,
220#if defined(CONFIG_NF_CT_NETLINK) || \ 180#if defined(CONFIG_NF_CT_NETLINK) || \
221 defined(CONFIG_NF_CT_NETLINK_MODULE) 181 defined(CONFIG_NF_CT_NETLINK_MODULE)
222 .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, 182 .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,