]> git.karo-electronics.de Git - mv-sheeva.git/blob - net/netfilter/nf_conntrack_netlink.c
[NETFILTER]: nfctnetlink: assign helper to newly created conntrack
[mv-sheeva.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         struct nf_conn_help *help;
953
954         ct = nf_conntrack_alloc(otuple, rtuple);
955         if (ct == NULL || IS_ERR(ct))
956                 return -ENOMEM; 
957
958         if (!cda[CTA_TIMEOUT-1])
959                 goto err;
960         ct->timeout.expires = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
961
962         ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
963         ct->status |= IPS_CONFIRMED;
964
965         err = ctnetlink_change_status(ct, cda);
966         if (err < 0)
967                 goto err;
968
969         if (cda[CTA_PROTOINFO-1]) {
970                 err = ctnetlink_change_protoinfo(ct, cda);
971                 if (err < 0)
972                         return err;
973         }
974
975 #if defined(CONFIG_NF_CONNTRACK_MARK)
976         if (cda[CTA_MARK-1])
977                 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
978 #endif
979
980         help = nfct_help(ct);
981         if (help)
982                 help->helper = nf_ct_helper_find_get(rtuple);
983
984         add_timer(&ct->timeout);
985         nf_conntrack_hash_insert(ct);
986
987         if (help && help->helper)
988                 nf_ct_helper_put(help->helper);
989
990         return 0;
991
992 err:    
993         nf_conntrack_free(ct);
994         return err;
995 }
996
997 static int 
998 ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, 
999                         struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
1000 {
1001         struct nf_conntrack_tuple otuple, rtuple;
1002         struct nf_conntrack_tuple_hash *h = NULL;
1003         struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
1004         u_int8_t u3 = nfmsg->nfgen_family;
1005         int err = 0;
1006
1007         if (nfattr_bad_size(cda, CTA_MAX, cta_min))
1008                 return -EINVAL;
1009
1010         if (cda[CTA_TUPLE_ORIG-1]) {
1011                 err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG, u3);
1012                 if (err < 0)
1013                         return err;
1014         }
1015
1016         if (cda[CTA_TUPLE_REPLY-1]) {
1017                 err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY, u3);
1018                 if (err < 0)
1019                         return err;
1020         }
1021
1022         write_lock_bh(&nf_conntrack_lock);
1023         if (cda[CTA_TUPLE_ORIG-1])
1024                 h = __nf_conntrack_find(&otuple, NULL);
1025         else if (cda[CTA_TUPLE_REPLY-1])
1026                 h = __nf_conntrack_find(&rtuple, NULL);
1027
1028         if (h == NULL) {
1029                 write_unlock_bh(&nf_conntrack_lock);
1030                 err = -ENOENT;
1031                 if (nlh->nlmsg_flags & NLM_F_CREATE)
1032                         err = ctnetlink_create_conntrack(cda, &otuple, &rtuple);
1033                 return err;
1034         }
1035         /* implicit 'else' */
1036
1037         /* we only allow nat config for new conntracks */
1038         if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
1039                 err = -EINVAL;
1040                 goto out_unlock;
1041         }
1042
1043         /* We manipulate the conntrack inside the global conntrack table lock,
1044          * so there's no need to increase the refcount */
1045         err = -EEXIST;
1046         if (!(nlh->nlmsg_flags & NLM_F_EXCL))
1047                 err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h), cda);
1048
1049 out_unlock:
1050         write_unlock_bh(&nf_conntrack_lock);
1051         return err;
1052 }
1053
1054 /*********************************************************************** 
1055  * EXPECT 
1056  ***********************************************************************/ 
1057
1058 static inline int
1059 ctnetlink_exp_dump_tuple(struct sk_buff *skb,
1060                          const struct nf_conntrack_tuple *tuple,
1061                          enum ctattr_expect type)
1062 {
1063         struct nfattr *nest_parms = NFA_NEST(skb, type);
1064         
1065         if (ctnetlink_dump_tuples(skb, tuple) < 0)
1066                 goto nfattr_failure;
1067
1068         NFA_NEST_END(skb, nest_parms);
1069
1070         return 0;
1071
1072 nfattr_failure:
1073         return -1;
1074 }                       
1075
1076 static inline int
1077 ctnetlink_exp_dump_mask(struct sk_buff *skb,
1078                         const struct nf_conntrack_tuple *tuple,
1079                         const struct nf_conntrack_tuple *mask)
1080 {
1081         int ret;
1082         struct nf_conntrack_l3proto *l3proto;
1083         struct nf_conntrack_protocol *proto;
1084         struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
1085
1086         l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
1087         ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto);
1088         nf_ct_l3proto_put(l3proto);
1089
1090         if (unlikely(ret < 0))
1091                 goto nfattr_failure;
1092
1093         proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
1094         ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
1095         nf_ct_proto_put(proto);
1096         if (unlikely(ret < 0))
1097                 goto nfattr_failure;
1098
1099         NFA_NEST_END(skb, nest_parms);
1100
1101         return 0;
1102
1103 nfattr_failure:
1104         return -1;
1105 }
1106
1107 static inline int
1108 ctnetlink_exp_dump_expect(struct sk_buff *skb,
1109                           const struct nf_conntrack_expect *exp)
1110 {
1111         struct nf_conn *master = exp->master;
1112         u_int32_t timeout = htonl((exp->timeout.expires - jiffies) / HZ);
1113         u_int32_t id = htonl(exp->id);
1114
1115         if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
1116                 goto nfattr_failure;
1117         if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
1118                 goto nfattr_failure;
1119         if (ctnetlink_exp_dump_tuple(skb,
1120                                  &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
1121                                  CTA_EXPECT_MASTER) < 0)
1122                 goto nfattr_failure;
1123         
1124         NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout);
1125         NFA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id);
1126
1127         return 0;
1128         
1129 nfattr_failure:
1130         return -1;
1131 }
1132
1133 static int
1134 ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
1135                     int event, 
1136                     int nowait, 
1137                     const struct nf_conntrack_expect *exp)
1138 {
1139         struct nlmsghdr *nlh;
1140         struct nfgenmsg *nfmsg;
1141         unsigned char *b;
1142
1143         b = skb->tail;
1144
1145         event |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
1146         nlh    = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg));
1147         nfmsg  = NLMSG_DATA(nlh);
1148
1149         nlh->nlmsg_flags    = (nowait && pid) ? NLM_F_MULTI : 0;
1150         nfmsg->nfgen_family = exp->tuple.src.l3num;
1151         nfmsg->version      = NFNETLINK_V0;
1152         nfmsg->res_id       = 0;
1153
1154         if (ctnetlink_exp_dump_expect(skb, exp) < 0)
1155                 goto nfattr_failure;
1156
1157         nlh->nlmsg_len = skb->tail - b;
1158         return skb->len;
1159
1160 nlmsg_failure:
1161 nfattr_failure:
1162         skb_trim(skb, b - skb->data);
1163         return -1;
1164 }
1165
1166 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1167 static int ctnetlink_expect_event(struct notifier_block *this,
1168                                   unsigned long events, void *ptr)
1169 {
1170         struct nlmsghdr *nlh;
1171         struct nfgenmsg *nfmsg;
1172         struct nf_conntrack_expect *exp = (struct nf_conntrack_expect *)ptr;
1173         struct sk_buff *skb;
1174         unsigned int type;
1175         unsigned char *b;
1176         int flags = 0;
1177
1178         if (events & IPEXP_NEW) {
1179                 type = IPCTNL_MSG_EXP_NEW;
1180                 flags = NLM_F_CREATE|NLM_F_EXCL;
1181         } else
1182                 return NOTIFY_DONE;
1183
1184         if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW))
1185                 return NOTIFY_DONE;
1186
1187         skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
1188         if (!skb)
1189                 return NOTIFY_DONE;
1190
1191         b = skb->tail;
1192
1193         type |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
1194         nlh   = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
1195         nfmsg = NLMSG_DATA(nlh);
1196
1197         nlh->nlmsg_flags    = flags;
1198         nfmsg->nfgen_family = exp->tuple.src.l3num;
1199         nfmsg->version      = NFNETLINK_V0;
1200         nfmsg->res_id       = 0;
1201
1202         if (ctnetlink_exp_dump_expect(skb, exp) < 0)
1203                 goto nfattr_failure;
1204
1205         nlh->nlmsg_len = skb->tail - b;
1206         nfnetlink_send(skb, 0, NFNLGRP_CONNTRACK_EXP_NEW, 0);
1207         return NOTIFY_DONE;
1208
1209 nlmsg_failure:
1210 nfattr_failure:
1211         kfree_skb(skb);
1212         return NOTIFY_DONE;
1213 }
1214 #endif
1215
1216 static int
1217 ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
1218 {
1219         struct nf_conntrack_expect *exp = NULL;
1220         struct list_head *i;
1221         u_int32_t *id = (u_int32_t *) &cb->args[0];
1222         struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
1223         u_int8_t l3proto = nfmsg->nfgen_family;
1224
1225         read_lock_bh(&nf_conntrack_lock);
1226         list_for_each_prev(i, &nf_conntrack_expect_list) {
1227                 exp = (struct nf_conntrack_expect *) i;
1228                 if (l3proto && exp->tuple.src.l3num != l3proto)
1229                         continue;
1230                 if (exp->id <= *id)
1231                         continue;
1232                 if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
1233                                             cb->nlh->nlmsg_seq,
1234                                             IPCTNL_MSG_EXP_NEW,
1235                                             1, exp) < 0)
1236                         goto out;
1237                 *id = exp->id;
1238         }
1239 out:    
1240         read_unlock_bh(&nf_conntrack_lock);
1241
1242         return skb->len;
1243 }
1244
1245 static const size_t cta_min_exp[CTA_EXPECT_MAX] = {
1246         [CTA_EXPECT_TIMEOUT-1]          = sizeof(u_int32_t),
1247         [CTA_EXPECT_ID-1]               = sizeof(u_int32_t)
1248 };
1249
1250 static int
1251 ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, 
1252                      struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
1253 {
1254         struct nf_conntrack_tuple tuple;
1255         struct nf_conntrack_expect *exp;
1256         struct sk_buff *skb2;
1257         struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
1258         u_int8_t u3 = nfmsg->nfgen_family;
1259         int err = 0;
1260
1261         if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
1262                 return -EINVAL;
1263
1264         if (nlh->nlmsg_flags & NLM_F_DUMP) {
1265                 u32 rlen;
1266
1267                 if ((*errp = netlink_dump_start(ctnl, skb, nlh,
1268                                                 ctnetlink_exp_dump_table,
1269                                                 ctnetlink_done)) != 0)
1270                         return -EINVAL;
1271                 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
1272                 if (rlen > skb->len)
1273                         rlen = skb->len;
1274                 skb_pull(skb, rlen);
1275                 return 0;
1276         }
1277
1278         if (cda[CTA_EXPECT_MASTER-1])
1279                 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3);
1280         else
1281                 return -EINVAL;
1282
1283         if (err < 0)
1284                 return err;
1285
1286         exp = nf_conntrack_expect_find(&tuple);
1287         if (!exp)
1288                 return -ENOENT;
1289
1290         if (cda[CTA_EXPECT_ID-1]) {
1291                 u_int32_t id = *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
1292                 if (exp->id != ntohl(id)) {
1293                         nf_conntrack_expect_put(exp);
1294                         return -ENOENT;
1295                 }
1296         }       
1297
1298         err = -ENOMEM;
1299         skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1300         if (!skb2)
1301                 goto out;
1302         NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
1303         
1304         err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, 
1305                                       nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
1306                                       1, exp);
1307         if (err <= 0)
1308                 goto free;
1309
1310         nf_conntrack_expect_put(exp);
1311
1312         return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1313
1314 free:
1315         kfree_skb(skb2);
1316 out:
1317         nf_conntrack_expect_put(exp);
1318         return err;
1319 }
1320
1321 static int
1322 ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, 
1323                      struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
1324 {
1325         struct nf_conntrack_expect *exp, *tmp;
1326         struct nf_conntrack_tuple tuple;
1327         struct nf_conntrack_helper *h;
1328         struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
1329         u_int8_t u3 = nfmsg->nfgen_family;
1330         int err;
1331
1332         if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
1333                 return -EINVAL;
1334
1335         if (cda[CTA_EXPECT_TUPLE-1]) {
1336                 /* delete a single expect by tuple */
1337                 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1338                 if (err < 0)
1339                         return err;
1340
1341                 /* bump usage count to 2 */
1342                 exp = nf_conntrack_expect_find(&tuple);
1343                 if (!exp)
1344                         return -ENOENT;
1345
1346                 if (cda[CTA_EXPECT_ID-1]) {
1347                         u_int32_t id = 
1348                                 *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
1349                         if (exp->id != ntohl(id)) {
1350                                 nf_conntrack_expect_put(exp);
1351                                 return -ENOENT;
1352                         }
1353                 }
1354
1355                 /* after list removal, usage count == 1 */
1356                 nf_conntrack_unexpect_related(exp);
1357                 /* have to put what we 'get' above. 
1358                  * after this line usage count == 0 */
1359                 nf_conntrack_expect_put(exp);
1360         } else if (cda[CTA_EXPECT_HELP_NAME-1]) {
1361                 char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]);
1362
1363                 /* delete all expectations for this helper */
1364                 write_lock_bh(&nf_conntrack_lock);
1365                 h = __nf_conntrack_helper_find_byname(name);
1366                 if (!h) {
1367                         write_unlock_bh(&nf_conntrack_lock);
1368                         return -EINVAL;
1369                 }
1370                 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
1371                                          list) {
1372                         struct nf_conn_help *m_help = nfct_help(exp->master);
1373                         if (m_help->helper == h
1374                             && del_timer(&exp->timeout)) {
1375                                 nf_ct_unlink_expect(exp);
1376                                 nf_conntrack_expect_put(exp);
1377                         }
1378                 }
1379                 write_unlock_bh(&nf_conntrack_lock);
1380         } else {
1381                 /* This basically means we have to flush everything*/
1382                 write_lock_bh(&nf_conntrack_lock);
1383                 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
1384                                          list) {
1385                         if (del_timer(&exp->timeout)) {
1386                                 nf_ct_unlink_expect(exp);
1387                                 nf_conntrack_expect_put(exp);
1388                         }
1389                 }
1390                 write_unlock_bh(&nf_conntrack_lock);
1391         }
1392
1393         return 0;
1394 }
1395 static int
1396 ctnetlink_change_expect(struct nf_conntrack_expect *x, struct nfattr *cda[])
1397 {
1398         return -EOPNOTSUPP;
1399 }
1400
1401 static int
1402 ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
1403 {
1404         struct nf_conntrack_tuple tuple, mask, master_tuple;
1405         struct nf_conntrack_tuple_hash *h = NULL;
1406         struct nf_conntrack_expect *exp;
1407         struct nf_conn *ct;
1408         struct nf_conn_help *help;
1409         int err = 0;
1410
1411         /* caller guarantees that those three CTA_EXPECT_* exist */
1412         err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1413         if (err < 0)
1414                 return err;
1415         err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK, u3);
1416         if (err < 0)
1417                 return err;
1418         err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER, u3);
1419         if (err < 0)
1420                 return err;
1421
1422         /* Look for master conntrack of this expectation */
1423         h = nf_conntrack_find_get(&master_tuple, NULL);
1424         if (!h)
1425                 return -ENOENT;
1426         ct = nf_ct_tuplehash_to_ctrack(h);
1427         help = nfct_help(ct);
1428
1429         if (!help || !help->helper) {
1430                 /* such conntrack hasn't got any helper, abort */
1431                 err = -EINVAL;
1432                 goto out;
1433         }
1434
1435         exp = nf_conntrack_expect_alloc(ct);
1436         if (!exp) {
1437                 err = -ENOMEM;
1438                 goto out;
1439         }
1440         
1441         exp->expectfn = NULL;
1442         exp->flags = 0;
1443         exp->master = ct;
1444         memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
1445         memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple));
1446
1447         err = nf_conntrack_expect_related(exp);
1448         nf_conntrack_expect_put(exp);
1449
1450 out:    
1451         nf_ct_put(nf_ct_tuplehash_to_ctrack(h));
1452         return err;
1453 }
1454
1455 static int
1456 ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
1457                      struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
1458 {
1459         struct nf_conntrack_tuple tuple;
1460         struct nf_conntrack_expect *exp;
1461         struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
1462         u_int8_t u3 = nfmsg->nfgen_family;
1463         int err = 0;
1464
1465         if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
1466                 return -EINVAL;
1467
1468         if (!cda[CTA_EXPECT_TUPLE-1]
1469             || !cda[CTA_EXPECT_MASK-1]
1470             || !cda[CTA_EXPECT_MASTER-1])
1471                 return -EINVAL;
1472
1473         err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1474         if (err < 0)
1475                 return err;
1476
1477         write_lock_bh(&nf_conntrack_lock);
1478         exp = __nf_conntrack_expect_find(&tuple);
1479
1480         if (!exp) {
1481                 write_unlock_bh(&nf_conntrack_lock);
1482                 err = -ENOENT;
1483                 if (nlh->nlmsg_flags & NLM_F_CREATE)
1484                         err = ctnetlink_create_expect(cda, u3);
1485                 return err;
1486         }
1487
1488         err = -EEXIST;
1489         if (!(nlh->nlmsg_flags & NLM_F_EXCL))
1490                 err = ctnetlink_change_expect(exp, cda);
1491         write_unlock_bh(&nf_conntrack_lock);
1492
1493         return err;
1494 }
1495
1496 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1497 static struct notifier_block ctnl_notifier = {
1498         .notifier_call  = ctnetlink_conntrack_event,
1499 };
1500
1501 static struct notifier_block ctnl_notifier_exp = {
1502         .notifier_call  = ctnetlink_expect_event,
1503 };
1504 #endif
1505
1506 static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
1507         [IPCTNL_MSG_CT_NEW]             = { .call = ctnetlink_new_conntrack,
1508                                             .attr_count = CTA_MAX, },
1509         [IPCTNL_MSG_CT_GET]             = { .call = ctnetlink_get_conntrack,
1510                                             .attr_count = CTA_MAX, },
1511         [IPCTNL_MSG_CT_DELETE]          = { .call = ctnetlink_del_conntrack,
1512                                             .attr_count = CTA_MAX, },
1513         [IPCTNL_MSG_CT_GET_CTRZERO]     = { .call = ctnetlink_get_conntrack,
1514                                             .attr_count = CTA_MAX, },
1515 };
1516
1517 static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
1518         [IPCTNL_MSG_EXP_GET]            = { .call = ctnetlink_get_expect,
1519                                             .attr_count = CTA_EXPECT_MAX, },
1520         [IPCTNL_MSG_EXP_NEW]            = { .call = ctnetlink_new_expect,
1521                                             .attr_count = CTA_EXPECT_MAX, },
1522         [IPCTNL_MSG_EXP_DELETE]         = { .call = ctnetlink_del_expect,
1523                                             .attr_count = CTA_EXPECT_MAX, },
1524 };
1525
1526 static struct nfnetlink_subsystem ctnl_subsys = {
1527         .name                           = "conntrack",
1528         .subsys_id                      = NFNL_SUBSYS_CTNETLINK,
1529         .cb_count                       = IPCTNL_MSG_MAX,
1530         .cb                             = ctnl_cb,
1531 };
1532
1533 static struct nfnetlink_subsystem ctnl_exp_subsys = {
1534         .name                           = "conntrack_expect",
1535         .subsys_id                      = NFNL_SUBSYS_CTNETLINK_EXP,
1536         .cb_count                       = IPCTNL_MSG_EXP_MAX,
1537         .cb                             = ctnl_exp_cb,
1538 };
1539
1540 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
1541 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
1542
1543 static int __init ctnetlink_init(void)
1544 {
1545         int ret;
1546
1547         printk("ctnetlink v%s: registering with nfnetlink.\n", version);
1548         ret = nfnetlink_subsys_register(&ctnl_subsys);
1549         if (ret < 0) {
1550                 printk("ctnetlink_init: cannot register with nfnetlink.\n");
1551                 goto err_out;
1552         }
1553
1554         ret = nfnetlink_subsys_register(&ctnl_exp_subsys);
1555         if (ret < 0) {
1556                 printk("ctnetlink_init: cannot register exp with nfnetlink.\n");
1557                 goto err_unreg_subsys;
1558         }
1559
1560 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1561         ret = nf_conntrack_register_notifier(&ctnl_notifier);
1562         if (ret < 0) {
1563                 printk("ctnetlink_init: cannot register notifier.\n");
1564                 goto err_unreg_exp_subsys;
1565         }
1566
1567         ret = nf_conntrack_expect_register_notifier(&ctnl_notifier_exp);
1568         if (ret < 0) {
1569                 printk("ctnetlink_init: cannot expect register notifier.\n");
1570                 goto err_unreg_notifier;
1571         }
1572 #endif
1573
1574         return 0;
1575
1576 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1577 err_unreg_notifier:
1578         nf_conntrack_unregister_notifier(&ctnl_notifier);
1579 err_unreg_exp_subsys:
1580         nfnetlink_subsys_unregister(&ctnl_exp_subsys);
1581 #endif
1582 err_unreg_subsys:
1583         nfnetlink_subsys_unregister(&ctnl_subsys);
1584 err_out:
1585         return ret;
1586 }
1587
1588 static void __exit ctnetlink_exit(void)
1589 {
1590         printk("ctnetlink: unregistering from nfnetlink.\n");
1591
1592 #ifdef CONFIG_NF_CONNTRACK_EVENTS
1593         nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
1594         nf_conntrack_unregister_notifier(&ctnl_notifier);
1595 #endif
1596
1597         nfnetlink_subsys_unregister(&ctnl_exp_subsys);
1598         nfnetlink_subsys_unregister(&ctnl_subsys);
1599         return;
1600 }
1601
1602 module_init(ctnetlink_init);
1603 module_exit(ctnetlink_exit);