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 { ...@@ -59,95 +59,20 @@ enum nf_ip_hook_priorities {
NF_IP_PRI_LAST = INT_MAX, 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: */ /* Arguments for setsockopt SOL_IP: */
/* 2.0 firewalling went from 64 through 71 (and +256, +512, etc). */ /* 2.0 firewalling went from 64 through 71 (and +256, +512, etc). */
/* 2.2 firewalling (+ masq) went from 64 through 76 */ /* 2.2 firewalling (+ masq) went from 64 through 76 */
/* 2.4 firewalling went 64 through 67. */ /* 2.4 firewalling went 64 through 67. */
#define SO_ORIGINAL_DST 80 #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 extern int ip_route_me_harder(struct sk_buff **pskb);
* #endif /*__KERNEL__*/
* 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;
}
#endif /*__LINUX_IP_NETFILTER_H*/ #endif /*__LINUX_IP_NETFILTER_H*/
...@@ -20,6 +20,10 @@ ...@@ -20,6 +20,10 @@
#include <linux/if.h> #include <linux/if.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/brlock.h> #include <linux/brlock.h>
#include <linux/inetdevice.h>
#include <net/sock.h>
#include <net/route.h>
#include <linux/ip.h>
#define __KERNEL_SYSCALLS__ #define __KERNEL_SYSCALLS__
#include <linux/unistd.h> #include <linux/unistd.h>
...@@ -122,9 +126,10 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg) ...@@ -122,9 +126,10 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
down(&nf_sockopt_mutex); down(&nf_sockopt_mutex);
if (reg->use != 0) { if (reg->use != 0) {
/* To be woken by nf_sockopt call... */ /* To be woken by nf_sockopt call... */
/* FIXME: Stuart Young's name appears gratuitously. */
set_current_state(TASK_UNINTERRUPTIBLE);
reg->cleanup_task = current; reg->cleanup_task = current;
up(&nf_sockopt_mutex); up(&nf_sockopt_mutex);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule(); schedule();
goto restart; goto restart;
} }
...@@ -553,6 +558,73 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, ...@@ -553,6 +558,73 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
return; 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 /* This does not belong here, but ipt_REJECT needs it if connection
tracking in use: without this, connection may not be in hash table, tracking in use: without this, connection may not be in hash table,
and hence manufactured ICMP or RST packets will not be associated and hence manufactured ICMP or RST packets will not be associated
......
/* IRC extension for IP connection tracking, Version 1.20 /* IRC extension for IP connection tracking, Version 1.21
* (C) 2000-2001 by Harald Welte <laforge@gnumonks.org> * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
* based on RR's ip_conntrack_ftp.c * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * 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, ...@@ -112,9 +112,9 @@ static int help(const struct iphdr *iph, size_t len,
struct ip_ct_irc *info = &ct->help.ct_irc_info; struct ip_ct_irc *info = &ct->help.ct_irc_info;
memset(&mask, 0, sizeof(struct ip_conntrack_tuple)); mask = ((struct ip_conntrack_tuple)
mask.dst.u.tcp.port = 0xFFFF; { { 0, { 0 } },
mask.dst.protonum = 0xFFFF; { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
DEBUGP("entered\n"); DEBUGP("entered\n");
/* Can't track connections formed before we registered */ /* Can't track connections formed before we registered */
......
...@@ -189,7 +189,7 @@ ip_nat_local_fn(unsigned int hooknum, ...@@ -189,7 +189,7 @@ ip_nat_local_fn(unsigned int hooknum,
if (ret != NF_DROP && ret != NF_STOLEN if (ret != NF_DROP && ret != NF_STOLEN
&& ((*pskb)->nh.iph->saddr != saddr && ((*pskb)->nh.iph->saddr != saddr
|| (*pskb)->nh.iph->daddr != daddr)) || (*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; return ret;
} }
......
...@@ -261,7 +261,7 @@ static int ipq_mangle_ipv4(ipq_verdict_msg_t *v, ipq_queue_element_t *e) ...@@ -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 if (!(iph->tos == e->rt_info.tos
&& iph->daddr == e->rt_info.daddr && iph->daddr == e->rt_info.daddr
&& iph->saddr == e->rt_info.saddr)) && iph->saddr == e->rt_info.saddr))
return route_me_harder(&e->skb); return ip_route_me_harder(&e->skb);
} }
return 0; return 0;
} }
......
...@@ -162,7 +162,7 @@ ipt_local_hook(unsigned int hook, ...@@ -162,7 +162,7 @@ ipt_local_hook(unsigned int hook,
|| (*pskb)->nh.iph->daddr != daddr || (*pskb)->nh.iph->daddr != daddr
|| (*pskb)->nfmark != nfmark || (*pskb)->nfmark != nfmark
|| (*pskb)->nh.iph->tos != tos)) || (*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; return ret;
} }
......
...@@ -577,6 +577,10 @@ EXPORT_SYMBOL(nf_hooks); ...@@ -577,6 +577,10 @@ EXPORT_SYMBOL(nf_hooks);
EXPORT_SYMBOL(nf_setsockopt); EXPORT_SYMBOL(nf_setsockopt);
EXPORT_SYMBOL(nf_getsockopt); EXPORT_SYMBOL(nf_getsockopt);
EXPORT_SYMBOL(ip_ct_attach); EXPORT_SYMBOL(ip_ct_attach);
#ifdef CONFIG_INET
#include <linux/netfilter_ipv4.h>
EXPORT_SYMBOL(ip_route_me_harder);
#endif
#endif #endif
EXPORT_SYMBOL(register_gifconf); 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