Merge branch 'upstream-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/linvil...
[pandora-kernel.git] / net / netfilter / nf_conntrack_netlink.c
1 /* Connection tracking via netlink socket. Allows for user space
2  * protocol helpers and general trouble making from userspace.
3  *
4  * (C) 2001 by Jay Schulist <jschlst@samba.org>
5  * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
6  * (C) 2003 by Patrick Mchardy <kaber@trash.net>
7  * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
8  *
9  * I've reworked this stuff to use attributes instead of conntrack 
10  * structures. 5.44 am. I need more tea. --pablo 05/07/11.
11  *
12  * Initial connection tracking via netlink development funded and 
13  * generally made possible by Network Robots, Inc. (www.networkrobots.com)
14  *
15  * Further development of this code funded by Astaro AG (http://www.astaro.com)
16  *
17  * This software may be used and distributed according to the terms
18  * of the GNU General Public License, incorporated herein by reference.
19  *
20  * Derived from ip_conntrack_netlink.c: Port by Pablo Neira Ayuso (05/11/14)
21  */
22
23 #include <linux/init.h>
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/types.h>
27 #include <linux/timer.h>
28 #include <linux/skbuff.h>
29 #include <linux/errno.h>
30 #include <linux/netlink.h>
31 #include <linux/spinlock.h>
32 #include <linux/interrupt.h>
33 #include <linux/notifier.h>
34
35 #include <linux/netfilter.h>
36 #include <net/netfilter/nf_conntrack.h>
37 #include <net/netfilter/nf_conntrack_core.h>
38 #include <net/netfilter/nf_conntrack_helper.h>
39 #include <net/netfilter/nf_conntrack_l3proto.h>
40 #include <net/netfilter/nf_conntrack_protocol.h>
41 #include <linux/netfilter_ipv4/ip_nat_protocol.h>
42
43 #include <linux/netfilter/nfnetlink.h>
44 #include <linux/netfilter/nfnetlink_conntrack.h>
45
46 MODULE_LICENSE("GPL");
47
48 static char __initdata version[] = "0.93";
49
50 static inline int
51 ctnetlink_dump_tuples_proto(struct sk_buff *skb, 
52                             const struct nf_conntrack_tuple *tuple,
53                             struct nf_conntrack_protocol *proto)
54 {
55         int ret = 0;
56         struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
57
58         NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
59
60         if (likely(proto->tuple_to_nfattr))
61                 ret = proto->tuple_to_nfattr(skb, tuple);
62         
63         NFA_NEST_END(skb, nest_parms);
64
65         return ret;
66
67 nfattr_failure:
68         return -1;
69 }
70
71 static inline int
72 ctnetlink_dump_tuples_ip(struct sk_buff *skb,
73                          const struct nf_conntrack_tuple *tuple,
74                          struct nf_conntrack_l3proto *l3proto)
75 {
76         int ret = 0;
77         struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
78
79         if (likely(l3proto->tuple_to_nfattr))
80                 ret = l3proto->tuple_to_nfattr(skb, tuple);
81
82         NFA_NEST_END(skb, nest_parms);
83
84         return ret;
85
86 nfattr_failure:
87         return -1;
88 }
89
90 static inline int
91 ctnetlink_dump_tuples(struct sk_buff *skb,
92                       const struct nf_conntrack_tuple *tuple)
93 {
94         int ret;
95         struct nf_conntrack_l3proto *l3proto;
96         struct nf_conntrack_protocol *proto;
97
98         l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
99         ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
100         nf_ct_l3proto_put(l3proto);
101
102         if (unlikely(ret < 0))
103                 return ret;
104
105         proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
106         ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
107         nf_ct_proto_put(proto);
108
109         return ret;
110 }
111
112 static inline int
113 ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
114 {
115         u_int32_t status = htonl((u_int32_t) ct->status);
116         NFA_PUT(skb, CTA_STATUS, sizeof(status), &status);
117         return 0;
118
119 nfattr_failure:
120         return -1;
121 }
122
123 static inline int
124 ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct)
125 {
126         long timeout_l = ct->timeout.expires - jiffies;
127         u_int32_t timeout;
128
129         if (timeout_l < 0)
130                 timeout = 0;
131         else
132                 timeout = htonl(timeout_l / HZ);
133         
134         NFA_PUT(skb, CTA_TIMEOUT, sizeof(timeout), &timeout);
135         return 0;
136
137 nfattr_failure:
138         return -1;
139 }
140
141 static inline int
142 ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct)
143 {
144         struct nf_conntrack_protocol *proto = nf_ct_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
145         struct nfattr *nest_proto;
146         int ret;
147
148         if (!proto->to_nfattr) {
149                 nf_ct_proto_put(proto);
150                 return 0;
151         }
152         
153         nest_proto = NFA_NEST(skb, CTA_PROTOINFO);
154
155         ret = proto->to_nfattr(skb, nest_proto, ct);
156
157         nf_ct_proto_put(proto);
158
159         NFA_NEST_END(skb, nest_proto);
160
161         return ret;
162
163 nfattr_failure:
164         return -1;
165 }
166
167 static inline int
168 ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
169 {
170         struct nfattr *nest_helper;
171         const struct nf_conn_help *help = nfct_help(ct);
172
173         if (!help || !help->helper)
174                 return 0;
175                 
176         nest_helper = NFA_NEST(skb, CTA_HELP);
177         NFA_PUT(skb, CTA_HELP_NAME, strlen(help->helper->name), help->helper->name);
178
179         if (help->helper->to_nfattr)
180                 help->helper->to_nfattr(skb, ct);
181
182         NFA_NEST_END(skb, nest_helper);
183
184         return 0;
185
186 nfattr_failure:
187         return -1;
188 }
189
190 #ifdef CONFIG_NF_CT_ACCT
191 static inline int
192 ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
193                         enum ip_conntrack_dir dir)
194 {
195         enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
196         struct nfattr *nest_count = NFA_NEST(skb, type);
197         u_int32_t tmp;
198
199         tmp = htonl(ct->counters[dir].packets);
200         NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
201
202         tmp = htonl(ct->counters[dir].bytes);
203         NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp);
204
205         NFA_NEST_END(skb, nest_count);
206
207         return 0;
208
209 nfattr_failure:
210         return -1;
211 }
212 #else
213 #define ctnetlink_dump_counters(a, b, c) (0)
214 #endif
215
216 #ifdef CONFIG_NF_CONNTRACK_MARK
217 static inline int
218 ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
219 {
220         u_int32_t mark = htonl(ct->mark);
221
222         NFA_PUT(skb, CTA_MARK, sizeof(u_int32_t), &mark);
223         return 0;
224
225 nfattr_failure:
226         return -1;
227 }
228 #else
229 #define ctnetlink_dump_mark(a, b) (0)
230 #endif
231
232 static inline int
233 ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
234 {
235         u_int32_t id = htonl(ct->id);
236         NFA_PUT(skb, CTA_ID, sizeof(u_int32_t), &id);
237         return 0;
238
239 nfattr_failure:
240         return -1;
241 }
242
243 static inline int
244 ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
245 {
246         u_int32_t use = htonl(atomic_read(&ct->ct_general.use));
247         
248         NFA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
249         return 0;
250
251 nfattr_failure:
252         return -1;
253 }
254
255 #define tuple(ct, dir) (&(ct)->tuplehash[dir].tuple)
256
257 static int
258 ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
259                     int event, int nowait, 
260                     const struct nf_conn *ct)
261 {
262         struct nlmsghdr *nlh;
263         struct nfgenmsg *nfmsg;
264         struct nfattr *nest_parms;
265         unsigned char *b;
266
267         b = skb->tail;
268
269         event |= NFNL_SUBSYS_CTNETLINK << 8;
270         nlh    = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg));
271         nfmsg  = NLMSG_DATA(nlh);
272
273         nlh->nlmsg_flags    = (nowait && pid) ? NLM_F_MULTI : 0;
274         nfmsg->nfgen_family = 
275                 ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
276         nfmsg->version      = NFNETLINK_V0;
277         nfmsg->res_id       = 0;
278
279         nest_parms = NFA_NEST(skb, CTA_TUPLE_ORIG);
280         if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
281                 goto nfattr_failure;
282         NFA_NEST_END(skb, nest_parms);
283         
284         nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
285         if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
286                 goto nfattr_failure;
287         NFA_NEST_END(skb, nest_parms);
288
289         if (ctnetlink_dump_status(skb, ct) < 0 ||
290             ctnetlink_dump_timeout(skb, ct) < 0 ||
291             ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
292             ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 ||
293             ctnetlink_dump_protoinfo(skb, ct) < 0 ||
294             ctnetlink_dump_helpinfo(skb, ct) < 0 ||
295             ctnetlink_dump_mark(skb, ct) < 0 ||
296             ctnetlink_dump_id(skb, ct) < 0 ||
297             ctnetlink_dump_use(skb, ct) < 0)
298                 goto nfattr_failure;
299
300         nlh->nlmsg_len = skb->tail - b;
301         return skb->len;
302
303 nlmsg_failure:
304 nfattr_failure:
305         skb_trim(skb, b - skb->data);
306         return -1;
307 }
308
309 #ifdef CONFIG_NF_CONNTRACK_EVENTS
310 static int ctnetlink_conntrack_event(struct notifier_block *this,
311                                      unsigned long events, void *ptr)
312 {
313         struct nlmsghdr *nlh;
314         struct nfgenmsg *nfmsg;
315         struct nfattr *nest_parms;
316         struct nf_conn *ct = (struct nf_conn *)ptr;
317         struct sk_buff *skb;
318         unsigned int type;
319         unsigned char *b;
320         unsigned int flags = 0, group;
321
322         /* ignore our fake conntrack entry */
323         if (ct == &nf_conntrack_untracked)
324                 return NOTIFY_DONE;
325
326         if (events & IPCT_DESTROY) {
327                 type = IPCTNL_MSG_CT_DELETE;
328                 group = NFNLGRP_CONNTRACK_DESTROY;
329         } else  if (events & (IPCT_NEW | IPCT_RELATED)) {
330                 type = IPCTNL_MSG_CT_NEW;
331                 flags = NLM_F_CREATE|NLM_F_EXCL;
332                 /* dump everything */
333                 events = ~0UL;
334                 group = NFNLGRP_CONNTRACK_NEW;
335         } else  if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
336                 type = IPCTNL_MSG_CT_NEW;
337                 group = NFNLGRP_CONNTRACK_UPDATE;
338         } else
339                 return NOTIFY_DONE;
340
341         if (!nfnetlink_has_listeners(group))
342                 return NOTIFY_DONE;
343
344         skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
345         if (!skb)
346                 return NOTIFY_DONE;
347
348         b = skb->tail;
349
350         type |= NFNL_SUBSYS_CTNETLINK << 8;
351         nlh   = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
352         nfmsg = NLMSG_DATA(nlh);
353
354         nlh->nlmsg_flags    = flags;
355         nfmsg->nfgen_family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
356         nfmsg->version  = NFNETLINK_V0;
357         nfmsg->res_id   = 0;
358
359         nest_parms = NFA_NEST(skb, CTA_TUPLE_ORIG);
360         if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
361                 goto nfattr_failure;
362         NFA_NEST_END(skb, nest_parms);
363         
364         nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
365         if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
366                 goto nfattr_failure;
367         NFA_NEST_END(skb, nest_parms);
368         
369         /* NAT stuff is now a status flag */
370         if ((events & IPCT_STATUS || events & IPCT_NATINFO)
371             && ctnetlink_dump_status(skb, ct) < 0)
372                 goto nfattr_failure;
373         if (events & IPCT_REFRESH
374             && ctnetlink_dump_timeout(skb, ct) < 0)
375                 goto nfattr_failure;
376         if (events & IPCT_PROTOINFO
377             && ctnetlink_dump_protoinfo(skb, ct) < 0)
378                 goto nfattr_failure;
379         if (events & IPCT_HELPINFO
380             && ctnetlink_dump_helpinfo(skb, ct) < 0)
381                 goto nfattr_failure;
382
383         if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
384             ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
385                 goto nfattr_failure;
386
387         if (events & IPCT_MARK
388             && ctnetlink_dump_mark(skb, ct) < 0)
389                 goto nfattr_failure;
390
391         nlh->nlmsg_len = skb->tail - b;
392         nfnetlink_send(skb, 0, group, 0);
393         return NOTIFY_DONE;
394
395 nlmsg_failure:
396 nfattr_failure:
397         kfree_skb(skb);
398         return NOTIFY_DONE;
399 }
400 #endif /* CONFIG_NF_CONNTRACK_EVENTS */
401
402 static int ctnetlink_done(struct netlink_callback *cb)
403 {
404         if (cb->args[1])
405                 nf_ct_put((struct nf_conn *)cb->args[1]);
406         return 0;
407 }
408
409 #define L3PROTO(ct) ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num
410
411 static int
412 ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
413 {
414         struct nf_conn *ct, *last;
415         struct nf_conntrack_tuple_hash *h;
416         struct list_head *i;
417         struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
418         u_int8_t l3proto = nfmsg->nfgen_family;
419
420         read_lock_bh(&nf_conntrack_lock);
421         last = (struct nf_conn *)cb->args[1];
422         for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
423 restart:
424                 list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
425                         h = (struct nf_conntrack_tuple_hash *) i;
426                         if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
427                                 continue;
428                         ct = nf_ct_tuplehash_to_ctrack(h);
429                         /* Dump entries of a given L3 protocol number.
430                          * If it is not specified, ie. l3proto == 0,
431                          * then dump everything. */
432                         if (l3proto && L3PROTO(ct) != l3proto)
433                                 continue;
434                         if (cb->args[1]) {
435                                 if (ct != last)
436                                         continue;
437                                 cb->args[1] = 0;
438                         }
439                         if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
440                                                 cb->nlh->nlmsg_seq,
441                                                 IPCTNL_MSG_CT_NEW,
442                                                 1, ct) < 0) {
443                                 nf_conntrack_get(&ct->ct_general);
444                                 cb->args[1] = (unsigned long)ct;
445                                 goto out;
446                         }
447 #ifdef CONFIG_NF_CT_ACCT
448                         if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) ==
449                                                 IPCTNL_MSG_CT_GET_CTRZERO)
450                                 memset(&ct->counters, 0, sizeof(ct->counters));
451 #endif
452                 }
453                 if (cb->args[1]) {
454                         cb->args[1] = 0;
455                         goto restart;
456                 }
457         }
458 out:
459         read_unlock_bh(&nf_conntrack_lock);
460         if (last)
461                 nf_ct_put(last);
462
463         return skb->len;
464 }
465
466 static inline int
467 ctnetlink_parse_tuple_ip(struct nfattr *attr, struct nf_conntrack_tuple *tuple)
468 {
469         struct nfattr *tb[CTA_IP_MAX];
470         struct nf_conntrack_l3proto *l3proto;
471         int ret = 0;
472
473         nfattr_parse_nested(tb, CTA_IP_MAX, attr);
474
475         l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
476
477         if (likely(l3proto->nfattr_to_tuple))
478                 ret = l3proto->nfattr_to_tuple(tb, tuple);
479
480         nf_ct_l3proto_put(l3proto);
481
482         return ret;
483 }
484
485 static const size_t cta_min_proto[CTA_PROTO_MAX] = {
486         [CTA_PROTO_NUM-1]       = sizeof(u_int8_t),
487 };
488
489 static inline int
490 ctnetlink_parse_tuple_proto(struct nfattr *attr, 
491                             struct nf_conntrack_tuple *tuple)
492 {
493         struct nfattr *tb[CTA_PROTO_MAX];
494         struct nf_conntrack_protocol *proto;
495         int ret = 0;
496
497         nfattr_parse_nested(tb, CTA_PROTO_MAX, attr);
498
499         if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
500                 return -EINVAL;
501
502         if (!tb[CTA_PROTO_NUM-1])
503                 return -EINVAL;
504         tuple->dst.protonum = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
505
506         proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
507
508         if (likely(proto->nfattr_to_tuple))
509                 ret = proto->nfattr_to_tuple(tb, tuple);
510
511         nf_ct_proto_put(proto);
512         
513         return ret;
514 }
515
516 static inline int
517 ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple,
518                       enum ctattr_tuple type, u_int8_t l3num)
519 {
520         struct nfattr *tb[CTA_TUPLE_MAX];
521         int err;
522
523         memset(tuple, 0, sizeof(*tuple));
524
525         nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]);
526
527         if (!tb[CTA_TUPLE_IP-1])
528                 return -EINVAL;
529
530         tuple->src.l3num = l3num;
531
532         err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP-1], tuple);
533         if (err < 0)
534                 return err;
535
536         if (!tb[CTA_TUPLE_PROTO-1])
537                 return -EINVAL;
538
539         err = ctnetlink_parse_tuple_proto(tb[CTA_TUPLE_PROTO-1], tuple);
540         if (err < 0)
541                 return err;
542
543         /* orig and expect tuples get DIR_ORIGINAL */
544         if (type == CTA_TUPLE_REPLY)
545                 tuple->dst.dir = IP_CT_DIR_REPLY;
546         else
547                 tuple->dst.dir = IP_CT_DIR_ORIGINAL;
548
549         return 0;
550 }
551
552 #ifdef CONFIG_IP_NF_NAT_NEEDED
553 static const size_t cta_min_protonat[CTA_PROTONAT_MAX] = {
554         [CTA_PROTONAT_PORT_MIN-1]       = sizeof(u_int16_t),
555         [CTA_PROTONAT_PORT_MAX-1]       = sizeof(u_int16_t),
556 };
557
558 static int ctnetlink_parse_nat_proto(struct nfattr *attr,
559                                      const struct nf_conn *ct,
560                                      struct ip_nat_range *range)
561 {
562         struct nfattr *tb[CTA_PROTONAT_MAX];
563         struct ip_nat_protocol *npt;
564
565         nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr);
566
567         if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
568                 return -EINVAL;
569
570         npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
571
572         if (!npt->nfattr_to_range) {
573                 ip_nat_proto_put(npt);
574                 return 0;
575         }
576
577         /* nfattr_to_range returns 1 if it parsed, 0 if not, neg. on error */
578         if (npt->nfattr_to_range(tb, range) > 0)
579                 range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
580
581         ip_nat_proto_put(npt);
582
583         return 0;
584 }
585
586 static const size_t cta_min_nat[CTA_NAT_MAX] = {
587         [CTA_NAT_MINIP-1]       = sizeof(u_int32_t),
588         [CTA_NAT_MAXIP-1]       = sizeof(u_int32_t),
589 };
590
591 static inline int
592 ctnetlink_parse_nat(struct nfattr *nat,
593                     const struct nf_conn *ct, struct ip_nat_range *range)
594 {
595         struct nfattr *tb[CTA_NAT_MAX];
596         int err;
597
598         memset(range, 0, sizeof(*range));
599         
600         nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
601
602         if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
603                 return -EINVAL;
604
605         if (tb[CTA_NAT_MINIP-1])
606                 range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]);
607
608         if (!tb[CTA_NAT_MAXIP-1])
609                 range->max_ip = range->min_ip;
610         else
611                 range->max_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MAXIP-1]);
612
613         if (range->min_ip)
614                 range->flags |= IP_NAT_RANGE_MAP_IPS;
615
616         if (!tb[CTA_NAT_PROTO-1])
617                 return 0;
618
619         err = ctnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range);
620         if (err < 0)
621                 return err;
622
623         return 0;
624 }
625 #endif
626
627 static inline int
628 ctnetlink_parse_help(struct nfattr *attr, char **helper_name)
629 {
630         struct nfattr *tb[CTA_HELP_MAX];
631
632         nfattr_parse_nested(tb, CTA_HELP_MAX, attr);
633
634         if (!tb[CTA_HELP_NAME-1])
635                 return -EINVAL;
636
637         *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]);
638
639         return 0;
640 }
641
642 static const size_t cta_min[CTA_MAX] = {
643         [CTA_STATUS-1]          = sizeof(u_int32_t),
644         [CTA_TIMEOUT-1]         = sizeof(u_int32_t),
645         [CTA_MARK-1]            = sizeof(u_int32_t),
646         [CTA_USE-1]             = sizeof(u_int32_t),
647         [CTA_ID-1]              = sizeof(u_int32_t)
648 };
649
650 static int
651 ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, 
652                         struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
653 {
654         struct nf_conntrack_tuple_hash *h;
655         struct nf_conntrack_tuple tuple;
656         struct nf_conn *ct;
657         struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
658         u_int8_t u3 = nfmsg->nfgen_family;
659         int err = 0;
660
661         if (nfattr_bad_size(cda, CTA_MAX, cta_min))
662                 return -EINVAL;
663
664         if (cda[CTA_TUPLE_ORIG-1])
665                 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
666         else if (cda[CTA_TUPLE_REPLY-1])
667                 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
668         else {
669                 /* Flush the whole table */
670                 nf_conntrack_flush();
671                 return 0;
672         }
673
674         if (err < 0)
675                 return err;
676
677         h = nf_conntrack_find_get(&tuple, NULL);
678         if (!h)
679                 return -ENOENT;
680
681         ct = nf_ct_tuplehash_to_ctrack(h);
682         
683         if (cda[CTA_ID-1]) {
684                 u_int32_t id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1]));
685                 if (ct->id != id) {
686                         nf_ct_put(ct);
687                         return -ENOENT;
688                 }
689         }       
690         if (del_timer(&ct->timeout))
691                 ct->timeout.function((unsigned long)ct);
692
693         nf_ct_put(ct);
694
695         return 0;
696 }
697
698 static int
699 ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, 
700                         struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
701 {
702         struct nf_conntrack_tuple_hash *h;
703         struct nf_conntrack_tuple tuple;
704         struct nf_conn *ct;
705         struct sk_buff *skb2 = NULL;
706         struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
707         u_int8_t u3 = nfmsg->nfgen_family;
708         int err = 0;
709
710         if (nlh->nlmsg_flags & NLM_F_DUMP) {
711                 u32 rlen;
712
713 #ifndef CONFIG_NF_CT_ACCT
714                 if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO)
715                         return -ENOTSUPP;
716 #endif
717                 if ((*errp = netlink_dump_start(ctnl, skb, nlh,
718                                                 ctnetlink_dump_table,
719                                                 ctnetlink_done)) != 0)
720                         return -EINVAL;
721
722                 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
723                 if (rlen > skb->len)
724                         rlen = skb->len;
725                 skb_pull(skb, rlen);
726                 return 0;
727         }
728
729         if (nfattr_bad_size(cda, CTA_MAX, cta_min))
730                 return -EINVAL;
731
732         if (cda[CTA_TUPLE_ORIG-1])
733                 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
734         else if (cda[CTA_TUPLE_REPLY-1])
735                 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
736         else
737                 return -EINVAL;
738
739         if (err < 0)
740                 return err;
741
742         h = nf_conntrack_find_get(&tuple, NULL);
743         if (!h)
744                 return -ENOENT;
745
746         ct = nf_ct_tuplehash_to_ctrack(h);
747
748         err = -ENOMEM;
749         skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
750         if (!skb2) {
751                 nf_ct_put(ct);
752                 return -ENOMEM;
753         }
754         NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
755
756         err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 
757                                   IPCTNL_MSG_CT_NEW, 1, ct);
758         nf_ct_put(ct);
759         if (err <= 0)
760                 goto free;
761
762         err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
763         if (err < 0)
764                 goto out;
765
766         return 0;
767
768 free:
769         kfree_skb(skb2);
770 out:
771         return err;
772 }
773
774 static inline int
775 ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
776 {
777         unsigned long d;
778         unsigned status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]));
779         d = ct->status ^ status;
780
781         if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
782                 /* unchangeable */
783                 return -EINVAL;
784         
785         if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
786                 /* SEEN_REPLY bit can only be set */
787                 return -EINVAL;
788
789         
790         if (d & IPS_ASSURED && !(status & IPS_ASSURED))
791                 /* ASSURED bit can only be set */
792                 return -EINVAL;
793
794         if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
795 #ifndef CONFIG_IP_NF_NAT_NEEDED
796                 return -EINVAL;
797 #else
798                 struct ip_nat_range range;
799
800                 if (cda[CTA_NAT_DST-1]) {
801                         if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
802                                                 &range) < 0)
803                                 return -EINVAL;
804                         if (ip_nat_initialized(ct,
805                                                HOOK2MANIP(NF_IP_PRE_ROUTING)))
806                                 return -EEXIST;
807                         ip_nat_setup_info(ct, &range, hooknum);
808                 }
809                 if (cda[CTA_NAT_SRC-1]) {
810                         if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
811                                                 &range) < 0)
812                                 return -EINVAL;
813                         if (ip_nat_initialized(ct,
814                                                HOOK2MANIP(NF_IP_POST_ROUTING)))
815                                 return -EEXIST;
816                         ip_nat_setup_info(ct, &range, hooknum);
817                 }
818 #endif
819         }
820
821         /* Be careful here, modifying NAT bits can screw up things,
822          * so don't let users modify them directly if they don't pass
823          * ip_nat_range. */
824         ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
825         return 0;
826 }
827
828
829 static inline int
830 ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
831 {
832         struct nf_conntrack_helper *helper;
833         struct nf_conn_help *help = nfct_help(ct);
834         char *helpname;
835         int err;
836
837         if (!help) {
838                 /* FIXME: we need to reallocate and rehash */
839                 return -EBUSY;
840         }
841
842         /* don't change helper of sibling connections */
843         if (ct->master)
844                 return -EINVAL;
845
846         err = ctnetlink_parse_help(cda[CTA_HELP-1], &helpname);
847         if (err < 0)
848                 return err;
849
850         helper = __nf_conntrack_helper_find_byname(helpname);
851         if (!helper) {
852                 if (!strcmp(helpname, ""))
853                         helper = NULL;
854                 else
855                         return -EINVAL;
856         }
857
858         if (help->helper) {
859                 if (!helper) {
860                         /* we had a helper before ... */
861                         nf_ct_remove_expectations(ct);
862                         help->helper = NULL;
863                 } else {
864                         /* need to zero data of old helper */
865                         memset(&help->help, 0, sizeof(help->help));
866                 }
867         }
868         
869         help->helper = helper;
870
871         return 0;
872 }
873
874 static inline int
875 ctnetlink_change_timeout(struct nf_conn *ct, struct nfattr *cda[])
876 {
877         u_int32_t timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
878         
879         if (!del_timer(&ct->timeout))
880                 return -ETIME;
881
882         ct->timeout.expires = jiffies + timeout * HZ;
883         add_timer(&ct->timeout);
884
885         return 0;
886 }
887
888 static inline int
889 ctnetlink_change_protoinfo(struct nf_conn *ct, struct nfattr *cda[])
890 {
891         struct nfattr *tb[CTA_PROTOINFO_MAX], *attr = cda[CTA_PROTOINFO-1];
892         struct nf_conntrack_protocol *proto;
893         u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
894         u_int16_t l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
895         int err = 0;
896
897         nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr);
898
899         proto = nf_ct_proto_find_get(l3num, npt);
900
901         if (proto->from_nfattr)
902                 err = proto->from_nfattr(tb, ct);
903         nf_ct_proto_put(proto); 
904
905         return err;
906 }
907
908 static int
909 ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[])
910 {
911         int err;
912
913         if (cda[CTA_HELP-1]) {
914                 err = ctnetlink_change_helper(ct, cda);
915                 if (err < 0)
916                         return err;
917         }
918
919         if (cda[CTA_TIMEOUT-1]) {
920                 err = ctnetlink_change_timeout(ct, cda);
921                 if (err < 0)
922                         return err;
923         }
924
925         if (cda[CTA_STATUS-1]) {
926                 err = ctnetlink_change_status(ct, cda);
927                 if (err < 0)
928                         return err;
929         }
930
931         if (cda[CTA_PROTOINFO-1]) {
932                 err = ctnetlink_change_protoinfo(ct, cda);
933                 if (err < 0)
934                         return err;
935         }
936
937 #if defined(CONFIG_NF_CONNTRACK_MARK)
938         if (cda[CTA_MARK-1])
939                 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
940 #endif
941
942         return 0;
943 }
944
945 static int
946 ctnetlink_create_conntrack(struct nfattr *cda[], 
947                            struct nf_conntrack_tuple *otuple,
948                            struct nf_conntrack_tuple *rtuple)
949 {
950         struct nf_conn *ct;
951         int err = -EINVAL;
952
953         ct = nf_conntrack_alloc(otuple, rtuple);
954         if (ct == NULL || IS_ERR(ct))
955                 return -ENOMEM; 
956
957         if (!cda[CTA_TIMEOUT-1])
958                 goto err;
959         ct->timeout.expires = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
960
961         ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
962         ct->status |= IPS_CONFIRMED;
963
964         err = ctnetlink_change_status(ct, cda);
965         if (err < 0)
966                 goto err;
967
968         if (cda[CTA_PROTOINFO-1]) {
969                 err = ctnetlink_change_protoinfo(ct, cda);
970                 if (err < 0)
971                         return err;
972         }
973
974 #if defined(CONFIG_NF_CONNTRACK_MARK)
975         if (cda[CTA_MARK-1])
976                 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
977 #endif
978
979         add_timer(&ct->timeout);
980         nf_conntrack_hash_insert(ct);
981
982         return 0;
983
984 err:    
985         nf_conntrack_free(ct);
986         return err;
987 }
988
989 static int 
990 ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, 
991                         struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
992 {
993         struct nf_conntrack_tuple otuple, rtuple;
994         struct nf_conntrack_tuple_hash *h = NULL;
995         struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
996         u_int8_t u3 = nfmsg->nfgen_family;
997         int err = 0;
998
999         if (nfattr_bad_size(cda, CTA_MAX, cta_min))
1000                 return -EINVAL;
1001
1002         if (cda[CTA_TUPLE_ORIG-1]) {
1003                 err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG, u3);
1004                 if (err < 0)
1005                         return err;
1006         }
1007
1008         if (cda[CTA_TUPLE_REPLY-1]) {
1009                 err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY, u3);
1010                 if (err < 0)
1011                         return err;
1012         }
1013
1014         write_lock_bh(&nf_conntrack_lock);
1015         if (cda[CTA_TUPLE_ORIG-1])
1016                 h = __nf_conntrack_find(&otuple, NULL);
1017         else if (cda[CTA_TUPLE_REPLY-1])
1018                 h = __nf_conntrack_find(&rtuple, NULL);
1019
1020         if (h == NULL) {
1021                 write_unlock_bh(&nf_conntrack_lock);
1022                 err = -ENOENT;
1023                 if (nlh->nlmsg_flags & NLM_F_CREATE)
1024                         err = ctnetlink_create_conntrack(cda, &otuple, &rtuple);
1025                 return err;
1026         }
1027         /* implicit 'else' */
1028
1029         /* we only allow nat config for new conntracks */
1030         if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
1031                 err = -EINVAL;
1032                 goto out_unlock;
1033         }
1034
1035         /* We manipulate the conntrack inside the global conntrack table lock,
1036          * so there's no need to increase the refcount */
1037         err = -EEXIST;
1038         if (!(nlh->nlmsg_flags & NLM_F_EXCL))
1039                 err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h), cda);
1040
1041 out_unlock:
1042         write_unlock_bh(&nf_conntrack_lock);
1043         return err;
1044 }
1045
1046 /*********************************************************************** 
1047  * EXPECT 
1048  ***********************************************************************/ 
1049
1050 static inline int
1051 ctnetlink_exp_dump_tuple(struct sk_buff *skb,
1052                          const struct nf_conntrack_tuple *tuple,
1053                          enum ctattr_expect type)
1054 {
1055         struct nfattr *nest_parms = NFA_NEST(skb, type);
1056         
1057         if (ctnetlink_dump_tuples(skb, tuple) < 0)
1058                 goto nfattr_failure;
1059
1060         NFA_NEST_END(skb, nest_parms);
1061
1062         return 0;
1063
1064 nfattr_failure:
1065         return -1;
1066 }                       
1067
1068 static inline int
1069 ctnetlink_exp_dump_mask(struct sk_buff *skb,
1070                         const struct nf_conntrack_tuple *tuple,
1071                         const struct nf_conntrack_tuple *mask)
1072 {
1073         int ret;
1074         struct nf_conntrack_l3proto *l3proto;
1075         struct nf_conntrack_protocol *proto;
1076         struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
1077
1078         l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
1079         ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto);
1080         nf_ct_l3proto_put(l3proto);
1081
1082         if (unlikely(ret < 0))
1083                 goto nfattr_failure;
1084
1085         proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
1086         ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
1087         nf_ct_proto_put(proto);
1088         if (unlikely(ret < 0))
1089                 goto nfattr_failure;
1090
1091         NFA_NEST_END(skb, nest_parms);
1092
1093         return 0;
1094
1095 nfattr_failure:
1096         return -1;
1097 }
1098
1099 static inline int
1100 ctnetlink_exp_dump_expect(struct sk_buff *skb,
1101                           const struct nf_conntrack_expect *exp)
1102 {
1103         struct nf_conn *master = exp->master;
1104         u_int32_t timeout = htonl((exp->timeout.expires - jiffies) / HZ);
1105         u_int32_t id = htonl(exp->id);
1106
1107         if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
1108                 goto nfattr_failure;
1109         if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
1110                 goto nfattr_failure;
1111         if (ctnetlink_exp_dump_tuple(skb,
1112                                  &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
1113                                  CTA_EXPECT_MASTER) < 0)
1114                 goto nfattr_failure;
1115         
1116         NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout);
1117         NFA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id);
1118
1119         return 0;
1120         
1121 nfattr_failure:
1122         return -1;
1123 }
1124
1125 static int
1126 ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
1127                     int event, 
1128                     int nowait, 
1129                     const struct nf_conntrack_expect *exp)
1130 {
1131         struct nlmsghdr *nlh;
1132         struct nfgenmsg *nfmsg;
1133         unsigned char *b;
1134
1135         b = skb->tail;
1136
1137         event |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
1138         nlh    = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg));
1139         nfmsg  = NLMSG_DATA(nlh);
1140
1141         nlh->nlmsg_flags    = (nowait && pid) ? NLM_F_MULTI : 0;
1142         nfmsg->nfgen_family = exp->tuple.src.l3num;
1143         nfmsg->version      = NFNETLINK_V0;
1144         nfmsg->res_id       = 0;
1145
1146         if (ctnetlink_exp_dump_expect(skb, exp) < 0)
1147                 goto nfattr_failure;
1148
1149         nlh->nlmsg_len = skb->tail - b;
1150         return skb->len;
1151
1152 nlmsg_failure:
1153 nfattr_failure:
1154         skb_trim(skb, b - skb->data);
1155         return -1;
1156 }
1157
1158 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1159 static int ctnetlink_expect_event(struct notifier_block *this,
1160                                   unsigned long events, void *ptr)
1161 {
1162         struct nlmsghdr *nlh;
1163         struct nfgenmsg *nfmsg;
1164         struct nf_conntrack_expect *exp = (struct nf_conntrack_expect *)ptr;
1165         struct sk_buff *skb;
1166         unsigned int type;
1167         unsigned char *b;
1168         int flags = 0;
1169
1170         if (events & IPEXP_NEW) {
1171                 type = IPCTNL_MSG_EXP_NEW;
1172                 flags = NLM_F_CREATE|NLM_F_EXCL;
1173         } else
1174                 return NOTIFY_DONE;
1175
1176         if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW))
1177                 return NOTIFY_DONE;
1178
1179         skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
1180         if (!skb)
1181                 return NOTIFY_DONE;
1182
1183         b = skb->tail;
1184
1185         type |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
1186         nlh   = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
1187         nfmsg = NLMSG_DATA(nlh);
1188
1189         nlh->nlmsg_flags    = flags;
1190         nfmsg->nfgen_family = exp->tuple.src.l3num;
1191         nfmsg->version      = NFNETLINK_V0;
1192         nfmsg->res_id       = 0;
1193
1194         if (ctnetlink_exp_dump_expect(skb, exp) < 0)
1195                 goto nfattr_failure;
1196
1197         nlh->nlmsg_len = skb->tail - b;
1198         nfnetlink_send(skb, 0, NFNLGRP_CONNTRACK_EXP_NEW, 0);
1199         return NOTIFY_DONE;
1200
1201 nlmsg_failure:
1202 nfattr_failure:
1203         kfree_skb(skb);
1204         return NOTIFY_DONE;
1205 }
1206 #endif
1207
1208 static int
1209 ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
1210 {
1211         struct nf_conntrack_expect *exp = NULL;
1212         struct list_head *i;
1213         u_int32_t *id = (u_int32_t *) &cb->args[0];
1214         struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
1215         u_int8_t l3proto = nfmsg->nfgen_family;
1216
1217         read_lock_bh(&nf_conntrack_lock);
1218         list_for_each_prev(i, &nf_conntrack_expect_list) {
1219                 exp = (struct nf_conntrack_expect *) i;
1220                 if (l3proto && exp->tuple.src.l3num != l3proto)
1221                         continue;
1222                 if (exp->id <= *id)
1223                         continue;
1224                 if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
1225                                             cb->nlh->nlmsg_seq,
1226                                             IPCTNL_MSG_EXP_NEW,
1227                                             1, exp) < 0)
1228                         goto out;
1229                 *id = exp->id;
1230         }
1231 out:    
1232         read_unlock_bh(&nf_conntrack_lock);
1233
1234         return skb->len;
1235 }
1236
1237 static const size_t cta_min_exp[CTA_EXPECT_MAX] = {
1238         [CTA_EXPECT_TIMEOUT-1]          = sizeof(u_int32_t),
1239         [CTA_EXPECT_ID-1]               = sizeof(u_int32_t)
1240 };
1241
1242 static int
1243 ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, 
1244                      struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
1245 {
1246         struct nf_conntrack_tuple tuple;
1247         struct nf_conntrack_expect *exp;
1248         struct sk_buff *skb2;
1249         struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
1250         u_int8_t u3 = nfmsg->nfgen_family;
1251         int err = 0;
1252
1253         if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
1254                 return -EINVAL;
1255
1256         if (nlh->nlmsg_flags & NLM_F_DUMP) {
1257                 u32 rlen;
1258
1259                 if ((*errp = netlink_dump_start(ctnl, skb, nlh,
1260                                                 ctnetlink_exp_dump_table,
1261                                                 ctnetlink_done)) != 0)
1262                         return -EINVAL;
1263                 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
1264                 if (rlen > skb->len)
1265                         rlen = skb->len;
1266                 skb_pull(skb, rlen);
1267                 return 0;
1268         }
1269
1270         if (cda[CTA_EXPECT_MASTER-1])
1271                 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3);
1272         else
1273                 return -EINVAL;
1274
1275         if (err < 0)
1276                 return err;
1277
1278         exp = nf_conntrack_expect_find(&tuple);
1279         if (!exp)
1280                 return -ENOENT;
1281
1282         if (cda[CTA_EXPECT_ID-1]) {
1283                 u_int32_t id = *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
1284                 if (exp->id != ntohl(id)) {
1285                         nf_conntrack_expect_put(exp);
1286                         return -ENOENT;
1287                 }
1288         }       
1289
1290         err = -ENOMEM;
1291         skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1292         if (!skb2)
1293                 goto out;
1294         NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
1295         
1296         err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, 
1297                                       nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
1298                                       1, exp);
1299         if (err <= 0)
1300                 goto free;
1301
1302         nf_conntrack_expect_put(exp);
1303
1304         return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1305
1306 free:
1307         kfree_skb(skb2);
1308 out:
1309         nf_conntrack_expect_put(exp);
1310         return err;
1311 }
1312
1313 static int
1314 ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, 
1315                      struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
1316 {
1317         struct nf_conntrack_expect *exp, *tmp;
1318         struct nf_conntrack_tuple tuple;
1319         struct nf_conntrack_helper *h;
1320         struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
1321         u_int8_t u3 = nfmsg->nfgen_family;
1322         int err;
1323
1324         if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
1325                 return -EINVAL;
1326
1327         if (cda[CTA_EXPECT_TUPLE-1]) {
1328                 /* delete a single expect by tuple */
1329                 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1330                 if (err < 0)
1331                         return err;
1332
1333                 /* bump usage count to 2 */
1334                 exp = nf_conntrack_expect_find(&tuple);
1335                 if (!exp)
1336                         return -ENOENT;
1337
1338                 if (cda[CTA_EXPECT_ID-1]) {
1339                         u_int32_t id = 
1340                                 *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
1341                         if (exp->id != ntohl(id)) {
1342                                 nf_conntrack_expect_put(exp);
1343                                 return -ENOENT;
1344                         }
1345                 }
1346
1347                 /* after list removal, usage count == 1 */
1348                 nf_conntrack_unexpect_related(exp);
1349                 /* have to put what we 'get' above. 
1350                  * after this line usage count == 0 */
1351                 nf_conntrack_expect_put(exp);
1352         } else if (cda[CTA_EXPECT_HELP_NAME-1]) {
1353                 char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]);
1354
1355                 /* delete all expectations for this helper */
1356                 write_lock_bh(&nf_conntrack_lock);
1357                 h = __nf_conntrack_helper_find_byname(name);
1358                 if (!h) {
1359                         write_unlock_bh(&nf_conntrack_lock);
1360                         return -EINVAL;
1361                 }
1362                 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
1363                                          list) {
1364                         struct nf_conn_help *m_help = nfct_help(exp->master);
1365                         if (m_help->helper == h
1366                             && del_timer(&exp->timeout)) {
1367                                 nf_ct_unlink_expect(exp);
1368                                 nf_conntrack_expect_put(exp);
1369                         }
1370                 }
1371                 write_unlock_bh(&nf_conntrack_lock);
1372         } else {
1373                 /* This basically means we have to flush everything*/
1374                 write_lock_bh(&nf_conntrack_lock);
1375                 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
1376                                          list) {
1377                         if (del_timer(&exp->timeout)) {
1378                                 nf_ct_unlink_expect(exp);
1379                                 nf_conntrack_expect_put(exp);
1380                         }
1381                 }
1382                 write_unlock_bh(&nf_conntrack_lock);
1383         }
1384
1385         return 0;
1386 }
1387 static int
1388 ctnetlink_change_expect(struct nf_conntrack_expect *x, struct nfattr *cda[])
1389 {
1390         return -EOPNOTSUPP;
1391 }
1392
1393 static int
1394 ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
1395 {
1396         struct nf_conntrack_tuple tuple, mask, master_tuple;
1397         struct nf_conntrack_tuple_hash *h = NULL;
1398         struct nf_conntrack_expect *exp;
1399         struct nf_conn *ct;
1400         struct nf_conn_help *help;
1401         int err = 0;
1402
1403         /* caller guarantees that those three CTA_EXPECT_* exist */
1404         err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1405         if (err < 0)
1406                 return err;
1407         err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK, u3);
1408         if (err < 0)
1409                 return err;
1410         err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER, u3);
1411         if (err < 0)
1412                 return err;
1413
1414         /* Look for master conntrack of this expectation */
1415         h = nf_conntrack_find_get(&master_tuple, NULL);
1416         if (!h)
1417                 return -ENOENT;
1418         ct = nf_ct_tuplehash_to_ctrack(h);
1419         help = nfct_help(ct);
1420
1421         if (!help || !help->helper) {
1422                 /* such conntrack hasn't got any helper, abort */
1423                 err = -EINVAL;
1424                 goto out;
1425         }
1426
1427         exp = nf_conntrack_expect_alloc(ct);
1428         if (!exp) {
1429                 err = -ENOMEM;
1430                 goto out;
1431         }
1432         
1433         exp->expectfn = NULL;
1434         exp->flags = 0;
1435         exp->master = ct;
1436         memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
1437         memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple));
1438
1439         err = nf_conntrack_expect_related(exp);
1440         nf_conntrack_expect_put(exp);
1441
1442 out:    
1443         nf_ct_put(nf_ct_tuplehash_to_ctrack(h));
1444         return err;
1445 }
1446
1447 static int
1448 ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
1449                      struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
1450 {
1451         struct nf_conntrack_tuple tuple;
1452         struct nf_conntrack_expect *exp;
1453         struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
1454         u_int8_t u3 = nfmsg->nfgen_family;
1455         int err = 0;
1456
1457         if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
1458                 return -EINVAL;
1459
1460         if (!cda[CTA_EXPECT_TUPLE-1]
1461             || !cda[CTA_EXPECT_MASK-1]
1462             || !cda[CTA_EXPECT_MASTER-1])
1463                 return -EINVAL;
1464
1465         err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1466         if (err < 0)
1467                 return err;
1468
1469         write_lock_bh(&nf_conntrack_lock);
1470         exp = __nf_conntrack_expect_find(&tuple);
1471
1472         if (!exp) {
1473                 write_unlock_bh(&nf_conntrack_lock);
1474                 err = -ENOENT;
1475                 if (nlh->nlmsg_flags & NLM_F_CREATE)
1476                         err = ctnetlink_create_expect(cda, u3);
1477                 return err;
1478         }
1479
1480         err = -EEXIST;
1481         if (!(nlh->nlmsg_flags & NLM_F_EXCL))
1482                 err = ctnetlink_change_expect(exp, cda);
1483         write_unlock_bh(&nf_conntrack_lock);
1484
1485         return err;
1486 }
1487
1488 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1489 static struct notifier_block ctnl_notifier = {
1490         .notifier_call  = ctnetlink_conntrack_event,
1491 };
1492
1493 static struct notifier_block ctnl_notifier_exp = {
1494         .notifier_call  = ctnetlink_expect_event,
1495 };
1496 #endif
1497
1498 static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
1499         [IPCTNL_MSG_CT_NEW]             = { .call = ctnetlink_new_conntrack,
1500                                             .attr_count = CTA_MAX, },
1501         [IPCTNL_MSG_CT_GET]             = { .call = ctnetlink_get_conntrack,
1502                                             .attr_count = CTA_MAX, },
1503         [IPCTNL_MSG_CT_DELETE]          = { .call = ctnetlink_del_conntrack,
1504                                             .attr_count = CTA_MAX, },
1505         [IPCTNL_MSG_CT_GET_CTRZERO]     = { .call = ctnetlink_get_conntrack,
1506                                             .attr_count = CTA_MAX, },
1507 };
1508
1509 static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
1510         [IPCTNL_MSG_EXP_GET]            = { .call = ctnetlink_get_expect,
1511                                             .attr_count = CTA_EXPECT_MAX, },
1512         [IPCTNL_MSG_EXP_NEW]            = { .call = ctnetlink_new_expect,
1513                                             .attr_count = CTA_EXPECT_MAX, },
1514         [IPCTNL_MSG_EXP_DELETE]         = { .call = ctnetlink_del_expect,
1515                                             .attr_count = CTA_EXPECT_MAX, },
1516 };
1517
1518 static struct nfnetlink_subsystem ctnl_subsys = {
1519         .name                           = "conntrack",
1520         .subsys_id                      = NFNL_SUBSYS_CTNETLINK,
1521         .cb_count                       = IPCTNL_MSG_MAX,
1522         .cb                             = ctnl_cb,
1523 };
1524
1525 static struct nfnetlink_subsystem ctnl_exp_subsys = {
1526         .name                           = "conntrack_expect",
1527         .subsys_id                      = NFNL_SUBSYS_CTNETLINK_EXP,
1528         .cb_count                       = IPCTNL_MSG_EXP_MAX,
1529         .cb                             = ctnl_exp_cb,
1530 };
1531
1532 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
1533 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
1534
1535 static int __init ctnetlink_init(void)
1536 {
1537         int ret;
1538
1539         printk("ctnetlink v%s: registering with nfnetlink.\n", version);
1540         ret = nfnetlink_subsys_register(&ctnl_subsys);
1541         if (ret < 0) {
1542                 printk("ctnetlink_init: cannot register with nfnetlink.\n");
1543                 goto err_out;
1544         }
1545
1546         ret = nfnetlink_subsys_register(&ctnl_exp_subsys);
1547         if (ret < 0) {
1548                 printk("ctnetlink_init: cannot register exp with nfnetlink.\n");
1549                 goto err_unreg_subsys;
1550         }
1551
1552 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1553         ret = nf_conntrack_register_notifier(&ctnl_notifier);
1554         if (ret < 0) {
1555                 printk("ctnetlink_init: cannot register notifier.\n");
1556                 goto err_unreg_exp_subsys;
1557         }
1558
1559         ret = nf_conntrack_expect_register_notifier(&ctnl_notifier_exp);
1560         if (ret < 0) {
1561                 printk("ctnetlink_init: cannot expect register notifier.\n");
1562                 goto err_unreg_notifier;
1563         }
1564 #endif
1565
1566         return 0;
1567
1568 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1569 err_unreg_notifier:
1570         nf_conntrack_unregister_notifier(&ctnl_notifier);
1571 err_unreg_exp_subsys:
1572         nfnetlink_subsys_unregister(&ctnl_exp_subsys);
1573 #endif
1574 err_unreg_subsys:
1575         nfnetlink_subsys_unregister(&ctnl_subsys);
1576 err_out:
1577         return ret;
1578 }
1579
1580 static void __exit ctnetlink_exit(void)
1581 {
1582         printk("ctnetlink: unregistering from nfnetlink.\n");
1583
1584 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1585         nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
1586         nf_conntrack_unregister_notifier(&ctnl_notifier);
1587 #endif
1588
1589         nfnetlink_subsys_unregister(&ctnl_exp_subsys);
1590         nfnetlink_subsys_unregister(&ctnl_subsys);
1591         return;
1592 }
1593
1594 module_init(ctnetlink_init);
1595 module_exit(ctnetlink_exit);