patch-2.4.21 linux-2.4.21/net/ipv4/netfilter/ipt_REJECT.c
Next file: linux-2.4.21/net/ipv4/netfilter/ipt_ULOG.c
Previous file: linux-2.4.21/net/ipv4/netfilter/ipt_ECN.c
Back to the patch index
Back to the overall index
- Lines: 98
- Date:
2003-06-13 07:51:39.000000000 -0700
- Orig file:
linux-2.4.20/net/ipv4/netfilter/ipt_REJECT.c
- Orig date:
2002-11-28 15:53:15.000000000 -0800
diff -urN linux-2.4.20/net/ipv4/netfilter/ipt_REJECT.c linux-2.4.21/net/ipv4/netfilter/ipt_REJECT.c
@@ -6,10 +6,11 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/icmp.h>
#include <net/icmp.h>
#include <net/ip.h>
#include <net/tcp.h>
-struct in_device;
#include <net/route.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_REJECT.h>
@@ -42,6 +43,7 @@
u_int16_t tmp_port;
u_int32_t tmp_addr;
int needs_ack;
+ int hh_len;
/* IP header checks: fragment, too short. */
if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
@@ -61,12 +63,28 @@
csum_partial((char *)otcph, otcplen, 0)) != 0)
return;
+ /* Routing: if not headed for us, route won't like source */
+ if (ip_route_output(&rt, oldskb->nh.iph->saddr,
+ local ? oldskb->nh.iph->daddr : 0,
+ RT_TOS(oldskb->nh.iph->tos), 0) != 0)
+ return;
+
+ hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
+
+
/* Copy skb (even if skb is about to be dropped, we can't just
clone it because there may be other things, such as tcpdump,
- interested in it) */
- nskb = skb_copy(oldskb, GFP_ATOMIC);
- if (!nskb)
+ interested in it). We also need to expand headroom in case
+ hh_len of incoming interface < hh_len of outgoing interface */
+ nskb = skb_copy_expand(oldskb, hh_len, skb_tailroom(oldskb),
+ GFP_ATOMIC);
+ if (!nskb) {
+ dst_release(&rt->u.dst);
return;
+ }
+
+ dst_release(nskb->dst);
+ nskb->dst = &rt->u.dst;
/* This packet will not be the same as the other: clear nf fields */
nf_conntrack_put(nskb->nfct);
@@ -130,16 +148,6 @@
nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
nskb->nh.iph->ihl);
- /* Routing: if not headed for us, route won't like source */
- if (ip_route_output(&rt, nskb->nh.iph->daddr,
- local ? nskb->nh.iph->saddr : 0,
- RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
- 0) != 0)
- goto free_nskb;
-
- dst_release(nskb->dst);
- nskb->dst = &rt->u.dst;
-
/* "Never happens" */
if (nskb->len > nskb->dst->pmtu)
goto free_nskb;
@@ -157,6 +165,7 @@
static void send_unreach(struct sk_buff *skb_in, int code)
{
struct iphdr *iph;
+ struct udphdr *udph;
struct icmphdr *icmph;
struct sk_buff *nskb;
u32 saddr;
@@ -186,6 +195,19 @@
if (iph->frag_off&htons(IP_OFFSET))
return;
+ /* if UDP checksum is set, verify it's correct */
+ if (iph->protocol == IPPROTO_UDP
+ && skb_in->tail-(u8*)iph >= sizeof(struct udphdr)) {
+ int datalen = skb_in->len - (iph->ihl<<2);
+ udph = (struct udphdr *)((char *)iph + (iph->ihl<<2));
+ if (udph->check
+ && csum_tcpudp_magic(iph->saddr, iph->daddr,
+ datalen, IPPROTO_UDP,
+ csum_partial((char *)udph, datalen,
+ 0)) != 0)
+ return;
+ }
+
/* If we send an ICMP error to an ICMP error a mess would result.. */
if (iph->protocol == IPPROTO_ICMP
&& skb_in->tail-(u8*)iph >= sizeof(struct icmphdr)) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)