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:
Родитель
e6464b8c63
Коммит
19b1518c29
|
@ -2830,20 +2830,9 @@ static int ipv6_mc_config(struct sock *sk, bool join,
|
|||
* Manual configuration of address on an interface
|
||||
*/
|
||||
static int inet6_addr_add(struct net *net, int ifindex,
|
||||
const struct in6_addr *pfx,
|
||||
const struct in6_addr *peer_pfx,
|
||||
unsigned int plen, __u32 ifa_flags,
|
||||
__u32 prefered_lft, __u32 valid_lft,
|
||||
struct ifa6_config *cfg,
|
||||
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_dev *idev;
|
||||
struct net_device *dev;
|
||||
|
@ -2853,14 +2842,14 @@ static int inet6_addr_add(struct net *net, int ifindex,
|
|||
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (plen > 128)
|
||||
if (cfg->plen > 128)
|
||||
return -EINVAL;
|
||||
|
||||
/* check the lifetime */
|
||||
if (!valid_lft || prefered_lft > valid_lft)
|
||||
if (!cfg->valid_lft || cfg->preferred_lft > cfg->valid_lft)
|
||||
return -EINVAL;
|
||||
|
||||
if (ifa_flags & IFA_F_MANAGETEMPADDR && plen != 64)
|
||||
if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR && cfg->plen != 64)
|
||||
return -EINVAL;
|
||||
|
||||
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))
|
||||
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,
|
||||
true, pfx, ifindex);
|
||||
true, cfg->pfx, ifindex);
|
||||
|
||||
if (ret < 0)
|
||||
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)) {
|
||||
expires = jiffies_to_clock_t(timeout * HZ);
|
||||
valid_lft = timeout;
|
||||
cfg->valid_lft = timeout;
|
||||
flags = RTF_EXPIRES;
|
||||
} else {
|
||||
expires = 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 (timeout == 0)
|
||||
ifa_flags |= IFA_F_DEPRECATED;
|
||||
prefered_lft = timeout;
|
||||
cfg->ifa_flags |= IFA_F_DEPRECATED;
|
||||
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 (!(ifa_flags & IFA_F_NOPREFIXROUTE)) {
|
||||
if (!(cfg->ifa_flags & IFA_F_NOPREFIXROUTE)) {
|
||||
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
|
||||
expires, flags, GFP_KERNEL);
|
||||
}
|
||||
|
@ -2917,15 +2906,15 @@ static int inet6_addr_add(struct net *net, int ifindex,
|
|||
* manually configured addresses
|
||||
*/
|
||||
addrconf_dad_start(ifp);
|
||||
if (ifa_flags & IFA_F_MANAGETEMPADDR)
|
||||
manage_tempaddrs(idev, ifp, valid_lft, prefered_lft,
|
||||
true, jiffies);
|
||||
if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR)
|
||||
manage_tempaddrs(idev, ifp, cfg->valid_lft,
|
||||
cfg->preferred_lft, true, jiffies);
|
||||
in6_ifa_put(ifp);
|
||||
addrconf_verify_rtnl();
|
||||
return 0;
|
||||
} else if (ifa_flags & IFA_F_MCAUTOJOIN) {
|
||||
ipv6_mc_config(net->ipv6.mc_autojoin_sk,
|
||||
false, pfx, ifindex);
|
||||
} else if (cfg->ifa_flags & IFA_F_MCAUTOJOIN) {
|
||||
ipv6_mc_config(net->ipv6.mc_autojoin_sk, false,
|
||||
cfg->pfx, ifindex);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct ifa6_config cfg = {
|
||||
.ifa_flags = IFA_F_PERMANENT,
|
||||
.preferred_lft = INFINITY_LIFE_TIME,
|
||||
.valid_lft = INFINITY_LIFE_TIME,
|
||||
};
|
||||
struct in6_ifreq ireq;
|
||||
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)))
|
||||
return -EFAULT;
|
||||
|
||||
cfg.pfx = &ireq.ifr6_addr;
|
||||
cfg.plen = ireq.ifr6_prefixlen;
|
||||
|
||||
rtnl_lock();
|
||||
err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL,
|
||||
ireq.ifr6_prefixlen, IFA_F_PERMANENT,
|
||||
INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, NULL);
|
||||
err = inet6_addr_add(net, ireq.ifr6_ifindex, &cfg, NULL);
|
||||
rtnl_unlock();
|
||||
return err;
|
||||
}
|
||||
|
@ -4624,12 +4619,11 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
struct net *net = sock_net(skb->sk);
|
||||
struct ifaddrmsg *ifm;
|
||||
struct nlattr *tb[IFA_MAX+1];
|
||||
struct in6_addr *pfx, *peer_pfx;
|
||||
struct in6_addr *peer_pfx;
|
||||
struct inet6_ifaddr *ifa;
|
||||
struct net_device *dev;
|
||||
struct inet6_dev *idev;
|
||||
u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
|
||||
u32 ifa_flags;
|
||||
struct ifa6_config cfg;
|
||||
int err;
|
||||
|
||||
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)
|
||||
return err;
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
|
||||
ifm = nlmsg_data(nlh);
|
||||
pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
|
||||
if (!pfx)
|
||||
cfg.pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
|
||||
if (!cfg.pfx)
|
||||
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]) {
|
||||
struct ifa_cacheinfo *ci;
|
||||
|
||||
ci = nla_data(tb[IFA_CACHEINFO]);
|
||||
valid_lft = ci->ifa_valid;
|
||||
preferred_lft = ci->ifa_prefered;
|
||||
} else {
|
||||
preferred_lft = INFINITY_LIFE_TIME;
|
||||
valid_lft = INFINITY_LIFE_TIME;
|
||||
cfg.valid_lft = ci->ifa_valid;
|
||||
cfg.preferred_lft = ci->ifa_prefered;
|
||||
}
|
||||
|
||||
dev = __dev_get_by_index(net, ifm->ifa_index);
|
||||
if (!dev)
|
||||
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. */
|
||||
ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR |
|
||||
IFA_F_NOPREFIXROUTE | IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC;
|
||||
cfg.ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS |
|
||||
IFA_F_MANAGETEMPADDR | IFA_F_NOPREFIXROUTE |
|
||||
IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC;
|
||||
|
||||
idev = ipv6_find_idev(dev);
|
||||
if (IS_ERR(idev))
|
||||
return PTR_ERR(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");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ifa = ipv6_get_ifaddr(net, pfx, dev, 1);
|
||||
ifa = ipv6_get_ifaddr(net, cfg.pfx, dev, 1);
|
||||
if (!ifa) {
|
||||
/*
|
||||
* It would be best to check for !NLM_F_CREATE here but
|
||||
* userspace already relies on not having to provide this.
|
||||
*/
|
||||
return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx,
|
||||
ifm->ifa_prefixlen, ifa_flags,
|
||||
preferred_lft, valid_lft, extack);
|
||||
return inet6_addr_add(net, ifm->ifa_index, &cfg, extack);
|
||||
}
|
||||
|
||||
if (nlh->nlmsg_flags & NLM_F_EXCL ||
|
||||
!(nlh->nlmsg_flags & NLM_F_REPLACE))
|
||||
err = -EEXIST;
|
||||
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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче