patch-2.4.18 linux/net/ipv4/netfilter/ip_fw_compat_redir.c
Next file: linux/net/ipv4/netfilter/ip_nat_rule.c
Previous file: linux/net/ipv4/netfilter/ip_fw_compat_masq.c
Back to the patch index
Back to the overall index
- Lines: 118
- Date:
Wed Jan 23 20:24:37 2002
- Orig file:
linux.orig/net/ipv4/netfilter/ip_fw_compat_redir.c
- Orig date:
Mon Feb 18 20:18:40 2002
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/net/ipv4/netfilter/ip_fw_compat_redir.c linux/net/ipv4/netfilter/ip_fw_compat_redir.c
@@ -20,6 +20,9 @@
#include <linux/netfilter_ipv4/lockhelp.h>
+/* Very simple timeout pushed back by each packet */
+#define REDIR_TIMEOUT (240*HZ)
+
static DECLARE_LOCK(redir_lock);
#define ASSERT_READ_LOCK(x) MUST_BE_LOCKED(&redir_lock)
#define ASSERT_WRITE_LOCK(x) MUST_BE_LOCKED(&redir_lock)
@@ -150,6 +153,14 @@
skb->nfcache |= NFC_ALTERED;
}
+static void destroyme(unsigned long me)
+{
+ LOCK_BH(&redir_lock);
+ LIST_DELETE(&redirs, (struct redir *)me);
+ UNLOCK_BH(&redir_lock);
+ kfree((struct redir *)me);
+}
+
/* REDIRECT a packet. */
unsigned int
do_redirect(struct sk_buff *skb,
@@ -172,6 +183,10 @@
struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph
+ iph->ihl);
+ /* Must have whole header */
+ if (skb->len < iph->ihl*4 + sizeof(*udph))
+ return NF_DROP;
+
if (udph->check) /* 0 is a special case meaning no checksum */
udph->check = cheat_check(~iph->daddr, newdst,
cheat_check(udph->dest ^ 0xFFFF,
@@ -191,6 +206,10 @@
struct redir *redir;
int ret;
+ /* Must have whole header */
+ if (skb->len < iph->ihl*4 + sizeof(*tcph))
+ return NF_DROP;
+
DEBUGP("Doing tcp redirect. %08X:%u %08X:%u -> %08X:%u\n",
iph->saddr, tcph->source, iph->daddr, tcph->dest,
newdst, redirpt);
@@ -206,7 +225,9 @@
}
list_prepend(&redirs, redir);
init_timer(&redir->destroyme);
- redir->destroyme.expires = jiffies + 75*HZ;
+ redir->destroyme.function = destroyme;
+ redir->destroyme.data = (unsigned long)redir;
+ redir->destroyme.expires = jiffies + REDIR_TIMEOUT;
add_timer(&redir->destroyme);
}
/* In case mangling has changed, rewrite this part. */
@@ -227,13 +248,6 @@
}
}
-static void destroyme(unsigned long me)
-{
- LOCK_BH(&redir_lock);
- LIST_DELETE(&redirs, (struct redir *)me);
- UNLOCK_BH(&redir_lock);
-}
-
/* Incoming packet: is it a reply to a masqueraded connection, or
part of an already-redirected TCP connection? */
void
@@ -247,15 +261,18 @@
if (iph->protocol != IPPROTO_TCP)
return;
+ /* Must have whole header */
+ if (skb->len < iph->ihl*4 + sizeof(*tcph))
+ return;
+
LOCK_BH(&redir_lock);
redir = find_redir(iph->saddr, iph->daddr, tcph->source, tcph->dest);
if (redir) {
DEBUGP("Doing tcp redirect again.\n");
do_tcp_redir(skb, redir);
- if (tcph->rst || tcph->fin) {
- redir->destroyme.function = destroyme;
- redir->destroyme.data = (unsigned long)redir;
- mod_timer(&redir->destroyme, 75*HZ);
+ if (del_timer(&redir->destroyme)) {
+ redir->destroyme.expires = jiffies + REDIR_TIMEOUT;
+ add_timer(&redir->destroyme);
}
}
UNLOCK_BH(&redir_lock);
@@ -272,15 +289,18 @@
if (iph->protocol != IPPROTO_TCP)
return;
+ /* Must have whole header */
+ if (skb->len < iph->ihl*4 + sizeof(*tcph))
+ return;
+
LOCK_BH(&redir_lock);
redir = find_unredir(iph->saddr, iph->daddr, tcph->source, tcph->dest);
if (redir) {
DEBUGP("Doing tcp unredirect.\n");
do_tcp_unredir(skb, redir);
- if (tcph->rst || tcph->fin) {
- redir->destroyme.function = destroyme;
- redir->destroyme.data = (unsigned long)redir;
- mod_timer(&redir->destroyme, 75*HZ);
+ if (del_timer(&redir->destroyme)) {
+ redir->destroyme.expires = jiffies + REDIR_TIMEOUT;
+ add_timer(&redir->destroyme);
}
}
UNLOCK_BH(&redir_lock);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)