netfilter: nf_tables: fix mismatch in big-endian system
[linux-2.6-microblaze.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                         return -EINVAL;
548                 }
549         }
550
551         priv->sreg = nft_parse_register(tb[NFTA_CT_SREG]);
552         err = nft_validate_register_load(priv->sreg, len);
553         if (err < 0)
554                 goto err1;
555
556         err = nft_ct_netns_get(ctx->net, ctx->afi->family);
557         if (err < 0)
558                 goto err1;
559
560         return 0;
561
562 err1:
563         __nft_ct_set_destroy(ctx, priv);
564         return err;
565 }
566
567 static void nft_ct_get_destroy(const struct nft_ctx *ctx,
568                                const struct nft_expr *expr)
569 {
570         nf_ct_netns_put(ctx->net, ctx->afi->family);
571 }
572
573 static void nft_ct_set_destroy(const struct nft_ctx *ctx,
574                                const struct nft_expr *expr)
575 {
576         struct nft_ct *priv = nft_expr_priv(expr);
577
578         __nft_ct_set_destroy(ctx, priv);
579         nft_ct_netns_put(ctx->net, ctx->afi->family);
580 }
581
582 static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
583 {
584         const struct nft_ct *priv = nft_expr_priv(expr);
585
586         if (nft_dump_register(skb, NFTA_CT_DREG, priv->dreg))
587                 goto nla_put_failure;
588         if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key)))
589                 goto nla_put_failure;
590
591         switch (priv->key) {
592         case NFT_CT_SRC:
593         case NFT_CT_DST:
594         case NFT_CT_PROTO_SRC:
595         case NFT_CT_PROTO_DST:
596                 if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
597                         goto nla_put_failure;
598                 break;
599         case NFT_CT_BYTES:
600         case NFT_CT_PKTS:
601         case NFT_CT_AVGPKT:
602         case NFT_CT_ZONE:
603                 if (priv->dir < IP_CT_DIR_MAX &&
604                     nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
605                         goto nla_put_failure;
606                 break;
607         default:
608                 break;
609         }
610
611         return 0;
612
613 nla_put_failure:
614         return -1;
615 }
616
617 static int nft_ct_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
618 {
619         const struct nft_ct *priv = nft_expr_priv(expr);
620
621         if (nft_dump_register(skb, NFTA_CT_SREG, priv->sreg))
622                 goto nla_put_failure;
623         if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key)))
624                 goto nla_put_failure;
625
626         switch (priv->key) {
627         case NFT_CT_ZONE:
628                 if (priv->dir < IP_CT_DIR_MAX &&
629                     nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
630                         goto nla_put_failure;
631                 break;
632         default:
633                 break;
634         }
635
636         return 0;
637
638 nla_put_failure:
639         return -1;
640 }
641
642 static struct nft_expr_type nft_ct_type;
643 static const struct nft_expr_ops nft_ct_get_ops = {
644         .type           = &nft_ct_type,
645         .size           = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
646         .eval           = nft_ct_get_eval,
647         .init           = nft_ct_get_init,
648         .destroy        = nft_ct_get_destroy,
649         .dump           = nft_ct_get_dump,
650 };
651
652 static const struct nft_expr_ops nft_ct_set_ops = {
653         .type           = &nft_ct_type,
654         .size           = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
655         .eval           = nft_ct_set_eval,
656         .init           = nft_ct_set_init,
657         .destroy        = nft_ct_set_destroy,
658         .dump           = nft_ct_set_dump,
659 };
660
661 #ifdef CONFIG_NF_CONNTRACK_ZONES
662 static const struct nft_expr_ops nft_ct_set_zone_ops = {
663         .type           = &nft_ct_type,
664         .size           = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
665         .eval           = nft_ct_set_zone_eval,
666         .init           = nft_ct_set_init,
667         .destroy        = nft_ct_set_destroy,
668         .dump           = nft_ct_set_dump,
669 };
670 #endif
671
672 static const struct nft_expr_ops *
673 nft_ct_select_ops(const struct nft_ctx *ctx,
674                     const struct nlattr * const tb[])
675 {
676         if (tb[NFTA_CT_KEY] == NULL)
677                 return ERR_PTR(-EINVAL);
678
679         if (tb[NFTA_CT_DREG] && tb[NFTA_CT_SREG])
680                 return ERR_PTR(-EINVAL);
681
682         if (tb[NFTA_CT_DREG])
683                 return &nft_ct_get_ops;
684
685         if (tb[NFTA_CT_SREG]) {
686 #ifdef CONFIG_NF_CONNTRACK_ZONES
687                 if (nla_get_be32(tb[NFTA_CT_KEY]) == htonl(NFT_CT_ZONE))
688                         return &nft_ct_set_zone_ops;
689 #endif
690                 return &nft_ct_set_ops;
691         }
692
693         return ERR_PTR(-EINVAL);
694 }
695
696 static struct nft_expr_type nft_ct_type __read_mostly = {
697         .name           = "ct",
698         .select_ops     = &nft_ct_select_ops,
699         .policy         = nft_ct_policy,
700         .maxattr        = NFTA_CT_MAX,
701         .owner          = THIS_MODULE,
702 };
703
704 static void nft_notrack_eval(const struct nft_expr *expr,
705                              struct nft_regs *regs,
706                              const struct nft_pktinfo *pkt)
707 {
708         struct sk_buff *skb = pkt->skb;
709         enum ip_conntrack_info ctinfo;
710         struct nf_conn *ct;
711
712         ct = nf_ct_get(pkt->skb, &ctinfo);
713         /* Previously seen (loopback or untracked)?  Ignore. */
714         if (ct)
715                 return;
716
717         ct = nf_ct_untracked_get();
718         atomic_inc(&ct->ct_general.use);
719         nf_ct_set(skb, ct, IP_CT_NEW);
720 }
721
722 static struct nft_expr_type nft_notrack_type;
723 static const struct nft_expr_ops nft_notrack_ops = {
724         .type           = &nft_notrack_type,
725         .size           = NFT_EXPR_SIZE(0),
726         .eval           = nft_notrack_eval,
727 };
728
729 static struct nft_expr_type nft_notrack_type __read_mostly = {
730         .name           = "notrack",
731         .ops            = &nft_notrack_ops,
732         .owner          = THIS_MODULE,
733 };
734
735 static int __init nft_ct_module_init(void)
736 {
737         int err;
738
739         BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE > NFT_REG_SIZE);
740
741         err = nft_register_expr(&nft_ct_type);
742         if (err < 0)
743                 return err;
744
745         err = nft_register_expr(&nft_notrack_type);
746         if (err < 0)
747                 goto err1;
748
749         return 0;
750 err1:
751         nft_unregister_expr(&nft_ct_type);
752         return err;
753 }
754
755 static void __exit nft_ct_module_exit(void)
756 {
757         nft_unregister_expr(&nft_notrack_type);
758         nft_unregister_expr(&nft_ct_type);
759 }
760
761 module_init(nft_ct_module_init);
762 module_exit(nft_ct_module_exit);
763
764 MODULE_LICENSE("GPL");
765 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
766 MODULE_ALIAS_NFT_EXPR("ct");
767 MODULE_ALIAS_NFT_EXPR("notrack");