diff options
author | davem <davem> | 2001-12-13 10:42:39 +0000 |
---|---|---|
committer | davem <davem> | 2001-12-13 10:42:39 +0000 |
commit | 52c281714563d37cb08de560eef8d1a6c298fb18 (patch) | |
tree | 0032366d4ebd9664e5775b8f791711bc34a6ce77 | |
parent | 07a8bd20cd42a0d3c9ed6854de8f1f59eacc95ff (diff) | |
download | netdev-vger-cvs-52c281714563d37cb08de560eef8d1a6c298fb18.tar.gz |
Forward port netfilter fixes from 2.4.x branch.
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_irc.c | 8 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_fw_compat.c | 10 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_core.c | 12 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_helper.c | 17 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_irc.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_MIRROR.c | 37 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_TCPMSS.c | 13 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_TOS.c | 11 |
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); |