Commit 96b8bc42 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[NETFILTER]: Fix various problems with MIRROR target.

- check TTL before rewriting so icmp_send gets clean packet
- skb_copy_expand(skb) for tcpdump and asymmetric routing
- inline some function
- remove unneccessary struct in_device declaration
- remove RTO_CONN
parent 3e93cabb
......@@ -9,6 +9,9 @@
Changes:
25 Aug 2001 Harald Welte <laforge@gnumonks.org>
- decrement and check TTL if not called from FORWARD hook
18 Jul 2003 Harald Welte <laforge@netfilter.org>
- merge Patrick McHardy's mirror fixes from 2.4.22 to
2.6.0-test1
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
......@@ -32,7 +35,6 @@
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netdevice.h>
#include <linux/route.h>
struct in_device;
#include <net/route.h>
#if 0
......@@ -41,46 +43,33 @@ struct in_device;
#define DEBUGP(format, args...)
#endif
static int route_mirror(struct sk_buff *skb)
static inline struct rtable *route_mirror(struct sk_buff *skb)
{
struct iphdr *iph = skb->nh.iph;
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->saddr,
.saddr = iph->daddr,
.tos = RT_TOS(iph->tos) | RTO_CONN } } };
.tos = RT_TOS(iph->tos) } } };
struct rtable *rt;
/* Backwards */
if (ip_route_output_key(&rt, &fl)) {
return 0;
}
if (ip_route_output_key(&rt, &fl))
return NULL;
/* check if the interface we are leaving by is the same as the
one we arrived on */
if (skb->dev == rt->u.dst.dev) {
/* Drop old route. */
dst_release(skb->dst);
skb->dst = &rt->u.dst;
return 1;
}
return 0;
return rt;
}
static int ip_rewrite(struct sk_buff **pskb)
static inline void ip_rewrite(struct sk_buff *skb)
{
u32 odaddr, osaddr;
if (!skb_ip_make_writable(pskb, sizeof(struct iphdr)))
return 0;
odaddr = skb->nh.iph->saddr;
osaddr = skb->nh.iph->daddr;
odaddr = (*pskb)->nh.iph->saddr;
osaddr = (*pskb)->nh.iph->daddr;
(*pskb)->nfcache |= NFC_ALTERED;
skb->nfcache |= NFC_ALTERED;
/* Rewrite IP header */
(*pskb)->nh.iph->daddr = odaddr;
(*pskb)->nh.iph->saddr = osaddr;
return 1;
skb->nh.iph->daddr = odaddr;
skb->nh.iph->saddr = osaddr;
}
/* Stolen from ip_finish_output2 */
......@@ -113,31 +102,51 @@ static unsigned int ipt_mirror_target(struct sk_buff **pskb,
const void *targinfo,
void *userinfo)
{
if (((*pskb)->dst != NULL) && route_mirror(*pskb)) {
if (!ip_rewrite(pskb))
return NF_DROP;
struct rtable *rt;
struct sk_buff *nskb;
unsigned int hh_len;
/* If we are not at FORWARD hook (INPUT/PREROUTING),
* the TTL isn't decreased by the IP stack */
if (hooknum != NF_IP_FORWARD) {
if ((*pskb)->nh.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;
}
/* Made writable by ip_rewrite */
ip_decrease_ttl((*pskb)->nh.iph);
/* Make skb writable */
if (!skb_ip_make_writable(pskb, sizeof(struct iphdr)))
return 0;
/* If we are not at FORWARD hook (INPUT/PREROUTING),
* the TTL isn't decreased by the IP stack */
if (hooknum != NF_IP_FORWARD) {
if ((*pskb)->nh.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((*pskb)->nh.iph);
}
/* Don't let conntrack code see this packet:
it will think we are starting a new
connection! --RR */
ip_direct_send(*pskb);
if ((rt = route_mirror(*pskb)) == NULL)
return NF_DROP;
return NF_STOLEN;
hh_len = (rt->u.dst.dev->hard_header_len + 15) & ~15;
/* Copy skb (even if skb is about to be dropped, we can't just
* clone it because there may be other things, such as tcpdump,
* interested in it). We also need to expand headroom in case
* hh_len of incoming interface < hh_len of outgoing interface */
nskb = skb_copy_expand(*pskb, hh_len, skb_tailroom(*pskb), GFP_ATOMIC);
if (nskb == NULL) {
dst_release(&rt->u.dst);
return NF_DROP;
}
dst_release(nskb->dst);
nskb->dst = &rt->u.dst;
ip_rewrite(nskb);
/* Don't let conntrack code see this packet:
* it will think we are starting a new
* connection! --RR */
ip_direct_send(*pskb);
return NF_DROP;
}
......
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