1 /* 2 * Copyright (c) 2014 Pablo Neira Ayuso <pablo@netfilter.org> 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 9 #include <linux/kernel.h> 10 #include <linux/init.h> 11 #include <linux/module.h> 12 #include <linux/netlink.h> 13 #include <linux/netfilter.h> 14 #include <linux/netfilter/nf_tables.h> 15 #include <net/netfilter/nf_tables.h> 16 #include <net/netfilter/nft_reject.h> 17 #include <net/netfilter/ipv4/nf_reject.h> 18 #include <net/netfilter/ipv6/nf_reject.h> 19 #include <linux/ip.h> 20 #include <net/ip.h> 21 #include <net/ip6_checksum.h> 22 #include <linux/netfilter_bridge.h> 23 #include <linux/netfilter_ipv6.h> 24 #include "../br_private.h" 25 26 static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb, 27 struct sk_buff *nskb) 28 { 29 struct ethhdr *eth; 30 31 eth = skb_push(nskb, ETH_HLEN); 32 skb_reset_mac_header(nskb); 33 ether_addr_copy(eth->h_source, eth_hdr(oldskb)->h_dest); 34 ether_addr_copy(eth->h_dest, eth_hdr(oldskb)->h_source); 35 eth->h_proto = eth_hdr(oldskb)->h_proto; 36 skb_pull(nskb, ETH_HLEN); 37 } 38 39 static int nft_bridge_iphdr_validate(struct sk_buff *skb) 40 { 41 struct iphdr *iph; 42 u32 len; 43 44 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 45 return 0; 46 47 iph = ip_hdr(skb); 48 if (iph->ihl < 5 || iph->version != 4) 49 return 0; 50 51 len = ntohs(iph->tot_len); 52 if (skb->len < len) 53 return 0; 54 else if (len < (iph->ihl*4)) 55 return 0; 56 57 if (!pskb_may_pull(skb, iph->ihl*4)) 58 return 0; 59 60 return 1; 61 } 62 63 /* We cannot use oldskb->dev, it can be either bridge device (NF_BRIDGE INPUT) 64 * or the bridge port (NF_BRIDGE PREROUTING). 65 */ 66 static void nft_reject_br_send_v4_tcp_reset(struct net *net, 67 struct sk_buff *oldskb, 68 const struct net_device *dev, 69 int hook) 70 { 71 struct sk_buff *nskb; 72 struct iphdr *niph; 73 const struct tcphdr *oth; 74 struct tcphdr _oth; 75 76 if (!nft_bridge_iphdr_validate(oldskb)) 77 return; 78 79 oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook); 80 if (!oth) 81 return; 82 83 nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) + 84 LL_MAX_HEADER, GFP_ATOMIC); 85 if (!nskb) 86 return; 87 88 skb_reserve(nskb, LL_MAX_HEADER); 89 niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP, 90 net->ipv4.sysctl_ip_default_ttl); 91 nf_reject_ip_tcphdr_put(nskb, oldskb, oth); 92 niph->tot_len = htons(nskb->len); 93 ip_send_check(niph); 94 95 nft_reject_br_push_etherhdr(oldskb, nskb); 96 97 br_forward(br_port_get_rcu(dev), nskb, false, true); 98 } 99 100 static void nft_reject_br_send_v4_unreach(struct net *net, 101 struct sk_buff *oldskb, 102 const struct net_device *dev, 103 int hook, u8 code) 104 { 105 struct sk_buff *nskb; 106 struct iphdr *niph; 107 struct icmphdr *icmph; 108 unsigned int len; 109 __wsum csum; 110 u8 proto; 111 112 if (!nft_bridge_iphdr_validate(oldskb)) 113 return; 114 115 /* IP header checks: fragment. */ 116 if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) 117 return; 118 119 /* RFC says return as much as we can without exceeding 576 bytes. */ 120 len = min_t(unsigned int, 536, oldskb->len); 121 122 if (!pskb_may_pull(oldskb, len)) 123 return; 124 125 if (pskb_trim_rcsum(oldskb, ntohs(ip_hdr(oldskb)->tot_len))) 126 return; 127 128 if (ip_hdr(oldskb)->protocol == IPPROTO_TCP || 129 ip_hdr(oldskb)->protocol == IPPROTO_UDP) 130 proto = ip_hdr(oldskb)->protocol; 131 else 132 proto = 0; 133 134 if (!skb_csum_unnecessary(oldskb) && 135 nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), proto)) 136 return; 137 138 nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmphdr) + 139 LL_MAX_HEADER + len, GFP_ATOMIC); 140 if (!nskb) 141 return; 142 143 skb_reserve(nskb, LL_MAX_HEADER); 144 niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_ICMP, 145 net->ipv4.sysctl_ip_default_ttl); 146 147 skb_reset_transport_header(nskb); 148 icmph = skb_put_zero(nskb, sizeof(struct icmphdr)); 149 icmph->type = ICMP_DEST_UNREACH; 150 icmph->code = code; 151 152 skb_put_data(nskb, skb_network_header(oldskb), len); 153 154 csum = csum_partial((void *)icmph, len + sizeof(struct icmphdr), 0); 155 icmph->checksum = csum_fold(csum); 156 157 niph->tot_len = htons(nskb->len); 158 ip_send_check(niph); 159 160 nft_reject_br_push_etherhdr(oldskb, nskb); 161 162 br_forward(br_port_get_rcu(dev), nskb, false, true); 163 } 164 165 static int nft_bridge_ip6hdr_validate(struct sk_buff *skb) 166 { 167 struct ipv6hdr *hdr; 168 u32 pkt_len; 169 170 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 171 return 0; 172 173 hdr = ipv6_hdr(skb); 174 if (hdr->version != 6) 175 return 0; 176 177 pkt_len = ntohs(hdr->payload_len); 178 if (pkt_len + sizeof(struct ipv6hdr) > skb->len) 179 return 0; 180 181 return 1; 182 } 183 184 static void nft_reject_br_send_v6_tcp_reset(struct net *net, 185 struct sk_buff *oldskb, 186 const struct net_device *dev, 187 int hook) 188 { 189 struct sk_buff *nskb; 190 const struct tcphdr *oth; 191 struct tcphdr _oth; 192 unsigned int otcplen; 193 struct ipv6hdr *nip6h; 194 195 if (!nft_bridge_ip6hdr_validate(oldskb)) 196 return; 197 198 oth = nf_reject_ip6_tcphdr_get(oldskb, &_oth, &otcplen, hook); 199 if (!oth) 200 return; 201 202 nskb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(struct tcphdr) + 203 LL_MAX_HEADER, GFP_ATOMIC); 204 if (!nskb) 205 return; 206 207 skb_reserve(nskb, LL_MAX_HEADER); 208 nip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP, 209 net->ipv6.devconf_all->hop_limit); 210 nf_reject_ip6_tcphdr_put(nskb, oldskb, oth, otcplen); 211 nip6h->payload_len = htons(nskb->len - sizeof(struct ipv6hdr)); 212 213 nft_reject_br_push_etherhdr(oldskb, nskb); 214 215 br_forward(br_port_get_rcu(dev), nskb, false, true); 216 } 217 218 static bool reject6_br_csum_ok(struct sk_buff *skb, int hook) 219 { 220 const struct ipv6hdr *ip6h = ipv6_hdr(skb); 221 int thoff; 222 __be16 fo; 223 u8 proto = ip6h->nexthdr; 224 225 if (skb_csum_unnecessary(skb)) 226 return true; 227 228 if (ip6h->payload_len && 229 pskb_trim_rcsum(skb, ntohs(ip6h->payload_len) + sizeof(*ip6h))) 230 return false; 231 232 thoff = ipv6_skip_exthdr(skb, ((u8*)(ip6h+1) - skb->data), &proto, &fo); 233 if (thoff < 0 || thoff >= skb->len || (fo & htons(~0x7)) != 0) 234 return false; 235 236 return nf_ip6_checksum(skb, hook, thoff, proto) == 0; 237 } 238 239 static void nft_reject_br_send_v6_unreach(struct net *net, 240 struct sk_buff *oldskb, 241 const struct net_device *dev, 242 int hook, u8 code) 243 { 244 struct sk_buff *nskb; 245 struct ipv6hdr *nip6h; 246 struct icmp6hdr *icmp6h; 247 unsigned int len; 248 249 if (!nft_bridge_ip6hdr_validate(oldskb)) 250 return; 251 252 /* Include "As much of invoking packet as possible without the ICMPv6 253 * packet exceeding the minimum IPv6 MTU" in the ICMP payload. 254 */ 255 len = min_t(unsigned int, 1220, oldskb->len); 256 257 if (!pskb_may_pull(oldskb, len)) 258 return; 259 260 if (!reject6_br_csum_ok(oldskb, hook)) 261 return; 262 263 nskb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr) + 264 LL_MAX_HEADER + len, GFP_ATOMIC); 265 if (!nskb) 266 return; 267 268 skb_reserve(nskb, LL_MAX_HEADER); 269 nip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_ICMPV6, 270 net->ipv6.devconf_all->hop_limit); 271 272 skb_reset_transport_header(nskb); 273 icmp6h = skb_put_zero(nskb, sizeof(struct icmp6hdr)); 274 icmp6h->icmp6_type = ICMPV6_DEST_UNREACH; 275 icmp6h->icmp6_code = code; 276 277 skb_put_data(nskb, skb_network_header(oldskb), len); 278 nip6h->payload_len = htons(nskb->len - sizeof(struct ipv6hdr)); 279 280 icmp6h->icmp6_cksum = 281 csum_ipv6_magic(&nip6h->saddr, &nip6h->daddr, 282 nskb->len - sizeof(struct ipv6hdr), 283 IPPROTO_ICMPV6, 284 csum_partial(icmp6h, 285 nskb->len - sizeof(struct ipv6hdr), 286 0)); 287 288 nft_reject_br_push_etherhdr(oldskb, nskb); 289 290 br_forward(br_port_get_rcu(dev), nskb, false, true); 291 } 292 293 static void nft_reject_bridge_eval(const struct nft_expr *expr, 294 struct nft_regs *regs, 295 const struct nft_pktinfo *pkt) 296 { 297 struct nft_reject *priv = nft_expr_priv(expr); 298 const unsigned char *dest = eth_hdr(pkt->skb)->h_dest; 299 300 if (is_broadcast_ether_addr(dest) || 301 is_multicast_ether_addr(dest)) 302 goto out; 303 304 switch (eth_hdr(pkt->skb)->h_proto) { 305 case htons(ETH_P_IP): 306 switch (priv->type) { 307 case NFT_REJECT_ICMP_UNREACH: 308 nft_reject_br_send_v4_unreach(nft_net(pkt), pkt->skb, 309 nft_in(pkt), 310 nft_hook(pkt), 311 priv->icmp_code); 312 break; 313 case NFT_REJECT_TCP_RST: 314 nft_reject_br_send_v4_tcp_reset(nft_net(pkt), pkt->skb, 315 nft_in(pkt), 316 nft_hook(pkt)); 317 break; 318 case NFT_REJECT_ICMPX_UNREACH: 319 nft_reject_br_send_v4_unreach(nft_net(pkt), pkt->skb, 320 nft_in(pkt), 321 nft_hook(pkt), 322 nft_reject_icmp_code(priv->icmp_code)); 323 break; 324 } 325 break; 326 case htons(ETH_P_IPV6): 327 switch (priv->type) { 328 case NFT_REJECT_ICMP_UNREACH: 329 nft_reject_br_send_v6_unreach(nft_net(pkt), pkt->skb, 330 nft_in(pkt), 331 nft_hook(pkt), 332 priv->icmp_code); 333 break; 334 case NFT_REJECT_TCP_RST: 335 nft_reject_br_send_v6_tcp_reset(nft_net(pkt), pkt->skb, 336 nft_in(pkt), 337 nft_hook(pkt)); 338 break; 339 case NFT_REJECT_ICMPX_UNREACH: 340 nft_reject_br_send_v6_unreach(nft_net(pkt), pkt->skb, 341 nft_in(pkt), 342 nft_hook(pkt), 343 nft_reject_icmpv6_code(priv->icmp_code)); 344 break; 345 } 346 break; 347 default: 348 /* No explicit way to reject this protocol, drop it. */ 349 break; 350 } 351 out: 352 regs->verdict.code = NF_DROP; 353 } 354 355 static int nft_reject_bridge_validate(const struct nft_ctx *ctx, 356 const struct nft_expr *expr, 357 const struct nft_data **data) 358 { 359 return nft_chain_validate_hooks(ctx->chain, (1 << NF_BR_PRE_ROUTING) | 360 (1 << NF_BR_LOCAL_IN)); 361 } 362 363 static int nft_reject_bridge_init(const struct nft_ctx *ctx, 364 const struct nft_expr *expr, 365 const struct nlattr * const tb[]) 366 { 367 struct nft_reject *priv = nft_expr_priv(expr); 368 int icmp_code; 369 370 if (tb[NFTA_REJECT_TYPE] == NULL) 371 return -EINVAL; 372 373 priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE])); 374 switch (priv->type) { 375 case NFT_REJECT_ICMP_UNREACH: 376 case NFT_REJECT_ICMPX_UNREACH: 377 if (tb[NFTA_REJECT_ICMP_CODE] == NULL) 378 return -EINVAL; 379 380 icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]); 381 if (priv->type == NFT_REJECT_ICMPX_UNREACH && 382 icmp_code > NFT_REJECT_ICMPX_MAX) 383 return -EINVAL; 384 385 priv->icmp_code = icmp_code; 386 break; 387 case NFT_REJECT_TCP_RST: 388 break; 389 default: 390 return -EINVAL; 391 } 392 return 0; 393 } 394 395 static int nft_reject_bridge_dump(struct sk_buff *skb, 396 const struct nft_expr *expr) 397 { 398 const struct nft_reject *priv = nft_expr_priv(expr); 399 400 if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type))) 401 goto nla_put_failure; 402 403 switch (priv->type) { 404 case NFT_REJECT_ICMP_UNREACH: 405 case NFT_REJECT_ICMPX_UNREACH: 406 if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code)) 407 goto nla_put_failure; 408 break; 409 default: 410 break; 411 } 412 413 return 0; 414 415 nla_put_failure: 416 return -1; 417 } 418 419 static struct nft_expr_type nft_reject_bridge_type; 420 static const struct nft_expr_ops nft_reject_bridge_ops = { 421 .type = &nft_reject_bridge_type, 422 .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), 423 .eval = nft_reject_bridge_eval, 424 .init = nft_reject_bridge_init, 425 .dump = nft_reject_bridge_dump, 426 .validate = nft_reject_bridge_validate, 427 }; 428 429 static struct nft_expr_type nft_reject_bridge_type __read_mostly = { 430 .family = NFPROTO_BRIDGE, 431 .name = "reject", 432 .ops = &nft_reject_bridge_ops, 433 .policy = nft_reject_policy, 434 .maxattr = NFTA_REJECT_MAX, 435 .owner = THIS_MODULE, 436 }; 437 438 static int __init nft_reject_bridge_module_init(void) 439 { 440 return nft_register_expr(&nft_reject_bridge_type); 441 } 442 443 static void __exit nft_reject_bridge_module_exit(void) 444 { 445 nft_unregister_expr(&nft_reject_bridge_type); 446 } 447 448 module_init(nft_reject_bridge_module_init); 449 module_exit(nft_reject_bridge_module_exit); 450 451 MODULE_LICENSE("GPL"); 452 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 453 MODULE_ALIAS_NFT_AF_EXPR(AF_BRIDGE, "reject"); 454