0001
0002
0003
0004
0005
0006
0007 #include <linux/etherdevice.h>
0008 #include <linux/kernel.h>
0009 #include <linux/init.h>
0010 #include <linux/module.h>
0011 #include <linux/netlink.h>
0012 #include <linux/netfilter.h>
0013 #include <linux/netfilter/nf_tables.h>
0014 #include <net/netfilter/nf_tables.h>
0015 #include <net/netfilter/nft_reject.h>
0016 #include <net/netfilter/ipv4/nf_reject.h>
0017 #include <net/netfilter/ipv6/nf_reject.h>
0018
0019 static void nft_reject_queue_xmit(struct sk_buff *nskb, struct sk_buff *oldskb)
0020 {
0021 dev_hard_header(nskb, nskb->dev, ntohs(oldskb->protocol),
0022 eth_hdr(oldskb)->h_source, eth_hdr(oldskb)->h_dest,
0023 nskb->len);
0024 dev_queue_xmit(nskb);
0025 }
0026
0027 static void nft_reject_netdev_send_v4_tcp_reset(struct net *net,
0028 struct sk_buff *oldskb,
0029 const struct net_device *dev,
0030 int hook)
0031 {
0032 struct sk_buff *nskb;
0033
0034 nskb = nf_reject_skb_v4_tcp_reset(net, oldskb, dev, hook);
0035 if (!nskb)
0036 return;
0037
0038 nft_reject_queue_xmit(nskb, oldskb);
0039 }
0040
0041 static void nft_reject_netdev_send_v4_unreach(struct net *net,
0042 struct sk_buff *oldskb,
0043 const struct net_device *dev,
0044 int hook, u8 code)
0045 {
0046 struct sk_buff *nskb;
0047
0048 nskb = nf_reject_skb_v4_unreach(net, oldskb, dev, hook, code);
0049 if (!nskb)
0050 return;
0051
0052 nft_reject_queue_xmit(nskb, oldskb);
0053 }
0054
0055 static void nft_reject_netdev_send_v6_tcp_reset(struct net *net,
0056 struct sk_buff *oldskb,
0057 const struct net_device *dev,
0058 int hook)
0059 {
0060 struct sk_buff *nskb;
0061
0062 nskb = nf_reject_skb_v6_tcp_reset(net, oldskb, dev, hook);
0063 if (!nskb)
0064 return;
0065
0066 nft_reject_queue_xmit(nskb, oldskb);
0067 }
0068
0069
0070 static void nft_reject_netdev_send_v6_unreach(struct net *net,
0071 struct sk_buff *oldskb,
0072 const struct net_device *dev,
0073 int hook, u8 code)
0074 {
0075 struct sk_buff *nskb;
0076
0077 nskb = nf_reject_skb_v6_unreach(net, oldskb, dev, hook, code);
0078 if (!nskb)
0079 return;
0080
0081 nft_reject_queue_xmit(nskb, oldskb);
0082 }
0083
0084 static void nft_reject_netdev_eval(const struct nft_expr *expr,
0085 struct nft_regs *regs,
0086 const struct nft_pktinfo *pkt)
0087 {
0088 struct ethhdr *eth = eth_hdr(pkt->skb);
0089 struct nft_reject *priv = nft_expr_priv(expr);
0090 const unsigned char *dest = eth->h_dest;
0091
0092 if (is_broadcast_ether_addr(dest) ||
0093 is_multicast_ether_addr(dest))
0094 goto out;
0095
0096 switch (eth->h_proto) {
0097 case htons(ETH_P_IP):
0098 switch (priv->type) {
0099 case NFT_REJECT_ICMP_UNREACH:
0100 nft_reject_netdev_send_v4_unreach(nft_net(pkt), pkt->skb,
0101 nft_in(pkt),
0102 nft_hook(pkt),
0103 priv->icmp_code);
0104 break;
0105 case NFT_REJECT_TCP_RST:
0106 nft_reject_netdev_send_v4_tcp_reset(nft_net(pkt), pkt->skb,
0107 nft_in(pkt),
0108 nft_hook(pkt));
0109 break;
0110 case NFT_REJECT_ICMPX_UNREACH:
0111 nft_reject_netdev_send_v4_unreach(nft_net(pkt), pkt->skb,
0112 nft_in(pkt),
0113 nft_hook(pkt),
0114 nft_reject_icmp_code(priv->icmp_code));
0115 break;
0116 }
0117 break;
0118 case htons(ETH_P_IPV6):
0119 switch (priv->type) {
0120 case NFT_REJECT_ICMP_UNREACH:
0121 nft_reject_netdev_send_v6_unreach(nft_net(pkt), pkt->skb,
0122 nft_in(pkt),
0123 nft_hook(pkt),
0124 priv->icmp_code);
0125 break;
0126 case NFT_REJECT_TCP_RST:
0127 nft_reject_netdev_send_v6_tcp_reset(nft_net(pkt), pkt->skb,
0128 nft_in(pkt),
0129 nft_hook(pkt));
0130 break;
0131 case NFT_REJECT_ICMPX_UNREACH:
0132 nft_reject_netdev_send_v6_unreach(nft_net(pkt), pkt->skb,
0133 nft_in(pkt),
0134 nft_hook(pkt),
0135 nft_reject_icmpv6_code(priv->icmp_code));
0136 break;
0137 }
0138 break;
0139 default:
0140
0141 break;
0142 }
0143 out:
0144 regs->verdict.code = NF_DROP;
0145 }
0146
0147 static int nft_reject_netdev_validate(const struct nft_ctx *ctx,
0148 const struct nft_expr *expr,
0149 const struct nft_data **data)
0150 {
0151 return nft_chain_validate_hooks(ctx->chain, (1 << NF_NETDEV_INGRESS));
0152 }
0153
0154 static struct nft_expr_type nft_reject_netdev_type;
0155 static const struct nft_expr_ops nft_reject_netdev_ops = {
0156 .type = &nft_reject_netdev_type,
0157 .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
0158 .eval = nft_reject_netdev_eval,
0159 .init = nft_reject_init,
0160 .dump = nft_reject_dump,
0161 .validate = nft_reject_netdev_validate,
0162 .reduce = NFT_REDUCE_READONLY,
0163 };
0164
0165 static struct nft_expr_type nft_reject_netdev_type __read_mostly = {
0166 .family = NFPROTO_NETDEV,
0167 .name = "reject",
0168 .ops = &nft_reject_netdev_ops,
0169 .policy = nft_reject_policy,
0170 .maxattr = NFTA_REJECT_MAX,
0171 .owner = THIS_MODULE,
0172 };
0173
0174 static int __init nft_reject_netdev_module_init(void)
0175 {
0176 return nft_register_expr(&nft_reject_netdev_type);
0177 }
0178
0179 static void __exit nft_reject_netdev_module_exit(void)
0180 {
0181 nft_unregister_expr(&nft_reject_netdev_type);
0182 }
0183
0184 module_init(nft_reject_netdev_module_init);
0185 module_exit(nft_reject_netdev_module_exit);
0186
0187 MODULE_LICENSE("GPL");
0188 MODULE_AUTHOR("Laura Garcia Liebana <nevola@gmail.com>");
0189 MODULE_AUTHOR("Jose M. Guisado <guigom@riseup.net>");
0190 MODULE_DESCRIPTION("Reject packets from netdev via nftables");
0191 MODULE_ALIAS_NFT_AF_EXPR(5, "reject");