[NETFILTER]: Call POST_ROUTING hook before fragmentation
[linux-2.6.git] / net / ipv4 / netfilter / nf_conntrack_l3proto_ipv4.c
1 /* (C) 1999-2001 Paul `Rusty' Russell
2  * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
9  *      - move L3 protocol dependent part to this file.
10  * 23 Mar 2004: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
11  *      - add get_features() to support various size of conntrack
12  *        structures.
13  *
14  * Derived from net/ipv4/netfilter/ip_conntrack_standalone.c
15  */
16
17 #include <linux/config.h>
18 #include <linux/types.h>
19 #include <linux/ip.h>
20 #include <linux/netfilter.h>
21 #include <linux/module.h>
22 #include <linux/skbuff.h>
23 #include <linux/icmp.h>
24 #include <linux/sysctl.h>
25 #include <net/ip.h>
26
27 #include <linux/netfilter_ipv4.h>
28 #include <net/netfilter/nf_conntrack.h>
29 #include <net/netfilter/nf_conntrack_helper.h>
30 #include <net/netfilter/nf_conntrack_protocol.h>
31 #include <net/netfilter/nf_conntrack_l3proto.h>
32 #include <net/netfilter/nf_conntrack_core.h>
33 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
34
35 #if 0
36 #define DEBUGP printk
37 #else
38 #define DEBUGP(format, args...)
39 #endif
40
41 DECLARE_PER_CPU(struct nf_conntrack_stat, nf_conntrack_stat);
42
43 static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
44                              struct nf_conntrack_tuple *tuple)
45 {
46         u_int32_t _addrs[2], *ap;
47         ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr),
48                                 sizeof(u_int32_t) * 2, _addrs);
49         if (ap == NULL)
50                 return 0;
51
52         tuple->src.u3.ip = ap[0];
53         tuple->dst.u3.ip = ap[1];
54
55         return 1;
56 }
57
58 static int ipv4_invert_tuple(struct nf_conntrack_tuple *tuple,
59                            const struct nf_conntrack_tuple *orig)
60 {
61         tuple->src.u3.ip = orig->dst.u3.ip;
62         tuple->dst.u3.ip = orig->src.u3.ip;
63
64         return 1;
65 }
66
67 static int ipv4_print_tuple(struct seq_file *s,
68                             const struct nf_conntrack_tuple *tuple)
69 {
70         return seq_printf(s, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
71                           NIPQUAD(tuple->src.u3.ip),
72                           NIPQUAD(tuple->dst.u3.ip));
73 }
74
75 static int ipv4_print_conntrack(struct seq_file *s,
76                                 const struct nf_conn *conntrack)
77 {
78         return 0;
79 }
80
81 /* Returns new sk_buff, or NULL */
82 static struct sk_buff *
83 nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
84 {
85         skb_orphan(skb);
86
87         local_bh_disable();
88         skb = ip_defrag(skb, user);
89         local_bh_enable();
90
91         if (skb)
92                 ip_send_check(skb->nh.iph);
93
94         return skb;
95 }
96
97 static int
98 ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff,
99              u_int8_t *protonum)
100 {
101         /* Never happen */
102         if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
103                 if (net_ratelimit()) {
104                         printk(KERN_ERR "ipv4_prepare: Frag of proto %u (hook=%u)\n",
105                         (*pskb)->nh.iph->protocol, hooknum);
106                 }
107                 return -NF_DROP;
108         }
109
110         *dataoff = (*pskb)->nh.raw - (*pskb)->data + (*pskb)->nh.iph->ihl*4;
111         *protonum = (*pskb)->nh.iph->protocol;
112
113         return NF_ACCEPT;
114 }
115
116 int nat_module_is_loaded = 0;
117 static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple)
118 {
119         if (nat_module_is_loaded)
120                 return NF_CT_F_NAT;
121
122         return NF_CT_F_BASIC;
123 }
124
125 static unsigned int ipv4_confirm(unsigned int hooknum,
126                                  struct sk_buff **pskb,
127                                  const struct net_device *in,
128                                  const struct net_device *out,
129                                  int (*okfn)(struct sk_buff *))
130 {
131         /* We've seen it coming out the other side: confirm it */
132         return nf_conntrack_confirm(pskb);
133 }
134
135 static unsigned int ipv4_conntrack_help(unsigned int hooknum,
136                                       struct sk_buff **pskb,
137                                       const struct net_device *in,
138                                       const struct net_device *out,
139                                       int (*okfn)(struct sk_buff *))
140 {
141         struct nf_conn *ct;
142         enum ip_conntrack_info ctinfo;
143
144         /* This is where we call the helper: as the packet goes out. */
145         ct = nf_ct_get(*pskb, &ctinfo);
146         if (ct && ct->helper) {
147                 unsigned int ret;
148                 ret = ct->helper->help(pskb,
149                                        (*pskb)->nh.raw - (*pskb)->data
150                                                        + (*pskb)->nh.iph->ihl*4,
151                                        ct, ctinfo);
152                 if (ret != NF_ACCEPT)
153                         return ret;
154         }
155         return NF_ACCEPT;
156 }
157
158 static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
159                                           struct sk_buff **pskb,
160                                           const struct net_device *in,
161                                           const struct net_device *out,
162                                           int (*okfn)(struct sk_buff *))
163 {
164 #if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
165         /* Previously seen (loopback)?  Ignore.  Do this before
166            fragment check. */
167         if ((*pskb)->nfct)
168                 return NF_ACCEPT;
169 #endif
170
171         /* Gather fragments. */
172         if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
173                 *pskb = nf_ct_ipv4_gather_frags(*pskb,
174                                                 hooknum == NF_IP_PRE_ROUTING ?
175                                                 IP_DEFRAG_CONNTRACK_IN :
176                                                 IP_DEFRAG_CONNTRACK_OUT);
177                 if (!*pskb)
178                         return NF_STOLEN;
179         }
180         return NF_ACCEPT;
181 }
182
183 static unsigned int ipv4_conntrack_in(unsigned int hooknum,
184                                       struct sk_buff **pskb,
185                                       const struct net_device *in,
186                                       const struct net_device *out,
187                                       int (*okfn)(struct sk_buff *))
188 {
189         return nf_conntrack_in(PF_INET, hooknum, pskb);
190 }
191
192 static unsigned int ipv4_conntrack_local(unsigned int hooknum,
193                                          struct sk_buff **pskb,
194                                          const struct net_device *in,
195                                          const struct net_device *out,
196                                          int (*okfn)(struct sk_buff *))
197 {
198         /* root is playing with raw sockets. */
199         if ((*pskb)->len < sizeof(struct iphdr)
200             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
201                 if (net_ratelimit())
202                         printk("ipt_hook: happy cracking.\n");
203                 return NF_ACCEPT;
204         }
205         return nf_conntrack_in(PF_INET, hooknum, pskb);
206 }
207
208 /* Connection tracking may drop packets, but never alters them, so
209    make it the first hook. */
210 static struct nf_hook_ops ipv4_conntrack_defrag_ops = {
211         .hook           = ipv4_conntrack_defrag,
212         .owner          = THIS_MODULE,
213         .pf             = PF_INET,
214         .hooknum        = NF_IP_PRE_ROUTING,
215         .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
216 };
217
218 static struct nf_hook_ops ipv4_conntrack_in_ops = {
219         .hook           = ipv4_conntrack_in,
220         .owner          = THIS_MODULE,
221         .pf             = PF_INET,
222         .hooknum        = NF_IP_PRE_ROUTING,
223         .priority       = NF_IP_PRI_CONNTRACK,
224 };
225
226 static struct nf_hook_ops ipv4_conntrack_defrag_local_out_ops = {
227         .hook           = ipv4_conntrack_defrag,
228         .owner          = THIS_MODULE,
229         .pf             = PF_INET,
230         .hooknum        = NF_IP_LOCAL_OUT,
231         .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
232 };
233
234 static struct nf_hook_ops ipv4_conntrack_local_out_ops = {
235         .hook           = ipv4_conntrack_local,
236         .owner          = THIS_MODULE,
237         .pf             = PF_INET,
238         .hooknum        = NF_IP_LOCAL_OUT,
239         .priority       = NF_IP_PRI_CONNTRACK,
240 };
241
242 /* helpers */
243 static struct nf_hook_ops ipv4_conntrack_helper_out_ops = {
244         .hook           = ipv4_conntrack_help,
245         .owner          = THIS_MODULE,
246         .pf             = PF_INET,
247         .hooknum        = NF_IP_POST_ROUTING,
248         .priority       = NF_IP_PRI_CONNTRACK_HELPER,
249 };
250
251 static struct nf_hook_ops ipv4_conntrack_helper_in_ops = {
252         .hook           = ipv4_conntrack_help,
253         .owner          = THIS_MODULE,
254         .pf             = PF_INET,
255         .hooknum        = NF_IP_LOCAL_IN,
256         .priority       = NF_IP_PRI_CONNTRACK_HELPER,
257 };
258
259
260 /* Refragmenter; last chance. */
261 static struct nf_hook_ops ipv4_conntrack_out_ops = {
262         .hook           = ipv4_confirm,
263         .owner          = THIS_MODULE,
264         .pf             = PF_INET,
265         .hooknum        = NF_IP_POST_ROUTING,
266         .priority       = NF_IP_PRI_CONNTRACK_CONFIRM,
267 };
268
269 static struct nf_hook_ops ipv4_conntrack_local_in_ops = {
270         .hook           = ipv4_confirm,
271         .owner          = THIS_MODULE,
272         .pf             = PF_INET,
273         .hooknum        = NF_IP_LOCAL_IN,
274         .priority       = NF_IP_PRI_CONNTRACK_CONFIRM,
275 };
276
277 #ifdef CONFIG_SYSCTL
278 /* From nf_conntrack_proto_icmp.c */
279 extern unsigned long nf_ct_icmp_timeout;
280 static struct ctl_table_header *nf_ct_ipv4_sysctl_header;
281
282 static ctl_table nf_ct_sysctl_table[] = {
283         {
284                 .ctl_name       = NET_NF_CONNTRACK_ICMP_TIMEOUT,
285                 .procname       = "nf_conntrack_icmp_timeout",
286                 .data           = &nf_ct_icmp_timeout,
287                 .maxlen         = sizeof(unsigned int),
288                 .mode           = 0644,
289                 .proc_handler   = &proc_dointvec_jiffies,
290         },
291         { .ctl_name = 0 }
292 };
293
294 static ctl_table nf_ct_netfilter_table[] = {
295         {
296                 .ctl_name       = NET_NETFILTER,
297                 .procname       = "netfilter",
298                 .mode           = 0555,
299                 .child          = nf_ct_sysctl_table,
300         },
301         { .ctl_name = 0 }
302 };
303
304 static ctl_table nf_ct_net_table[] = {
305         {
306                 .ctl_name       = CTL_NET,
307                 .procname       = "net",
308                 .mode           = 0555,
309                 .child          = nf_ct_netfilter_table,
310         },
311         { .ctl_name = 0 }
312 };
313 #endif
314
315 /* Fast function for those who don't want to parse /proc (and I don't
316    blame them). */
317 /* Reversing the socket's dst/src point of view gives us the reply
318    mapping. */
319 static int
320 getorigdst(struct sock *sk, int optval, void __user *user, int *len)
321 {
322         struct inet_sock *inet = inet_sk(sk);
323         struct nf_conntrack_tuple_hash *h;
324         struct nf_conntrack_tuple tuple;
325         
326         NF_CT_TUPLE_U_BLANK(&tuple);
327         tuple.src.u3.ip = inet->rcv_saddr;
328         tuple.src.u.tcp.port = inet->sport;
329         tuple.dst.u3.ip = inet->daddr;
330         tuple.dst.u.tcp.port = inet->dport;
331         tuple.src.l3num = PF_INET;
332         tuple.dst.protonum = IPPROTO_TCP;
333
334         /* We only do TCP at the moment: is there a better way? */
335         if (strcmp(sk->sk_prot->name, "TCP")) {
336                 DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n");
337                 return -ENOPROTOOPT;
338         }
339
340         if ((unsigned int) *len < sizeof(struct sockaddr_in)) {
341                 DEBUGP("SO_ORIGINAL_DST: len %u not %u\n",
342                        *len, sizeof(struct sockaddr_in));
343                 return -EINVAL;
344         }
345
346         h = nf_conntrack_find_get(&tuple, NULL);
347         if (h) {
348                 struct sockaddr_in sin;
349                 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
350
351                 sin.sin_family = AF_INET;
352                 sin.sin_port = ct->tuplehash[IP_CT_DIR_ORIGINAL]
353                         .tuple.dst.u.tcp.port;
354                 sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL]
355                         .tuple.dst.u3.ip;
356
357                 DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
358                        NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
359                 nf_ct_put(ct);
360                 if (copy_to_user(user, &sin, sizeof(sin)) != 0)
361                         return -EFAULT;
362                 else
363                         return 0;
364         }
365         DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n",
366                NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port),
367                NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port));
368         return -ENOENT;
369 }
370
371 #if defined(CONFIG_NF_CT_NETLINK) || \
372     defined(CONFIG_NF_CT_NETLINK_MODULE)
373
374 #include <linux/netfilter/nfnetlink.h>
375 #include <linux/netfilter/nfnetlink_conntrack.h>
376
377 static int ipv4_tuple_to_nfattr(struct sk_buff *skb,
378                                 const struct nf_conntrack_tuple *tuple)
379 {
380         NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t),
381                 &tuple->src.u3.ip);
382         NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t),
383                 &tuple->dst.u3.ip);
384         return 0;
385
386 nfattr_failure:
387         return -1;
388 }
389
390 static const size_t cta_min_ip[CTA_IP_MAX] = {
391         [CTA_IP_V4_SRC-1]       = sizeof(u_int32_t),
392         [CTA_IP_V4_DST-1]       = sizeof(u_int32_t),
393 };
394
395 static int ipv4_nfattr_to_tuple(struct nfattr *tb[],
396                                 struct nf_conntrack_tuple *t)
397 {
398         if (!tb[CTA_IP_V4_SRC-1] || !tb[CTA_IP_V4_DST-1])
399                 return -EINVAL;
400
401         if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
402                 return -EINVAL;
403
404         t->src.u3.ip =
405                 *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
406         t->dst.u3.ip =
407                 *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
408
409         return 0;
410 }
411 #endif
412
413 static struct nf_sockopt_ops so_getorigdst = {
414         .pf             = PF_INET,
415         .get_optmin     = SO_ORIGINAL_DST,
416         .get_optmax     = SO_ORIGINAL_DST+1,
417         .get            = &getorigdst,
418 };
419
420 struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
421         .l3proto         = PF_INET,
422         .name            = "ipv4",
423         .pkt_to_tuple    = ipv4_pkt_to_tuple,
424         .invert_tuple    = ipv4_invert_tuple,
425         .print_tuple     = ipv4_print_tuple,
426         .print_conntrack = ipv4_print_conntrack,
427         .prepare         = ipv4_prepare,
428         .get_features    = ipv4_get_features,
429 #if defined(CONFIG_NF_CT_NETLINK) || \
430     defined(CONFIG_NF_CT_NETLINK_MODULE)
431         .tuple_to_nfattr = ipv4_tuple_to_nfattr,
432         .nfattr_to_tuple = ipv4_nfattr_to_tuple,
433 #endif
434         .me              = THIS_MODULE,
435 };
436
437 extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4;
438 extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
439 extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp;
440 static int init_or_cleanup(int init)
441 {
442         int ret = 0;
443
444         if (!init) goto cleanup;
445
446         ret = nf_register_sockopt(&so_getorigdst);
447         if (ret < 0) {
448                 printk(KERN_ERR "Unable to register netfilter socket option\n");
449                 goto cleanup_nothing;
450         }
451
452         ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4);
453         if (ret < 0) {
454                 printk("nf_conntrack_ipv4: can't register tcp.\n");
455                 goto cleanup_sockopt;
456         }
457
458         ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_udp4);
459         if (ret < 0) {
460                 printk("nf_conntrack_ipv4: can't register udp.\n");
461                 goto cleanup_tcp;
462         }
463
464         ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_icmp);
465         if (ret < 0) {
466                 printk("nf_conntrack_ipv4: can't register icmp.\n");
467                 goto cleanup_udp;
468         }
469
470         ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv4);
471         if (ret < 0) {
472                 printk("nf_conntrack_ipv4: can't register ipv4\n");
473                 goto cleanup_icmp;
474         }
475
476         ret = nf_register_hook(&ipv4_conntrack_defrag_ops);
477         if (ret < 0) {
478                 printk("nf_conntrack_ipv4: can't register pre-routing defrag hook.\n");
479                 goto cleanup_ipv4;
480         }
481         ret = nf_register_hook(&ipv4_conntrack_defrag_local_out_ops);
482         if (ret < 0) {
483                 printk("nf_conntrack_ipv4: can't register local_out defrag hook.\n");
484                 goto cleanup_defragops;
485         }
486
487         ret = nf_register_hook(&ipv4_conntrack_in_ops);
488         if (ret < 0) {
489                 printk("nf_conntrack_ipv4: can't register pre-routing hook.\n");
490                 goto cleanup_defraglocalops;
491         }
492
493         ret = nf_register_hook(&ipv4_conntrack_local_out_ops);
494         if (ret < 0) {
495                 printk("nf_conntrack_ipv4: can't register local out hook.\n");
496                 goto cleanup_inops;
497         }
498
499         ret = nf_register_hook(&ipv4_conntrack_helper_in_ops);
500         if (ret < 0) {
501                 printk("nf_conntrack_ipv4: can't register local helper hook.\n");
502                 goto cleanup_inandlocalops;
503         }
504
505         ret = nf_register_hook(&ipv4_conntrack_helper_out_ops);
506         if (ret < 0) {
507                 printk("nf_conntrack_ipv4: can't register postrouting helper hook.\n");
508                 goto cleanup_helperinops;
509         }
510
511         ret = nf_register_hook(&ipv4_conntrack_out_ops);
512         if (ret < 0) {
513                 printk("nf_conntrack_ipv4: can't register post-routing hook.\n");
514                 goto cleanup_helperoutops;
515         }
516
517         ret = nf_register_hook(&ipv4_conntrack_local_in_ops);
518         if (ret < 0) {
519                 printk("nf_conntrack_ipv4: can't register local in hook.\n");
520                 goto cleanup_inoutandlocalops;
521         }
522
523 #ifdef CONFIG_SYSCTL
524         nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
525         if (nf_ct_ipv4_sysctl_header == NULL) {
526                 printk("nf_conntrack: can't register to sysctl.\n");
527                 ret = -ENOMEM;
528                 goto cleanup_localinops;
529         }
530 #endif
531
532         /* For use by REJECT target */
533         ip_ct_attach = __nf_conntrack_attach;
534
535         return ret;
536
537  cleanup:
538         synchronize_net();
539         ip_ct_attach = NULL;
540 #ifdef CONFIG_SYSCTL
541         unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
542  cleanup_localinops:
543 #endif
544         nf_unregister_hook(&ipv4_conntrack_local_in_ops);
545  cleanup_inoutandlocalops:
546         nf_unregister_hook(&ipv4_conntrack_out_ops);
547  cleanup_helperoutops:
548         nf_unregister_hook(&ipv4_conntrack_helper_out_ops);
549  cleanup_helperinops:
550         nf_unregister_hook(&ipv4_conntrack_helper_in_ops);
551  cleanup_inandlocalops:
552         nf_unregister_hook(&ipv4_conntrack_local_out_ops);
553  cleanup_inops:
554         nf_unregister_hook(&ipv4_conntrack_in_ops);
555  cleanup_defraglocalops:
556         nf_unregister_hook(&ipv4_conntrack_defrag_local_out_ops);
557  cleanup_defragops:
558         nf_unregister_hook(&ipv4_conntrack_defrag_ops);
559  cleanup_ipv4:
560         nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
561  cleanup_icmp:
562         nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp);
563  cleanup_udp:
564         nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4);
565  cleanup_tcp:
566         nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
567  cleanup_sockopt:
568         nf_unregister_sockopt(&so_getorigdst);
569  cleanup_nothing:
570         return ret;
571 }
572
573 MODULE_LICENSE("GPL");
574
575 static int __init init(void)
576 {
577         need_nf_conntrack();
578         return init_or_cleanup(1);
579 }
580
581 static void __exit fini(void)
582 {
583         init_or_cleanup(0);
584 }
585
586 module_init(init);
587 module_exit(fini);
588
589 void need_ip_conntrack(void)
590 {
591 }
592
593 EXPORT_SYMBOL(need_ip_conntrack);
594 EXPORT_SYMBOL(nf_ct_ipv4_gather_frags);