0001
0002
0003
0004
0005
0006 #include <linux/kernel.h>
0007 #include <linux/init.h>
0008 #include <linux/module.h>
0009 #include <linux/netlink.h>
0010 #include <linux/netfilter.h>
0011 #include <linux/netfilter/nf_tables.h>
0012 #include <net/netfilter/nf_tables.h>
0013 #include <net/netfilter/nft_reject.h>
0014 #include <net/netfilter/ipv4/nf_reject.h>
0015 #include <net/netfilter/ipv6/nf_reject.h>
0016
0017 static void nft_reject_inet_eval(const struct nft_expr *expr,
0018 struct nft_regs *regs,
0019 const struct nft_pktinfo *pkt)
0020 {
0021 struct nft_reject *priv = nft_expr_priv(expr);
0022
0023 switch (nft_pf(pkt)) {
0024 case NFPROTO_IPV4:
0025 switch (priv->type) {
0026 case NFT_REJECT_ICMP_UNREACH:
0027 nf_send_unreach(pkt->skb, priv->icmp_code,
0028 nft_hook(pkt));
0029 break;
0030 case NFT_REJECT_TCP_RST:
0031 nf_send_reset(nft_net(pkt), nft_sk(pkt),
0032 pkt->skb, nft_hook(pkt));
0033 break;
0034 case NFT_REJECT_ICMPX_UNREACH:
0035 nf_send_unreach(pkt->skb,
0036 nft_reject_icmp_code(priv->icmp_code),
0037 nft_hook(pkt));
0038 break;
0039 }
0040 break;
0041 case NFPROTO_IPV6:
0042 switch (priv->type) {
0043 case NFT_REJECT_ICMP_UNREACH:
0044 nf_send_unreach6(nft_net(pkt), pkt->skb,
0045 priv->icmp_code, nft_hook(pkt));
0046 break;
0047 case NFT_REJECT_TCP_RST:
0048 nf_send_reset6(nft_net(pkt), nft_sk(pkt),
0049 pkt->skb, nft_hook(pkt));
0050 break;
0051 case NFT_REJECT_ICMPX_UNREACH:
0052 nf_send_unreach6(nft_net(pkt), pkt->skb,
0053 nft_reject_icmpv6_code(priv->icmp_code),
0054 nft_hook(pkt));
0055 break;
0056 }
0057 break;
0058 }
0059
0060 regs->verdict.code = NF_DROP;
0061 }
0062
0063 static int nft_reject_inet_validate(const struct nft_ctx *ctx,
0064 const struct nft_expr *expr,
0065 const struct nft_data **data)
0066 {
0067 return nft_chain_validate_hooks(ctx->chain,
0068 (1 << NF_INET_LOCAL_IN) |
0069 (1 << NF_INET_FORWARD) |
0070 (1 << NF_INET_LOCAL_OUT) |
0071 (1 << NF_INET_PRE_ROUTING) |
0072 (1 << NF_INET_INGRESS));
0073 }
0074
0075 static struct nft_expr_type nft_reject_inet_type;
0076 static const struct nft_expr_ops nft_reject_inet_ops = {
0077 .type = &nft_reject_inet_type,
0078 .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
0079 .eval = nft_reject_inet_eval,
0080 .init = nft_reject_init,
0081 .dump = nft_reject_dump,
0082 .validate = nft_reject_inet_validate,
0083 .reduce = NFT_REDUCE_READONLY,
0084 };
0085
0086 static struct nft_expr_type nft_reject_inet_type __read_mostly = {
0087 .family = NFPROTO_INET,
0088 .name = "reject",
0089 .ops = &nft_reject_inet_ops,
0090 .policy = nft_reject_policy,
0091 .maxattr = NFTA_REJECT_MAX,
0092 .owner = THIS_MODULE,
0093 };
0094
0095 static int __init nft_reject_inet_module_init(void)
0096 {
0097 return nft_register_expr(&nft_reject_inet_type);
0098 }
0099
0100 static void __exit nft_reject_inet_module_exit(void)
0101 {
0102 nft_unregister_expr(&nft_reject_inet_type);
0103 }
0104
0105 module_init(nft_reject_inet_module_init);
0106 module_exit(nft_reject_inet_module_exit);
0107
0108 MODULE_LICENSE("GPL");
0109 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
0110 MODULE_ALIAS_NFT_AF_EXPR(1, "reject");
0111 MODULE_DESCRIPTION("Netfilter nftables reject inet support");