Commit 302d201b authored by Guillaume Nault's avatar Guillaume Nault Committed by David S. Miller
Browse files

bareudp: forbid mixing IP and MPLS in multiproto mode



In multiproto mode, bareudp_xmit() accepts sending multicast MPLS and
IPv6 packets regardless of the bareudp ethertype. In practice, this
let an IP tunnel send multicast MPLS packets, or an MPLS tunnel send
IPv6 packets.

We need to restrict the test further, so that the multiproto mode only
enables
  * IPv6 for IPv4 tunnels,
  * or multicast MPLS for unicast MPLS tunnels.

To improve clarity, the protocol validation is moved to its own
function, where each logical test has its own condition.

v2: s/ntohs/htons/

Fixes: 4b5f6723 ("net: Special handling for IP & MPLS.")
Signed-off-by: default avatarGuillaume Nault <gnault@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 706ec919
Loading
Loading
Loading
Loading
+22 −7
Original line number Diff line number Diff line
@@ -407,20 +407,35 @@ free_dst:
	return err;
}

static bool bareudp_proto_valid(struct bareudp_dev *bareudp, __be16 proto)
{
	if (bareudp->ethertype == proto)
		return true;

	if (!bareudp->multi_proto_mode)
		return false;

	if (bareudp->ethertype == htons(ETH_P_MPLS_UC) &&
	    proto == htons(ETH_P_MPLS_MC))
		return true;

	if (bareudp->ethertype == htons(ETH_P_IP) &&
	    proto == htons(ETH_P_IPV6))
		return true;

	return false;
}

static netdev_tx_t bareudp_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct bareudp_dev *bareudp = netdev_priv(dev);
	struct ip_tunnel_info *info = NULL;
	int err;

	if (skb->protocol != bareudp->ethertype) {
		if (!bareudp->multi_proto_mode ||
		    (skb->protocol !=  htons(ETH_P_MPLS_MC) &&
		     skb->protocol !=  htons(ETH_P_IPV6))) {
	if (!bareudp_proto_valid(bareudp, skb->protocol)) {
		err = -EINVAL;
		goto tx_error;
	}
	}

	info = skb_tunnel_info(skb);
	if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {