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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* Everything about the rules for NAT. */
2
#include <linux/types.h>
3
#include <linux/ip.h>
4
#include <linux/netfilter.h>
5
#include <linux/netfilter_ipv4.h>
6
#include <linux/module.h>
7
#include <linux/kmod.h>
8
#include <linux/skbuff.h>
9
#include <linux/proc_fs.h>
10
#include <net/checksum.h>
11
#include <linux/bitops.h>
12
#include <linux/version.h>
13
 
14
#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
15
#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
16
 
17
#include <linux/netfilter_ipv4/ip_tables.h>
18
#include <linux/netfilter_ipv4/ip_nat.h>
19
#include <linux/netfilter_ipv4/ip_nat_core.h>
20
#include <linux/netfilter_ipv4/ip_nat_rule.h>
21
#include <linux/netfilter_ipv4/listhelp.h>
22
 
23
#if 0
24
#define DEBUGP printk
25
#else
26
#define DEBUGP(format, args...)
27
#endif
28
 
29
#define NAT_VALID_HOOKS ((1<<NF_IP_PRE_ROUTING) | (1<<NF_IP_POST_ROUTING) | (1<<NF_IP_LOCAL_OUT))
30
 
31
/* Standard entry. */
32
struct ipt_standard
33
{
34
        struct ipt_entry entry;
35
        struct ipt_standard_target target;
36
};
37
 
38
struct ipt_error_target
39
{
40
        struct ipt_entry_target target;
41
        char errorname[IPT_FUNCTION_MAXNAMELEN];
42
};
43
 
44
struct ipt_error
45
{
46
        struct ipt_entry entry;
47
        struct ipt_error_target target;
48
};
49
 
50
static struct
51
{
52
        struct ipt_replace repl;
53
        struct ipt_standard entries[3];
54
        struct ipt_error term;
55
} nat_initial_table __initdata
56
= { { "nat", NAT_VALID_HOOKS, 4,
57
      sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
58
      { [NF_IP_PRE_ROUTING] 0,
59
        [NF_IP_POST_ROUTING] sizeof(struct ipt_standard),
60
        [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) * 2 },
61
      { [NF_IP_PRE_ROUTING] 0,
62
        [NF_IP_POST_ROUTING] sizeof(struct ipt_standard),
63
        [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) * 2 },
64
      0, NULL, { } },
65
    {
66
            /* PRE_ROUTING */
67
            { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
68
                0,
69
                sizeof(struct ipt_entry),
70
                sizeof(struct ipt_standard),
71
                0, { 0, 0 }, { } },
72
              { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
73
                -NF_ACCEPT - 1 } },
74
            /* POST_ROUTING */
75
            { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
76
                0,
77
                sizeof(struct ipt_entry),
78
                sizeof(struct ipt_standard),
79
                0, { 0, 0 }, { } },
80
              { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
81
                -NF_ACCEPT - 1 } },
82
            /* LOCAL_OUT */
83
            { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
84
                0,
85
                sizeof(struct ipt_entry),
86
                sizeof(struct ipt_standard),
87
                0, { 0, 0 }, { } },
88
              { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
89
                -NF_ACCEPT - 1 } }
90
    },
91
    /* ERROR */
92
    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
93
        0,
94
        sizeof(struct ipt_entry),
95
        sizeof(struct ipt_error),
96
        0, { 0, 0 }, { } },
97
      { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
98
          { } },
99
        "ERROR"
100
      }
101
    }
102
};
103
 
104
static struct ipt_table nat_table
105
= { { NULL, NULL }, "nat", &nat_initial_table.repl,
106
    NAT_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
107
 
108
/* Source NAT */
109
static unsigned int ipt_snat_target(struct sk_buff **pskb,
110
                                    unsigned int hooknum,
111
                                    const struct net_device *in,
112
                                    const struct net_device *out,
113
                                    const void *targinfo,
114
                                    void *userinfo)
115
{
116
        struct ip_conntrack *ct;
117
        enum ip_conntrack_info ctinfo;
118
 
119
        IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
120
 
121
        ct = ip_conntrack_get(*pskb, &ctinfo);
122
 
123
        /* Connection must be valid and new. */
124
        IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
125
        IP_NF_ASSERT(out);
126
 
127
        return ip_nat_setup_info(ct, targinfo, hooknum);
128
}
129
 
130
static unsigned int ipt_dnat_target(struct sk_buff **pskb,
131
                                    unsigned int hooknum,
132
                                    const struct net_device *in,
133
                                    const struct net_device *out,
134
                                    const void *targinfo,
135
                                    void *userinfo)
136
{
137
        struct ip_conntrack *ct;
138
        enum ip_conntrack_info ctinfo;
139
 
140
#ifdef CONFIG_IP_NF_NAT_LOCAL
141
        IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
142
                     || hooknum == NF_IP_LOCAL_OUT);
143
#else
144
        IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING);
145
#endif
146
 
147
        ct = ip_conntrack_get(*pskb, &ctinfo);
148
 
149
        /* Connection must be valid and new. */
150
        IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
151
 
152
        return ip_nat_setup_info(ct, targinfo, hooknum);
153
}
154
 
155
static int ipt_snat_checkentry(const char *tablename,
156
                               const struct ipt_entry *e,
157
                               void *targinfo,
158
                               unsigned int targinfosize,
159
                               unsigned int hook_mask)
160
{
161
        struct ip_nat_multi_range *mr = targinfo;
162
 
163
        /* Must be a valid range */
164
        if (targinfosize < sizeof(struct ip_nat_multi_range)) {
165
                DEBUGP("SNAT: Target size %u too small\n", targinfosize);
166
                return 0;
167
        }
168
 
169
        if (targinfosize != IPT_ALIGN((sizeof(struct ip_nat_multi_range)
170
                                       + (sizeof(struct ip_nat_range)
171
                                          * (mr->rangesize - 1))))) {
172
                DEBUGP("SNAT: Target size %u wrong for %u ranges\n",
173
                       targinfosize, mr->rangesize);
174
                return 0;
175
        }
176
 
177
        /* Only allow these for NAT. */
178
        if (strcmp(tablename, "nat") != 0) {
179
                DEBUGP("SNAT: wrong table %s\n", tablename);
180
                return 0;
181
        }
182
 
183
        if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
184
                DEBUGP("SNAT: hook mask 0x%x bad\n", hook_mask);
185
                return 0;
186
        }
187
        return 1;
188
}
189
 
190
static int ipt_dnat_checkentry(const char *tablename,
191
                               const struct ipt_entry *e,
192
                               void *targinfo,
193
                               unsigned int targinfosize,
194
                               unsigned int hook_mask)
195
{
196
        struct ip_nat_multi_range *mr = targinfo;
197
 
198
        /* Must be a valid range */
199
        if (targinfosize < sizeof(struct ip_nat_multi_range)) {
200
                DEBUGP("DNAT: Target size %u too small\n", targinfosize);
201
                return 0;
202
        }
203
 
204
        if (targinfosize != IPT_ALIGN((sizeof(struct ip_nat_multi_range)
205
                                       + (sizeof(struct ip_nat_range)
206
                                          * (mr->rangesize - 1))))) {
207
                DEBUGP("DNAT: Target size %u wrong for %u ranges\n",
208
                       targinfosize, mr->rangesize);
209
                return 0;
210
        }
211
 
212
        /* Only allow these for NAT. */
213
        if (strcmp(tablename, "nat") != 0) {
214
                DEBUGP("DNAT: wrong table %s\n", tablename);
215
                return 0;
216
        }
217
 
218
        if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))) {
219
                DEBUGP("DNAT: hook mask 0x%x bad\n", hook_mask);
220
                return 0;
221
        }
222
 
223
#ifndef CONFIG_IP_NF_NAT_LOCAL
224
        if (hook_mask & (1 << NF_IP_LOCAL_OUT)) {
225
                DEBUGP("DNAT: CONFIG_IP_NF_NAT_LOCAL not enabled\n");
226
                return 0;
227
        }
228
#endif
229
 
230
        return 1;
231
}
232
 
233
inline unsigned int
234
alloc_null_binding(struct ip_conntrack *conntrack,
235
                   struct ip_nat_info *info,
236
                   unsigned int hooknum)
237
{
238
        /* Force range to this IP; let proto decide mapping for
239
           per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
240
           Use reply in case it's already been mangled (eg local packet).
241
        */
242
        u_int32_t ip
243
                = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
244
                   ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
245
                   : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
246
        struct ip_nat_multi_range mr
247
                = { 1, { { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } } } };
248
 
249
        DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n", conntrack,
250
               NIPQUAD(ip));
251
        return ip_nat_setup_info(conntrack, &mr, hooknum);
252
}
253
 
254
int ip_nat_rule_find(struct sk_buff **pskb,
255
                     unsigned int hooknum,
256
                     const struct net_device *in,
257
                     const struct net_device *out,
258
                     struct ip_conntrack *ct,
259
                     struct ip_nat_info *info)
260
{
261
        int ret;
262
 
263
        ret = ipt_do_table(pskb, hooknum, in, out, &nat_table, NULL);
264
 
265
        if (ret == NF_ACCEPT) {
266
                if (!(info->initialized & (1 << HOOK2MANIP(hooknum))))
267
                        /* NUL mapping */
268
                        ret = alloc_null_binding(ct, info, hooknum);
269
        }
270
        return ret;
271
}
272
 
273
static struct ipt_target ipt_snat_reg
274
= { { NULL, NULL }, "SNAT", ipt_snat_target, ipt_snat_checkentry, NULL };
275
static struct ipt_target ipt_dnat_reg
276
= { { NULL, NULL }, "DNAT", ipt_dnat_target, ipt_dnat_checkentry, NULL };
277
 
278
int __init ip_nat_rule_init(void)
279
{
280
        int ret;
281
 
282
        ret = ipt_register_table(&nat_table);
283
        if (ret != 0)
284
                return ret;
285
        ret = ipt_register_target(&ipt_snat_reg);
286
        if (ret != 0)
287
                goto unregister_table;
288
 
289
        ret = ipt_register_target(&ipt_dnat_reg);
290
        if (ret != 0)
291
                goto unregister_snat;
292
 
293
        return ret;
294
 
295
 unregister_snat:
296
        ipt_unregister_target(&ipt_snat_reg);
297
 unregister_table:
298
        ipt_unregister_table(&nat_table);
299
 
300
        return ret;
301
}
302
 
303
void ip_nat_rule_cleanup(void)
304
{
305
        ipt_unregister_target(&ipt_dnat_reg);
306
        ipt_unregister_target(&ipt_snat_reg);
307
        ipt_unregister_table(&nat_table);
308
}

powered by: WebSVN 2.1.0

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