Commit ce44a4ae authored by Matthias Schiffer's avatar Matthias Schiffer Committed by David S. Miller

vxlan: improve validation of address family configuration

Address families of source and destination addresses must match, and
changelink operations can't change the address family.

In addition, always use the VXLAN_F_IPV6 to check if a VXLAN device uses
IPv4 or IPv6.
Signed-off-by: default avatarMatthias Schiffer <mschiffer@universe-factory.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dc5321d7
...@@ -2484,10 +2484,7 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu) ...@@ -2484,10 +2484,7 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
struct vxlan_rdst *dst = &vxlan->default_dst; struct vxlan_rdst *dst = &vxlan->default_dst;
struct net_device *lowerdev = __dev_get_by_index(vxlan->net, struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
dst->remote_ifindex); dst->remote_ifindex);
bool use_ipv6 = false; bool use_ipv6 = !!(vxlan->cfg.flags & VXLAN_F_IPV6);
if (dst->remote_ip.sa.sa_family == AF_INET6)
use_ipv6 = true;
/* This check is different than dev->max_mtu, because it looks at /* This check is different than dev->max_mtu, because it looks at
* the lowerdev->mtu, rather than the static dev->max_mtu * the lowerdev->mtu, rather than the static dev->max_mtu
...@@ -2897,11 +2894,20 @@ static int vxlan_config_validate(struct net *src_net, struct vxlan_config *conf, ...@@ -2897,11 +2894,20 @@ static int vxlan_config_validate(struct net *src_net, struct vxlan_config *conf,
} }
} }
if (!conf->remote_ip.sa.sa_family) if (!conf->remote_ip.sa.sa_family && !conf->saddr.sa.sa_family) {
/* Unless IPv6 is explicitly requested, assume IPv4 */
conf->remote_ip.sa.sa_family = AF_INET; conf->remote_ip.sa.sa_family = AF_INET;
conf->saddr.sa.sa_family = AF_INET;
} else if (!conf->remote_ip.sa.sa_family) {
conf->remote_ip.sa.sa_family = conf->saddr.sa.sa_family;
} else if (!conf->saddr.sa.sa_family) {
conf->saddr.sa.sa_family = conf->remote_ip.sa.sa_family;
}
if (conf->saddr.sa.sa_family != conf->remote_ip.sa.sa_family)
return -EINVAL;
if (conf->remote_ip.sa.sa_family == AF_INET6 || if (conf->saddr.sa.sa_family == AF_INET6) {
conf->saddr.sa.sa_family == AF_INET6) {
if (!IS_ENABLED(CONFIG_IPV6)) if (!IS_ENABLED(CONFIG_IPV6))
return -EPFNOSUPPORT; return -EPFNOSUPPORT;
use_ipv6 = true; use_ipv6 = true;
...@@ -2949,11 +2955,9 @@ static int vxlan_config_validate(struct net *src_net, struct vxlan_config *conf, ...@@ -2949,11 +2955,9 @@ static int vxlan_config_validate(struct net *src_net, struct vxlan_config *conf,
continue; continue;
if (tmp->cfg.vni == conf->vni && if (tmp->cfg.vni == conf->vni &&
(tmp->default_dst.remote_ip.sa.sa_family == AF_INET6 ||
tmp->cfg.saddr.sa.sa_family == AF_INET6) == use_ipv6 &&
tmp->cfg.dst_port == conf->dst_port && tmp->cfg.dst_port == conf->dst_port &&
(tmp->cfg.flags & VXLAN_F_RCV_FLAGS) == (tmp->cfg.flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6)) ==
(conf->flags & VXLAN_F_RCV_FLAGS)) (conf->flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6)))
return -EEXIST; return -EEXIST;
} }
...@@ -3084,22 +3088,35 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], ...@@ -3084,22 +3088,35 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
} }
if (data[IFLA_VXLAN_GROUP]) { if (data[IFLA_VXLAN_GROUP]) {
if (changelink && (conf->remote_ip.sa.sa_family != AF_INET))
return -EOPNOTSUPP;
conf->remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]); conf->remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]);
conf->remote_ip.sa.sa_family = AF_INET;
} else if (data[IFLA_VXLAN_GROUP6]) { } else if (data[IFLA_VXLAN_GROUP6]) {
if (!IS_ENABLED(CONFIG_IPV6)) if (!IS_ENABLED(CONFIG_IPV6))
return -EPFNOSUPPORT; return -EPFNOSUPPORT;
if (changelink && (conf->remote_ip.sa.sa_family != AF_INET6))
return -EOPNOTSUPP;
conf->remote_ip.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_GROUP6]); conf->remote_ip.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_GROUP6]);
conf->remote_ip.sa.sa_family = AF_INET6; conf->remote_ip.sa.sa_family = AF_INET6;
} }
if (data[IFLA_VXLAN_LOCAL]) { if (data[IFLA_VXLAN_LOCAL]) {
if (changelink && (conf->saddr.sa.sa_family != AF_INET))
return -EOPNOTSUPP;
conf->saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]); conf->saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]);
conf->saddr.sa.sa_family = AF_INET; conf->saddr.sa.sa_family = AF_INET;
} else if (data[IFLA_VXLAN_LOCAL6]) { } else if (data[IFLA_VXLAN_LOCAL6]) {
if (!IS_ENABLED(CONFIG_IPV6)) if (!IS_ENABLED(CONFIG_IPV6))
return -EPFNOSUPPORT; return -EPFNOSUPPORT;
if (changelink && (conf->saddr.sa.sa_family != AF_INET6))
return -EOPNOTSUPP;
/* TODO: respect scope id */ /* TODO: respect scope id */
conf->saddr.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_LOCAL6]); conf->saddr.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_LOCAL6]);
conf->saddr.sa.sa_family = AF_INET6; conf->saddr.sa.sa_family = AF_INET6;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment