]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/netfilter/nft_ct.c
Merge branch 'linus' into x86/urgent, to pick up dependent commits
[karo-tx-linux.git] / net / netfilter / nft_ct.c
1 /*
2  * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
3  * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Development of this code funded by Astaro AG (http://www.astaro.com/)
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/netlink.h>
16 #include <linux/netfilter.h>
17 #include <linux/netfilter/nf_tables.h>
18 #include <net/netfilter/nf_tables.h>
19 #include <net/netfilter/nf_conntrack.h>
20 #include <net/netfilter/nf_conntrack_acct.h>
21 #include <net/netfilter/nf_conntrack_tuple.h>
22 #include <net/netfilter/nf_conntrack_helper.h>
23 #include <net/netfilter/nf_conntrack_ecache.h>
24 #include <net/netfilter/nf_conntrack_labels.h>
25
26 struct nft_ct {
27         enum nft_ct_keys        key:8;
28         enum ip_conntrack_dir   dir:8;
29         union {
30                 enum nft_registers      dreg:8;
31                 enum nft_registers      sreg:8;
32         };
33 };
34
35 #ifdef CONFIG_NF_CONNTRACK_ZONES
36 static DEFINE_PER_CPU(struct nf_conn *, nft_ct_pcpu_template);
37 static unsigned int nft_ct_pcpu_template_refcnt __read_mostly;
38 #endif
39
40 static u64 nft_ct_get_eval_counter(const struct nf_conn_counter *c,
41                                    enum nft_ct_keys k,
42                                    enum ip_conntrack_dir d)
43 {
44         if (d < IP_CT_DIR_MAX)
45                 return k == NFT_CT_BYTES ? atomic64_read(&c[d].bytes) :
46                                            atomic64_read(&c[d].packets);
47
48         return nft_ct_get_eval_counter(c, k, IP_CT_DIR_ORIGINAL) +
49                nft_ct_get_eval_counter(c, k, IP_CT_DIR_REPLY);
50 }
51
52 static void nft_ct_get_eval(const struct nft_expr *expr,
53                             struct nft_regs *regs,
54                             const struct nft_pktinfo *pkt)
55 {
56         const struct nft_ct *priv = nft_expr_priv(expr);
57         u32 *dest = &regs->data[priv->dreg];
58         enum ip_conntrack_info ctinfo;
59         const struct nf_conn *ct;
60         const struct nf_conn_help *help;
61         const struct nf_conntrack_tuple *tuple;
62         const struct nf_conntrack_helper *helper;
63         unsigned int state;
64
65         ct = nf_ct_get(pkt->skb, &ctinfo);
66
67         switch (priv->key) {
68         case NFT_CT_STATE:
69                 if (ct == NULL)
70                         state = NF_CT_STATE_INVALID_BIT;
71                 else if (nf_ct_is_untracked(ct))
72                         state = NF_CT_STATE_UNTRACKED_BIT;
73                 else
74                         state = NF_CT_STATE_BIT(ctinfo);
75                 *dest = state;
76                 return;
77         default:
78                 break;
79         }
80
81         if (ct == NULL)
82                 goto err;
83
84         switch (priv->key) {
85         case NFT_CT_DIRECTION:
86                 nft_reg_store8(dest, CTINFO2DIR(ctinfo));
87                 return;
88         case NFT_CT_STATUS:
89                 *dest = ct->status;
90                 return;
91 #ifdef CONFIG_NF_CONNTRACK_MARK
92         case NFT_CT_MARK:
93                 *dest = ct->mark;
94                 return;
95 #endif
96 #ifdef CONFIG_NF_CONNTRACK_SECMARK
97         case NFT_CT_SECMARK:
98                 *dest = ct->secmark;
99                 return;
100 #endif
101         case NFT_CT_EXPIRATION:
102                 *dest = jiffies_to_msecs(nf_ct_expires(ct));
103                 return;
104         case NFT_CT_HELPER:
105                 if (ct->master == NULL)
106                         goto err;
107                 help = nfct_help(ct->master);
108                 if (help == NULL)
109                         goto err;
110                 helper = rcu_dereference(help->helper);
111                 if (helper == NULL)
112                         goto err;
113                 strncpy((char *)dest, helper->name, NF_CT_HELPER_NAME_LEN);
114                 return;
115 #ifdef CONFIG_NF_CONNTRACK_LABELS
116         case NFT_CT_LABELS: {
117                 struct nf_conn_labels *labels = nf_ct_labels_find(ct);
118
119                 if (labels)
120                         memcpy(dest, labels->bits, NF_CT_LABELS_MAX_SIZE);
121                 else
122                         memset(dest, 0, NF_CT_LABELS_MAX_SIZE);
123                 return;
124         }
125 #endif
126         case NFT_CT_BYTES: /* fallthrough */
127         case NFT_CT_PKTS: {
128                 const struct nf_conn_acct *acct = nf_conn_acct_find(ct);
129                 u64 count = 0;
130
131                 if (acct)
132                         count = nft_ct_get_eval_counter(acct->counter,
133                                                         priv->key, priv->dir);
134                 memcpy(dest, &count, sizeof(count));
135                 return;
136         }
137         case NFT_CT_AVGPKT: {
138                 const struct nf_conn_acct *acct = nf_conn_acct_find(ct);
139                 u64 avgcnt = 0, bcnt = 0, pcnt = 0;
140
141                 if (acct) {
142                         pcnt = nft_ct_get_eval_counter(acct->counter,
143                                                        NFT_CT_PKTS, priv->dir);
144                         bcnt = nft_ct_get_eval_counter(acct->counter,
145                                                        NFT_CT_BYTES, priv->dir);
146                         if (pcnt != 0)
147                                 avgcnt = div64_u64(bcnt, pcnt);
148                 }
149
150                 memcpy(dest, &avgcnt, sizeof(avgcnt));
151                 return;
152         }
153         case NFT_CT_L3PROTOCOL:
154                 nft_reg_store8(dest, nf_ct_l3num(ct));
155                 return;
156         case NFT_CT_PROTOCOL:
157                 nft_reg_store8(dest, nf_ct_protonum(ct));
158                 return;
159 #ifdef CONFIG_NF_CONNTRACK_ZONES
160         case NFT_CT_ZONE: {
161                 const struct nf_conntrack_zone *zone = nf_ct_zone(ct);
162                 u16 zoneid;
163
164                 if (priv->dir < IP_CT_DIR_MAX)
165                         zoneid = nf_ct_zone_id(zone, priv->dir);
166                 else
167                         zoneid = zone->id;
168
169                 nft_reg_store16(dest, zoneid);
170                 return;
171         }
172 #endif
173         default:
174                 break;
175         }
176
177         tuple = &ct->tuplehash[priv->dir].tuple;
178         switch (priv->key) {
179         case NFT_CT_SRC:
180                 memcpy(dest, tuple->src.u3.all,
181                        nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
182                 return;
183         case NFT_CT_DST:
184                 memcpy(dest, tuple->dst.u3.all,
185                        nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
186                 return;
187         case NFT_CT_PROTO_SRC:
188                 nft_reg_store16(dest, (__force u16)tuple->src.u.all);
189                 return;
190         case NFT_CT_PROTO_DST:
191                 nft_reg_store16(dest, (__force u16)tuple->dst.u.all);
192                 return;
193         default:
194                 break;
195         }
196         return;
197 err:
198         regs->verdict.code = NFT_BREAK;
199 }
200
201 #ifdef CONFIG_NF_CONNTRACK_ZONES
202 static void nft_ct_set_zone_eval(const struct nft_expr *expr,
203                                  struct nft_regs *regs,
204                                  const struct nft_pktinfo *pkt)
205 {
206         struct nf_conntrack_zone zone = { .dir = NF_CT_DEFAULT_ZONE_DIR };
207         const struct nft_ct *priv = nft_expr_priv(expr);
208         struct sk_buff *skb = pkt->skb;
209         enum ip_conntrack_info ctinfo;
210         u16 value = nft_reg_load16(&regs->data[priv->sreg]);
211         struct nf_conn *ct;
212
213         ct = nf_ct_get(skb, &ctinfo);
214         if (ct) /* already tracked */
215                 return;
216
217         zone.id = value;
218
219         switch (priv->dir) {
220         case IP_CT_DIR_ORIGINAL:
221                 zone.dir = NF_CT_ZONE_DIR_ORIG;
222                 break;
223         case IP_CT_DIR_REPLY:
224                 zone.dir = NF_CT_ZONE_DIR_REPL;
225                 break;
226         default:
227                 break;
228         }
229
230         ct = this_cpu_read(nft_ct_pcpu_template);
231
232         if (likely(atomic_read(&ct->ct_general.use) == 1)) {
233                 nf_ct_zone_add(ct, &zone);
234         } else {
235                 /* previous skb got queued to userspace */
236                 ct = nf_ct_tmpl_alloc(nft_net(pkt), &zone, GFP_ATOMIC);
237                 if (!ct) {
238                         regs->verdict.code = NF_DROP;
239                         return;
240                 }
241         }
242
243         atomic_inc(&ct->ct_general.use);
244         nf_ct_set(skb, ct, IP_CT_NEW);
245 }
246 #endif
247
248 static void nft_ct_set_eval(const struct nft_expr *expr,
249                             struct nft_regs *regs,
250                             const struct nft_pktinfo *pkt)
251 {
252         const struct nft_ct *priv = nft_expr_priv(expr);
253         struct sk_buff *skb = pkt->skb;
254 #ifdef CONFIG_NF_CONNTRACK_MARK
255         u32 value = regs->data[priv->sreg];
256 #endif
257         enum ip_conntrack_info ctinfo;
258         struct nf_conn *ct;
259
260         ct = nf_ct_get(skb, &ctinfo);
261         if (ct == NULL)
262                 return;
263
264         switch (priv->key) {
265 #ifdef CONFIG_NF_CONNTRACK_MARK
266         case NFT_CT_MARK:
267                 if (ct->mark != value) {
268                         ct->mark = value;
269                         nf_conntrack_event_cache(IPCT_MARK, ct);
270                 }
271                 break;
272 #endif
273 #ifdef CONFIG_NF_CONNTRACK_LABELS
274         case NFT_CT_LABELS:
275                 nf_connlabels_replace(ct,
276                                       &regs->data[priv->sreg],
277                                       &regs->data[priv->sreg],
278                                       NF_CT_LABELS_MAX_SIZE / sizeof(u32));
279                 break;
280 #endif
281         default:
282                 break;
283         }
284 }
285
286 static const struct nla_policy nft_ct_policy[NFTA_CT_MAX + 1] = {
287         [NFTA_CT_DREG]          = { .type = NLA_U32 },
288         [NFTA_CT_KEY]           = { .type = NLA_U32 },
289         [NFTA_CT_DIRECTION]     = { .type = NLA_U8 },
290         [NFTA_CT_SREG]          = { .type = NLA_U32 },
291 };
292
293 static int nft_ct_netns_get(struct net *net, uint8_t family)
294 {
295         int err;
296
297         if (family == NFPROTO_INET) {
298                 err = nf_ct_netns_get(net, NFPROTO_IPV4);
299                 if (err < 0)
300                         goto err1;
301                 err = nf_ct_netns_get(net, NFPROTO_IPV6);
302                 if (err < 0)
303                         goto err2;
304         } else {
305                 err = nf_ct_netns_get(net, family);
306                 if (err < 0)
307                         goto err1;
308         }
309         return 0;
310
311 err2:
312         nf_ct_netns_put(net, NFPROTO_IPV4);
313 err1:
314         return err;
315 }
316
317 static void nft_ct_netns_put(struct net *net, uint8_t family)
318 {
319         if (family == NFPROTO_INET) {
320                 nf_ct_netns_put(net, NFPROTO_IPV4);
321                 nf_ct_netns_put(net, NFPROTO_IPV6);
322         } else
323                 nf_ct_netns_put(net, family);
324 }
325
326 #ifdef CONFIG_NF_CONNTRACK_ZONES
327 static void nft_ct_tmpl_put_pcpu(void)
328 {
329         struct nf_conn *ct;
330         int cpu;
331
332         for_each_possible_cpu(cpu) {
333                 ct = per_cpu(nft_ct_pcpu_template, cpu);
334                 if (!ct)
335                         break;
336                 nf_ct_put(ct);
337                 per_cpu(nft_ct_pcpu_template, cpu) = NULL;
338         }
339 }
340
341 static bool nft_ct_tmpl_alloc_pcpu(void)
342 {
343         struct nf_conntrack_zone zone = { .id = 0 };
344         struct nf_conn *tmp;
345         int cpu;
346
347         if (nft_ct_pcpu_template_refcnt)
348                 return true;
349
350         for_each_possible_cpu(cpu) {
351                 tmp = nf_ct_tmpl_alloc(&init_net, &zone, GFP_KERNEL);
352                 if (!tmp) {
353                         nft_ct_tmpl_put_pcpu();
354                         return false;
355                 }
356
357                 atomic_set(&tmp->ct_general.use, 1);
358                 per_cpu(nft_ct_pcpu_template, cpu) = tmp;
359         }
360
361         return true;
362 }
363 #endif
364
365 static int nft_ct_get_init(const struct nft_ctx *ctx,
366                            const struct nft_expr *expr,
367                            const struct nlattr * const tb[])
368 {
369         struct nft_ct *priv = nft_expr_priv(expr);
370         unsigned int len;
371         int err;
372
373         priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
374         priv->dir = IP_CT_DIR_MAX;
375         switch (priv->key) {
376         case NFT_CT_DIRECTION:
377                 if (tb[NFTA_CT_DIRECTION] != NULL)
378                         return -EINVAL;
379                 len = sizeof(u8);
380                 break;
381         case NFT_CT_STATE:
382         case NFT_CT_STATUS:
383 #ifdef CONFIG_NF_CONNTRACK_MARK
384         case NFT_CT_MARK:
385 #endif
386 #ifdef CONFIG_NF_CONNTRACK_SECMARK
387         case NFT_CT_SECMARK:
388 #endif
389         case NFT_CT_EXPIRATION:
390                 if (tb[NFTA_CT_DIRECTION] != NULL)
391                         return -EINVAL;
392                 len = sizeof(u32);
393                 break;
394 #ifdef CONFIG_NF_CONNTRACK_LABELS
395         case NFT_CT_LABELS:
396                 if (tb[NFTA_CT_DIRECTION] != NULL)
397                         return -EINVAL;
398                 len = NF_CT_LABELS_MAX_SIZE;
399                 break;
400 #endif
401         case NFT_CT_HELPER:
402                 if (tb[NFTA_CT_DIRECTION] != NULL)
403                         return -EINVAL;
404                 len = NF_CT_HELPER_NAME_LEN;
405                 break;
406
407         case NFT_CT_L3PROTOCOL:
408         case NFT_CT_PROTOCOL:
409                 /* For compatibility, do not report error if NFTA_CT_DIRECTION
410                  * attribute is specified.
411                  */
412                 len = sizeof(u8);
413                 break;
414         case NFT_CT_SRC:
415         case NFT_CT_DST:
416                 if (tb[NFTA_CT_DIRECTION] == NULL)
417                         return -EINVAL;
418
419                 switch (ctx->afi->family) {
420                 case NFPROTO_IPV4:
421                         len = FIELD_SIZEOF(struct nf_conntrack_tuple,
422                                            src.u3.ip);
423                         break;
424                 case NFPROTO_IPV6:
425                 case NFPROTO_INET:
426                         len = FIELD_SIZEOF(struct nf_conntrack_tuple,
427                                            src.u3.ip6);
428                         break;
429                 default:
430                         return -EAFNOSUPPORT;
431                 }
432                 break;
433         case NFT_CT_PROTO_SRC:
434         case NFT_CT_PROTO_DST:
435                 if (tb[NFTA_CT_DIRECTION] == NULL)
436                         return -EINVAL;
437                 len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all);
438                 break;
439         case NFT_CT_BYTES:
440         case NFT_CT_PKTS:
441         case NFT_CT_AVGPKT:
442                 len = sizeof(u64);
443                 break;
444 #ifdef CONFIG_NF_CONNTRACK_ZONES
445         case NFT_CT_ZONE:
446                 len = sizeof(u16);
447                 break;
448 #endif
449         default:
450                 return -EOPNOTSUPP;
451         }
452
453         if (tb[NFTA_CT_DIRECTION] != NULL) {
454                 priv->dir = nla_get_u8(tb[NFTA_CT_DIRECTION]);
455                 switch (priv->dir) {
456                 case IP_CT_DIR_ORIGINAL:
457                 case IP_CT_DIR_REPLY:
458                         break;
459                 default:
460                         return -EINVAL;
461                 }
462         }
463
464         priv->dreg = nft_parse_register(tb[NFTA_CT_DREG]);
465         err = nft_validate_register_store(ctx, priv->dreg, NULL,
466                                           NFT_DATA_VALUE, len);
467         if (err < 0)
468                 return err;
469
470         err = nft_ct_netns_get(ctx->net, ctx->afi->family);
471         if (err < 0)
472                 return err;
473
474         if (priv->key == NFT_CT_BYTES ||
475             priv->key == NFT_CT_PKTS  ||
476             priv->key == NFT_CT_AVGPKT)
477                 nf_ct_set_acct(ctx->net, true);
478
479         return 0;
480 }
481
482 static void __nft_ct_set_destroy(const struct nft_ctx *ctx, struct nft_ct *priv)
483 {
484         switch (priv->key) {
485 #ifdef CONFIG_NF_CONNTRACK_LABELS
486         case NFT_CT_LABELS:
487                 nf_connlabels_put(ctx->net);
488                 break;
489 #endif
490 #ifdef CONFIG_NF_CONNTRACK_ZONES
491         case NFT_CT_ZONE:
492                 if (--nft_ct_pcpu_template_refcnt == 0)
493                         nft_ct_tmpl_put_pcpu();
494 #endif
495         default:
496                 break;
497         }
498 }
499
500 static int nft_ct_set_init(const struct nft_ctx *ctx,
501                            const struct nft_expr *expr,
502                            const struct nlattr * const tb[])
503 {
504         struct nft_ct *priv = nft_expr_priv(expr);
505         unsigned int len;
506         int err;
507
508         priv->dir = IP_CT_DIR_MAX;
509         priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
510         switch (priv->key) {
511 #ifdef CONFIG_NF_CONNTRACK_MARK
512         case NFT_CT_MARK:
513                 if (tb[NFTA_CT_DIRECTION])
514                         return -EINVAL;
515                 len = FIELD_SIZEOF(struct nf_conn, mark);
516                 break;
517 #endif
518 #ifdef CONFIG_NF_CONNTRACK_LABELS
519         case NFT_CT_LABELS:
520                 if (tb[NFTA_CT_DIRECTION])
521                         return -EINVAL;
522                 len = NF_CT_LABELS_MAX_SIZE;
523                 err = nf_connlabels_get(ctx->net, (len * BITS_PER_BYTE) - 1);
524                 if (err)
525                         return err;
526                 break;
527 #endif
528 #ifdef CONFIG_NF_CONNTRACK_ZONES
529         case NFT_CT_ZONE:
530                 if (!nft_ct_tmpl_alloc_pcpu())
531                         return -ENOMEM;
532                 nft_ct_pcpu_template_refcnt++;
533                 len = sizeof(u16);
534                 break;
535 #endif
536         default:
537                 return -EOPNOTSUPP;
538         }
539
540         if (tb[NFTA_CT_DIRECTION]) {
541                 priv->dir = nla_get_u8(tb[NFTA_CT_DIRECTION]);
542                 switch (priv->dir) {
543                 case IP_CT_DIR_ORIGINAL:
544                 case IP_CT_DIR_REPLY:
545                         break;
546                 default:
547                         err = -EINVAL;
548                         goto err1;
549                 }
550         }
551
552         priv->sreg = nft_parse_register(tb[NFTA_CT_SREG]);
553         err = nft_validate_register_load(priv->sreg, len);
554         if (err < 0)
555                 goto err1;
556
557         err = nft_ct_netns_get(ctx->net, ctx->afi->family);
558         if (err < 0)
559                 goto err1;
560
561         return 0;
562
563 err1:
564         __nft_ct_set_destroy(ctx, priv);
565         return err;
566 }
567
568 static void nft_ct_get_destroy(const struct nft_ctx *ctx,
569                                const struct nft_expr *expr)
570 {
571         nf_ct_netns_put(ctx->net, ctx->afi->family);
572 }
573
574 static void nft_ct_set_destroy(const struct nft_ctx *ctx,
575                                const struct nft_expr *expr)
576 {
577         struct nft_ct *priv = nft_expr_priv(expr);
578
579         __nft_ct_set_destroy(ctx, priv);
580         nft_ct_netns_put(ctx->net, ctx->afi->family);
581 }
582
583 static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
584 {
585         const struct nft_ct *priv = nft_expr_priv(expr);
586
587         if (nft_dump_register(skb, NFTA_CT_DREG, priv->dreg))
588                 goto nla_put_failure;
589         if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key)))
590                 goto nla_put_failure;
591
592         switch (priv->key) {
593         case NFT_CT_SRC:
594         case NFT_CT_DST:
595         case NFT_CT_PROTO_SRC:
596         case NFT_CT_PROTO_DST:
597                 if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
598                         goto nla_put_failure;
599                 break;
600         case NFT_CT_BYTES:
601         case NFT_CT_PKTS:
602         case NFT_CT_AVGPKT:
603         case NFT_CT_ZONE:
604                 if (priv->dir < IP_CT_DIR_MAX &&
605                     nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
606                         goto nla_put_failure;
607                 break;
608         default:
609                 break;
610         }
611
612         return 0;
613
614 nla_put_failure:
615         return -1;
616 }
617
618 static int nft_ct_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
619 {
620         const struct nft_ct *priv = nft_expr_priv(expr);
621
622         if (nft_dump_register(skb, NFTA_CT_SREG, priv->sreg))
623                 goto nla_put_failure;
624         if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key)))
625                 goto nla_put_failure;
626
627         switch (priv->key) {
628         case NFT_CT_ZONE:
629                 if (priv->dir < IP_CT_DIR_MAX &&
630                     nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
631                         goto nla_put_failure;
632                 break;
633         default:
634                 break;
635         }
636
637         return 0;
638
639 nla_put_failure:
640         return -1;
641 }
642
643 static struct nft_expr_type nft_ct_type;
644 static const struct nft_expr_ops nft_ct_get_ops = {
645         .type           = &nft_ct_type,
646         .size           = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
647         .eval           = nft_ct_get_eval,
648         .init           = nft_ct_get_init,
649         .destroy        = nft_ct_get_destroy,
650         .dump           = nft_ct_get_dump,
651 };
652
653 static const struct nft_expr_ops nft_ct_set_ops = {
654         .type           = &nft_ct_type,
655         .size           = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
656         .eval           = nft_ct_set_eval,
657         .init           = nft_ct_set_init,
658         .destroy        = nft_ct_set_destroy,
659         .dump           = nft_ct_set_dump,
660 };
661
662 #ifdef CONFIG_NF_CONNTRACK_ZONES
663 static const struct nft_expr_ops nft_ct_set_zone_ops = {
664         .type           = &nft_ct_type,
665         .size           = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
666         .eval           = nft_ct_set_zone_eval,
667         .init           = nft_ct_set_init,
668         .destroy        = nft_ct_set_destroy,
669         .dump           = nft_ct_set_dump,
670 };
671 #endif
672
673 static const struct nft_expr_ops *
674 nft_ct_select_ops(const struct nft_ctx *ctx,
675                     const struct nlattr * const tb[])
676 {
677         if (tb[NFTA_CT_KEY] == NULL)
678                 return ERR_PTR(-EINVAL);
679
680         if (tb[NFTA_CT_DREG] && tb[NFTA_CT_SREG])
681                 return ERR_PTR(-EINVAL);
682
683         if (tb[NFTA_CT_DREG])
684                 return &nft_ct_get_ops;
685
686         if (tb[NFTA_CT_SREG]) {
687 #ifdef CONFIG_NF_CONNTRACK_ZONES
688                 if (nla_get_be32(tb[NFTA_CT_KEY]) == htonl(NFT_CT_ZONE))
689                         return &nft_ct_set_zone_ops;
690 #endif
691                 return &nft_ct_set_ops;
692         }
693
694         return ERR_PTR(-EINVAL);
695 }
696
697 static struct nft_expr_type nft_ct_type __read_mostly = {
698         .name           = "ct",
699         .select_ops     = &nft_ct_select_ops,
700         .policy         = nft_ct_policy,
701         .maxattr        = NFTA_CT_MAX,
702         .owner          = THIS_MODULE,
703 };
704
705 static void nft_notrack_eval(const struct nft_expr *expr,
706                              struct nft_regs *regs,
707                              const struct nft_pktinfo *pkt)
708 {
709         struct sk_buff *skb = pkt->skb;
710         enum ip_conntrack_info ctinfo;
711         struct nf_conn *ct;
712
713         ct = nf_ct_get(pkt->skb, &ctinfo);
714         /* Previously seen (loopback or untracked)?  Ignore. */
715         if (ct)
716                 return;
717
718         ct = nf_ct_untracked_get();
719         atomic_inc(&ct->ct_general.use);
720         nf_ct_set(skb, ct, IP_CT_NEW);
721 }
722
723 static struct nft_expr_type nft_notrack_type;
724 static const struct nft_expr_ops nft_notrack_ops = {
725         .type           = &nft_notrack_type,
726         .size           = NFT_EXPR_SIZE(0),
727         .eval           = nft_notrack_eval,
728 };
729
730 static struct nft_expr_type nft_notrack_type __read_mostly = {
731         .name           = "notrack",
732         .ops            = &nft_notrack_ops,
733         .owner          = THIS_MODULE,
734 };
735
736 static int __init nft_ct_module_init(void)
737 {
738         int err;
739
740         BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE > NFT_REG_SIZE);
741
742         err = nft_register_expr(&nft_ct_type);
743         if (err < 0)
744                 return err;
745
746         err = nft_register_expr(&nft_notrack_type);
747         if (err < 0)
748                 goto err1;
749
750         return 0;
751 err1:
752         nft_unregister_expr(&nft_ct_type);
753         return err;
754 }
755
756 static void __exit nft_ct_module_exit(void)
757 {
758         nft_unregister_expr(&nft_notrack_type);
759         nft_unregister_expr(&nft_ct_type);
760 }
761
762 module_init(nft_ct_module_init);
763 module_exit(nft_ct_module_exit);
764
765 MODULE_LICENSE("GPL");
766 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
767 MODULE_ALIAS_NFT_EXPR("ct");
768 MODULE_ALIAS_NFT_EXPR("notrack");