1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2014 Pablo Neira Ayuso <pablo@netfilter.org> 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/init.h> 8 #include <linux/module.h> 9 #include <linux/netlink.h> 10 #include <linux/netfilter.h> 11 #include <linux/netfilter/nf_tables.h> 12 #include <net/netfilter/nf_tables.h> 13 #include <net/netfilter/nft_reject.h> 14 #include <net/netfilter/ipv4/nf_reject.h> 15 #include <net/netfilter/ipv6/nf_reject.h> 16 #include <linux/ip.h> 17 #include <net/ip.h> 18 #include <net/ip6_checksum.h> 19 #include <linux/netfilter_bridge.h> 20 #include <linux/netfilter_ipv6.h> 21 #include "../br_private.h" 22 23 static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb, 24 struct sk_buff *nskb) 25 { 26 struct ethhdr *eth; 27 28 eth = skb_push(nskb, ETH_HLEN); 29 skb_reset_mac_header(nskb); 30 ether_addr_copy(eth->h_source, eth_hdr(oldskb)->h_dest); 31 ether_addr_copy(eth->h_dest, eth_hdr(oldskb)->h_source); 32 eth->h_proto = eth_hdr(oldskb)->h_proto; 33 skb_pull(nskb, ETH_HLEN); 34 35 if (skb_vlan_tag_present(oldskb)) { 36 u16 vid = skb_vlan_tag_get(oldskb); 37 38 __vlan_hwaccel_put_tag(nskb, oldskb->vlan_proto, vid); 39 } 40 } 41 42 /* We cannot use oldskb->dev, it can be either bridge device (NF_BRIDGE INPUT) 43 * or the bridge port (NF_BRIDGE PREROUTING). 44 */ 45 static void nft_reject_br_send_v4_tcp_reset(struct net *net, 46 struct sk_buff *oldskb, 47 const struct net_device *dev, 48 int hook) 49 { 50 struct sk_buff *nskb; 51 52 nskb = nf_reject_skb_v4_tcp_reset(net, oldskb, NULL, hook); 53 if (!nskb) 54 return; 55 56 nft_reject_br_push_etherhdr(oldskb, nskb); 57 58 br_forward(br_port_get_rcu(dev), nskb, false, true); 59 } 60 61 static void nft_reject_br_send_v4_unreach(struct net *net, 62 struct sk_buff *oldskb, 63 const struct net_device *dev, 64 int hook, u8 code) 65 { 66 struct sk_buff *nskb; 67 68 nskb = nf_reject_skb_v4_unreach(net, oldskb, NULL, hook, code); 69 if (!nskb) 70 return; 71 72 nft_reject_br_push_etherhdr(oldskb, nskb); 73 74 br_forward(br_port_get_rcu(dev), nskb, false, true); 75 } 76 77 static void nft_reject_br_send_v6_tcp_reset(struct net *net, 78 struct sk_buff *oldskb, 79 const struct net_device *dev, 80 int hook) 81 { 82 struct sk_buff *nskb; 83 84 nskb = nf_reject_skb_v6_tcp_reset(net, oldskb, NULL, hook); 85 if (!nskb) 86 return; 87 88 nft_reject_br_push_etherhdr(oldskb, nskb); 89 90 br_forward(br_port_get_rcu(dev), nskb, false, true); 91 } 92 93 94 static void nft_reject_br_send_v6_unreach(struct net *net, 95 struct sk_buff *oldskb, 96 const struct net_device *dev, 97 int hook, u8 code) 98 { 99 struct sk_buff *nskb; 100 101 nskb = nf_reject_skb_v6_unreach(net, oldskb, NULL, hook, code); 102 if (!nskb) 103 return; 104 105 nft_reject_br_push_etherhdr(oldskb, nskb); 106 107 br_forward(br_port_get_rcu(dev), nskb, false, true); 108 } 109 110 static void nft_reject_bridge_eval(const struct nft_expr *expr, 111 struct nft_regs *regs, 112 const struct nft_pktinfo *pkt) 113 { 114 struct nft_reject *priv = nft_expr_priv(expr); 115 const unsigned char *dest = eth_hdr(pkt->skb)->h_dest; 116 117 if (is_broadcast_ether_addr(dest) || 118 is_multicast_ether_addr(dest)) 119 goto out; 120 121 switch (eth_hdr(pkt->skb)->h_proto) { 122 case htons(ETH_P_IP): 123 switch (priv->type) { 124 case NFT_REJECT_ICMP_UNREACH: 125 nft_reject_br_send_v4_unreach(nft_net(pkt), pkt->skb, 126 nft_in(pkt), 127 nft_hook(pkt), 128 priv->icmp_code); 129 break; 130 case NFT_REJECT_TCP_RST: 131 nft_reject_br_send_v4_tcp_reset(nft_net(pkt), pkt->skb, 132 nft_in(pkt), 133 nft_hook(pkt)); 134 break; 135 case NFT_REJECT_ICMPX_UNREACH: 136 nft_reject_br_send_v4_unreach(nft_net(pkt), pkt->skb, 137 nft_in(pkt), 138 nft_hook(pkt), 139 nft_reject_icmp_code(priv->icmp_code)); 140 break; 141 } 142 break; 143 case htons(ETH_P_IPV6): 144 switch (priv->type) { 145 case NFT_REJECT_ICMP_UNREACH: 146 nft_reject_br_send_v6_unreach(nft_net(pkt), pkt->skb, 147 nft_in(pkt), 148 nft_hook(pkt), 149 priv->icmp_code); 150 break; 151 case NFT_REJECT_TCP_RST: 152 nft_reject_br_send_v6_tcp_reset(nft_net(pkt), pkt->skb, 153 nft_in(pkt), 154 nft_hook(pkt)); 155 break; 156 case NFT_REJECT_ICMPX_UNREACH: 157 nft_reject_br_send_v6_unreach(nft_net(pkt), pkt->skb, 158 nft_in(pkt), 159 nft_hook(pkt), 160 nft_reject_icmpv6_code(priv->icmp_code)); 161 break; 162 } 163 break; 164 default: 165 /* No explicit way to reject this protocol, drop it. */ 166 break; 167 } 168 out: 169 regs->verdict.code = NF_DROP; 170 } 171 172 static int nft_reject_bridge_validate(const struct nft_ctx *ctx, 173 const struct nft_expr *expr, 174 const struct nft_data **data) 175 { 176 return nft_chain_validate_hooks(ctx->chain, (1 << NF_BR_PRE_ROUTING) | 177 (1 << NF_BR_LOCAL_IN)); 178 } 179 180 static struct nft_expr_type nft_reject_bridge_type; 181 static const struct nft_expr_ops nft_reject_bridge_ops = { 182 .type = &nft_reject_bridge_type, 183 .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), 184 .eval = nft_reject_bridge_eval, 185 .init = nft_reject_init, 186 .dump = nft_reject_dump, 187 .validate = nft_reject_bridge_validate, 188 .reduce = NFT_REDUCE_READONLY, 189 }; 190 191 static struct nft_expr_type nft_reject_bridge_type __read_mostly = { 192 .family = NFPROTO_BRIDGE, 193 .name = "reject", 194 .ops = &nft_reject_bridge_ops, 195 .policy = nft_reject_policy, 196 .maxattr = NFTA_REJECT_MAX, 197 .owner = THIS_MODULE, 198 }; 199 200 static int __init nft_reject_bridge_module_init(void) 201 { 202 return nft_register_expr(&nft_reject_bridge_type); 203 } 204 205 static void __exit nft_reject_bridge_module_exit(void) 206 { 207 nft_unregister_expr(&nft_reject_bridge_type); 208 } 209 210 module_init(nft_reject_bridge_module_init); 211 module_exit(nft_reject_bridge_module_exit); 212 213 MODULE_LICENSE("GPL"); 214 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 215 MODULE_ALIAS_NFT_AF_EXPR(AF_BRIDGE, "reject"); 216 MODULE_DESCRIPTION("Reject packets from bridge via nftables"); 217