Diff markup
1 /* (C) 1999-2001 Paul `Rusty' Russell 1 /* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2006 Netfilter Core Team <coreteam 2 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
3 * 3 *
4 * This program is free software; you can redi 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Publi 5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 #include <linux/types.h> 8 #include <linux/types.h>
9 #include <linux/icmp.h> 9 #include <linux/icmp.h>
10 #include <linux/ip.h> 10 #include <linux/ip.h>
11 #include <linux/netfilter.h> 11 #include <linux/netfilter.h>
12 #include <linux/netfilter_ipv4.h> 12 #include <linux/netfilter_ipv4.h>
13 #include <linux/module.h> 13 #include <linux/module.h>
14 #include <linux/skbuff.h> 14 #include <linux/skbuff.h>
15 #include <linux/proc_fs.h> 15 #include <linux/proc_fs.h>
16 #include <net/ip.h> 16 #include <net/ip.h>
17 #include <net/checksum.h> 17 #include <net/checksum.h>
18 #include <linux/spinlock.h> 18 #include <linux/spinlock.h>
19 19
20 #include <net/netfilter/nf_conntrack.h> 20 #include <net/netfilter/nf_conntrack.h>
21 #include <net/netfilter/nf_conntrack_core.h> 21 #include <net/netfilter/nf_conntrack_core.h>
22 #include <net/netfilter/nf_conntrack_extend.h> 22 #include <net/netfilter/nf_conntrack_extend.h>
23 #include <net/netfilter/nf_nat.h> 23 #include <net/netfilter/nf_nat.h>
24 #include <net/netfilter/nf_nat_rule.h> 24 #include <net/netfilter/nf_nat_rule.h>
25 #include <net/netfilter/nf_nat_protocol.h> 25 #include <net/netfilter/nf_nat_protocol.h>
26 #include <net/netfilter/nf_nat_core.h> 26 #include <net/netfilter/nf_nat_core.h>
27 #include <net/netfilter/nf_nat_helper.h> 27 #include <net/netfilter/nf_nat_helper.h>
28 #include <linux/netfilter_ipv4/ip_tables.h> 28 #include <linux/netfilter_ipv4/ip_tables.h>
29 29
30 #ifdef CONFIG_XFRM 30 #ifdef CONFIG_XFRM
31 static void nat_decode_session(struct sk_buff 31 static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
32 { 32 {
33 struct nf_conn *ct; !! 33 const struct nf_conn *ct;
34 struct nf_conntrack_tuple *t; !! 34 const struct nf_conntrack_tuple *t;
35 enum ip_conntrack_info ctinfo; 35 enum ip_conntrack_info ctinfo;
36 enum ip_conntrack_dir dir; 36 enum ip_conntrack_dir dir;
37 unsigned long statusbit; 37 unsigned long statusbit;
38 38
39 ct = nf_ct_get(skb, &ctinfo); 39 ct = nf_ct_get(skb, &ctinfo);
40 if (ct == NULL) 40 if (ct == NULL)
41 return; 41 return;
42 dir = CTINFO2DIR(ctinfo); 42 dir = CTINFO2DIR(ctinfo);
43 t = &ct->tuplehash[dir].tuple; 43 t = &ct->tuplehash[dir].tuple;
44 44
45 if (dir == IP_CT_DIR_ORIGINAL) 45 if (dir == IP_CT_DIR_ORIGINAL)
46 statusbit = IPS_DST_NAT; 46 statusbit = IPS_DST_NAT;
47 else 47 else
48 statusbit = IPS_SRC_NAT; 48 statusbit = IPS_SRC_NAT;
49 49
50 if (ct->status & statusbit) { 50 if (ct->status & statusbit) {
51 fl->fl4_dst = t->dst.u3.ip; 51 fl->fl4_dst = t->dst.u3.ip;
52 if (t->dst.protonum == IPPROTO 52 if (t->dst.protonum == IPPROTO_TCP ||
53 t->dst.protonum == IPPROTO !! 53 t->dst.protonum == IPPROTO_UDP ||
>> 54 t->dst.protonum == IPPROTO_UDPLITE ||
>> 55 t->dst.protonum == IPPROTO_DCCP ||
>> 56 t->dst.protonum == IPPROTO_SCTP)
54 fl->fl_ip_dport = t->d 57 fl->fl_ip_dport = t->dst.u.tcp.port;
55 } 58 }
56 59
57 statusbit ^= IPS_NAT_MASK; 60 statusbit ^= IPS_NAT_MASK;
58 61
59 if (ct->status & statusbit) { 62 if (ct->status & statusbit) {
60 fl->fl4_src = t->src.u3.ip; 63 fl->fl4_src = t->src.u3.ip;
61 if (t->dst.protonum == IPPROTO 64 if (t->dst.protonum == IPPROTO_TCP ||
62 t->dst.protonum == IPPROTO !! 65 t->dst.protonum == IPPROTO_UDP ||
>> 66 t->dst.protonum == IPPROTO_UDPLITE ||
>> 67 t->dst.protonum == IPPROTO_DCCP ||
>> 68 t->dst.protonum == IPPROTO_SCTP)
63 fl->fl_ip_sport = t->s 69 fl->fl_ip_sport = t->src.u.tcp.port;
64 } 70 }
65 } 71 }
66 #endif 72 #endif
67 73
68 static unsigned int 74 static unsigned int
69 nf_nat_fn(unsigned int hooknum, 75 nf_nat_fn(unsigned int hooknum,
70 struct sk_buff *skb, 76 struct sk_buff *skb,
71 const struct net_device *in, 77 const struct net_device *in,
72 const struct net_device *out, 78 const struct net_device *out,
73 int (*okfn)(struct sk_buff *)) 79 int (*okfn)(struct sk_buff *))
74 { 80 {
75 struct nf_conn *ct; 81 struct nf_conn *ct;
76 enum ip_conntrack_info ctinfo; 82 enum ip_conntrack_info ctinfo;
77 struct nf_conn_nat *nat; 83 struct nf_conn_nat *nat;
78 /* maniptype == SRC for postrouting. * 84 /* maniptype == SRC for postrouting. */
79 enum nf_nat_manip_type maniptype = HOO 85 enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
80 86
81 /* We never see fragments: conntrack d 87 /* We never see fragments: conntrack defrags on pre-routing
82 and local-out, and nf_nat_out prote 88 and local-out, and nf_nat_out protects post-routing. */
83 NF_CT_ASSERT(!(ip_hdr(skb)->frag_off & 89 NF_CT_ASSERT(!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)));
84 90
85 ct = nf_ct_get(skb, &ctinfo); 91 ct = nf_ct_get(skb, &ctinfo);
86 /* Can't track? It's not due to stres 92 /* Can't track? It's not due to stress, or conntrack would
87 have dropped it. Hence it's the us 93 have dropped it. Hence it's the user's responsibilty to
88 packet filter it out, or implement 94 packet filter it out, or implement conntrack/NAT for that
89 protocol. 8) --RR */ 95 protocol. 8) --RR */
90 if (!ct) { !! 96 if (!ct)
91 /* Exception: ICMP redirect to <<
92 hash table yet). We must n <<
93 case we're doing NAT to the <<
94 if (ip_hdr(skb)->protocol == I <<
95 struct icmphdr _hdr, * <<
96 <<
97 hp = skb_header_pointe <<
98 <<
99 if (hp != NULL && <<
100 hp->type == ICMP_R <<
101 return NF_DROP <<
102 } <<
103 return NF_ACCEPT; 97 return NF_ACCEPT;
104 } <<
105 98
106 /* Don't try to NAT if this packet is 99 /* Don't try to NAT if this packet is not conntracked */
107 if (ct == &nf_conntrack_untracked) 100 if (ct == &nf_conntrack_untracked)
108 return NF_ACCEPT; 101 return NF_ACCEPT;
109 102
110 nat = nfct_nat(ct); 103 nat = nfct_nat(ct);
111 if (!nat) { 104 if (!nat) {
>> 105 /* NAT module was loaded late. */
>> 106 if (nf_ct_is_confirmed(ct))
>> 107 return NF_ACCEPT;
112 nat = nf_ct_ext_add(ct, NF_CT_ 108 nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
113 if (nat == NULL) { 109 if (nat == NULL) {
114 pr_debug("failed to ad 110 pr_debug("failed to add NAT extension\n");
115 return NF_ACCEPT; 111 return NF_ACCEPT;
116 } 112 }
117 } 113 }
118 114
119 switch (ctinfo) { 115 switch (ctinfo) {
120 case IP_CT_RELATED: 116 case IP_CT_RELATED:
121 case IP_CT_RELATED+IP_CT_IS_REPLY: 117 case IP_CT_RELATED+IP_CT_IS_REPLY:
122 if (ip_hdr(skb)->protocol == I 118 if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
123 if (!nf_nat_icmp_reply 119 if (!nf_nat_icmp_reply_translation(ct, ctinfo,
124 120 hooknum, skb))
125 return NF_DROP 121 return NF_DROP;
126 else 122 else
127 return NF_ACCE 123 return NF_ACCEPT;
128 } 124 }
129 /* Fall thru... (Only ICMPs ca 125 /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
130 case IP_CT_NEW: 126 case IP_CT_NEW:
131 127
132 /* Seen it before? This can h 128 /* Seen it before? This can happen for loopback, retrans,
133 or local packets.. */ 129 or local packets.. */
134 if (!nf_nat_initialized(ct, ma 130 if (!nf_nat_initialized(ct, maniptype)) {
135 unsigned int ret; 131 unsigned int ret;
136 132
137 if (unlikely(nf_ct_is_ !! 133 if (hooknum == NF_INET_LOCAL_IN)
138 /* NAT module <<
139 ret = alloc_nu <<
140 else if (hooknum == NF <<
141 /* LOCAL_IN ho 134 /* LOCAL_IN hook doesn't have a chain! */
142 ret = alloc_nu 135 ret = alloc_null_binding(ct, hooknum);
143 else 136 else
144 ret = nf_nat_r 137 ret = nf_nat_rule_find(skb, hooknum, in, out,
145 138 ct);
146 139
147 if (ret != NF_ACCEPT) 140 if (ret != NF_ACCEPT) {
148 return ret; 141 return ret;
149 } 142 }
150 } else 143 } else
151 pr_debug("Already setu 144 pr_debug("Already setup manip %s for ct %p\n",
152 maniptype == 145 maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
153 ct); 146 ct);
154 break; 147 break;
155 148
156 default: 149 default:
157 /* ESTABLISHED */ 150 /* ESTABLISHED */
158 NF_CT_ASSERT(ctinfo == IP_CT_E 151 NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
159 ctinfo == (IP_CT_ 152 ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
160 } 153 }
161 154
162 return nf_nat_packet(ct, ctinfo, hookn 155 return nf_nat_packet(ct, ctinfo, hooknum, skb);
163 } 156 }
164 157
165 static unsigned int 158 static unsigned int
166 nf_nat_in(unsigned int hooknum, 159 nf_nat_in(unsigned int hooknum,
167 struct sk_buff *skb, 160 struct sk_buff *skb,
168 const struct net_device *in, 161 const struct net_device *in,
169 const struct net_device *out, 162 const struct net_device *out,
170 int (*okfn)(struct sk_buff *)) 163 int (*okfn)(struct sk_buff *))
171 { 164 {
172 unsigned int ret; 165 unsigned int ret;
173 __be32 daddr = ip_hdr(skb)->daddr; 166 __be32 daddr = ip_hdr(skb)->daddr;
174 167
175 ret = nf_nat_fn(hooknum, skb, in, out, 168 ret = nf_nat_fn(hooknum, skb, in, out, okfn);
176 if (ret != NF_DROP && ret != NF_STOLEN 169 if (ret != NF_DROP && ret != NF_STOLEN &&
177 daddr != ip_hdr(skb)->daddr) { !! 170 daddr != ip_hdr(skb)->daddr)
178 dst_release(skb->dst); !! 171 skb_dst_drop(skb);
179 skb->dst = NULL; !! 172
180 } <<
181 return ret; 173 return ret;
182 } 174 }
183 175
184 static unsigned int 176 static unsigned int
185 nf_nat_out(unsigned int hooknum, 177 nf_nat_out(unsigned int hooknum,
186 struct sk_buff *skb, 178 struct sk_buff *skb,
187 const struct net_device *in, 179 const struct net_device *in,
188 const struct net_device *out, 180 const struct net_device *out,
189 int (*okfn)(struct sk_buff *)) 181 int (*okfn)(struct sk_buff *))
190 { 182 {
191 #ifdef CONFIG_XFRM 183 #ifdef CONFIG_XFRM
192 struct nf_conn *ct; !! 184 const struct nf_conn *ct;
193 enum ip_conntrack_info ctinfo; 185 enum ip_conntrack_info ctinfo;
194 #endif 186 #endif
195 unsigned int ret; 187 unsigned int ret;
196 188
197 /* root is playing with raw sockets. * 189 /* root is playing with raw sockets. */
198 if (skb->len < sizeof(struct iphdr) || 190 if (skb->len < sizeof(struct iphdr) ||
199 ip_hdrlen(skb) < sizeof(struct iph 191 ip_hdrlen(skb) < sizeof(struct iphdr))
200 return NF_ACCEPT; 192 return NF_ACCEPT;
201 193
202 ret = nf_nat_fn(hooknum, skb, in, out, 194 ret = nf_nat_fn(hooknum, skb, in, out, okfn);
203 #ifdef CONFIG_XFRM 195 #ifdef CONFIG_XFRM
204 if (ret != NF_DROP && ret != NF_STOLEN 196 if (ret != NF_DROP && ret != NF_STOLEN &&
205 (ct = nf_ct_get(skb, &ctinfo)) != 197 (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
206 enum ip_conntrack_dir dir = CT 198 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
207 199
208 if (ct->tuplehash[dir].tuple.s 200 if (ct->tuplehash[dir].tuple.src.u3.ip !=
209 ct->tuplehash[!dir].tuple. 201 ct->tuplehash[!dir].tuple.dst.u3.ip
210 || ct->tuplehash[dir].tupl 202 || ct->tuplehash[dir].tuple.src.u.all !=
211 ct->tuplehash[!dir].tup 203 ct->tuplehash[!dir].tuple.dst.u.all
212 ) 204 )
213 return ip_xfrm_me_hard 205 return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP;
214 } 206 }
215 #endif 207 #endif
216 return ret; 208 return ret;
217 } 209 }
218 210
219 static unsigned int 211 static unsigned int
220 nf_nat_local_fn(unsigned int hooknum, 212 nf_nat_local_fn(unsigned int hooknum,
221 struct sk_buff *skb, 213 struct sk_buff *skb,
222 const struct net_device *in, 214 const struct net_device *in,
223 const struct net_device *out, 215 const struct net_device *out,
224 int (*okfn)(struct sk_buff *)) 216 int (*okfn)(struct sk_buff *))
225 { 217 {
226 struct nf_conn *ct; !! 218 const struct nf_conn *ct;
227 enum ip_conntrack_info ctinfo; 219 enum ip_conntrack_info ctinfo;
228 unsigned int ret; 220 unsigned int ret;
229 221
230 /* root is playing with raw sockets. * 222 /* root is playing with raw sockets. */
231 if (skb->len < sizeof(struct iphdr) || 223 if (skb->len < sizeof(struct iphdr) ||
232 ip_hdrlen(skb) < sizeof(struct iph 224 ip_hdrlen(skb) < sizeof(struct iphdr))
233 return NF_ACCEPT; 225 return NF_ACCEPT;
234 226
235 ret = nf_nat_fn(hooknum, skb, in, out, 227 ret = nf_nat_fn(hooknum, skb, in, out, okfn);
236 if (ret != NF_DROP && ret != NF_STOLEN 228 if (ret != NF_DROP && ret != NF_STOLEN &&
237 (ct = nf_ct_get(skb, &ctinfo)) != 229 (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
238 enum ip_conntrack_dir dir = CT 230 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
239 231
240 if (ct->tuplehash[dir].tuple.d 232 if (ct->tuplehash[dir].tuple.dst.u3.ip !=
241 ct->tuplehash[!dir].tuple. 233 ct->tuplehash[!dir].tuple.src.u3.ip) {
242 if (ip_route_me_harder 234 if (ip_route_me_harder(skb, RTN_UNSPEC))
243 ret = NF_DROP; 235 ret = NF_DROP;
244 } 236 }
245 #ifdef CONFIG_XFRM 237 #ifdef CONFIG_XFRM
246 else if (ct->tuplehash[dir].tu 238 else if (ct->tuplehash[dir].tuple.dst.u.all !=
247 ct->tuplehash[!dir].t 239 ct->tuplehash[!dir].tuple.src.u.all)
248 if (ip_xfrm_me_harder( 240 if (ip_xfrm_me_harder(skb))
249 ret = NF_DROP; 241 ret = NF_DROP;
250 #endif 242 #endif
251 } 243 }
252 return ret; 244 return ret;
253 } 245 }
254 246
255 static unsigned int <<
256 nf_nat_adjust(unsigned int hooknum, <<
257 struct sk_buff *skb, <<
258 const struct net_device *in, <<
259 const struct net_device *out, <<
260 int (*okfn)(struct sk_buff *)) <<
261 { <<
262 struct nf_conn *ct; <<
263 enum ip_conntrack_info ctinfo; <<
264 <<
265 ct = nf_ct_get(skb, &ctinfo); <<
266 if (ct && test_bit(IPS_SEQ_ADJUST_BIT, <<
267 pr_debug("nf_nat_standalone: a <<
268 if (!nf_nat_seq_adjust(skb, ct <<
269 return NF_DROP; <<
270 } <<
271 return NF_ACCEPT; <<
272 } <<
273 <<
274 /* We must be after connection tracking and be 247 /* We must be after connection tracking and before packet filtering. */
275 248
276 static struct nf_hook_ops nf_nat_ops[] __read_ 249 static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
277 /* Before packet filtering, change des 250 /* Before packet filtering, change destination */
278 { 251 {
279 .hook = nf_nat_in, 252 .hook = nf_nat_in,
280 .owner = THIS_MODULE, 253 .owner = THIS_MODULE,
281 .pf = PF_INET, 254 .pf = PF_INET,
282 .hooknum = NF_INET_PRE_ 255 .hooknum = NF_INET_PRE_ROUTING,
283 .priority = NF_IP_PRI_NA 256 .priority = NF_IP_PRI_NAT_DST,
284 }, 257 },
285 /* After packet filtering, change sour 258 /* After packet filtering, change source */
286 { 259 {
287 .hook = nf_nat_out, 260 .hook = nf_nat_out,
288 .owner = THIS_MODULE, 261 .owner = THIS_MODULE,
289 .pf = PF_INET, 262 .pf = PF_INET,
290 .hooknum = NF_INET_POST 263 .hooknum = NF_INET_POST_ROUTING,
291 .priority = NF_IP_PRI_NA 264 .priority = NF_IP_PRI_NAT_SRC,
292 }, 265 },
293 /* After conntrack, adjust sequence nu <<
294 { <<
295 .hook = nf_nat_adjus <<
296 .owner = THIS_MODULE, <<
297 .pf = PF_INET, <<
298 .hooknum = NF_INET_POST <<
299 .priority = NF_IP_PRI_NA <<
300 }, <<
301 /* Before packet filtering, change des 266 /* Before packet filtering, change destination */
302 { 267 {
303 .hook = nf_nat_local 268 .hook = nf_nat_local_fn,
304 .owner = THIS_MODULE, 269 .owner = THIS_MODULE,
305 .pf = PF_INET, 270 .pf = PF_INET,
306 .hooknum = NF_INET_LOCA 271 .hooknum = NF_INET_LOCAL_OUT,
307 .priority = NF_IP_PRI_NA 272 .priority = NF_IP_PRI_NAT_DST,
308 }, 273 },
309 /* After packet filtering, change sour 274 /* After packet filtering, change source */
310 { 275 {
311 .hook = nf_nat_fn, 276 .hook = nf_nat_fn,
312 .owner = THIS_MODULE, 277 .owner = THIS_MODULE,
313 .pf = PF_INET, 278 .pf = PF_INET,
314 .hooknum = NF_INET_LOCA 279 .hooknum = NF_INET_LOCAL_IN,
315 .priority = NF_IP_PRI_NA 280 .priority = NF_IP_PRI_NAT_SRC,
316 }, 281 },
317 /* After conntrack, adjust sequence nu <<
318 { <<
319 .hook = nf_nat_adjus <<
320 .owner = THIS_MODULE, <<
321 .pf = PF_INET, <<
322 .hooknum = NF_INET_LOCA <<
323 .priority = NF_IP_PRI_NA <<
324 }, <<
325 }; 282 };
326 283
327 static int __init nf_nat_standalone_init(void) 284 static int __init nf_nat_standalone_init(void)
328 { 285 {
329 int ret = 0; 286 int ret = 0;
330 287
331 need_ipv4_conntrack(); 288 need_ipv4_conntrack();
332 289
333 #ifdef CONFIG_XFRM 290 #ifdef CONFIG_XFRM
334 BUG_ON(ip_nat_decode_session != NULL); 291 BUG_ON(ip_nat_decode_session != NULL);
335 rcu_assign_pointer(ip_nat_decode_sessi 292 rcu_assign_pointer(ip_nat_decode_session, nat_decode_session);
336 #endif 293 #endif
337 ret = nf_nat_rule_init(); 294 ret = nf_nat_rule_init();
338 if (ret < 0) { 295 if (ret < 0) {
339 printk("nf_nat_init: can't set 296 printk("nf_nat_init: can't setup rules.\n");
340 goto cleanup_decode_session; 297 goto cleanup_decode_session;
341 } 298 }
342 ret = nf_register_hooks(nf_nat_ops, AR 299 ret = nf_register_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
343 if (ret < 0) { 300 if (ret < 0) {
344 printk("nf_nat_init: can't reg 301 printk("nf_nat_init: can't register hooks.\n");
345 goto cleanup_rule_init; 302 goto cleanup_rule_init;
346 } 303 }
347 return ret; 304 return ret;
348 305
349 cleanup_rule_init: 306 cleanup_rule_init:
350 nf_nat_rule_cleanup(); 307 nf_nat_rule_cleanup();
351 cleanup_decode_session: 308 cleanup_decode_session:
352 #ifdef CONFIG_XFRM 309 #ifdef CONFIG_XFRM
353 rcu_assign_pointer(ip_nat_decode_sessi 310 rcu_assign_pointer(ip_nat_decode_session, NULL);
354 synchronize_net(); 311 synchronize_net();
355 #endif 312 #endif
356 return ret; 313 return ret;
357 } 314 }
358 315
359 static void __exit nf_nat_standalone_fini(void 316 static void __exit nf_nat_standalone_fini(void)
360 { 317 {
361 nf_unregister_hooks(nf_nat_ops, ARRAY_ 318 nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
362 nf_nat_rule_cleanup(); 319 nf_nat_rule_cleanup();
363 #ifdef CONFIG_XFRM 320 #ifdef CONFIG_XFRM
364 rcu_assign_pointer(ip_nat_decode_sessi 321 rcu_assign_pointer(ip_nat_decode_session, NULL);
365 synchronize_net(); 322 synchronize_net();
366 #endif 323 #endif
367 /* Conntrack caches are unregistered i 324 /* Conntrack caches are unregistered in nf_conntrack_cleanup */
368 } 325 }
369 326
370 module_init(nf_nat_standalone_init); 327 module_init(nf_nat_standalone_init);
371 module_exit(nf_nat_standalone_fini); 328 module_exit(nf_nat_standalone_fini);
372 329
373 MODULE_LICENSE("GPL"); 330 MODULE_LICENSE("GPL");
374 MODULE_ALIAS("ip_nat"); 331 MODULE_ALIAS("ip_nat");
375 332
|
This page was automatically generated by the
LXR engine.
|