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

net: Add extack to validator_info structs used for address notifier

Add extack to in_validator_info and in6_validator_info. Update the one
user of each, ipvlan, to return an error message for failures.

Only manual configuration of an address is plumbed in the IPv6 code path.
Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Reviewed-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ff7883ea
...@@ -847,8 +847,11 @@ static int ipvlan_addr6_validator_event(struct notifier_block *unused, ...@@ -847,8 +847,11 @@ static int ipvlan_addr6_validator_event(struct notifier_block *unused,
switch (event) { switch (event) {
case NETDEV_UP: case NETDEV_UP:
if (ipvlan_addr_busy(ipvlan->port, &i6vi->i6vi_addr, true)) if (ipvlan_addr_busy(ipvlan->port, &i6vi->i6vi_addr, true)) {
NL_SET_ERR_MSG(i6vi->extack,
"Address already assigned to an ipvlan device");
return notifier_from_errno(-EADDRINUSE); return notifier_from_errno(-EADDRINUSE);
}
break; break;
} }
...@@ -917,8 +920,11 @@ static int ipvlan_addr4_validator_event(struct notifier_block *unused, ...@@ -917,8 +920,11 @@ static int ipvlan_addr4_validator_event(struct notifier_block *unused,
switch (event) { switch (event) {
case NETDEV_UP: case NETDEV_UP:
if (ipvlan_addr_busy(ipvlan->port, &ivi->ivi_addr, false)) if (ipvlan_addr_busy(ipvlan->port, &ivi->ivi_addr, false)) {
NL_SET_ERR_MSG(ivi->extack,
"Address already assigned to an ipvlan device");
return notifier_from_errno(-EADDRINUSE); return notifier_from_errno(-EADDRINUSE);
}
break; break;
} }
......
...@@ -154,6 +154,7 @@ struct in_ifaddr { ...@@ -154,6 +154,7 @@ struct in_ifaddr {
struct in_validator_info { struct in_validator_info {
__be32 ivi_addr; __be32 ivi_addr;
struct in_device *ivi_dev; struct in_device *ivi_dev;
struct netlink_ext_ack *extack;
}; };
int register_inetaddr_notifier(struct notifier_block *nb); int register_inetaddr_notifier(struct notifier_block *nb);
......
...@@ -55,6 +55,7 @@ struct prefix_info { ...@@ -55,6 +55,7 @@ struct prefix_info {
struct in6_validator_info { struct in6_validator_info {
struct in6_addr i6vi_addr; struct in6_addr i6vi_addr;
struct inet6_dev *i6vi_dev; struct inet6_dev *i6vi_dev;
struct netlink_ext_ack *extack;
}; };
#define IN6_ADDR_HSIZE_SHIFT 4 #define IN6_ADDR_HSIZE_SHIFT 4
......
...@@ -444,7 +444,7 @@ static void check_lifetime(struct work_struct *work); ...@@ -444,7 +444,7 @@ static void check_lifetime(struct work_struct *work);
static DECLARE_DELAYED_WORK(check_lifetime_work, check_lifetime); static DECLARE_DELAYED_WORK(check_lifetime_work, check_lifetime);
static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
u32 portid) u32 portid, struct netlink_ext_ack *extack)
{ {
struct in_device *in_dev = ifa->ifa_dev; struct in_device *in_dev = ifa->ifa_dev;
struct in_ifaddr *ifa1, **ifap, **last_primary; struct in_ifaddr *ifa1, **ifap, **last_primary;
...@@ -489,6 +489,7 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, ...@@ -489,6 +489,7 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
*/ */
ivi.ivi_addr = ifa->ifa_address; ivi.ivi_addr = ifa->ifa_address;
ivi.ivi_dev = ifa->ifa_dev; ivi.ivi_dev = ifa->ifa_dev;
ivi.extack = extack;
ret = blocking_notifier_call_chain(&inetaddr_validator_chain, ret = blocking_notifier_call_chain(&inetaddr_validator_chain,
NETDEV_UP, &ivi); NETDEV_UP, &ivi);
ret = notifier_to_errno(ret); ret = notifier_to_errno(ret);
...@@ -521,7 +522,7 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, ...@@ -521,7 +522,7 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
static int inet_insert_ifa(struct in_ifaddr *ifa) static int inet_insert_ifa(struct in_ifaddr *ifa)
{ {
return __inet_insert_ifa(ifa, NULL, 0); return __inet_insert_ifa(ifa, NULL, 0, NULL);
} }
static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
...@@ -902,7 +903,8 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -902,7 +903,8 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
return ret; return ret;
} }
} }
return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid); return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid,
extack);
} else { } else {
inet_free_ifa(ifa); inet_free_ifa(ifa);
......
...@@ -987,7 +987,7 @@ static struct inet6_ifaddr * ...@@ -987,7 +987,7 @@ static struct inet6_ifaddr *
ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
const struct in6_addr *peer_addr, int pfxlen, const struct in6_addr *peer_addr, int pfxlen,
int scope, u32 flags, u32 valid_lft, u32 prefered_lft, int scope, u32 flags, u32 valid_lft, u32 prefered_lft,
bool can_block) bool can_block, struct netlink_ext_ack *extack)
{ {
gfp_t gfp_flags = can_block ? GFP_KERNEL : GFP_ATOMIC; gfp_t gfp_flags = can_block ? GFP_KERNEL : GFP_ATOMIC;
struct net *net = dev_net(idev->dev); struct net *net = dev_net(idev->dev);
...@@ -1019,6 +1019,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, ...@@ -1019,6 +1019,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
struct in6_validator_info i6vi = { struct in6_validator_info i6vi = {
.i6vi_addr = *addr, .i6vi_addr = *addr,
.i6vi_dev = idev, .i6vi_dev = idev,
.extack = extack,
}; };
err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi); err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi);
...@@ -1356,7 +1357,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i ...@@ -1356,7 +1357,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
ift = ipv6_add_addr(idev, &addr, NULL, tmp_plen, ift = ipv6_add_addr(idev, &addr, NULL, tmp_plen,
ipv6_addr_scope(&addr), addr_flags, ipv6_addr_scope(&addr), addr_flags,
tmp_valid_lft, tmp_prefered_lft, true); tmp_valid_lft, tmp_prefered_lft, true, NULL);
if (IS_ERR(ift)) { if (IS_ERR(ift)) {
in6_ifa_put(ifp); in6_ifa_put(ifp);
in6_dev_put(idev); in6_dev_put(idev);
...@@ -2040,7 +2041,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) ...@@ -2040,7 +2041,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
ifp2 = ipv6_add_addr(idev, &new_addr, NULL, pfxlen, ifp2 = ipv6_add_addr(idev, &new_addr, NULL, pfxlen,
scope, flags, valid_lft, scope, flags, valid_lft,
preferred_lft, false); preferred_lft, false, NULL);
if (IS_ERR(ifp2)) if (IS_ERR(ifp2))
goto lock_errdad; goto lock_errdad;
...@@ -2498,7 +2499,7 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev, ...@@ -2498,7 +2499,7 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
pinfo->prefix_len, pinfo->prefix_len,
addr_type&IPV6_ADDR_SCOPE_MASK, addr_type&IPV6_ADDR_SCOPE_MASK,
addr_flags, valid_lft, addr_flags, valid_lft,
prefered_lft, false); prefered_lft, false, NULL);
if (IS_ERR_OR_NULL(ifp)) if (IS_ERR_OR_NULL(ifp))
return -1; return -1;
...@@ -2808,7 +2809,8 @@ static int inet6_addr_add(struct net *net, int ifindex, ...@@ -2808,7 +2809,8 @@ static int inet6_addr_add(struct net *net, int ifindex,
const struct in6_addr *pfx, const struct in6_addr *pfx,
const struct in6_addr *peer_pfx, const struct in6_addr *peer_pfx,
unsigned int plen, __u32 ifa_flags, unsigned int plen, __u32 ifa_flags,
__u32 prefered_lft, __u32 valid_lft) __u32 prefered_lft, __u32 valid_lft,
struct netlink_ext_ack *extack)
{ {
struct inet6_ifaddr *ifp; struct inet6_ifaddr *ifp;
struct inet6_dev *idev; struct inet6_dev *idev;
...@@ -2867,7 +2869,7 @@ static int inet6_addr_add(struct net *net, int ifindex, ...@@ -2867,7 +2869,7 @@ static int inet6_addr_add(struct net *net, int ifindex,
} }
ifp = ipv6_add_addr(idev, pfx, peer_pfx, plen, scope, ifa_flags, ifp = ipv6_add_addr(idev, pfx, peer_pfx, plen, scope, ifa_flags,
valid_lft, prefered_lft, true); valid_lft, prefered_lft, true, extack);
if (!IS_ERR(ifp)) { if (!IS_ERR(ifp)) {
if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) { if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) {
...@@ -2952,7 +2954,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg) ...@@ -2952,7 +2954,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
rtnl_lock(); rtnl_lock();
err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL, err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL,
ireq.ifr6_prefixlen, IFA_F_PERMANENT, ireq.ifr6_prefixlen, IFA_F_PERMANENT,
INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, NULL);
rtnl_unlock(); rtnl_unlock();
return err; return err;
} }
...@@ -2983,7 +2985,7 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr, ...@@ -2983,7 +2985,7 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
ifp = ipv6_add_addr(idev, addr, NULL, plen, ifp = ipv6_add_addr(idev, addr, NULL, plen,
scope, IFA_F_PERMANENT, scope, IFA_F_PERMANENT,
INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME,
true); true, NULL);
if (!IS_ERR(ifp)) { if (!IS_ERR(ifp)) {
spin_lock_bh(&ifp->lock); spin_lock_bh(&ifp->lock);
ifp->flags &= ~IFA_F_TENTATIVE; ifp->flags &= ~IFA_F_TENTATIVE;
...@@ -3083,7 +3085,7 @@ void addrconf_add_linklocal(struct inet6_dev *idev, ...@@ -3083,7 +3085,7 @@ void addrconf_add_linklocal(struct inet6_dev *idev,
#endif #endif
ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags, ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags,
INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, true); INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, true, NULL);
if (!IS_ERR(ifp)) { if (!IS_ERR(ifp)) {
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0); addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
addrconf_dad_start(ifp); addrconf_dad_start(ifp);
...@@ -4586,7 +4588,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -4586,7 +4588,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
*/ */
return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx, return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx,
ifm->ifa_prefixlen, ifa_flags, ifm->ifa_prefixlen, ifa_flags,
preferred_lft, valid_lft); preferred_lft, valid_lft, extack);
} }
if (nlh->nlmsg_flags & NLM_F_EXCL || if (nlh->nlmsg_flags & NLM_F_EXCL ||
......
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