[RFC ovpn net-next 3/5] ovpn: filter incoming multicast data packets

Marco Baffo <[email protected]>
Newsgroups gmane.network.openvpn.devel
Message-ID <[email protected]>
When the Ovpn server receive a multicast data packet that
has to be trasmitted to the peers, if its IP destination
is a multicast group to which no peer is currently subscribed,
the packet is dropped instead of being broadcasted.
Multicast control messages (IGMP/MLD) are still broadcasted
to all peers.

Signed-off-by: Marco Baffo <[email protected]>
---
 drivers/net/ovpn/mcast.c | 41 ++++++++++++++++++++++++++++++++++++++--
 drivers/net/ovpn/mcast.h |  1 +
 drivers/net/ovpn/peer.c  |  7 +++++--
 3 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ovpn/mcast.c b/drivers/net/ovpn/mcast.c
index c90ef2b8d8b8..59b0b62afcde 100644
--- a/drivers/net/ovpn/mcast.c
+++ b/drivers/net/ovpn/mcast.c
@@ -358,12 +358,49 @@ bool ovpn_mcast_snoop_skb(struct ovpn_peer *peer, struct sk_buff *skb)
 {
 	if (peer->ovpn->mode != OVPN_MODE_MP)
 		return false;
+
 	if (skb->protocol == htons(ETH_P_IP)) {
 		if (ip_hdr(skb)->protocol == IPPROTO_IGMP)
 			return ovpn_mcast_snoop_igmp(peer, skb);
 	} else if (skb->protocol == htons(ETH_P_IPV6)) {
-		if (ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6)
-			return ovpn_mcast_snoop_mld(peer, skb);
+		return ovpn_mcast_snoop_mld(peer, skb);
+	}
+
+	return false;
+}
+
+/**
+ * ovpn_mcast_is_control - determine whether an skb is multicast control traffic
+ * @skb: the packet to inspect
+ *
+ * Return: true if the skb contains IGMP or MLD control traffic,
+ *         false otherwise
+ */
+bool ovpn_mcast_is_control(struct sk_buff *skb)
+{
+	unsigned int offset;
+	struct icmp6hdr *ih;
+
+	if (skb->protocol == htons(ETH_P_IP))
+		return ip_hdr(skb)->protocol == IPPROTO_IGMP;
+
+	if (skb->protocol != htons(ETH_P_IPV6))
+		return false;
+
+	if (!ovpn_mcast_mld_offset(skb, &offset))
+		return false;
+
+	if (!pskb_may_pull(skb, offset + sizeof(*ih)))
+		return false;
+
+	ih = (struct icmp6hdr *)(skb_network_header(skb) + offset);
+	switch (ih->icmp6_type) {
+	case ICMPV6_MGM_QUERY:
+	case ICMPV6_MGM_REPORT:
+	case ICMPV6_MGM_REDUCTION:
+	case ICMPV6_MLD2_REPORT:
+		return true;
 	}
+
 	return false;
 }
diff --git a/drivers/net/ovpn/mcast.h b/drivers/net/ovpn/mcast.h
index e9e14d807270..9e06e893a355 100644
--- a/drivers/net/ovpn/mcast.h
+++ b/drivers/net/ovpn/mcast.h
@@ -22,6 +22,7 @@ void ovpn_mcast_leave_all(struct ovpn_peer *peer);
 bool ovpn_peer_list_get_by_mcast_group(struct ovpn_priv *ovpn,
 				       const struct in6_addr *group_addr,
 				       struct llist_head *list);
+bool ovpn_mcast_is_control(struct sk_buff *skb);
 bool ovpn_mcast_snoop_skb(struct ovpn_peer *peer, struct sk_buff *skb);
 
 #endif /* _NET_OVPN_MCAST_H_ */
diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index 5159a8f9dfba..a9728a157210 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -779,8 +779,10 @@ void ovpn_peer_list_get_by_dst(struct ovpn_priv *ovpn, struct sk_buff *skb,
 		addr_type = inet_dev_addr_type(dev_net(ovpn->dev), ovpn->dev, addr4);
 		if (addr_type == RTN_MULTICAST) {
 			ipv6_addr_set_v4mapped(addr4, &addr6);
-			if (!ovpn_peer_list_get_by_mcast_group(ovpn, &addr6, list))
+			if (!ovpn_peer_list_get_by_mcast_group(ovpn, &addr6, list) &&
+			    ovpn_mcast_is_control(skb)) {
 				ovpn_peer_list_get_all(ovpn, list);
+			}
 		} else if (addr_type == RTN_BROADCAST) {
 			ovpn_peer_list_get_all(ovpn, list);
 		}
@@ -795,7 +797,8 @@ void ovpn_peer_list_get_by_dst(struct ovpn_priv *ovpn, struct sk_buff *skb,
 
 		rcu_read_unlock();
 		if (ipv6_addr_is_multicast(&addr6) &&
-		    !ovpn_peer_list_get_by_mcast_group(ovpn, &addr6, list)) {
+		    !ovpn_peer_list_get_by_mcast_group(ovpn, &addr6, list) &&
+		    ovpn_mcast_is_control(skb)) {
 			ovpn_peer_list_get_all(ovpn, list);
 		}
 		return;
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.