OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [ipv4/] [netfilter/] [ipt_MIRROR.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
  This is a module which is used for resending packets with inverted src and dst.
3
 
4
  Based on code from: ip_nat_dumb.c,v 1.9 1999/08/20
5
  and various sources.
6
 
7
  Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
8
 
9
  Changes:
10
        25 Aug 2001 Harald Welte <laforge@gnumonks.org>
11
                - decrement and check TTL if not called from FORWARD hook
12
 
13
  This program is free software; you can redistribute it and/or modify it
14
  under the terms of the GNU General Public License as published by the
15
  Free Software Foundation; either version 2 of the License, or (at your
16
  option) any later version.
17
 
18
  This program is distributed in the hope that it will be useful, but
19
  WITHOUT ANY WARRANTY; without even the implied warranty of
20
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21
  General Public License for more details.
22
 
23
  You should have received a copy of the GNU General Public License
24
  along with this program; if not, write to the Free Software Foundation,
25
  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
26
 */
27
#include <linux/module.h>
28
#include <linux/skbuff.h>
29
#include <linux/ip.h>
30
#include <net/ip.h>
31
#include <net/icmp.h>
32
#include <linux/netfilter_ipv4/ip_tables.h>
33
#include <linux/netdevice.h>
34
#include <linux/route.h>
35
#include <net/route.h>
36
 
37
#if 0
38
#define DEBUGP printk
39
#else
40
#define DEBUGP(format, args...)
41
#endif
42
 
43
static inline struct rtable *route_mirror(struct sk_buff *skb, int local)
44
{
45
        struct iphdr *iph = skb->nh.iph;
46
        struct dst_entry *odst;
47
        struct rt_key key = {};
48
        struct rtable *rt;
49
 
50
        if (local) {
51
                key.dst = iph->saddr;
52
                key.src = iph->daddr;
53
                key.tos = RT_TOS(iph->tos);
54
 
55
                if (ip_route_output_key(&rt, &key) != 0)
56
                        return NULL;
57
        } else {
58
                /* non-local src, find valid iif to satisfy
59
                 * rp-filter when calling ip_route_input. */
60
                key.dst = iph->daddr;
61
                if (ip_route_output_key(&rt, &key) != 0)
62
                        return NULL;
63
 
64
                odst = skb->dst;
65
                if (ip_route_input(skb, iph->saddr, iph->daddr,
66
                                   RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
67
                        dst_release(&rt->u.dst);
68
                        return NULL;
69
                }
70
                dst_release(&rt->u.dst);
71
                rt = (struct rtable *)skb->dst;
72
                skb->dst = odst;
73
        }
74
 
75
        if (rt->u.dst.error) {
76
                dst_release(&rt->u.dst);
77
                rt = NULL;
78
        }
79
 
80
        return rt;
81
}
82
 
83
static inline void ip_rewrite(struct sk_buff *skb)
84
{
85
        struct iphdr *iph = skb->nh.iph;
86
        u32 odaddr = iph->saddr;
87
        u32 osaddr = iph->daddr;
88
 
89
        skb->nfcache |= NFC_ALTERED;
90
 
91
        /* Rewrite IP header */
92
        iph->daddr = odaddr;
93
        iph->saddr = osaddr;
94
}
95
 
96
/* Stolen from ip_finish_output2 */
97
static void ip_direct_send(struct sk_buff *skb)
98
{
99
        struct dst_entry *dst = skb->dst;
100
        struct hh_cache *hh = dst->hh;
101
 
102
        if (hh) {
103
                int hh_alen;
104
 
105
                read_lock_bh(&hh->hh_lock);
106
                hh_alen = HH_DATA_ALIGN(hh->hh_len);
107
                memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
108
                read_unlock_bh(&hh->hh_lock);
109
                skb_push(skb, hh->hh_len);
110
                hh->hh_output(skb);
111
        } else if (dst->neighbour)
112
                dst->neighbour->output(skb);
113
        else {
114
                printk(KERN_DEBUG "khm in MIRROR\n");
115
                kfree_skb(skb);
116
        }
117
}
118
 
119
static unsigned int ipt_mirror_target(struct sk_buff **pskb,
120
                                      unsigned int hooknum,
121
                                      const struct net_device *in,
122
                                      const struct net_device *out,
123
                                      const void *targinfo,
124
                                      void *userinfo)
125
{
126
        struct rtable *rt;
127
        struct sk_buff *nskb;
128
        unsigned int hh_len;
129
 
130
        /* If we are not at FORWARD hook (INPUT/PREROUTING),
131
         * the TTL isn't decreased by the IP stack */
132
        if (hooknum != NF_IP_FORWARD) {
133
                struct iphdr *iph = (*pskb)->nh.iph;
134
                if (iph->ttl <= 1) {
135
                        /* this will traverse normal stack, and
136
                         * thus call conntrack on the icmp packet */
137
                        icmp_send(*pskb, ICMP_TIME_EXCEEDED,
138
                                  ICMP_EXC_TTL, 0);
139
                        return NF_DROP;
140
                }
141
                ip_decrease_ttl(iph);
142
        }
143
 
144
        if ((rt = route_mirror(*pskb, hooknum == NF_IP_LOCAL_IN)) == NULL)
145
                return NF_DROP;
146
 
147
        hh_len = (rt->u.dst.dev->hard_header_len + 15) & ~15;
148
 
149
        /* Copy skb (even if skb is about to be dropped, we can't just
150
         * clone it because there may be other things, such as tcpdump,
151
         * interested in it). We also need to expand headroom in case
152
         * hh_len of incoming interface < hh_len of outgoing interface */
153
        nskb = skb_copy_expand(*pskb, hh_len, skb_tailroom(*pskb), GFP_ATOMIC);
154
        if (nskb == NULL) {
155
                dst_release(&rt->u.dst);
156
                return NF_DROP;
157
        }
158
 
159
        dst_release(nskb->dst);
160
        nskb->dst = &rt->u.dst;
161
 
162
        ip_rewrite(nskb);
163
        /* Don't let conntrack code see this packet:
164
           it will think we are starting a new
165
           connection! --RR */
166
        ip_direct_send(nskb);
167
 
168
        return NF_DROP;
169
}
170
 
171
static int ipt_mirror_checkentry(const char *tablename,
172
                                 const struct ipt_entry *e,
173
                                 void *targinfo,
174
                                 unsigned int targinfosize,
175
                                 unsigned int hook_mask)
176
{
177
        /* Only on INPUT, FORWARD or PRE_ROUTING, otherwise loop danger. */
178
        if (hook_mask & ~((1 << NF_IP_PRE_ROUTING)
179
                          | (1 << NF_IP_FORWARD)
180
                          | (1 << NF_IP_LOCAL_IN))) {
181
                DEBUGP("MIRROR: bad hook\n");
182
                return 0;
183
        }
184
 
185
        if (targinfosize != IPT_ALIGN(0)) {
186
                DEBUGP("MIRROR: targinfosize %u != 0\n", targinfosize);
187
                return 0;
188
        }
189
 
190
        return 1;
191
}
192
 
193
static struct ipt_target ipt_mirror_reg
194
= { { NULL, NULL }, "MIRROR", ipt_mirror_target, ipt_mirror_checkentry, NULL,
195
    THIS_MODULE };
196
 
197
static int __init init(void)
198
{
199
        return ipt_register_target(&ipt_mirror_reg);
200
}
201
 
202
static void __exit fini(void)
203
{
204
        ipt_unregister_target(&ipt_mirror_reg);
205
}
206
 
207
module_init(init);
208
module_exit(fini);
209
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.