2 * Copyright (c) 2014 Pablo Neira Ayuso <pablo@netfilter.org>
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.
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>
21 #include <net/ip6_checksum.h>
22 #include <linux/netfilter_bridge.h>
23 #include <linux/netfilter_ipv6.h>
24 #include "../br_private.h"
26 static void nft_reject_br_push_etherhdr(struct sk_buff
*oldskb
,
31 eth
= (struct ethhdr
*)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
);
39 static int nft_bridge_iphdr_validate(struct sk_buff
*skb
)
44 if (!pskb_may_pull(skb
, sizeof(struct iphdr
)))
48 if (iph
->ihl
< 5 || iph
->version
!= 4)
51 len
= ntohs(iph
->tot_len
);
54 else if (len
< (iph
->ihl
*4))
57 if (!pskb_may_pull(skb
, iph
->ihl
*4))
63 /* We cannot use oldskb->dev, it can be either bridge device (NF_BRIDGE INPUT)
64 * or the bridge port (NF_BRIDGE PREROUTING).
66 static void nft_reject_br_send_v4_tcp_reset(struct net
*net
,
67 struct sk_buff
*oldskb
,
68 const struct net_device
*dev
,
73 const struct tcphdr
*oth
;
76 if (!nft_bridge_iphdr_validate(oldskb
))
79 oth
= nf_reject_ip_tcphdr_get(oldskb
, &_oth
, hook
);
83 nskb
= alloc_skb(sizeof(struct iphdr
) + sizeof(struct tcphdr
) +
84 LL_MAX_HEADER
, GFP_ATOMIC
);
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
->ttl
= net
->ipv4
.sysctl_ip_default_ttl
;
93 niph
->tot_len
= htons(nskb
->len
);
96 nft_reject_br_push_etherhdr(oldskb
, nskb
);
98 br_forward(br_port_get_rcu(dev
), nskb
, false, true);
101 static void nft_reject_br_send_v4_unreach(struct net
*net
,
102 struct sk_buff
*oldskb
,
103 const struct net_device
*dev
,
106 struct sk_buff
*nskb
;
108 struct icmphdr
*icmph
;
114 if (oldskb
->csum_bad
|| !nft_bridge_iphdr_validate(oldskb
))
117 /* IP header checks: fragment. */
118 if (ip_hdr(oldskb
)->frag_off
& htons(IP_OFFSET
))
121 /* RFC says return as much as we can without exceeding 576 bytes. */
122 len
= min_t(unsigned int, 536, oldskb
->len
);
124 if (!pskb_may_pull(oldskb
, len
))
127 if (pskb_trim_rcsum(oldskb
, ntohs(ip_hdr(oldskb
)->tot_len
)))
130 if (ip_hdr(oldskb
)->protocol
== IPPROTO_TCP
||
131 ip_hdr(oldskb
)->protocol
== IPPROTO_UDP
)
132 proto
= ip_hdr(oldskb
)->protocol
;
136 if (!skb_csum_unnecessary(oldskb
) &&
137 nf_ip_checksum(oldskb
, hook
, ip_hdrlen(oldskb
), proto
))
140 nskb
= alloc_skb(sizeof(struct iphdr
) + sizeof(struct icmphdr
) +
141 LL_MAX_HEADER
+ len
, GFP_ATOMIC
);
145 skb_reserve(nskb
, LL_MAX_HEADER
);
146 niph
= nf_reject_iphdr_put(nskb
, oldskb
, IPPROTO_ICMP
,
147 net
->ipv4
.sysctl_ip_default_ttl
);
149 skb_reset_transport_header(nskb
);
150 icmph
= (struct icmphdr
*)skb_put(nskb
, sizeof(struct icmphdr
));
151 memset(icmph
, 0, sizeof(*icmph
));
152 icmph
->type
= ICMP_DEST_UNREACH
;
155 payload
= skb_put(nskb
, len
);
156 memcpy(payload
, skb_network_header(oldskb
), len
);
158 csum
= csum_partial((void *)icmph
, len
+ sizeof(struct icmphdr
), 0);
159 icmph
->checksum
= csum_fold(csum
);
161 niph
->tot_len
= htons(nskb
->len
);
164 nft_reject_br_push_etherhdr(oldskb
, nskb
);
166 br_forward(br_port_get_rcu(dev
), nskb
, false, true);
169 static int nft_bridge_ip6hdr_validate(struct sk_buff
*skb
)
174 if (!pskb_may_pull(skb
, sizeof(struct ipv6hdr
)))
178 if (hdr
->version
!= 6)
181 pkt_len
= ntohs(hdr
->payload_len
);
182 if (pkt_len
+ sizeof(struct ipv6hdr
) > skb
->len
)
188 static void nft_reject_br_send_v6_tcp_reset(struct net
*net
,
189 struct sk_buff
*oldskb
,
190 const struct net_device
*dev
,
193 struct sk_buff
*nskb
;
194 const struct tcphdr
*oth
;
196 unsigned int otcplen
;
197 struct ipv6hdr
*nip6h
;
199 if (!nft_bridge_ip6hdr_validate(oldskb
))
202 oth
= nf_reject_ip6_tcphdr_get(oldskb
, &_oth
, &otcplen
, hook
);
206 nskb
= alloc_skb(sizeof(struct ipv6hdr
) + sizeof(struct tcphdr
) +
207 LL_MAX_HEADER
, GFP_ATOMIC
);
211 skb_reserve(nskb
, LL_MAX_HEADER
);
212 nip6h
= nf_reject_ip6hdr_put(nskb
, oldskb
, IPPROTO_TCP
,
213 net
->ipv6
.devconf_all
->hop_limit
);
214 nf_reject_ip6_tcphdr_put(nskb
, oldskb
, oth
, otcplen
);
215 nip6h
->payload_len
= htons(nskb
->len
- sizeof(struct ipv6hdr
));
217 nft_reject_br_push_etherhdr(oldskb
, nskb
);
219 br_forward(br_port_get_rcu(dev
), nskb
, false, true);
222 static bool reject6_br_csum_ok(struct sk_buff
*skb
, int hook
)
224 const struct ipv6hdr
*ip6h
= ipv6_hdr(skb
);
227 u8 proto
= ip6h
->nexthdr
;
232 if (skb_csum_unnecessary(skb
))
235 if (ip6h
->payload_len
&&
236 pskb_trim_rcsum(skb
, ntohs(ip6h
->payload_len
) + sizeof(*ip6h
)))
239 thoff
= ipv6_skip_exthdr(skb
, ((u8
*)(ip6h
+1) - skb
->data
), &proto
, &fo
);
240 if (thoff
< 0 || thoff
>= skb
->len
|| (fo
& htons(~0x7)) != 0)
243 return nf_ip6_checksum(skb
, hook
, thoff
, proto
) == 0;
246 static void nft_reject_br_send_v6_unreach(struct net
*net
,
247 struct sk_buff
*oldskb
,
248 const struct net_device
*dev
,
251 struct sk_buff
*nskb
;
252 struct ipv6hdr
*nip6h
;
253 struct icmp6hdr
*icmp6h
;
257 if (!nft_bridge_ip6hdr_validate(oldskb
))
260 /* Include "As much of invoking packet as possible without the ICMPv6
261 * packet exceeding the minimum IPv6 MTU" in the ICMP payload.
263 len
= min_t(unsigned int, 1220, oldskb
->len
);
265 if (!pskb_may_pull(oldskb
, len
))
268 if (!reject6_br_csum_ok(oldskb
, hook
))
271 nskb
= alloc_skb(sizeof(struct iphdr
) + sizeof(struct icmp6hdr
) +
272 LL_MAX_HEADER
+ len
, GFP_ATOMIC
);
276 skb_reserve(nskb
, LL_MAX_HEADER
);
277 nip6h
= nf_reject_ip6hdr_put(nskb
, oldskb
, IPPROTO_ICMPV6
,
278 net
->ipv6
.devconf_all
->hop_limit
);
280 skb_reset_transport_header(nskb
);
281 icmp6h
= (struct icmp6hdr
*)skb_put(nskb
, sizeof(struct icmp6hdr
));
282 memset(icmp6h
, 0, sizeof(*icmp6h
));
283 icmp6h
->icmp6_type
= ICMPV6_DEST_UNREACH
;
284 icmp6h
->icmp6_code
= code
;
286 payload
= skb_put(nskb
, len
);
287 memcpy(payload
, skb_network_header(oldskb
), len
);
288 nip6h
->payload_len
= htons(nskb
->len
- sizeof(struct ipv6hdr
));
290 icmp6h
->icmp6_cksum
=
291 csum_ipv6_magic(&nip6h
->saddr
, &nip6h
->daddr
,
292 nskb
->len
- sizeof(struct ipv6hdr
),
295 nskb
->len
- sizeof(struct ipv6hdr
),
298 nft_reject_br_push_etherhdr(oldskb
, nskb
);
300 br_forward(br_port_get_rcu(dev
), nskb
, false, true);
303 static void nft_reject_bridge_eval(const struct nft_expr
*expr
,
304 struct nft_regs
*regs
,
305 const struct nft_pktinfo
*pkt
)
307 struct nft_reject
*priv
= nft_expr_priv(expr
);
308 const unsigned char *dest
= eth_hdr(pkt
->skb
)->h_dest
;
310 if (is_broadcast_ether_addr(dest
) ||
311 is_multicast_ether_addr(dest
))
314 switch (eth_hdr(pkt
->skb
)->h_proto
) {
315 case htons(ETH_P_IP
):
316 switch (priv
->type
) {
317 case NFT_REJECT_ICMP_UNREACH
:
318 nft_reject_br_send_v4_unreach(nft_net(pkt
), pkt
->skb
,
323 case NFT_REJECT_TCP_RST
:
324 nft_reject_br_send_v4_tcp_reset(nft_net(pkt
), pkt
->skb
,
328 case NFT_REJECT_ICMPX_UNREACH
:
329 nft_reject_br_send_v4_unreach(nft_net(pkt
), pkt
->skb
,
332 nft_reject_icmp_code(priv
->icmp_code
));
336 case htons(ETH_P_IPV6
):
337 switch (priv
->type
) {
338 case NFT_REJECT_ICMP_UNREACH
:
339 nft_reject_br_send_v6_unreach(nft_net(pkt
), pkt
->skb
,
344 case NFT_REJECT_TCP_RST
:
345 nft_reject_br_send_v6_tcp_reset(nft_net(pkt
), pkt
->skb
,
349 case NFT_REJECT_ICMPX_UNREACH
:
350 nft_reject_br_send_v6_unreach(nft_net(pkt
), pkt
->skb
,
353 nft_reject_icmpv6_code(priv
->icmp_code
));
358 /* No explicit way to reject this protocol, drop it. */
362 regs
->verdict
.code
= NF_DROP
;
365 static int nft_reject_bridge_validate(const struct nft_ctx
*ctx
,
366 const struct nft_expr
*expr
,
367 const struct nft_data
**data
)
369 return nft_chain_validate_hooks(ctx
->chain
, (1 << NF_BR_PRE_ROUTING
) |
370 (1 << NF_BR_LOCAL_IN
));
373 static int nft_reject_bridge_init(const struct nft_ctx
*ctx
,
374 const struct nft_expr
*expr
,
375 const struct nlattr
* const tb
[])
377 struct nft_reject
*priv
= nft_expr_priv(expr
);
380 err
= nft_reject_bridge_validate(ctx
, expr
, NULL
);
384 if (tb
[NFTA_REJECT_TYPE
] == NULL
)
387 priv
->type
= ntohl(nla_get_be32(tb
[NFTA_REJECT_TYPE
]));
388 switch (priv
->type
) {
389 case NFT_REJECT_ICMP_UNREACH
:
390 case NFT_REJECT_ICMPX_UNREACH
:
391 if (tb
[NFTA_REJECT_ICMP_CODE
] == NULL
)
394 icmp_code
= nla_get_u8(tb
[NFTA_REJECT_ICMP_CODE
]);
395 if (priv
->type
== NFT_REJECT_ICMPX_UNREACH
&&
396 icmp_code
> NFT_REJECT_ICMPX_MAX
)
399 priv
->icmp_code
= icmp_code
;
401 case NFT_REJECT_TCP_RST
:
409 static int nft_reject_bridge_dump(struct sk_buff
*skb
,
410 const struct nft_expr
*expr
)
412 const struct nft_reject
*priv
= nft_expr_priv(expr
);
414 if (nla_put_be32(skb
, NFTA_REJECT_TYPE
, htonl(priv
->type
)))
415 goto nla_put_failure
;
417 switch (priv
->type
) {
418 case NFT_REJECT_ICMP_UNREACH
:
419 case NFT_REJECT_ICMPX_UNREACH
:
420 if (nla_put_u8(skb
, NFTA_REJECT_ICMP_CODE
, priv
->icmp_code
))
421 goto nla_put_failure
;
433 static struct nft_expr_type nft_reject_bridge_type
;
434 static const struct nft_expr_ops nft_reject_bridge_ops
= {
435 .type
= &nft_reject_bridge_type
,
436 .size
= NFT_EXPR_SIZE(sizeof(struct nft_reject
)),
437 .eval
= nft_reject_bridge_eval
,
438 .init
= nft_reject_bridge_init
,
439 .dump
= nft_reject_bridge_dump
,
440 .validate
= nft_reject_bridge_validate
,
443 static struct nft_expr_type nft_reject_bridge_type __read_mostly
= {
444 .family
= NFPROTO_BRIDGE
,
446 .ops
= &nft_reject_bridge_ops
,
447 .policy
= nft_reject_policy
,
448 .maxattr
= NFTA_REJECT_MAX
,
449 .owner
= THIS_MODULE
,
452 static int __init
nft_reject_bridge_module_init(void)
454 return nft_register_expr(&nft_reject_bridge_type
);
457 static void __exit
nft_reject_bridge_module_exit(void)
459 nft_unregister_expr(&nft_reject_bridge_type
);
462 module_init(nft_reject_bridge_module_init
);
463 module_exit(nft_reject_bridge_module_exit
);
465 MODULE_LICENSE("GPL");
466 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
467 MODULE_ALIAS_NFT_AF_EXPR(AF_BRIDGE
, "reject");