Commit 4bf64838 authored by David S. Miller's avatar David S. Miller

Netfilter bugfixes from Harald and Paul Russell.

parent e210f5c4
......@@ -59,95 +59,20 @@ enum nf_ip_hook_priorities {
NF_IP_PRI_LAST = INT_MAX,
};
#ifdef CONFIG_NETFILTER_DEBUG
#ifdef __KERNEL__
void nf_debug_ip_local_deliver(struct sk_buff *skb);
void nf_debug_ip_loopback_xmit(struct sk_buff *newskb);
void nf_debug_ip_finish_output2(struct sk_buff *skb);
#endif /*__KERNEL__*/
#endif /*CONFIG_NETFILTER_DEBUG*/
/* Arguments for setsockopt SOL_IP: */
/* 2.0 firewalling went from 64 through 71 (and +256, +512, etc). */
/* 2.2 firewalling (+ masq) went from 64 through 76 */
/* 2.4 firewalling went 64 through 67. */
#define SO_ORIGINAL_DST 80
#ifdef __KERNEL__
#ifdef CONFIG_NETFILTER_DEBUG
void nf_debug_ip_local_deliver(struct sk_buff *skb);
void nf_debug_ip_loopback_xmit(struct sk_buff *newskb);
void nf_debug_ip_finish_output2(struct sk_buff *skb);
#endif /*CONFIG_NETFILTER_DEBUG*/
/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue
*
* Ideally this would be ins some netfilter_utility module, but creating this
* module for just one function doesn't make sense. -HW */
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/route.h>
#include <linux/ip.h>
static inline int route_me_harder(struct sk_buff **pskb)
{
struct iphdr *iph = (*pskb)->nh.iph;
struct rtable *rt;
struct rt_key key = { dst:iph->daddr,
src:iph->saddr,
oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
tos:RT_TOS(iph->tos)|RTO_CONN,
#ifdef CONFIG_IP_ROUTE_FWMARK
fwmark:(*pskb)->nfmark
#endif
};
struct net_device *dev_src = NULL;
int err;
/* accomodate ip_route_output_slow(), which expects the key src to be
0 or a local address; however some non-standard hacks like
ipt_REJECT.c:send_reset() can cause packets with foreign
saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */
if(key.src && !(dev_src = ip_dev_find(key.src)))
key.src = 0;
if ((err=ip_route_output_key(&rt, &key)) != 0) {
printk("route_me_harder: ip_route_output_key(dst=%u.%u.%u.%u, src=%u.%u.%u.%u, oif=%d, tos=0x%x, fwmark=0x%lx) error %d\n",
NIPQUAD(iph->daddr), NIPQUAD(iph->saddr),
(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
RT_TOS(iph->tos)|RTO_CONN,
#ifdef CONFIG_IP_ROUTE_FWMARK
(*pskb)->nfmark,
#else
0UL,
#endif
err);
goto out;
}
/* Drop old route. */
dst_release((*pskb)->dst);
(*pskb)->dst = &rt->u.dst;
/* Change in oif may mean change in hh_len. */
if (skb_headroom(*pskb) < (*pskb)->dst->dev->hard_header_len) {
struct sk_buff *nskb;
nskb = skb_realloc_headroom(*pskb,
(*pskb)->dst->dev->hard_header_len);
if (!nskb) {
err = -ENOMEM;
goto out;
}
if ((*pskb)->sk)
skb_set_owner_w(nskb, (*pskb)->sk);
kfree_skb(*pskb);
*pskb = nskb;
}
out:
if (dev_src)
dev_put(dev_src);
return err;
}
extern int ip_route_me_harder(struct sk_buff **pskb);
#endif /*__KERNEL__*/
#endif /*__LINUX_IP_NETFILTER_H*/
......@@ -20,6 +20,10 @@
#include <linux/if.h>
#include <linux/netdevice.h>
#include <linux/brlock.h>
#include <linux/inetdevice.h>
#include <net/sock.h>
#include <net/route.h>
#include <linux/ip.h>
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
......@@ -122,9 +126,10 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
down(&nf_sockopt_mutex);
if (reg->use != 0) {
/* To be woken by nf_sockopt call... */
/* FIXME: Stuart Young's name appears gratuitously. */
set_current_state(TASK_UNINTERRUPTIBLE);
reg->cleanup_task = current;
up(&nf_sockopt_mutex);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule();
goto restart;
}
......@@ -553,6 +558,73 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
return;
}
#ifdef CONFIG_INET
/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
int ip_route_me_harder(struct sk_buff **pskb)
{
struct iphdr *iph = (*pskb)->nh.iph;
struct rtable *rt;
struct rt_key key = { dst:iph->daddr,
src:iph->saddr,
oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
tos:RT_TOS(iph->tos)|RTO_CONN,
#ifdef CONFIG_IP_ROUTE_FWMARK
fwmark:(*pskb)->nfmark
#endif
};
struct net_device *dev_src = NULL;
int err;
/* accomodate ip_route_output_slow(), which expects the key src to be
0 or a local address; however some non-standard hacks like
ipt_REJECT.c:send_reset() can cause packets with foreign
saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */
if(key.src && !(dev_src = ip_dev_find(key.src)))
key.src = 0;
if ((err=ip_route_output_key(&rt, &key)) != 0) {
printk("route_me_harder: ip_route_output_key(dst=%u.%u.%u.%u, src=%u.%u.%u.%u, oif=%d, tos=0x%x, fwmark=0x%lx) error %d\n",
NIPQUAD(iph->daddr), NIPQUAD(iph->saddr),
(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
RT_TOS(iph->tos)|RTO_CONN,
#ifdef CONFIG_IP_ROUTE_FWMARK
(*pskb)->nfmark,
#else
0UL,
#endif
err);
goto out;
}
/* Drop old route. */
dst_release((*pskb)->dst);
(*pskb)->dst = &rt->u.dst;
/* Change in oif may mean change in hh_len. */
if (skb_headroom(*pskb) < (*pskb)->dst->dev->hard_header_len) {
struct sk_buff *nskb;
nskb = skb_realloc_headroom(*pskb,
(*pskb)->dst->dev->hard_header_len);
if (!nskb) {
err = -ENOMEM;
goto out;
}
if ((*pskb)->sk)
skb_set_owner_w(nskb, (*pskb)->sk);
kfree_skb(*pskb);
*pskb = nskb;
}
out:
if (dev_src)
dev_put(dev_src);
return err;
}
#endif /*CONFIG_INET*/
/* This does not belong here, but ipt_REJECT needs it if connection
tracking in use: without this, connection may not be in hash table,
and hence manufactured ICMP or RST packets will not be associated
......
/* IRC extension for IP connection tracking, Version 1.20
* (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
/* IRC extension for IP connection tracking, Version 1.21
* (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
* based on RR's ip_conntrack_ftp.c
*
* ip_conntrack_irc.c,v 1.20 2001/12/06 07:42:10 laforge Exp
* ip_conntrack_irc.c,v 1.21 2002/02/05 14:49:26 laforge Exp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -112,9 +112,9 @@ static int help(const struct iphdr *iph, size_t len,
struct ip_ct_irc *info = &ct->help.ct_irc_info;
memset(&mask, 0, sizeof(struct ip_conntrack_tuple));
mask.dst.u.tcp.port = 0xFFFF;
mask.dst.protonum = 0xFFFF;
mask = ((struct ip_conntrack_tuple)
{ { 0, { 0 } },
{ 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
DEBUGP("entered\n");
/* Can't track connections formed before we registered */
......
......@@ -189,7 +189,7 @@ ip_nat_local_fn(unsigned int hooknum,
if (ret != NF_DROP && ret != NF_STOLEN
&& ((*pskb)->nh.iph->saddr != saddr
|| (*pskb)->nh.iph->daddr != daddr))
return route_me_harder(pskb) == 0 ? ret : NF_DROP;
return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
return ret;
}
......
......@@ -261,7 +261,7 @@ static int ipq_mangle_ipv4(ipq_verdict_msg_t *v, ipq_queue_element_t *e)
if (!(iph->tos == e->rt_info.tos
&& iph->daddr == e->rt_info.daddr
&& iph->saddr == e->rt_info.saddr))
return route_me_harder(&e->skb);
return ip_route_me_harder(&e->skb);
}
return 0;
}
......
......@@ -162,7 +162,7 @@ ipt_local_hook(unsigned int hook,
|| (*pskb)->nh.iph->daddr != daddr
|| (*pskb)->nfmark != nfmark
|| (*pskb)->nh.iph->tos != tos))
return route_me_harder(pskb) == 0 ? ret : NF_DROP;
return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
return ret;
}
......
......@@ -577,6 +577,10 @@ EXPORT_SYMBOL(nf_hooks);
EXPORT_SYMBOL(nf_setsockopt);
EXPORT_SYMBOL(nf_getsockopt);
EXPORT_SYMBOL(ip_ct_attach);
#ifdef CONFIG_INET
#include <linux/netfilter_ipv4.h>
EXPORT_SYMBOL(ip_route_me_harder);
#endif
#endif
EXPORT_SYMBOL(register_gifconf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment