aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavem <davem>2001-12-13 10:42:39 +0000
committerdavem <davem>2001-12-13 10:42:39 +0000
commit52c281714563d37cb08de560eef8d1a6c298fb18 (patch)
tree0032366d4ebd9664e5775b8f791711bc34a6ce77
parent07a8bd20cd42a0d3c9ed6854de8f1f59eacc95ff (diff)
downloadnetdev-vger-cvs-52c281714563d37cb08de560eef8d1a6c298fb18.tar.gz
Forward port netfilter fixes from 2.4.x branch.
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c8
-rw-r--r--net/ipv4/netfilter/ip_fw_compat.c10
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c12
-rw-r--r--net/ipv4/netfilter/ip_nat_helper.c17
-rw-r--r--net/ipv4/netfilter/ip_nat_irc.c6
-rw-r--r--net/ipv4/netfilter/ipt_MIRROR.c37
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c13
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c11
8 files changed, 98 insertions, 16 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index bf1c7793a..79cec8993 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -1,8 +1,8 @@
-/* IRC extension for IP connection tracking, Version 1.19
- * (C) 2000 by Harald Welte <laforge@gnumonks.org>
+/* IRC extension for IP connection tracking, Version 1.20
+ * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
* based on RR's ip_conntrack_ftp.c
*
- * ip_conntrack_irc.c,v 1.19 2001/10/25 14:34:21 laforge Exp
+ * ip_conntrack_irc.c,v 1.20 2001/12/06 07:42:10 laforge Exp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -10,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
**
* Module load syntax:
- * insmod ip_nat_irc.o ports=port1,port2,...port<MAX_PORTS>
+ * insmod ip_conntrack_irc.o ports=port1,port2,...port<MAX_PORTS>
*
* please give the ports of all IRC servers You wish to connect to.
* If You don't specify ports, the default will be port 6667
diff --git a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c
index 6489ad787..021d125f3 100644
--- a/net/ipv4/netfilter/ip_fw_compat.c
+++ b/net/ipv4/netfilter/ip_fw_compat.c
@@ -84,6 +84,16 @@ fw_in(unsigned int hooknum,
if ((*pskb)->ip_summed == CHECKSUM_HW)
(*pskb)->ip_summed = CHECKSUM_NONE;
+ /* Firewall rules can alter TOS: raw socket (tcpdump) may have
+ clone of incoming skb: don't disturb it --RR */
+ if (skb_cloned(*pskb) && !(*pskb)->sk) {
+ struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!nskb)
+ return NF_DROP;
+ kfree_skb(*pskb);
+ *pskb = nskb;
+ }
+
switch (hooknum) {
case NF_IP_PRE_ROUTING:
if (fwops->fw_acct_in)
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 79d533aae..07ebd39fa 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -734,6 +734,18 @@ do_bindings(struct ip_conntrack *ct,
synchronize_bh()) can vanish. */
READ_LOCK(&ip_nat_lock);
for (i = 0; i < info->num_manips; i++) {
+ /* raw socket (tcpdump) may have clone of incoming
+ skb: don't disturb it --RR */
+ if (skb_cloned(*pskb) && !(*pskb)->sk) {
+ struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!nskb) {
+ READ_UNLOCK(&ip_nat_lock);
+ return NF_DROP;
+ }
+ kfree_skb(*pskb);
+ *pskb = nskb;
+ }
+
if (info->manips[i].direction == dir
&& info->manips[i].hooknum == hooknum) {
DEBUGP("Mangling %p: %s to %u.%u.%u.%u %u\n",
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index d62b5bf41..183ba3f85 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -143,6 +143,23 @@ ip_nat_mangle_tcp_packet(struct sk_buff **skb,
}
}
+ /* Alexey says: if a hook changes _data_ ... it can break
+ original packet sitting in tcp queue and this is fatal */
+ if (skb_cloned(*skb)) {
+ struct sk_buff *nskb = skb_copy(*skb, GFP_ATOMIC);
+ if (!nskb) {
+ if (net_ratelimit())
+ printk("Out of memory cloning TCP packet\n");
+ return 0;
+ }
+ /* Rest of kernel will get very unhappy if we pass it
+ a suddenly-orphaned skbuff */
+ if ((*skb)->sk)
+ skb_set_owner_w(nskb, (*skb)->sk);
+ kfree_skb(*skb);
+ *skb = nskb;
+ }
+
/* skb may be copied !! */
iph = (*skb)->nh.iph;
tcph = (void *)iph + iph->ihl*4;
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index 02102b369..2a8b83afa 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -1,8 +1,8 @@
/* IRC extension for TCP NAT alteration.
- * (C) 2000 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
* based on a copy of RR's ip_nat_ftp.c
*
- * ip_nat_irc.c,v 1.15 2001/10/22 10:43:53 laforge Exp
+ * ip_nat_irc.c,v 1.16 2001/12/06 07:42:10 laforge Exp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -81,7 +81,7 @@ irc_nat_expected(struct sk_buff **pskb,
}
newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
- newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
DEBUGP("nat_expected: DCC cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
NIPQUAD(newsrcip), NIPQUAD(newdstip));
diff --git a/net/ipv4/netfilter/ipt_MIRROR.c b/net/ipv4/netfilter/ipt_MIRROR.c
index d984d7e1f..2fd35b699 100644
--- a/net/ipv4/netfilter/ipt_MIRROR.c
+++ b/net/ipv4/netfilter/ipt_MIRROR.c
@@ -6,6 +6,10 @@
Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
+ Changes:
+ 25 Aug 2001 Harald Welte <laforge@gnumonks.org>
+ - decrement and check TTL if not called from FORWARD hook
+
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
@@ -24,6 +28,7 @@
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <net/ip.h>
+#include <net/icmp.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netdevice.h>
#include <linux/route.h>
@@ -100,15 +105,31 @@ static unsigned int ipt_mirror_target(struct sk_buff **pskb,
const void *targinfo,
void *userinfo)
{
- if ((*pskb)->dst != NULL) {
- if (route_mirror(*pskb)) {
- ip_rewrite(*pskb);
- /* Don't let conntrack code see this packet:
- it will think we are starting a new
- connection! --RR */
- ip_direct_send(*pskb);
- return NF_STOLEN;
+ if (((*pskb)->dst != NULL) &&
+ route_mirror(*pskb)) {
+
+ ip_rewrite(*pskb);
+
+ /* If we are not at FORWARD hook (INPUT/PREROUTING),
+ * the TTL isn't decreased by the IP stack */
+ if (hooknum != NF_IP_FORWARD) {
+ struct iphdr *iph = (*pskb)->nh.iph;
+ if (iph->ttl <= 1) {
+ /* this will traverse normal stack, and
+ * thus call conntrack on the icmp packet */
+ icmp_send(*pskb, ICMP_TIME_EXCEEDED,
+ ICMP_EXC_TTL, 0);
+ return NF_DROP;
+ }
+ ip_decrease_ttl(iph);
}
+
+ /* Don't let conntrack code see this packet:
+ it will think we are starting a new
+ connection! --RR */
+ ip_direct_send(*pskb);
+
+ return NF_STOLEN;
}
return NF_DROP;
}
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index ced0a9dce..68eb02cd9 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -44,11 +44,22 @@ ipt_tcpmss_target(struct sk_buff **pskb,
{
const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
struct tcphdr *tcph;
- struct iphdr *iph = (*pskb)->nh.iph;
+ struct iphdr *iph;
u_int16_t tcplen, newtotlen, oldval, newmss;
unsigned int i;
u_int8_t *opt;
+ /* raw socket (tcpdump) may have clone of incoming skb: don't
+ disturb it --RR */
+ if (skb_cloned(*pskb) && !(*pskb)->sk) {
+ struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!nskb)
+ return NF_DROP;
+ kfree_skb(*pskb);
+ *pskb = nskb;
+ }
+
+ iph = (*pskb)->nh.iph;
tcplen = (*pskb)->len - iph->ihl*4;
tcph = (void *)iph + iph->ihl*4;
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index e6061d707..00d963a52 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -21,6 +21,17 @@ target(struct sk_buff **pskb,
if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
u_int16_t diffs[2];
+ /* raw socket (tcpdump) may have clone of incoming
+ skb: don't disturb it --RR */
+ if (skb_cloned(*pskb) && !(*pskb)->sk) {
+ struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!nskb)
+ return NF_DROP;
+ *pskb = nskb;
+ kfree_skb(*pskb);
+ iph = (*pskb)->nh.iph;
+ }
+
diffs[0] = htons(iph->tos) ^ 0xFFFF;
iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
diffs[1] = htons(iph->tos);