Skip to content

Commit

Permalink
[NEIGH]: Convert neighbour addition to new netlink api
Browse files Browse the repository at this point in the history
Fixes:
    Return EAFNOSUPPORT if no table matches the specified
    address family.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Thomas Graf authored and David S. Miller committed Sep 22, 2006
1 parent a14a49d commit 5208deb
Showing 1 changed file with 51 additions and 39 deletions.
90 changes: 51 additions & 39 deletions net/core/neighbour.c
Original file line number Diff line number Diff line change
Expand Up @@ -1506,76 +1506,88 @@ int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)

int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct ndmsg *ndm = NLMSG_DATA(nlh);
struct rtattr **nda = arg;
struct ndmsg *ndm;
struct nlattr *tb[NDA_MAX+1];
struct neigh_table *tbl;
struct net_device *dev = NULL;
int err = -ENODEV;
int err;

err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
if (err < 0)
goto out;

if (ndm->ndm_ifindex &&
(dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL)
err = -EINVAL;
if (tb[NDA_DST] == NULL)
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;
}

if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
goto out_dev_put;
}

read_lock(&neigh_tbl_lock);
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;
struct neighbour *n;
int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
struct neighbour *neigh;
void *dst, *lladdr;

if (tbl->family != ndm->ndm_family)
continue;
read_unlock(&neigh_tbl_lock);

err = -EINVAL;
if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len)
if (nla_len(tb[NDA_DST]) < tbl->key_len)
goto out_dev_put;
dst = nla_data(tb[NDA_DST]);
lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;

if (ndm->ndm_flags & NTF_PROXY) {
err = -ENOBUFS;
if (pneigh_lookup(tbl, RTA_DATA(dst_attr), dev, 1))
err = 0;
err = 0;
if (pneigh_lookup(tbl, dst, dev, 1) == NULL)
err = -ENOBUFS;
goto out_dev_put;
}

err = -EINVAL;
if (!dev)
goto out;
if (lladdr_attr && RTA_PAYLOAD(lladdr_attr) < dev->addr_len)
if (dev == NULL)
goto out_dev_put;

neigh = neigh_lookup(tbl, dst, dev);
if (neigh == NULL) {
if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
err = -ENOENT;
goto out_dev_put;
}

n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev);
if (n) {
if (nlh->nlmsg_flags & NLM_F_EXCL) {
err = -EEXIST;
neigh_release(n);
neigh = __neigh_lookup_errno(tbl, dst, dev);
if (IS_ERR(neigh)) {
err = PTR_ERR(neigh);
goto out_dev_put;
}

override = nlh->nlmsg_flags & NLM_F_REPLACE;
} else if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
err = -ENOENT;
goto out_dev_put;
} else {
n = __neigh_lookup_errno(tbl, RTA_DATA(dst_attr), dev);
if (IS_ERR(n)) {
err = PTR_ERR(n);
if (nlh->nlmsg_flags & NLM_F_EXCL) {
err = -EEXIST;
neigh_release(neigh);
goto out_dev_put;
}
}

err = neigh_update(n,
lladdr_attr ? RTA_DATA(lladdr_attr) : NULL,
ndm->ndm_state,
(override ? NEIGH_UPDATE_F_OVERRIDE : 0) |
NEIGH_UPDATE_F_ADMIN);
if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
flags &= ~NEIGH_UPDATE_F_OVERRIDE;
}

neigh_release(n);
err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
neigh_release(neigh);
goto out_dev_put;
}

read_unlock(&neigh_tbl_lock);
err = -EADDRNOTAVAIL;
err = -EAFNOSUPPORT;

out_dev_put:
if (dev)
dev_put(dev);
Expand Down

0 comments on commit 5208deb

Please sign in to comment.