| From foo@baz Thu Nov 9 09:48:01 CET 2017 |
| From: Liping Zhang <zlpnobody@gmail.com> |
| Date: Sat, 7 Jan 2017 21:33:55 +0800 |
| Subject: netfilter: nft_meta: deal with PACKET_LOOPBACK in netdev family |
| |
| From: Liping Zhang <zlpnobody@gmail.com> |
| |
| |
| [ Upstream commit f169fd695b192dd7b23aff8e69d25a1bc881bbfa ] |
| |
| After adding the following nft rule, then ping 224.0.0.1: |
| # nft add rule netdev t c pkttype host counter |
| |
| The warning complain message will be printed out again and again: |
| WARNING: CPU: 0 PID: 10182 at net/netfilter/nft_meta.c:163 \ |
| nft_meta_get_eval+0x3fe/0x460 [nft_meta] |
| [...] |
| Call Trace: |
| <IRQ> |
| dump_stack+0x85/0xc2 |
| __warn+0xcb/0xf0 |
| warn_slowpath_null+0x1d/0x20 |
| nft_meta_get_eval+0x3fe/0x460 [nft_meta] |
| nft_do_chain+0xff/0x5e0 [nf_tables] |
| |
| So we should deal with PACKET_LOOPBACK in netdev family too. For ipv4, |
| convert it to PACKET_BROADCAST/MULTICAST according to the destination |
| address's type; For ipv6, convert it to PACKET_MULTICAST directly. |
| |
| Signed-off-by: Liping Zhang <zlpnobody@gmail.com> |
| Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/netfilter/nft_meta.c | 28 +++++++++++++++++++++++++++- |
| 1 file changed, 27 insertions(+), 1 deletion(-) |
| |
| --- a/net/netfilter/nft_meta.c |
| +++ b/net/netfilter/nft_meta.c |
| @@ -159,8 +159,34 @@ void nft_meta_get_eval(const struct nft_ |
| else |
| *dest = PACKET_BROADCAST; |
| break; |
| + case NFPROTO_NETDEV: |
| + switch (skb->protocol) { |
| + case htons(ETH_P_IP): { |
| + int noff = skb_network_offset(skb); |
| + struct iphdr *iph, _iph; |
| + |
| + iph = skb_header_pointer(skb, noff, |
| + sizeof(_iph), &_iph); |
| + if (!iph) |
| + goto err; |
| + |
| + if (ipv4_is_multicast(iph->daddr)) |
| + *dest = PACKET_MULTICAST; |
| + else |
| + *dest = PACKET_BROADCAST; |
| + |
| + break; |
| + } |
| + case htons(ETH_P_IPV6): |
| + *dest = PACKET_MULTICAST; |
| + break; |
| + default: |
| + WARN_ON_ONCE(1); |
| + goto err; |
| + } |
| + break; |
| default: |
| - WARN_ON(1); |
| + WARN_ON_ONCE(1); |
| goto err; |
| } |
| break; |