Commit a14a49d2 authored by Thomas Graf's avatar Thomas Graf Committed by David S. Miller

[NEIGH]: Convert neighbour deletion to new netlink api

Fixes:
  Return ENOENT if the neighbour is not found (was EINVAL)
  Return EAFNOSUPPORT if no table matches the specified
  address family.
Signed-off-by: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3226f688
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <net/dst.h> #include <net/dst.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/netevent.h> #include <net/netevent.h>
#include <net/netlink.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -1440,48 +1441,62 @@ int neigh_table_clear(struct neigh_table *tbl) ...@@ -1440,48 +1441,62 @@ int neigh_table_clear(struct neigh_table *tbl)
int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{ {
struct ndmsg *ndm = NLMSG_DATA(nlh); struct ndmsg *ndm;
struct rtattr **nda = arg; struct nlattr *dst_attr;
struct neigh_table *tbl; struct neigh_table *tbl;
struct net_device *dev = NULL; struct net_device *dev = NULL;
int err = -ENODEV; int err = -EINVAL;
if (ndm->ndm_ifindex && if (nlmsg_len(nlh) < sizeof(*ndm))
(dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL) goto out;
dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
if (dst_attr == NULL)
goto out; goto out;
ndm = nlmsg_data(nlh);
if (ndm->ndm_ifindex) {
dev = dev_get_by_index(ndm->ndm_ifindex);
if (dev == NULL) {
err = -ENODEV;
goto out;
}
}
read_lock(&neigh_tbl_lock); read_lock(&neigh_tbl_lock);
for (tbl = neigh_tables; tbl; tbl = tbl->next) { for (tbl = neigh_tables; tbl; tbl = tbl->next) {
struct rtattr *dst_attr = nda[NDA_DST - 1]; struct neighbour *neigh;
struct neighbour *n;
if (tbl->family != ndm->ndm_family) if (tbl->family != ndm->ndm_family)
continue; continue;
read_unlock(&neigh_tbl_lock); read_unlock(&neigh_tbl_lock);
err = -EINVAL; if (nla_len(dst_attr) < tbl->key_len)
if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len)
goto out_dev_put; goto out_dev_put;
if (ndm->ndm_flags & NTF_PROXY) { if (ndm->ndm_flags & NTF_PROXY) {
err = pneigh_delete(tbl, RTA_DATA(dst_attr), dev); err = pneigh_delete(tbl, nla_data(dst_attr), dev);
goto out_dev_put; goto out_dev_put;
} }
if (!dev) if (dev == NULL)
goto out; goto out_dev_put;
n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev); neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
if (n) { if (neigh == NULL) {
err = neigh_update(n, NULL, NUD_FAILED, err = -ENOENT;
NEIGH_UPDATE_F_OVERRIDE| goto out_dev_put;
NEIGH_UPDATE_F_ADMIN);
neigh_release(n);
} }
err = neigh_update(neigh, NULL, NUD_FAILED,
NEIGH_UPDATE_F_OVERRIDE |
NEIGH_UPDATE_F_ADMIN);
neigh_release(neigh);
goto out_dev_put; goto out_dev_put;
} }
read_unlock(&neigh_tbl_lock); read_unlock(&neigh_tbl_lock);
err = -EADDRNOTAVAIL; err = -EAFNOSUPPORT;
out_dev_put: out_dev_put:
if (dev) if (dev)
dev_put(dev); dev_put(dev);
......
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