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