]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - net/netfilter/nft_ct.c
netfilter: nf_tables: add bitmap set type
[mirror_ubuntu-bionic-kernel.git] / net / netfilter / nft_ct.c
CommitLineData
96518518 1/*
ef1f7df9 2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
25443261 3 * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org>
96518518
PM
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>
48f66c90 20#include <net/netfilter/nf_conntrack_acct.h>
96518518
PM
21#include <net/netfilter/nf_conntrack_tuple.h>
22#include <net/netfilter/nf_conntrack_helper.h>
c4ede3d3 23#include <net/netfilter/nf_conntrack_ecache.h>
d2bf2f34 24#include <net/netfilter/nf_conntrack_labels.h>
96518518
PM
25
26struct nft_ct {
27 enum nft_ct_keys key:8;
28 enum ip_conntrack_dir dir:8;
d46f2cd2 29 union {
c4ede3d3
KE
30 enum nft_registers dreg:8;
31 enum nft_registers sreg:8;
32 };
96518518
PM
33};
34
48f66c90
FW
35static u64 nft_ct_get_eval_counter(const struct nf_conn_counter *c,
36 enum nft_ct_keys k,
37 enum ip_conntrack_dir d)
38{
39 if (d < IP_CT_DIR_MAX)
40 return k == NFT_CT_BYTES ? atomic64_read(&c[d].bytes) :
41 atomic64_read(&c[d].packets);
42
43 return nft_ct_get_eval_counter(c, k, IP_CT_DIR_ORIGINAL) +
44 nft_ct_get_eval_counter(c, k, IP_CT_DIR_REPLY);
45}
46
c4ede3d3 47static void nft_ct_get_eval(const struct nft_expr *expr,
a55e22e9 48 struct nft_regs *regs,
c4ede3d3 49 const struct nft_pktinfo *pkt)
96518518
PM
50{
51 const struct nft_ct *priv = nft_expr_priv(expr);
49499c3e 52 u32 *dest = &regs->data[priv->dreg];
96518518
PM
53 enum ip_conntrack_info ctinfo;
54 const struct nf_conn *ct;
55 const struct nf_conn_help *help;
56 const struct nf_conntrack_tuple *tuple;
57 const struct nf_conntrack_helper *helper;
96518518
PM
58 unsigned int state;
59
60 ct = nf_ct_get(pkt->skb, &ctinfo);
61
62 switch (priv->key) {
63 case NFT_CT_STATE:
64 if (ct == NULL)
65 state = NF_CT_STATE_INVALID_BIT;
66 else if (nf_ct_is_untracked(ct))
67 state = NF_CT_STATE_UNTRACKED_BIT;
68 else
69 state = NF_CT_STATE_BIT(ctinfo);
fad136ea 70 *dest = state;
96518518 71 return;
c1f86676
DM
72 default:
73 break;
96518518
PM
74 }
75
76 if (ct == NULL)
77 goto err;
78
79 switch (priv->key) {
80 case NFT_CT_DIRECTION:
fad136ea 81 *dest = CTINFO2DIR(ctinfo);
96518518
PM
82 return;
83 case NFT_CT_STATUS:
fad136ea 84 *dest = ct->status;
96518518
PM
85 return;
86#ifdef CONFIG_NF_CONNTRACK_MARK
87 case NFT_CT_MARK:
fad136ea 88 *dest = ct->mark;
96518518
PM
89 return;
90#endif
91#ifdef CONFIG_NF_CONNTRACK_SECMARK
92 case NFT_CT_SECMARK:
fad136ea 93 *dest = ct->secmark;
96518518
PM
94 return;
95#endif
96 case NFT_CT_EXPIRATION:
c8607e02 97 *dest = jiffies_to_msecs(nf_ct_expires(ct));
96518518
PM
98 return;
99 case NFT_CT_HELPER:
100 if (ct->master == NULL)
101 goto err;
102 help = nfct_help(ct->master);
103 if (help == NULL)
104 goto err;
105 helper = rcu_dereference(help->helper);
106 if (helper == NULL)
107 goto err;
fad136ea 108 strncpy((char *)dest, helper->name, NF_CT_HELPER_NAME_LEN);
96518518 109 return;
d2bf2f34
FW
110#ifdef CONFIG_NF_CONNTRACK_LABELS
111 case NFT_CT_LABELS: {
112 struct nf_conn_labels *labels = nf_ct_labels_find(ct);
d2bf2f34 113
23014011
FW
114 if (labels)
115 memcpy(dest, labels->bits, NF_CT_LABELS_MAX_SIZE);
116 else
fad136ea 117 memset(dest, 0, NF_CT_LABELS_MAX_SIZE);
d2bf2f34
FW
118 return;
119 }
efaea94a 120#endif
48f66c90
FW
121 case NFT_CT_BYTES: /* fallthrough */
122 case NFT_CT_PKTS: {
123 const struct nf_conn_acct *acct = nf_conn_acct_find(ct);
124 u64 count = 0;
125
126 if (acct)
127 count = nft_ct_get_eval_counter(acct->counter,
128 priv->key, priv->dir);
129 memcpy(dest, &count, sizeof(count));
130 return;
131 }
949a3584
LZ
132 case NFT_CT_AVGPKT: {
133 const struct nf_conn_acct *acct = nf_conn_acct_find(ct);
134 u64 avgcnt = 0, bcnt = 0, pcnt = 0;
135
136 if (acct) {
137 pcnt = nft_ct_get_eval_counter(acct->counter,
138 NFT_CT_PKTS, priv->dir);
139 bcnt = nft_ct_get_eval_counter(acct->counter,
140 NFT_CT_BYTES, priv->dir);
141 if (pcnt != 0)
142 avgcnt = div64_u64(bcnt, pcnt);
143 }
144
145 memcpy(dest, &avgcnt, sizeof(avgcnt));
146 return;
147 }
d767ff2c
LZ
148 case NFT_CT_L3PROTOCOL:
149 *dest = nf_ct_l3num(ct);
150 return;
151 case NFT_CT_PROTOCOL:
152 *dest = nf_ct_protonum(ct);
153 return;
c1f86676
DM
154 default:
155 break;
96518518
PM
156 }
157
158 tuple = &ct->tuplehash[priv->dir].tuple;
159 switch (priv->key) {
96518518 160 case NFT_CT_SRC:
fad136ea 161 memcpy(dest, tuple->src.u3.all,
96518518
PM
162 nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
163 return;
164 case NFT_CT_DST:
fad136ea 165 memcpy(dest, tuple->dst.u3.all,
96518518
PM
166 nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
167 return;
96518518 168 case NFT_CT_PROTO_SRC:
fad136ea 169 *dest = (__force __u16)tuple->src.u.all;
96518518
PM
170 return;
171 case NFT_CT_PROTO_DST:
fad136ea 172 *dest = (__force __u16)tuple->dst.u.all;
96518518 173 return;
c1f86676
DM
174 default:
175 break;
96518518
PM
176 }
177 return;
178err:
a55e22e9 179 regs->verdict.code = NFT_BREAK;
96518518
PM
180}
181
c4ede3d3 182static void nft_ct_set_eval(const struct nft_expr *expr,
a55e22e9 183 struct nft_regs *regs,
c4ede3d3
KE
184 const struct nft_pktinfo *pkt)
185{
186 const struct nft_ct *priv = nft_expr_priv(expr);
187 struct sk_buff *skb = pkt->skb;
847c8e29 188#ifdef CONFIG_NF_CONNTRACK_MARK
49499c3e 189 u32 value = regs->data[priv->sreg];
847c8e29 190#endif
c4ede3d3
KE
191 enum ip_conntrack_info ctinfo;
192 struct nf_conn *ct;
193
194 ct = nf_ct_get(skb, &ctinfo);
195 if (ct == NULL)
196 return;
197
198 switch (priv->key) {
199#ifdef CONFIG_NF_CONNTRACK_MARK
200 case NFT_CT_MARK:
201 if (ct->mark != value) {
202 ct->mark = value;
203 nf_conntrack_event_cache(IPCT_MARK, ct);
204 }
205 break;
1ad8f48d
FW
206#endif
207#ifdef CONFIG_NF_CONNTRACK_LABELS
208 case NFT_CT_LABELS:
209 nf_connlabels_replace(ct,
210 &regs->data[priv->sreg],
211 &regs->data[priv->sreg],
212 NF_CT_LABELS_MAX_SIZE / sizeof(u32));
213 break;
c4ede3d3 214#endif
c1f86676
DM
215 default:
216 break;
c4ede3d3
KE
217 }
218}
219
96518518
PM
220static const struct nla_policy nft_ct_policy[NFTA_CT_MAX + 1] = {
221 [NFTA_CT_DREG] = { .type = NLA_U32 },
222 [NFTA_CT_KEY] = { .type = NLA_U32 },
223 [NFTA_CT_DIRECTION] = { .type = NLA_U8 },
c4ede3d3 224 [NFTA_CT_SREG] = { .type = NLA_U32 },
96518518
PM
225};
226
ecb2421b 227static int nft_ct_netns_get(struct net *net, uint8_t family)
9638f33e
PM
228{
229 int err;
230
231 if (family == NFPROTO_INET) {
ecb2421b 232 err = nf_ct_netns_get(net, NFPROTO_IPV4);
9638f33e
PM
233 if (err < 0)
234 goto err1;
ecb2421b 235 err = nf_ct_netns_get(net, NFPROTO_IPV6);
9638f33e
PM
236 if (err < 0)
237 goto err2;
238 } else {
ecb2421b 239 err = nf_ct_netns_get(net, family);
9638f33e
PM
240 if (err < 0)
241 goto err1;
242 }
243 return 0;
244
245err2:
ecb2421b 246 nf_ct_netns_put(net, NFPROTO_IPV4);
9638f33e
PM
247err1:
248 return err;
249}
250
ecb2421b 251static void nft_ct_netns_put(struct net *net, uint8_t family)
9638f33e
PM
252{
253 if (family == NFPROTO_INET) {
ecb2421b
FW
254 nf_ct_netns_put(net, NFPROTO_IPV4);
255 nf_ct_netns_put(net, NFPROTO_IPV6);
9638f33e 256 } else
ecb2421b 257 nf_ct_netns_put(net, family);
9638f33e
PM
258}
259
fe92ca45
PM
260static int nft_ct_get_init(const struct nft_ctx *ctx,
261 const struct nft_expr *expr,
262 const struct nlattr * const tb[])
96518518
PM
263{
264 struct nft_ct *priv = nft_expr_priv(expr);
45d9bcda 265 unsigned int len;
fe92ca45 266 int err;
96518518 267
fe92ca45 268 priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
96518518 269 switch (priv->key) {
96518518 270 case NFT_CT_DIRECTION:
45d9bcda
PM
271 if (tb[NFTA_CT_DIRECTION] != NULL)
272 return -EINVAL;
273 len = sizeof(u8);
274 break;
275 case NFT_CT_STATE:
96518518
PM
276 case NFT_CT_STATUS:
277#ifdef CONFIG_NF_CONNTRACK_MARK
278 case NFT_CT_MARK:
279#endif
280#ifdef CONFIG_NF_CONNTRACK_SECMARK
281 case NFT_CT_SECMARK:
d2bf2f34 282#endif
45d9bcda
PM
283 case NFT_CT_EXPIRATION:
284 if (tb[NFTA_CT_DIRECTION] != NULL)
285 return -EINVAL;
286 len = sizeof(u32);
287 break;
d2bf2f34
FW
288#ifdef CONFIG_NF_CONNTRACK_LABELS
289 case NFT_CT_LABELS:
45d9bcda
PM
290 if (tb[NFTA_CT_DIRECTION] != NULL)
291 return -EINVAL;
292 len = NF_CT_LABELS_MAX_SIZE;
293 break;
96518518 294#endif
96518518
PM
295 case NFT_CT_HELPER:
296 if (tb[NFTA_CT_DIRECTION] != NULL)
297 return -EINVAL;
45d9bcda 298 len = NF_CT_HELPER_NAME_LEN;
96518518 299 break;
45d9bcda 300
51292c07 301 case NFT_CT_L3PROTOCOL:
96518518 302 case NFT_CT_PROTOCOL:
d767ff2c
LZ
303 /* For compatibility, do not report error if NFTA_CT_DIRECTION
304 * attribute is specified.
305 */
45d9bcda
PM
306 len = sizeof(u8);
307 break;
96518518
PM
308 case NFT_CT_SRC:
309 case NFT_CT_DST:
45d9bcda
PM
310 if (tb[NFTA_CT_DIRECTION] == NULL)
311 return -EINVAL;
312
313 switch (ctx->afi->family) {
314 case NFPROTO_IPV4:
315 len = FIELD_SIZEOF(struct nf_conntrack_tuple,
316 src.u3.ip);
317 break;
318 case NFPROTO_IPV6:
319 case NFPROTO_INET:
320 len = FIELD_SIZEOF(struct nf_conntrack_tuple,
321 src.u3.ip6);
322 break;
323 default:
324 return -EAFNOSUPPORT;
325 }
326 break;
96518518
PM
327 case NFT_CT_PROTO_SRC:
328 case NFT_CT_PROTO_DST:
329 if (tb[NFTA_CT_DIRECTION] == NULL)
330 return -EINVAL;
45d9bcda 331 len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all);
96518518 332 break;
48f66c90
FW
333 case NFT_CT_BYTES:
334 case NFT_CT_PKTS:
949a3584 335 case NFT_CT_AVGPKT:
48f66c90
FW
336 /* no direction? return sum of original + reply */
337 if (tb[NFTA_CT_DIRECTION] == NULL)
338 priv->dir = IP_CT_DIR_MAX;
339 len = sizeof(u64);
340 break;
96518518
PM
341 default:
342 return -EOPNOTSUPP;
343 }
344
fe92ca45
PM
345 if (tb[NFTA_CT_DIRECTION] != NULL) {
346 priv->dir = nla_get_u8(tb[NFTA_CT_DIRECTION]);
347 switch (priv->dir) {
348 case IP_CT_DIR_ORIGINAL:
349 case IP_CT_DIR_REPLY:
350 break;
351 default:
352 return -EINVAL;
353 }
354 }
355
b1c96ed3 356 priv->dreg = nft_parse_register(tb[NFTA_CT_DREG]);
1ec10212
PM
357 err = nft_validate_register_store(ctx, priv->dreg, NULL,
358 NFT_DATA_VALUE, len);
fe92ca45
PM
359 if (err < 0)
360 return err;
361
ecb2421b 362 err = nft_ct_netns_get(ctx->net, ctx->afi->family);
fe92ca45
PM
363 if (err < 0)
364 return err;
365
949a3584
LZ
366 if (priv->key == NFT_CT_BYTES ||
367 priv->key == NFT_CT_PKTS ||
368 priv->key == NFT_CT_AVGPKT)
3f8b61b7
LZ
369 nf_ct_set_acct(ctx->net, true);
370
c4ede3d3
KE
371 return 0;
372}
373
fe92ca45
PM
374static int nft_ct_set_init(const struct nft_ctx *ctx,
375 const struct nft_expr *expr,
376 const struct nlattr * const tb[])
c4ede3d3 377{
fe92ca45 378 struct nft_ct *priv = nft_expr_priv(expr);
590025a2 379 bool label_got = false;
d07db988 380 unsigned int len;
fe92ca45
PM
381 int err;
382
383 priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
384 switch (priv->key) {
e88e514e 385#ifdef CONFIG_NF_CONNTRACK_MARK
c4ede3d3 386 case NFT_CT_MARK:
7bfdde70
LZ
387 if (tb[NFTA_CT_DIRECTION])
388 return -EINVAL;
d07db988 389 len = FIELD_SIZEOF(struct nf_conn, mark);
c4ede3d3 390 break;
1ad8f48d
FW
391#endif
392#ifdef CONFIG_NF_CONNTRACK_LABELS
393 case NFT_CT_LABELS:
394 if (tb[NFTA_CT_DIRECTION])
395 return -EINVAL;
396 len = NF_CT_LABELS_MAX_SIZE;
397 err = nf_connlabels_get(ctx->net, (len * BITS_PER_BYTE) - 1);
398 if (err)
399 return err;
590025a2 400 label_got = true;
1ad8f48d 401 break;
e88e514e 402#endif
c4ede3d3
KE
403 default:
404 return -EOPNOTSUPP;
405 }
406
b1c96ed3 407 priv->sreg = nft_parse_register(tb[NFTA_CT_SREG]);
d07db988 408 err = nft_validate_register_load(priv->sreg, len);
fe92ca45 409 if (err < 0)
590025a2 410 goto err1;
c4ede3d3 411
ecb2421b 412 err = nft_ct_netns_get(ctx->net, ctx->afi->family);
96518518 413 if (err < 0)
590025a2 414 goto err1;
96518518 415
96518518 416 return 0;
590025a2
LZ
417
418err1:
419 if (label_got)
420 nf_connlabels_put(ctx->net);
421 return err;
422}
423
424static void nft_ct_get_destroy(const struct nft_ctx *ctx,
425 const struct nft_expr *expr)
426{
ecb2421b 427 nf_ct_netns_put(ctx->net, ctx->afi->family);
96518518
PM
428}
429
590025a2
LZ
430static void nft_ct_set_destroy(const struct nft_ctx *ctx,
431 const struct nft_expr *expr)
96518518 432{
1ad8f48d
FW
433 struct nft_ct *priv = nft_expr_priv(expr);
434
435 switch (priv->key) {
436#ifdef CONFIG_NF_CONNTRACK_LABELS
437 case NFT_CT_LABELS:
438 nf_connlabels_put(ctx->net);
439 break;
440#endif
441 default:
442 break;
443 }
444
ecb2421b 445 nft_ct_netns_put(ctx->net, ctx->afi->family);
96518518
PM
446}
447
c4ede3d3 448static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
96518518
PM
449{
450 const struct nft_ct *priv = nft_expr_priv(expr);
451
b1c96ed3 452 if (nft_dump_register(skb, NFTA_CT_DREG, priv->dreg))
96518518
PM
453 goto nla_put_failure;
454 if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key)))
455 goto nla_put_failure;
2a53bfb3
AB
456
457 switch (priv->key) {
2a53bfb3
AB
458 case NFT_CT_SRC:
459 case NFT_CT_DST:
460 case NFT_CT_PROTO_SRC:
461 case NFT_CT_PROTO_DST:
462 if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
463 goto nla_put_failure;
48f66c90
FW
464 break;
465 case NFT_CT_BYTES:
466 case NFT_CT_PKTS:
949a3584 467 case NFT_CT_AVGPKT:
48f66c90
FW
468 if (priv->dir < IP_CT_DIR_MAX &&
469 nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
470 goto nla_put_failure;
471 break;
2a53bfb3
AB
472 default:
473 break;
474 }
475
96518518
PM
476 return 0;
477
478nla_put_failure:
479 return -1;
480}
481
c4ede3d3
KE
482static int nft_ct_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
483{
484 const struct nft_ct *priv = nft_expr_priv(expr);
485
b1c96ed3 486 if (nft_dump_register(skb, NFTA_CT_SREG, priv->sreg))
c4ede3d3
KE
487 goto nla_put_failure;
488 if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key)))
489 goto nla_put_failure;
490 return 0;
491
492nla_put_failure:
493 return -1;
494}
495
ef1f7df9 496static struct nft_expr_type nft_ct_type;
c4ede3d3 497static const struct nft_expr_ops nft_ct_get_ops = {
ef1f7df9 498 .type = &nft_ct_type,
96518518 499 .size = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
c4ede3d3 500 .eval = nft_ct_get_eval,
fe92ca45 501 .init = nft_ct_get_init,
590025a2 502 .destroy = nft_ct_get_destroy,
c4ede3d3 503 .dump = nft_ct_get_dump,
ef1f7df9
PM
504};
505
c4ede3d3
KE
506static const struct nft_expr_ops nft_ct_set_ops = {
507 .type = &nft_ct_type,
508 .size = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
509 .eval = nft_ct_set_eval,
fe92ca45 510 .init = nft_ct_set_init,
590025a2 511 .destroy = nft_ct_set_destroy,
c4ede3d3
KE
512 .dump = nft_ct_set_dump,
513};
514
515static const struct nft_expr_ops *
516nft_ct_select_ops(const struct nft_ctx *ctx,
517 const struct nlattr * const tb[])
518{
519 if (tb[NFTA_CT_KEY] == NULL)
520 return ERR_PTR(-EINVAL);
521
522 if (tb[NFTA_CT_DREG] && tb[NFTA_CT_SREG])
523 return ERR_PTR(-EINVAL);
524
525 if (tb[NFTA_CT_DREG])
526 return &nft_ct_get_ops;
527
528 if (tb[NFTA_CT_SREG])
529 return &nft_ct_set_ops;
530
531 return ERR_PTR(-EINVAL);
532}
533
ef1f7df9
PM
534static struct nft_expr_type nft_ct_type __read_mostly = {
535 .name = "ct",
c4ede3d3 536 .select_ops = &nft_ct_select_ops,
96518518
PM
537 .policy = nft_ct_policy,
538 .maxattr = NFTA_CT_MAX,
ef1f7df9 539 .owner = THIS_MODULE,
96518518
PM
540};
541
25443261
PNA
542static void nft_notrack_eval(const struct nft_expr *expr,
543 struct nft_regs *regs,
544 const struct nft_pktinfo *pkt)
545{
546 struct sk_buff *skb = pkt->skb;
547 enum ip_conntrack_info ctinfo;
548 struct nf_conn *ct;
549
550 ct = nf_ct_get(pkt->skb, &ctinfo);
551 /* Previously seen (loopback or untracked)? Ignore. */
552 if (ct)
553 return;
554
555 ct = nf_ct_untracked_get();
556 atomic_inc(&ct->ct_general.use);
c74454fa 557 nf_ct_set(skb, ct, IP_CT_NEW);
25443261
PNA
558}
559
560static struct nft_expr_type nft_notrack_type;
561static const struct nft_expr_ops nft_notrack_ops = {
562 .type = &nft_notrack_type,
563 .size = NFT_EXPR_SIZE(0),
564 .eval = nft_notrack_eval,
565};
566
567static struct nft_expr_type nft_notrack_type __read_mostly = {
568 .name = "notrack",
569 .ops = &nft_notrack_ops,
570 .owner = THIS_MODULE,
571};
572
96518518
PM
573static int __init nft_ct_module_init(void)
574{
25443261
PNA
575 int err;
576
adff6c65
FW
577 BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE > NFT_REG_SIZE);
578
25443261
PNA
579 err = nft_register_expr(&nft_ct_type);
580 if (err < 0)
581 return err;
582
583 err = nft_register_expr(&nft_notrack_type);
584 if (err < 0)
585 goto err1;
586
587 return 0;
588err1:
589 nft_unregister_expr(&nft_ct_type);
590 return err;
96518518
PM
591}
592
593static void __exit nft_ct_module_exit(void)
594{
25443261 595 nft_unregister_expr(&nft_notrack_type);
ef1f7df9 596 nft_unregister_expr(&nft_ct_type);
96518518
PM
597}
598
599module_init(nft_ct_module_init);
600module_exit(nft_ct_module_exit);
601
602MODULE_LICENSE("GPL");
603MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
604MODULE_ALIAS_NFT_EXPR("ct");
25443261 605MODULE_ALIAS_NFT_EXPR("notrack");