diff options
| author | David S. Miller <davem@davemloft.net> | 2014-01-06 13:29:30 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-01-06 13:29:30 -0500 |
| commit | 9aa28f2b71055d5ae17a2e1daee359d4174bb13e (patch) | |
| tree | fbf4e0fd11eb924e0bece74a87f442bc54441b35 /net/ipv4 | |
| parent | 6a8c4796df74045088a916581c736432d08c53c0 (diff) | |
| parent | c9c8e485978a308c8a359140da187d55120f8fee (diff) | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nftables
Pablo Neira Ayuso says: <pablo@netfilter.org>
====================
nftables updates for net-next
The following patchset contains nftables updates for your net-next tree,
they are:
* Add set operation to the meta expression by means of the select_ops()
infrastructure, this allows us to set the packet mark among other things.
From Arturo Borrero Gonzalez.
* Fix wrong format in sscanf in nf_tables_set_alloc_name(), from Daniel
Borkmann.
* Add new queue expression to nf_tables. These comes with two previous patches
to prepare this new feature, one to add mask in nf_tables_core to
evaluate the queue verdict appropriately and another to refactor common
code with xt_NFQUEUE, from Eric Leblond.
* Do not hide nftables from Kconfig if nfnetlink is not enabled, also from
Eric Leblond.
* Add the reject expression to nf_tables, this adds the missing TCP RST
support. It comes with an initial patch to refactor common code with
xt_NFQUEUE, again from Eric Leblond.
* Remove an unused variable assignment in nf_tables_dump_set(), from Michal
Nazarewicz.
* Remove the nft_meta_target code, now that Arturo added the set operation
to the meta expression, from me.
* Add help information for nf_tables to Kconfig, also from me.
* Allow to dump all sets by specifying NFPROTO_UNSPEC, similar feature is
available to other nf_tables objects, requested by Arturo, from me.
* Expose the table usage counter, so we can know how many chains are using
this table without dumping the list of chains, from Tomasz Bursztyka.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/netfilter/Kconfig | 18 | ||||
| -rw-r--r-- | net/ipv4/netfilter/Makefile | 1 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ipt_REJECT.c | 140 | ||||
| -rw-r--r-- | net/ipv4/netfilter/nft_reject_ipv4.c | 123 |
4 files changed, 24 insertions, 258 deletions
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 40d56073cd19..81c6910cfa92 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
| @@ -39,23 +39,33 @@ config NF_CONNTRACK_PROC_COMPAT | |||
| 39 | config NF_TABLES_IPV4 | 39 | config NF_TABLES_IPV4 |
| 40 | depends on NF_TABLES | 40 | depends on NF_TABLES |
| 41 | tristate "IPv4 nf_tables support" | 41 | tristate "IPv4 nf_tables support" |
| 42 | 42 | help | |
| 43 | config NFT_REJECT_IPV4 | 43 | This option enables the IPv4 support for nf_tables. |
| 44 | depends on NF_TABLES_IPV4 | ||
| 45 | tristate "nf_tables IPv4 reject support" | ||
| 46 | 44 | ||
| 47 | config NFT_CHAIN_ROUTE_IPV4 | 45 | config NFT_CHAIN_ROUTE_IPV4 |
| 48 | depends on NF_TABLES_IPV4 | 46 | depends on NF_TABLES_IPV4 |
| 49 | tristate "IPv4 nf_tables route chain support" | 47 | tristate "IPv4 nf_tables route chain support" |
| 48 | help | ||
| 49 | This option enables the "route" chain for IPv4 in nf_tables. This | ||
| 50 | chain type is used to force packet re-routing after mangling header | ||
| 51 | fields such as the source, destination, type of service and | ||
| 52 | the packet mark. | ||
| 50 | 53 | ||
| 51 | config NFT_CHAIN_NAT_IPV4 | 54 | config NFT_CHAIN_NAT_IPV4 |
| 52 | depends on NF_TABLES_IPV4 | 55 | depends on NF_TABLES_IPV4 |
| 53 | depends on NF_NAT_IPV4 && NFT_NAT | 56 | depends on NF_NAT_IPV4 && NFT_NAT |
| 54 | tristate "IPv4 nf_tables nat chain support" | 57 | tristate "IPv4 nf_tables nat chain support" |
| 58 | help | ||
| 59 | This option enables the "nat" chain for IPv4 in nf_tables. This | ||
| 60 | chain type is used to perform Network Address Translation (NAT) | ||
| 61 | packet transformations such as the source, destination address and | ||
| 62 | source and destination ports. | ||
| 55 | 63 | ||
| 56 | config NF_TABLES_ARP | 64 | config NF_TABLES_ARP |
| 57 | depends on NF_TABLES | 65 | depends on NF_TABLES |
| 58 | tristate "ARP nf_tables support" | 66 | tristate "ARP nf_tables support" |
| 67 | help | ||
| 68 | This option enables the ARP support for nf_tables. | ||
| 59 | 69 | ||
| 60 | config IP_NF_IPTABLES | 70 | config IP_NF_IPTABLES |
| 61 | tristate "IP tables support (required for filtering/masq/NAT)" | 71 | tristate "IP tables support (required for filtering/masq/NAT)" |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 19df72b7ba88..c16be9d58420 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
| @@ -28,7 +28,6 @@ obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o | |||
| 28 | obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o | 28 | obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o |
| 29 | 29 | ||
| 30 | obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o | 30 | obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o |
| 31 | obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o | ||
| 32 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o | 31 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o |
| 33 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o | 32 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o |
| 34 | obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o | 33 | obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index b969131ad1c1..5b6e0df4ccff 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
| @@ -17,10 +17,6 @@ | |||
| 17 | #include <linux/udp.h> | 17 | #include <linux/udp.h> |
| 18 | #include <linux/icmp.h> | 18 | #include <linux/icmp.h> |
| 19 | #include <net/icmp.h> | 19 | #include <net/icmp.h> |
| 20 | #include <net/ip.h> | ||
| 21 | #include <net/tcp.h> | ||
| 22 | #include <net/route.h> | ||
| 23 | #include <net/dst.h> | ||
| 24 | #include <linux/netfilter/x_tables.h> | 20 | #include <linux/netfilter/x_tables.h> |
| 25 | #include <linux/netfilter_ipv4/ip_tables.h> | 21 | #include <linux/netfilter_ipv4/ip_tables.h> |
| 26 | #include <linux/netfilter_ipv4/ipt_REJECT.h> | 22 | #include <linux/netfilter_ipv4/ipt_REJECT.h> |
| @@ -28,128 +24,12 @@ | |||
| 28 | #include <linux/netfilter_bridge.h> | 24 | #include <linux/netfilter_bridge.h> |
| 29 | #endif | 25 | #endif |
| 30 | 26 | ||
| 27 | #include <net/netfilter/ipv4/nf_reject.h> | ||
| 28 | |||
| 31 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
| 32 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 30 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
| 33 | MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv4"); | 31 | MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv4"); |
| 34 | 32 | ||
| 35 | /* Send RST reply */ | ||
| 36 | static void send_reset(struct sk_buff *oldskb, int hook) | ||
| 37 | { | ||
| 38 | struct sk_buff *nskb; | ||
| 39 | const struct iphdr *oiph; | ||
| 40 | struct iphdr *niph; | ||
| 41 | const struct tcphdr *oth; | ||
| 42 | struct tcphdr _otcph, *tcph; | ||
| 43 | |||
| 44 | /* IP header checks: fragment. */ | ||
| 45 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) | ||
| 46 | return; | ||
| 47 | |||
| 48 | oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb), | ||
| 49 | sizeof(_otcph), &_otcph); | ||
| 50 | if (oth == NULL) | ||
| 51 | return; | ||
| 52 | |||
| 53 | /* No RST for RST. */ | ||
| 54 | if (oth->rst) | ||
| 55 | return; | ||
| 56 | |||
| 57 | if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) | ||
| 58 | return; | ||
| 59 | |||
| 60 | /* Check checksum */ | ||
| 61 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) | ||
| 62 | return; | ||
| 63 | oiph = ip_hdr(oldskb); | ||
| 64 | |||
| 65 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) + | ||
| 66 | LL_MAX_HEADER, GFP_ATOMIC); | ||
| 67 | if (!nskb) | ||
| 68 | return; | ||
| 69 | |||
| 70 | skb_reserve(nskb, LL_MAX_HEADER); | ||
| 71 | |||
| 72 | skb_reset_network_header(nskb); | ||
| 73 | niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr)); | ||
| 74 | niph->version = 4; | ||
| 75 | niph->ihl = sizeof(struct iphdr) / 4; | ||
| 76 | niph->tos = 0; | ||
| 77 | niph->id = 0; | ||
| 78 | niph->frag_off = htons(IP_DF); | ||
| 79 | niph->protocol = IPPROTO_TCP; | ||
| 80 | niph->check = 0; | ||
| 81 | niph->saddr = oiph->daddr; | ||
| 82 | niph->daddr = oiph->saddr; | ||
| 83 | |||
| 84 | skb_reset_transport_header(nskb); | ||
| 85 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); | ||
| 86 | memset(tcph, 0, sizeof(*tcph)); | ||
| 87 | tcph->source = oth->dest; | ||
| 88 | tcph->dest = oth->source; | ||
| 89 | tcph->doff = sizeof(struct tcphdr) / 4; | ||
| 90 | |||
| 91 | if (oth->ack) | ||
| 92 | tcph->seq = oth->ack_seq; | ||
| 93 | else { | ||
| 94 | tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + | ||
| 95 | oldskb->len - ip_hdrlen(oldskb) - | ||
| 96 | (oth->doff << 2)); | ||
| 97 | tcph->ack = 1; | ||
| 98 | } | ||
| 99 | |||
| 100 | tcph->rst = 1; | ||
| 101 | tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr, | ||
| 102 | niph->daddr, 0); | ||
| 103 | nskb->ip_summed = CHECKSUM_PARTIAL; | ||
| 104 | nskb->csum_start = (unsigned char *)tcph - nskb->head; | ||
| 105 | nskb->csum_offset = offsetof(struct tcphdr, check); | ||
| 106 | |||
| 107 | /* ip_route_me_harder expects skb->dst to be set */ | ||
| 108 | skb_dst_set_noref(nskb, skb_dst(oldskb)); | ||
| 109 | |||
| 110 | nskb->protocol = htons(ETH_P_IP); | ||
| 111 | if (ip_route_me_harder(nskb, RTN_UNSPEC)) | ||
| 112 | goto free_nskb; | ||
| 113 | |||
| 114 | niph->ttl = ip4_dst_hoplimit(skb_dst(nskb)); | ||
| 115 | |||
| 116 | /* "Never happens" */ | ||
| 117 | if (nskb->len > dst_mtu(skb_dst(nskb))) | ||
| 118 | goto free_nskb; | ||
| 119 | |||
| 120 | nf_ct_attach(nskb, oldskb); | ||
| 121 | |||
| 122 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
| 123 | /* If we use ip_local_out for bridged traffic, the MAC source on | ||
| 124 | * the RST will be ours, instead of the destination's. This confuses | ||
| 125 | * some routers/firewalls, and they drop the packet. So we need to | ||
| 126 | * build the eth header using the original destination's MAC as the | ||
| 127 | * source, and send the RST packet directly. | ||
| 128 | */ | ||
| 129 | if (oldskb->nf_bridge) { | ||
| 130 | struct ethhdr *oeth = eth_hdr(oldskb); | ||
| 131 | nskb->dev = oldskb->nf_bridge->physindev; | ||
| 132 | niph->tot_len = htons(nskb->len); | ||
| 133 | ip_send_check(niph); | ||
| 134 | if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol), | ||
| 135 | oeth->h_source, oeth->h_dest, nskb->len) < 0) | ||
| 136 | goto free_nskb; | ||
| 137 | dev_queue_xmit(nskb); | ||
| 138 | } else | ||
| 139 | #endif | ||
| 140 | ip_local_out(nskb); | ||
| 141 | |||
| 142 | return; | ||
| 143 | |||
| 144 | free_nskb: | ||
| 145 | kfree_skb(nskb); | ||
| 146 | } | ||
| 147 | |||
| 148 | static inline void send_unreach(struct sk_buff *skb_in, int code) | ||
| 149 | { | ||
| 150 | icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); | ||
| 151 | } | ||
| 152 | |||
| 153 | static unsigned int | 33 | static unsigned int |
| 154 | reject_tg(struct sk_buff *skb, const struct xt_action_param *par) | 34 | reject_tg(struct sk_buff *skb, const struct xt_action_param *par) |
| 155 | { | 35 | { |
| @@ -157,28 +37,28 @@ reject_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 157 | 37 | ||
| 158 | switch (reject->with) { | 38 | switch (reject->with) { |
| 159 | case IPT_ICMP_NET_UNREACHABLE: | 39 | case IPT_ICMP_NET_UNREACHABLE: |
| 160 | send_unreach(skb, ICMP_NET_UNREACH); | 40 | nf_send_unreach(skb, ICMP_NET_UNREACH); |
| 161 | break; | 41 | break; |
| 162 | case IPT_ICMP_HOST_UNREACHABLE: | 42 | case IPT_ICMP_HOST_UNREACHABLE: |
| 163 | send_unreach(skb, ICMP_HOST_UNREACH); | 43 | nf_send_unreach(skb, ICMP_HOST_UNREACH); |
| 164 | break; | 44 | break; |
| 165 | case IPT_ICMP_PROT_UNREACHABLE: | 45 | case IPT_ICMP_PROT_UNREACHABLE: |
| 166 | send_unreach(skb, ICMP_PROT_UNREACH); | 46 | nf_send_unreach(skb, ICMP_PROT_UNREACH); |
| 167 | break; | 47 | break; |
| 168 | case IPT_ICMP_PORT_UNREACHABLE: | 48 | case IPT_ICMP_PORT_UNREACHABLE: |
| 169 | send_unreach(skb, ICMP_PORT_UNREACH); | 49 | nf_send_unreach(skb, ICMP_PORT_UNREACH); |
| 170 | break; | 50 | break; |
| 171 | case IPT_ICMP_NET_PROHIBITED: | 51 | case IPT_ICMP_NET_PROHIBITED: |
| 172 | send_unreach(skb, ICMP_NET_ANO); | 52 | nf_send_unreach(skb, ICMP_NET_ANO); |
| 173 | break; | 53 | break; |
| 174 | case IPT_ICMP_HOST_PROHIBITED: | 54 | case IPT_ICMP_HOST_PROHIBITED: |
| 175 | send_unreach(skb, ICMP_HOST_ANO); | 55 | nf_send_unreach(skb, ICMP_HOST_ANO); |
| 176 | break; | 56 | break; |
| 177 | case IPT_ICMP_ADMIN_PROHIBITED: | 57 | case IPT_ICMP_ADMIN_PROHIBITED: |
| 178 | send_unreach(skb, ICMP_PKT_FILTERED); | 58 | nf_send_unreach(skb, ICMP_PKT_FILTERED); |
| 179 | break; | 59 | break; |
| 180 | case IPT_TCP_RESET: | 60 | case IPT_TCP_RESET: |
| 181 | send_reset(skb, par->hooknum); | 61 | nf_send_reset(skb, par->hooknum); |
| 182 | case IPT_ICMP_ECHOREPLY: | 62 | case IPT_ICMP_ECHOREPLY: |
| 183 | /* Doesn't happen. */ | 63 | /* Doesn't happen. */ |
| 184 | break; | 64 | break; |
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c deleted file mode 100644 index 4a5e94ac314a..000000000000 --- a/net/ipv4/netfilter/nft_reject_ipv4.c +++ /dev/null | |||
| @@ -1,123 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/netlink.h> | ||
| 15 | #include <linux/netfilter.h> | ||
| 16 | #include <linux/netfilter/nf_tables.h> | ||
| 17 | #include <net/netfilter/nf_tables.h> | ||
| 18 | #include <net/icmp.h> | ||
| 19 | |||
| 20 | struct nft_reject { | ||
| 21 | enum nft_reject_types type:8; | ||
| 22 | u8 icmp_code; | ||
| 23 | }; | ||
| 24 | |||
| 25 | static void nft_reject_eval(const struct nft_expr *expr, | ||
| 26 | struct nft_data data[NFT_REG_MAX + 1], | ||
| 27 | const struct nft_pktinfo *pkt) | ||
| 28 | { | ||
| 29 | struct nft_reject *priv = nft_expr_priv(expr); | ||
| 30 | |||
| 31 | switch (priv->type) { | ||
| 32 | case NFT_REJECT_ICMP_UNREACH: | ||
| 33 | icmp_send(pkt->skb, ICMP_DEST_UNREACH, priv->icmp_code, 0); | ||
| 34 | break; | ||
| 35 | case NFT_REJECT_TCP_RST: | ||
| 36 | break; | ||
| 37 | } | ||
| 38 | |||
| 39 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
| 40 | } | ||
| 41 | |||
| 42 | static const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = { | ||
| 43 | [NFTA_REJECT_TYPE] = { .type = NLA_U32 }, | ||
| 44 | [NFTA_REJECT_ICMP_CODE] = { .type = NLA_U8 }, | ||
| 45 | }; | ||
| 46 | |||
| 47 | static int nft_reject_init(const struct nft_ctx *ctx, | ||
| 48 | const struct nft_expr *expr, | ||
| 49 | const struct nlattr * const tb[]) | ||
| 50 | { | ||
| 51 | struct nft_reject *priv = nft_expr_priv(expr); | ||
| 52 | |||
| 53 | if (tb[NFTA_REJECT_TYPE] == NULL) | ||
| 54 | return -EINVAL; | ||
| 55 | |||
| 56 | priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE])); | ||
| 57 | switch (priv->type) { | ||
| 58 | case NFT_REJECT_ICMP_UNREACH: | ||
| 59 | if (tb[NFTA_REJECT_ICMP_CODE] == NULL) | ||
| 60 | return -EINVAL; | ||
| 61 | priv->icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]); | ||
| 62 | case NFT_REJECT_TCP_RST: | ||
| 63 | break; | ||
| 64 | default: | ||
| 65 | return -EINVAL; | ||
| 66 | } | ||
| 67 | |||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) | ||
| 72 | { | ||
| 73 | const struct nft_reject *priv = nft_expr_priv(expr); | ||
| 74 | |||
| 75 | if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type))) | ||
| 76 | goto nla_put_failure; | ||
| 77 | |||
| 78 | switch (priv->type) { | ||
| 79 | case NFT_REJECT_ICMP_UNREACH: | ||
| 80 | if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code)) | ||
| 81 | goto nla_put_failure; | ||
| 82 | break; | ||
| 83 | } | ||
| 84 | |||
| 85 | return 0; | ||
| 86 | |||
| 87 | nla_put_failure: | ||
| 88 | return -1; | ||
| 89 | } | ||
| 90 | |||
| 91 | static struct nft_expr_type nft_reject_type; | ||
| 92 | static const struct nft_expr_ops nft_reject_ops = { | ||
| 93 | .type = &nft_reject_type, | ||
| 94 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
| 95 | .eval = nft_reject_eval, | ||
| 96 | .init = nft_reject_init, | ||
| 97 | .dump = nft_reject_dump, | ||
| 98 | }; | ||
| 99 | |||
| 100 | static struct nft_expr_type nft_reject_type __read_mostly = { | ||
| 101 | .name = "reject", | ||
| 102 | .ops = &nft_reject_ops, | ||
| 103 | .policy = nft_reject_policy, | ||
| 104 | .maxattr = NFTA_REJECT_MAX, | ||
| 105 | .owner = THIS_MODULE, | ||
| 106 | }; | ||
| 107 | |||
| 108 | static int __init nft_reject_module_init(void) | ||
| 109 | { | ||
| 110 | return nft_register_expr(&nft_reject_type); | ||
| 111 | } | ||
| 112 | |||
| 113 | static void __exit nft_reject_module_exit(void) | ||
| 114 | { | ||
| 115 | nft_unregister_expr(&nft_reject_type); | ||
| 116 | } | ||
| 117 | |||
| 118 | module_init(nft_reject_module_init); | ||
| 119 | module_exit(nft_reject_module_exit); | ||
| 120 | |||
| 121 | MODULE_LICENSE("GPL"); | ||
| 122 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
| 123 | MODULE_ALIAS_NFT_EXPR("reject"); | ||
