Commit 19b1518c authored by David Ahern's avatar David Ahern Committed by David S. Miller

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: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e6464b8c
...@@ -2830,20 +2830,9 @@ static int ipv6_mc_config(struct sock *sk, bool join, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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);
......
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