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

[NEIGH]: rtnetlink neighbour cleanups

Signed-off-by: default avatarThomas Graf <tgraf@suug.ch>
Acked-by: default avatarHideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c99be4f8
...@@ -1430,6 +1430,7 @@ int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -1430,6 +1430,7 @@ int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
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 *n; struct neighbour *n;
if (tbl->family != ndm->ndm_family) if (tbl->family != ndm->ndm_family)
...@@ -1437,20 +1438,18 @@ int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -1437,20 +1438,18 @@ int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
read_unlock(&neigh_tbl_lock); read_unlock(&neigh_tbl_lock);
err = -EINVAL; err = -EINVAL;
if (!nda[NDA_DST - 1] || if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len)
nda[NDA_DST - 1]->rta_len != RTA_LENGTH(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, err = pneigh_delete(tbl, RTA_DATA(dst_attr), dev);
RTA_DATA(nda[NDA_DST - 1]), dev);
goto out_dev_put; goto out_dev_put;
} }
if (!dev) if (!dev)
goto out; goto out;
n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST - 1]), dev); n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev);
if (n) { if (n) {
err = neigh_update(n, NULL, NUD_FAILED, err = neigh_update(n, NULL, NUD_FAILED,
NEIGH_UPDATE_F_OVERRIDE| NEIGH_UPDATE_F_OVERRIDE|
...@@ -1482,6 +1481,8 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -1482,6 +1481,8 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
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 *lladdr_attr = nda[NDA_LLADDR - 1];
struct rtattr *dst_attr = nda[NDA_DST - 1];
int override = 1; int override = 1;
struct neighbour *n; struct neighbour *n;
...@@ -1490,48 +1491,49 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -1490,48 +1491,49 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
read_unlock(&neigh_tbl_lock); read_unlock(&neigh_tbl_lock);
err = -EINVAL; err = -EINVAL;
if (!nda[NDA_DST - 1] || if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len)
nda[NDA_DST - 1]->rta_len != RTA_LENGTH(tbl->key_len))
goto out_dev_put; goto out_dev_put;
if (ndm->ndm_flags & NTF_PROXY) { if (ndm->ndm_flags & NTF_PROXY) {
err = -ENOBUFS; err = -ENOBUFS;
if (pneigh_lookup(tbl, if (pneigh_lookup(tbl, RTA_DATA(dst_attr), dev, 1))
RTA_DATA(nda[NDA_DST - 1]), dev, 1))
err = 0; err = 0;
goto out_dev_put; goto out_dev_put;
} }
err = -EINVAL; err = -EINVAL;
if (!dev) if (!dev)
goto out; goto out;
if (nda[NDA_LLADDR - 1] && if (lladdr_attr && RTA_PAYLOAD(lladdr_attr) < dev->addr_len)
nda[NDA_LLADDR - 1]->rta_len != RTA_LENGTH(dev->addr_len))
goto out_dev_put; goto out_dev_put;
err = 0;
n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST - 1]), dev); n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev);
if (n) { if (n) {
if (nlh->nlmsg_flags & NLM_F_EXCL) if (nlh->nlmsg_flags & NLM_F_EXCL) {
err = -EEXIST; err = -EEXIST;
neigh_release(n);
goto out_dev_put;
}
override = nlh->nlmsg_flags & NLM_F_REPLACE; override = nlh->nlmsg_flags & NLM_F_REPLACE;
} else if (!(nlh->nlmsg_flags & NLM_F_CREATE)) } else if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
err = -ENOENT; err = -ENOENT;
else { goto out_dev_put;
n = __neigh_lookup_errno(tbl, RTA_DATA(nda[NDA_DST - 1]), } else {
dev); n = __neigh_lookup_errno(tbl, RTA_DATA(dst_attr), dev);
if (IS_ERR(n)) { if (IS_ERR(n)) {
err = PTR_ERR(n); err = PTR_ERR(n);
n = NULL; goto out_dev_put;
} }
} }
if (!err) {
err = neigh_update(n, nda[NDA_LLADDR - 1] ? err = neigh_update(n,
RTA_DATA(nda[NDA_LLADDR - 1]) : lladdr_attr ? RTA_DATA(lladdr_attr) : NULL,
NULL, ndm->ndm_state,
ndm->ndm_state, (override ? NEIGH_UPDATE_F_OVERRIDE : 0) |
(override ? NEIGH_UPDATE_F_OVERRIDE : 0) | NEIGH_UPDATE_F_ADMIN);
NEIGH_UPDATE_F_ADMIN);
} neigh_release(n);
if (n)
neigh_release(n);
goto out_dev_put; goto out_dev_put;
} }
......
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