Linus, please apply.
For the curious:
Bugs fixed: (most to least important)
conntrack: ip_defrag crash fix Andi Kleen
conntrack: local ICMPs on NAT'ed conns fix Rusty
MASQUERADE: reset on address change (diald) Rusty
ip_queue: Pass mark field James Morris
ftp nat: don't overallocate space Marc Boucher/Rusty
MIRROR: must not track mirrored packets Rusty
Enhancements:
NAT: Set NFC_ALTERED bit only when skb altered Rusty
compat: Always set NFC_ALTERED: no rules Rusty
ftp conntrack: Always print partial matches Rusty
mac: matching in FORWARD chain Rusty
Cheers!
Rusty.
diff -urN -X /tmp/fileJ6etyF --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ip_fw_compat.c
tmp-cleanpatch/net/ipv4/netfilter/ip_fw_compat.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ip_fw_compat.c Thu Jun 29
01:26:09 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ip_fw_compat.c Fri Jul 7 13:08:37 2000
@@ -86,7 +86,8 @@
int ret = FW_BLOCK;
u_int16_t redirpt;
- (*pskb)->nfcache |= NFC_UNKNOWN;
+ /* Assume worse case: any hook could change packet */
+ (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;
(*pskb)->ip_summed = CHECKSUM_NONE;
switch (hooknum) {
diff -urN -X /tmp/fileJ6etyF --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ip_nat_core.c
tmp-cleanpatch/net/ipv4/netfilter/ip_nat_core.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ip_nat_core.c Thu Jun 29
01:26:09 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ip_nat_core.c Fri Jul 7 13:08:37 2000
@@ -663,8 +663,10 @@
static void
manip_pkt(u_int16_t proto, struct iphdr *iph, size_t len,
const struct ip_conntrack_manip *manip,
- enum ip_nat_manip_type maniptype)
+ enum ip_nat_manip_type maniptype,
+ __u32 *nfcache)
{
+ *nfcache |= NFC_ALTERED;
find_nat_proto(proto)->manip_pkt(iph, len, manip, maniptype);
if (maniptype == IP_NAT_MANIP_SRC) {
@@ -718,7 +720,8 @@
(*pskb)->nh.iph,
(*pskb)->len,
&info->manips[i].manip,
- info->manips[i].maniptype);
+ info->manips[i].maniptype,
+ &(*pskb)->nfcache);
}
}
helper = info->helper;
@@ -782,7 +785,8 @@
manip_pkt(inner->protocol, inner,
skb->len - ((void *)inner - (void *)iph),
&info->manips[i].manip,
- !info->manips[i].maniptype);
+ !info->manips[i].maniptype,
+ &skb->nfcache);
/* Outer packet needs to have IP header NATed like
it's a reply. */
} else if (info->manips[i].direction == dir
@@ -795,7 +799,8 @@
IP_PARTS(info->manips[i].manip.ip));
manip_pkt(0, iph, skb->len,
&info->manips[i].manip,
- info->manips[i].maniptype);
+ info->manips[i].maniptype,
+ &skb->nfcache);
}
}
READ_UNLOCK(&ip_nat_lock);
diff -urN -X /tmp/fileJ6etyF --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ip_nat_standalone.c
tmp-cleanpatch/net/ipv4/netfilter/ip_nat_standalone.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ip_nat_standalone.c Thu Jun 29
01:26:09 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ip_nat_standalone.c Fri Jul 7
13:08:37 2000
@@ -60,8 +60,7 @@
IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
& __constant_htons(IP_MF|IP_OFFSET)));
- /* FIXME: One day, fill in properly. --RR */
- (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;
+ (*pskb)->nfcache |= NFC_UNKNOWN;
/* If we had a hardware checksum before, it's now invalid */
if ((*pskb)->pkt_type != PACKET_LOOPBACK)
diff -urN -X /tmp/fileEbRxnx --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ip_queue.c
tmp-cleanpatch/net/ipv4/netfilter/ip_queue.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ip_queue.c Thu Jun 29 01:26:09 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ip_queue.c Fri Jul 7 13:08:45 2000
@@ -6,6 +6,8 @@
*
* 2000-03-27: Simplified code (thanks to Andi Kleen for clues). (JM)
* 2000-05-20: Fixed notifier problems (following Miguel Freitas' report). (JM)
+ * 2000-06-19: Fixed so nfmark is copied to metadata (reported by Sebastian
+ * Zander). (JM)
*
*/
#include <linux/module.h>
@@ -391,6 +393,7 @@
pm->data_len = data_len;
pm->timestamp_sec = e->skb->stamp.tv_sec;
pm->timestamp_usec = e->skb->stamp.tv_usec;
+ pm->mark = e->skb->nfmark;
pm->hook = e->info->hook;
if (e->info->indev) strcpy(pm->indev_name, e->info->indev->name);
else pm->indev_name[0] = '\0';
diff -urN -X /tmp/filenRRBei --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ip_conntrack_ftp.c
tmp-cleanpatch/net/ipv4/netfilter/ip_conntrack_ftp.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ip_conntrack_ftp.c Thu Jun 29
01:26:09 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ip_conntrack_ftp.c Fri Jul 7
13:08:51 2000
@@ -181,8 +181,9 @@
connection tracking, not packet filtering.
However, it is neccessary for accurate tracking in
this case. */
- DEBUGP("conntrack_ftp: partial `%.*s'\n",
- (int)datalen, data);
+ if (net_ratelimit())
+ printk("conntrack_ftp: partial %u+%u\n",
+ ntohl(tcph->seq), datalen);
return NF_DROP;
case 0: /* no match */
diff -urN -X /tmp/fileLO7Uag --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ip_conntrack_core.c
tmp-cleanpatch/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ip_conntrack_core.c Thu Jun 29
01:26:09 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ip_conntrack_core.c Fri Jul 7
13:09:03 2000
@@ -816,7 +816,9 @@
unsigned int olddebug = skb->nf_debug;
#endif
if (sk) sock_hold(sk);
+ local_bh_disable();
skb = ip_defrag(skb);
+ local_bh_enable();
if (!skb) {
if (sk) sock_put(sk);
return skb;
diff -urN -X /tmp/filen7QCuR --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ipt_mac.c
tmp-cleanpatch/net/ipv4/netfilter/ipt_mac.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ipt_mac.c Fri May 12 13:22:38 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ipt_mac.c Fri Jul 7 13:09:10 2000
@@ -33,9 +33,11 @@
unsigned int matchsize,
unsigned int hook_mask)
{
+ /* FORWARD isn't always valid, but it's nice to be able to do --RR */
if (hook_mask
- & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN))) {
- printk("ipt_mac: only valid for PRE_ROUTING or LOCAL_IN.\n");
+ & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN)
+ | (1 << NF_IP_FORWARD))) {
+ printk("ipt_mac: only valid for PRE_ROUTING, LOCAL_IN or
FORWARD.\n");
return 0;
}
diff -urN -X /tmp/fileEFGdiT --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ipt_MASQUERADE.c
tmp-cleanpatch/net/ipv4/netfilter/ipt_MASQUERADE.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ipt_MASQUERADE.c Thu Jun 29
01:26:09 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ipt_MASQUERADE.c Fri Jul 7 13:09:16 2000
@@ -127,8 +127,8 @@
{
struct net_device *dev = ptr;
- if (event == NETDEV_DOWN) {
- /* Device was downed. Search entire table for
+ if (event == NETDEV_DOWN || event == NETDEV_CHANGEADDR) {
+ /* Device was downed/changed (diald) Search entire table for
conntracks which were associated with that device,
and forget them. */
IP_NF_ASSERT(dev->ifindex != 0);
diff -urN -X /tmp/filevIBgPs --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ip_conntrack_core.c
tmp-cleanpatch/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ip_conntrack_core.c Thu Jun 29
01:26:09 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ip_conntrack_core.c Fri Jul 7
13:09:22 2000
@@ -303,6 +303,7 @@
struct ip_conntrack_tuple_hash *h;
IP_NF_ASSERT(iph->protocol == IPPROTO_ICMP);
+ IP_NF_ASSERT(skb->nfct == NULL);
iph = skb->nh.iph;
hdr = (struct icmphdr *)((u_int32_t *)iph + iph->ihl);
@@ -350,10 +351,27 @@
DEBUGP("icmp_error_track: Can't invert tuple\n");
return NULL;
}
+
+ *ctinfo = IP_CT_RELATED;
+
h = ip_conntrack_find_get(&innertuple, NULL);
if (!h) {
- DEBUGP("icmp_error_track: no match\n");
- return NULL;
+ /* Locally generated ICMPs will match inverted if they
+ haven't been SNAT'ed yet */
+ /* FIXME: NAT code has to handle half-done double NAT --RR */
+ if (hooknum == NF_IP_LOCAL_OUT)
+ h = ip_conntrack_find_get(&origtuple, NULL);
+
+ if (!h) {
+ DEBUGP("icmp_error_track: no match\n");
+ return NULL;
+ }
+ /* Reverse direction from that found */
+ if (DIRECTION(h) != IP_CT_DIR_REPLY)
+ *ctinfo += IP_CT_IS_REPLY;
+ } else {
+ if (DIRECTION(h) == IP_CT_DIR_REPLY)
+ *ctinfo += IP_CT_IS_REPLY;
}
/* REJECT target does this commonly, so allow locally
@@ -364,10 +382,6 @@
ip_conntrack_put(h->ctrack);
return NULL;
}
-
- *ctinfo = IP_CT_RELATED;
- if (DIRECTION(h) == IP_CT_DIR_REPLY)
- *ctinfo += IP_CT_IS_REPLY;
/* Update skb to refer to this connection */
skb->nfct = &h->ctrack->infos[*ctinfo];
diff -urN -X /tmp/filevIBgPs --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ip_nat_core.c
tmp-cleanpatch/net/ipv4/netfilter/ip_nat_core.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ip_nat_core.c Thu Jun 29
01:26:09 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ip_nat_core.c Fri Jul 7 13:09:22 2000
@@ -467,7 +467,7 @@
static unsigned int opposite_hook[NF_IP_NUMHOOKS]
= { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING,
[NF_IP_POST_ROUTING] = NF_IP_PRE_ROUTING,
- [NF_IP_LOCAL_OUT] = NF_IP_PRE_ROUTING
+ [NF_IP_LOCAL_OUT] = NF_IP_POST_ROUTING
};
unsigned int
@@ -754,7 +754,7 @@
(even though a "host unreachable" coming from the host
itself is a bit wierd).
- More explanation: some people use NAT for anonomizing.
+ More explanation: some people use NAT for anonymizing.
Also, CERT recommends dropping all packets from private IP
addresses (although ICMP errors from internal links with
such addresses are not too uncommon, as Alan Cox points
@@ -785,8 +785,7 @@
!info->manips[i].maniptype);
/* Outer packet needs to have IP header NATed like
it's a reply. */
- } else if (info->manips[i].direction == dir
- && info->manips[i].hooknum == hooknum) {
+ } else if (info->manips[i].hooknum == hooknum) {
/* Use mapping to map outer packet: 0 give no
per-proto mapping */
DEBUGP("icmp_reply: outer %s -> %u.%u.%u.%u\n",
diff -urN -X /tmp/fileciI17V --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ip_nat_ftp.c
tmp-cleanpatch/net/ipv4/netfilter/ip_nat_ftp.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ip_nat_ftp.c Wed Apr 12 17:43:07 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ip_nat_ftp.c Fri Jul 7 13:09:28 2000
@@ -123,7 +123,8 @@
if (newlen > (*pskb)->len + skb_tailroom(*pskb)) {
struct sk_buff *newskb;
- newskb = skb_copy_expand(*pskb, skb_headroom(*pskb), newlen,
+ newskb = skb_copy_expand(*pskb, skb_headroom(*pskb),
+ newlen - (*pskb)->len,
GFP_ATOMIC);
if (!newskb) {
DEBUGP("ftp: oom\n");
diff -urN -X /tmp/filev1eVOB --minimal
linux-2.4.0-test3-4/net/ipv4/netfilter/ipt_MIRROR.c
tmp-cleanpatch/net/ipv4/netfilter/ipt_MIRROR.c
--- linux-2.4.0-test3-4/net/ipv4/netfilter/ipt_MIRROR.c Fri May 12 13:22:38 2000
+++ tmp-cleanpatch/net/ipv4/netfilter/ipt_MIRROR.c Fri Jul 7 13:09:42 2000
@@ -41,23 +41,25 @@
struct iphdr *iph = skb->nh.iph;
struct rtable *rt;
- if (ip_route_output(&rt, iph->daddr, iph->saddr,
+ /* Backwards */
+ if (ip_route_output(&rt, iph->saddr, iph->daddr,
RT_TOS(iph->tos) | RTO_CONN,
0)) {
- return -EINVAL;
+ return 0;
}
- /* check if the interface we are living by is the same as the one we
arrived on */
+ /* check if the interface we are leaving by is the same as the
+ one we arrived on */
if (skb->rx_dev == rt->u.dst.dev) {
/* Drop old route. */
dst_release(skb->dst);
skb->dst = &rt->u.dst;
- return 0;
+ return 1;
}
- else return -EINVAL;
+ return 0;
}
-static int
+static void
ip_rewrite(struct sk_buff *skb)
{
struct iphdr *iph = skb->nh.iph;
@@ -69,10 +71,27 @@
/* Rewrite IP header */
iph->daddr = odaddr;
iph->saddr = osaddr;
-
- return 0;
}
+/* Stolen from ip_finish_output2 */
+static void ip_direct_send(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct hh_cache *hh = dst->hh;
+
+ if (hh) {
+ read_lock_bh(&hh->hh_lock);
+ memcpy(skb->data - 16, hh->hh_data, 16);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
+ hh->hh_output(skb);
+ } else if (dst->neighbour)
+ dst->neighbour->output(skb);
+ else {
+ printk(KERN_DEBUG "khm in MIRROR\n");
+ kfree(skb);
+ }
+}
static unsigned int ipt_mirror_target(struct sk_buff **pskb,
unsigned int hooknum,
@@ -82,8 +101,12 @@
void *userinfo)
{
if ((*pskb)->dst != NULL) {
- if (!ip_rewrite(*pskb) && !route_mirror(*pskb)) {
- ip_send(*pskb);
+ 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;
}
}
--
Hacking time.
|