summaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-09 02:54:55 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-09 02:54:55 +0000
commit493c987f7a352ca64fdb4dc03a21e24cbaf46f55 (patch)
tree184cddc0925e082c0500afd042f92e9f340fe890 /net/ipv4
parent2d25612a92c62b5708d6d43f38d28c6141173328 (diff)
Merge with Linux 2.4.0-pre3-test6.
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/ip_gre.c10
-rw-r--r--net/ipv4/ipip.c12
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c28
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c5
-rw-r--r--net/ipv4/netfilter/ip_fw_compat.c3
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c20
-rw-r--r--net/ipv4/netfilter/ip_nat_ftp.c3
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c3
-rw-r--r--net/ipv4/netfilter/ip_queue.c3
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c4
-rw-r--r--net/ipv4/netfilter/ipt_MIRROR.c43
-rw-r--r--net/ipv4/netfilter/ipt_mac.c6
12 files changed, 103 insertions, 37 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index b51d1c4e9..79dc3d629 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -27,6 +27,7 @@
#include <linux/in6.h>
#include <linux/inetdevice.h>
#include <linux/igmp.h>
+#include <linux/netfilter_ipv4.h>
#include <net/sock.h>
#include <net/ip.h>
@@ -616,6 +617,12 @@ drop_nolock:
return(0);
}
+/* Need this wrapper because NF_HOOK takes the function address */
+static inline int do_ip_send(struct sk_buff *skb)
+{
+ return ip_send(skb);
+}
+
static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
@@ -829,7 +836,8 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_bytes += skb->len;
stats->tx_packets++;
- ip_send(skb);
+ NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+ do_ip_send);
tunnel->recursion--;
return 0;
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 4069795fb..e343f34e8 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -1,7 +1,7 @@
/*
* Linux NET3: IP/IP protocol decoder.
*
- * Version: $Id: ipip.c,v 1.34 2000/05/22 08:12:19 davem Exp $
+ * Version: $Id: ipip.c,v 1.35 2000/07/07 01:55:20 davem Exp $
*
* Authors:
* Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95
@@ -107,6 +107,7 @@
#include <linux/if_arp.h>
#include <linux/mroute.h>
#include <linux/init.h>
+#include <linux/netfilter_ipv4.h>
#include <net/sock.h>
#include <net/ip.h>
@@ -499,6 +500,12 @@ int ipip_rcv(struct sk_buff *skb, unsigned short len)
return 0;
}
+/* Need this wrapper because NF_HOOK takes the function address */
+static inline int do_ip_send(struct sk_buff *skb)
+{
+ return ip_send(skb);
+}
+
/*
* This function assumes it is being called from dev_queue_xmit()
* and that skb is filled properly by that function.
@@ -631,7 +638,8 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_bytes += skb->len;
stats->tx_packets++;
- ip_send(skb);
+ NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+ do_ip_send);
tunnel->recursion--;
return 0;
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 780afc05b..47e7fb01b 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -303,6 +303,7 @@ icmp_error_track(struct sk_buff *skb,
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 @@ icmp_error_track(struct sk_buff *skb,
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
@@ -365,10 +383,6 @@ icmp_error_track(struct sk_buff *skb,
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];
return h->ctrack;
@@ -816,7 +830,9 @@ ip_ct_gather_frags(struct sk_buff *skb)
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 --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index c3b1091cf..2e7547c38 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -181,8 +181,9 @@ static int help(const struct iphdr *iph, size_t len,
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 --git a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c
index 501dd0463..6f0503e05 100644
--- a/net/ipv4/netfilter/ip_fw_compat.c
+++ b/net/ipv4/netfilter/ip_fw_compat.c
@@ -86,7 +86,8 @@ fw_in(unsigned int hooknum,
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 --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 56b08a9ed..a07749ecb 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -467,7 +467,7 @@ helper_cmp(const struct ip_nat_helper *helper,
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
@@ -663,8 +663,10 @@ void place_in_hashes(struct ip_conntrack *conntrack,
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 @@ do_bindings(struct ip_conntrack *ct,
(*pskb)->nh.iph,
(*pskb)->len,
&info->manips[i].manip,
- info->manips[i].maniptype);
+ info->manips[i].maniptype,
+ &(*pskb)->nfcache);
}
}
helper = info->helper;
@@ -754,7 +757,7 @@ icmp_reply_translation(struct sk_buff *skb,
(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
@@ -782,11 +785,11 @@ icmp_reply_translation(struct sk_buff *skb,
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
- && 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",
@@ -795,7 +798,8 @@ icmp_reply_translation(struct sk_buff *skb,
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 --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index 12d40f554..a0de5a351 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -123,7 +123,8 @@ mangle_packet(struct sk_buff **pskb,
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 --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 3c8f4f2d6..11e16e25e 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -60,8 +60,7 @@ ip_nat_fn(unsigned int hooknum,
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 --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 82e798f71..792ae1552 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -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 @@ static struct sk_buff *netlink_build_message(ipq_queue_element_t *e, int *errp)
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 --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index c739eda3d..2f9c11915 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -127,8 +127,8 @@ int masq_device_event(struct notifier_block *this,
{
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 --git a/net/ipv4/netfilter/ipt_MIRROR.c b/net/ipv4/netfilter/ipt_MIRROR.c
index 54e62c000..d7718b557 100644
--- a/net/ipv4/netfilter/ipt_MIRROR.c
+++ b/net/ipv4/netfilter/ipt_MIRROR.c
@@ -41,23 +41,25 @@ static int route_mirror(struct sk_buff *skb)
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 @@ ip_rewrite(struct sk_buff *skb)
/* 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 @@ static unsigned int ipt_mirror_target(struct sk_buff **pskb,
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;
}
}
diff --git a/net/ipv4/netfilter/ipt_mac.c b/net/ipv4/netfilter/ipt_mac.c
index 1cc17398d..ce280b3c2 100644
--- a/net/ipv4/netfilter/ipt_mac.c
+++ b/net/ipv4/netfilter/ipt_mac.c
@@ -33,9 +33,11 @@ ipt_mac_checkentry(const char *tablename,
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;
}