|
@@ -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;
|
|
|
|
-
|
|
|
|
- if (dst->remote_ip.sa.sa_family == AF_INET6)
|
|
|
|
- use_ipv6 = true;
|
|
|
|
|
|
+ bool use_ipv6 = !!(vxlan->cfg.flags & VXLAN_F_IPV6);
|
|
|
|
|
|
/* 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,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- 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 ||
|
|
|
|
- conf->saddr.sa.sa_family == AF_INET6) {
|
|
|
|
|
|
+ if (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,
|
|
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) ==
|
|
|
|
- (conf->flags & VXLAN_F_RCV_FLAGS))
|
|
|
|
|
|
+ (tmp->cfg.flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6)) ==
|
|
|
|
+ (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[],
|
|
}
|
|
}
|
|
|
|
|
|
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;
|