196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy/*
2ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardy * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
309d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso * Copyright (c) 2012-2014 Pablo Neira Ayuso <pablo@netfilter.org>
496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy *
596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy * This program is free software; you can redistribute it and/or modify
696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy * it under the terms of the GNU General Public License version 2 as
796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy * published by the Free Software Foundation.
896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy *
996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy * Development of this code funded by Astaro AG (http://www.astaro.com/)
1096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy */
1196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
1296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <linux/kernel.h>
1396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <linux/init.h>
1496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <linux/module.h>
1596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <linux/netlink.h>
1696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <linux/netfilter.h>
1796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <linux/netfilter/nf_tables.h>
1896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <net/netfilter/nf_tables.h>
1996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <net/netfilter/nf_log.h>
2096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <linux/netdevice.h>
2196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
2296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardystatic const char *nft_log_null_prefix = "";
2396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
2496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardystruct nft_log {
2596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	struct nf_loginfo	loginfo;
2696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	char			*prefix;
2796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy};
2896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
2996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardystatic void nft_log_eval(const struct nft_expr *expr,
3096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy			 struct nft_data data[NFT_REG_MAX + 1],
3196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy			 const struct nft_pktinfo *pkt)
3296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy{
3396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	const struct nft_log *priv = nft_expr_priv(expr);
3496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
3596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
36b8ecbee67c732ef9fc47fcf50aed6b7bb6231d98Patrick McHardy	nf_log_packet(net, pkt->ops->pf, pkt->ops->hooknum, pkt->skb, pkt->in,
3796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy		      pkt->out, &priv->loginfo, "%s", priv->prefix);
3896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy}
3996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
4096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardystatic const struct nla_policy nft_log_policy[NFTA_LOG_MAX + 1] = {
4196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	[NFTA_LOG_GROUP]	= { .type = NLA_U16 },
4296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	[NFTA_LOG_PREFIX]	= { .type = NLA_STRING },
4396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	[NFTA_LOG_SNAPLEN]	= { .type = NLA_U32 },
4496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	[NFTA_LOG_QTHRESHOLD]	= { .type = NLA_U16 },
4509d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	[NFTA_LOG_LEVEL]	= { .type = NLA_U32 },
4609d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	[NFTA_LOG_FLAGS]	= { .type = NLA_U32 },
4796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy};
4896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
4996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardystatic int nft_log_init(const struct nft_ctx *ctx,
5096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy			const struct nft_expr *expr,
5196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy			const struct nlattr * const tb[])
5296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy{
5396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	struct nft_log *priv = nft_expr_priv(expr);
5496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	struct nf_loginfo *li = &priv->loginfo;
5596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	const struct nlattr *nla;
5685d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso	int ret;
5796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
5896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	nla = tb[NFTA_LOG_PREFIX];
5996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	if (nla != NULL) {
6096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy		priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL);
6196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy		if (priv->prefix == NULL)
6296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy			return -ENOMEM;
6396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy		nla_strlcpy(priv->prefix, nla, nla_len(nla) + 1);
6409d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	} else {
6596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy		priv->prefix = (char *)nft_log_null_prefix;
6609d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	}
6796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
6809d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	li->type = NF_LOG_TYPE_LOG;
6909d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	if (tb[NFTA_LOG_LEVEL] != NULL &&
7009d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	    tb[NFTA_LOG_GROUP] != NULL)
7109d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		return -EINVAL;
7296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	if (tb[NFTA_LOG_GROUP] != NULL)
7309d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		li->type = NF_LOG_TYPE_ULOG;
7409d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso
7509d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	switch (li->type) {
7609d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	case NF_LOG_TYPE_LOG:
7709d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		if (tb[NFTA_LOG_LEVEL] != NULL) {
7809d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso			li->u.log.level =
795cbfda2043814f4989efad12be02086a2e4c59fdFengguang Wu				ntohl(nla_get_be32(tb[NFTA_LOG_LEVEL]));
8009d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		} else {
8109d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso			li->u.log.level = 4;
8209d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		}
8309d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		if (tb[NFTA_LOG_FLAGS] != NULL) {
8409d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso			li->u.log.logflags =
8509d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso				ntohl(nla_get_be32(tb[NFTA_LOG_FLAGS]));
8609d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		}
8709d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		break;
8809d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	case NF_LOG_TYPE_ULOG:
8996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy		li->u.ulog.group = ntohs(nla_get_be16(tb[NFTA_LOG_GROUP]));
9009d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		if (tb[NFTA_LOG_SNAPLEN] != NULL) {
9109d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso			li->u.ulog.copy_len =
9209d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso				ntohl(nla_get_be32(tb[NFTA_LOG_SNAPLEN]));
9309d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		}
9409d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		if (tb[NFTA_LOG_QTHRESHOLD] != NULL) {
9509d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso			li->u.ulog.qthreshold =
9609d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso				ntohs(nla_get_be16(tb[NFTA_LOG_QTHRESHOLD]));
9709d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		}
9809d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		break;
9996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	}
10096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
10185d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso	if (ctx->afi->family == NFPROTO_INET) {
10285d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso		ret = nf_logger_find_get(NFPROTO_IPV4, li->type);
10385d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso		if (ret < 0)
10485d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso			return ret;
10585d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso
10685d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso		ret = nf_logger_find_get(NFPROTO_IPV6, li->type);
10785d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso		if (ret < 0) {
10885d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso			nf_logger_put(NFPROTO_IPV4, li->type);
10985d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso			return ret;
11085d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso		}
11185d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso		return 0;
11285d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso	}
11385d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso
11485d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso	return nf_logger_find_get(ctx->afi->family, li->type);
11596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy}
11696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
11762472bcefb56ae9c3a6be3284949ce758656cdecPatrick McHardystatic void nft_log_destroy(const struct nft_ctx *ctx,
11862472bcefb56ae9c3a6be3284949ce758656cdecPatrick McHardy			    const struct nft_expr *expr)
11996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy{
12096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	struct nft_log *priv = nft_expr_priv(expr);
12185d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso	struct nf_loginfo *li = &priv->loginfo;
12296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
12396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	if (priv->prefix != nft_log_null_prefix)
12496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy		kfree(priv->prefix);
12585d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso
12685d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso	if (ctx->afi->family == NFPROTO_INET) {
12785d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso		nf_logger_put(NFPROTO_IPV4, li->type);
12885d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso		nf_logger_put(NFPROTO_IPV6, li->type);
12985d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso	} else {
13085d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso		nf_logger_put(ctx->afi->family, li->type);
13185d30e24166e86686aa2d805e2ef1fa8d770852cPablo Neira Ayuso	}
13296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy}
13396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
13496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardystatic int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr)
13596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy{
13696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	const struct nft_log *priv = nft_expr_priv(expr);
13796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	const struct nf_loginfo *li = &priv->loginfo;
13896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
13996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	if (priv->prefix != nft_log_null_prefix)
14096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy		if (nla_put_string(skb, NFTA_LOG_PREFIX, priv->prefix))
14196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy			goto nla_put_failure;
14209d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	switch (li->type) {
14309d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	case NF_LOG_TYPE_LOG:
14409d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		if (nla_put_be32(skb, NFTA_LOG_LEVEL, htonl(li->u.log.level)))
14596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy			goto nla_put_failure;
14609d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso
14709d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		if (li->u.log.logflags) {
14809d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso			if (nla_put_be32(skb, NFTA_LOG_FLAGS,
14909d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso					 htonl(li->u.log.logflags)))
15009d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso				goto nla_put_failure;
15109d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		}
15209d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		break;
15309d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	case NF_LOG_TYPE_ULOG:
15409d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		if (nla_put_be16(skb, NFTA_LOG_GROUP, htons(li->u.ulog.group)))
15596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy			goto nla_put_failure;
15609d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso
15709d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		if (li->u.ulog.copy_len) {
15809d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso			if (nla_put_be32(skb, NFTA_LOG_SNAPLEN,
15909d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso					 htonl(li->u.ulog.copy_len)))
16009d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso				goto nla_put_failure;
16109d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		}
16209d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		if (li->u.ulog.qthreshold) {
16309d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso			if (nla_put_be16(skb, NFTA_LOG_QTHRESHOLD,
16409d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso					 htons(li->u.ulog.qthreshold)))
16509d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso				goto nla_put_failure;
16609d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		}
16709d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso		break;
16809d27b88f15f08fcfbaf57d9b0b4489816264815Pablo Neira Ayuso	}
16996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	return 0;
17096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
17196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardynla_put_failure:
17296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	return -1;
17396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy}
17496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
175ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardystatic struct nft_expr_type nft_log_type;
176ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardystatic const struct nft_expr_ops nft_log_ops = {
177ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardy	.type		= &nft_log_type,
17896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	.size		= NFT_EXPR_SIZE(sizeof(struct nft_log)),
17996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	.eval		= nft_log_eval,
18096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	.init		= nft_log_init,
18196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	.destroy	= nft_log_destroy,
18296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	.dump		= nft_log_dump,
183ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardy};
184ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardy
185ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardystatic struct nft_expr_type nft_log_type __read_mostly = {
186ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardy	.name		= "log",
187ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardy	.ops		= &nft_log_ops,
18896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	.policy		= nft_log_policy,
18996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	.maxattr	= NFTA_LOG_MAX,
190ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardy	.owner		= THIS_MODULE,
19196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy};
19296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
19396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardystatic int __init nft_log_module_init(void)
19496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy{
195ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardy	return nft_register_expr(&nft_log_type);
19696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy}
19796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
19896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardystatic void __exit nft_log_module_exit(void)
19996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy{
200ef1f7df9170dbd875ce198ba84e6ab80f6fc139ePatrick McHardy	nft_unregister_expr(&nft_log_type);
20196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy}
20296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
20396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardymodule_init(nft_log_module_init);
20496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardymodule_exit(nft_log_module_exit);
20596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
20696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardyMODULE_LICENSE("GPL");
20796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardyMODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
20896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardyMODULE_ALIAS_NFT_EXPR("log");
209