mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-14 08:13:56 +08:00
net/ipv6: Pass ifa6_config struct to inet6_addr_add
Move the creation of struct ifa6_config up to callers of inet6_addr_add. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e6464b8c63
commit
19b1518c29
@ -2830,20 +2830,9 @@ static int ipv6_mc_config(struct sock *sk, bool join,
|
|||||||
* Manual configuration of address on an interface
|
* Manual configuration of address on an interface
|
||||||
*/
|
*/
|
||||||
static int inet6_addr_add(struct net *net, int ifindex,
|
static int inet6_addr_add(struct net *net, int ifindex,
|
||||||
const struct in6_addr *pfx,
|
struct ifa6_config *cfg,
|
||||||
const struct in6_addr *peer_pfx,
|
|
||||||
unsigned int plen, __u32 ifa_flags,
|
|
||||||
__u32 prefered_lft, __u32 valid_lft,
|
|
||||||
struct netlink_ext_ack *extack)
|
struct netlink_ext_ack *extack)
|
||||||
{
|
{
|
||||||
struct ifa6_config cfg = {
|
|
||||||
.pfx = pfx,
|
|
||||||
.plen = plen,
|
|
||||||
.peer_pfx = peer_pfx,
|
|
||||||
.ifa_flags = ifa_flags,
|
|
||||||
.preferred_lft = prefered_lft,
|
|
||||||
.valid_lft = valid_lft,
|
|
||||||
};
|
|
||||||
struct inet6_ifaddr *ifp;
|
struct inet6_ifaddr *ifp;
|
||||||
struct inet6_dev *idev;
|
struct inet6_dev *idev;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
@ -2853,14 +2842,14 @@ static int inet6_addr_add(struct net *net, int ifindex,
|
|||||||
|
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
|
||||||
if (plen > 128)
|
if (cfg->plen > 128)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* check the lifetime */
|
/* check the lifetime */
|
||||||
if (!valid_lft || prefered_lft > valid_lft)
|
if (!cfg->valid_lft || cfg->preferred_lft > cfg->valid_lft)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (ifa_flags & IFA_F_MANAGETEMPADDR && plen != 64)
|
if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR && cfg->plen != 64)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
dev = __dev_get_by_index(net, ifindex);
|
dev = __dev_get_by_index(net, ifindex);
|
||||||
@ -2871,37 +2860,37 @@ static int inet6_addr_add(struct net *net, int ifindex,
|
|||||||
if (IS_ERR(idev))
|
if (IS_ERR(idev))
|
||||||
return PTR_ERR(idev);
|
return PTR_ERR(idev);
|
||||||
|
|
||||||
if (ifa_flags & IFA_F_MCAUTOJOIN) {
|
if (cfg->ifa_flags & IFA_F_MCAUTOJOIN) {
|
||||||
int ret = ipv6_mc_config(net->ipv6.mc_autojoin_sk,
|
int ret = ipv6_mc_config(net->ipv6.mc_autojoin_sk,
|
||||||
true, pfx, ifindex);
|
true, cfg->pfx, ifindex);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.scope = ipv6_addr_scope(pfx);
|
cfg->scope = ipv6_addr_scope(cfg->pfx);
|
||||||
|
|
||||||
timeout = addrconf_timeout_fixup(valid_lft, HZ);
|
timeout = addrconf_timeout_fixup(cfg->valid_lft, HZ);
|
||||||
if (addrconf_finite_timeout(timeout)) {
|
if (addrconf_finite_timeout(timeout)) {
|
||||||
expires = jiffies_to_clock_t(timeout * HZ);
|
expires = jiffies_to_clock_t(timeout * HZ);
|
||||||
valid_lft = timeout;
|
cfg->valid_lft = timeout;
|
||||||
flags = RTF_EXPIRES;
|
flags = RTF_EXPIRES;
|
||||||
} else {
|
} else {
|
||||||
expires = 0;
|
expires = 0;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
ifa_flags |= IFA_F_PERMANENT;
|
cfg->ifa_flags |= IFA_F_PERMANENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout = addrconf_timeout_fixup(prefered_lft, HZ);
|
timeout = addrconf_timeout_fixup(cfg->preferred_lft, HZ);
|
||||||
if (addrconf_finite_timeout(timeout)) {
|
if (addrconf_finite_timeout(timeout)) {
|
||||||
if (timeout == 0)
|
if (timeout == 0)
|
||||||
ifa_flags |= IFA_F_DEPRECATED;
|
cfg->ifa_flags |= IFA_F_DEPRECATED;
|
||||||
prefered_lft = timeout;
|
cfg->preferred_lft = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
ifp = ipv6_add_addr(idev, &cfg, true, extack);
|
ifp = ipv6_add_addr(idev, cfg, true, extack);
|
||||||
if (!IS_ERR(ifp)) {
|
if (!IS_ERR(ifp)) {
|
||||||
if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) {
|
if (!(cfg->ifa_flags & IFA_F_NOPREFIXROUTE)) {
|
||||||
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
|
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
|
||||||
expires, flags, GFP_KERNEL);
|
expires, flags, GFP_KERNEL);
|
||||||
}
|
}
|
||||||
@ -2917,15 +2906,15 @@ static int inet6_addr_add(struct net *net, int ifindex,
|
|||||||
* manually configured addresses
|
* manually configured addresses
|
||||||
*/
|
*/
|
||||||
addrconf_dad_start(ifp);
|
addrconf_dad_start(ifp);
|
||||||
if (ifa_flags & IFA_F_MANAGETEMPADDR)
|
if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR)
|
||||||
manage_tempaddrs(idev, ifp, valid_lft, prefered_lft,
|
manage_tempaddrs(idev, ifp, cfg->valid_lft,
|
||||||
true, jiffies);
|
cfg->preferred_lft, true, jiffies);
|
||||||
in6_ifa_put(ifp);
|
in6_ifa_put(ifp);
|
||||||
addrconf_verify_rtnl();
|
addrconf_verify_rtnl();
|
||||||
return 0;
|
return 0;
|
||||||
} else if (ifa_flags & IFA_F_MCAUTOJOIN) {
|
} else if (cfg->ifa_flags & IFA_F_MCAUTOJOIN) {
|
||||||
ipv6_mc_config(net->ipv6.mc_autojoin_sk,
|
ipv6_mc_config(net->ipv6.mc_autojoin_sk, false,
|
||||||
false, pfx, ifindex);
|
cfg->pfx, ifindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PTR_ERR(ifp);
|
return PTR_ERR(ifp);
|
||||||
@ -2976,6 +2965,11 @@ static int inet6_addr_del(struct net *net, int ifindex, u32 ifa_flags,
|
|||||||
|
|
||||||
int addrconf_add_ifaddr(struct net *net, void __user *arg)
|
int addrconf_add_ifaddr(struct net *net, void __user *arg)
|
||||||
{
|
{
|
||||||
|
struct ifa6_config cfg = {
|
||||||
|
.ifa_flags = IFA_F_PERMANENT,
|
||||||
|
.preferred_lft = INFINITY_LIFE_TIME,
|
||||||
|
.valid_lft = INFINITY_LIFE_TIME,
|
||||||
|
};
|
||||||
struct in6_ifreq ireq;
|
struct in6_ifreq ireq;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -2985,10 +2979,11 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
|
|||||||
if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
|
if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
cfg.pfx = &ireq.ifr6_addr;
|
||||||
|
cfg.plen = ireq.ifr6_prefixlen;
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL,
|
err = inet6_addr_add(net, ireq.ifr6_ifindex, &cfg, NULL);
|
||||||
ireq.ifr6_prefixlen, IFA_F_PERMANENT,
|
|
||||||
INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, NULL);
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -4624,12 +4619,11 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||||||
struct net *net = sock_net(skb->sk);
|
struct net *net = sock_net(skb->sk);
|
||||||
struct ifaddrmsg *ifm;
|
struct ifaddrmsg *ifm;
|
||||||
struct nlattr *tb[IFA_MAX+1];
|
struct nlattr *tb[IFA_MAX+1];
|
||||||
struct in6_addr *pfx, *peer_pfx;
|
struct in6_addr *peer_pfx;
|
||||||
struct inet6_ifaddr *ifa;
|
struct inet6_ifaddr *ifa;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
struct inet6_dev *idev;
|
struct inet6_dev *idev;
|
||||||
u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
|
struct ifa6_config cfg;
|
||||||
u32 ifa_flags;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy,
|
err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy,
|
||||||
@ -4637,60 +4631,68 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
memset(&cfg, 0, sizeof(cfg));
|
||||||
|
|
||||||
ifm = nlmsg_data(nlh);
|
ifm = nlmsg_data(nlh);
|
||||||
pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
|
cfg.pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
|
||||||
if (!pfx)
|
if (!cfg.pfx)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
cfg.peer_pfx = peer_pfx;
|
||||||
|
cfg.plen = ifm->ifa_prefixlen;
|
||||||
|
cfg.valid_lft = INFINITY_LIFE_TIME;
|
||||||
|
cfg.preferred_lft = INFINITY_LIFE_TIME;
|
||||||
|
|
||||||
if (tb[IFA_CACHEINFO]) {
|
if (tb[IFA_CACHEINFO]) {
|
||||||
struct ifa_cacheinfo *ci;
|
struct ifa_cacheinfo *ci;
|
||||||
|
|
||||||
ci = nla_data(tb[IFA_CACHEINFO]);
|
ci = nla_data(tb[IFA_CACHEINFO]);
|
||||||
valid_lft = ci->ifa_valid;
|
cfg.valid_lft = ci->ifa_valid;
|
||||||
preferred_lft = ci->ifa_prefered;
|
cfg.preferred_lft = ci->ifa_prefered;
|
||||||
} else {
|
|
||||||
preferred_lft = INFINITY_LIFE_TIME;
|
|
||||||
valid_lft = INFINITY_LIFE_TIME;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = __dev_get_by_index(net, ifm->ifa_index);
|
dev = __dev_get_by_index(net, ifm->ifa_index);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifm->ifa_flags;
|
if (tb[IFA_FLAGS])
|
||||||
|
cfg.ifa_flags = nla_get_u32(tb[IFA_FLAGS]);
|
||||||
|
else
|
||||||
|
cfg.ifa_flags = ifm->ifa_flags;
|
||||||
|
|
||||||
/* We ignore other flags so far. */
|
/* We ignore other flags so far. */
|
||||||
ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR |
|
cfg.ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS |
|
||||||
IFA_F_NOPREFIXROUTE | IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC;
|
IFA_F_MANAGETEMPADDR | IFA_F_NOPREFIXROUTE |
|
||||||
|
IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC;
|
||||||
|
|
||||||
idev = ipv6_find_idev(dev);
|
idev = ipv6_find_idev(dev);
|
||||||
if (IS_ERR(idev))
|
if (IS_ERR(idev))
|
||||||
return PTR_ERR(idev);
|
return PTR_ERR(idev);
|
||||||
|
|
||||||
if (!ipv6_allow_optimistic_dad(net, idev))
|
if (!ipv6_allow_optimistic_dad(net, idev))
|
||||||
ifa_flags &= ~IFA_F_OPTIMISTIC;
|
cfg.ifa_flags &= ~IFA_F_OPTIMISTIC;
|
||||||
|
|
||||||
if (ifa_flags & IFA_F_NODAD && ifa_flags & IFA_F_OPTIMISTIC) {
|
if (cfg.ifa_flags & IFA_F_NODAD &&
|
||||||
|
cfg.ifa_flags & IFA_F_OPTIMISTIC) {
|
||||||
NL_SET_ERR_MSG(extack, "IFA_F_NODAD and IFA_F_OPTIMISTIC are mutually exclusive");
|
NL_SET_ERR_MSG(extack, "IFA_F_NODAD and IFA_F_OPTIMISTIC are mutually exclusive");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ifa = ipv6_get_ifaddr(net, pfx, dev, 1);
|
ifa = ipv6_get_ifaddr(net, cfg.pfx, dev, 1);
|
||||||
if (!ifa) {
|
if (!ifa) {
|
||||||
/*
|
/*
|
||||||
* It would be best to check for !NLM_F_CREATE here but
|
* It would be best to check for !NLM_F_CREATE here but
|
||||||
* userspace already relies on not having to provide this.
|
* userspace already relies on not having to provide this.
|
||||||
*/
|
*/
|
||||||
return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx,
|
return inet6_addr_add(net, ifm->ifa_index, &cfg, extack);
|
||||||
ifm->ifa_prefixlen, ifa_flags,
|
|
||||||
preferred_lft, valid_lft, extack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nlh->nlmsg_flags & NLM_F_EXCL ||
|
if (nlh->nlmsg_flags & NLM_F_EXCL ||
|
||||||
!(nlh->nlmsg_flags & NLM_F_REPLACE))
|
!(nlh->nlmsg_flags & NLM_F_REPLACE))
|
||||||
err = -EEXIST;
|
err = -EEXIST;
|
||||||
else
|
else
|
||||||
err = inet6_addr_modify(ifa, ifa_flags, preferred_lft, valid_lft);
|
err = inet6_addr_modify(ifa, cfg.ifa_flags, cfg.preferred_lft,
|
||||||
|
cfg.valid_lft);
|
||||||
|
|
||||||
in6_ifa_put(ifa);
|
in6_ifa_put(ifa);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user