diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-10-04 00:27:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-05 17:54:35 -0400 |
commit | 110b2499370c401cdcc7c63e481084467291d556 (patch) | |
tree | 22c0c6ef4f1780a51c20a83e65cd7ce8b70f8b58 /net/core/neighbour.c | |
parent | caf586e5f23cebb2a68cbaf288d59dbbf2d74052 (diff) |
net neigh: neigh_delete() and neigh_add() changes
neigh_delete() and neigh_add() dont need to touch device refcount,
we hold RTNL when calling them, so device cannot disappear under us.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/neighbour.c')
-rw-r--r-- | net/core/neighbour.c | 39 |
1 files changed, 17 insertions, 22 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b142a0d76072..d6996e072a41 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -1531,6 +1531,7 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1531 | struct net_device *dev = NULL; | 1531 | struct net_device *dev = NULL; |
1532 | int err = -EINVAL; | 1532 | int err = -EINVAL; |
1533 | 1533 | ||
1534 | ASSERT_RTNL(); | ||
1534 | if (nlmsg_len(nlh) < sizeof(*ndm)) | 1535 | if (nlmsg_len(nlh) < sizeof(*ndm)) |
1535 | goto out; | 1536 | goto out; |
1536 | 1537 | ||
@@ -1540,7 +1541,7 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1540 | 1541 | ||
1541 | ndm = nlmsg_data(nlh); | 1542 | ndm = nlmsg_data(nlh); |
1542 | if (ndm->ndm_ifindex) { | 1543 | if (ndm->ndm_ifindex) { |
1543 | dev = dev_get_by_index(net, ndm->ndm_ifindex); | 1544 | dev = __dev_get_by_index(net, ndm->ndm_ifindex); |
1544 | if (dev == NULL) { | 1545 | if (dev == NULL) { |
1545 | err = -ENODEV; | 1546 | err = -ENODEV; |
1546 | goto out; | 1547 | goto out; |
@@ -1556,34 +1557,31 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1556 | read_unlock(&neigh_tbl_lock); | 1557 | read_unlock(&neigh_tbl_lock); |
1557 | 1558 | ||
1558 | if (nla_len(dst_attr) < tbl->key_len) | 1559 | if (nla_len(dst_attr) < tbl->key_len) |
1559 | goto out_dev_put; | 1560 | goto out; |
1560 | 1561 | ||
1561 | if (ndm->ndm_flags & NTF_PROXY) { | 1562 | if (ndm->ndm_flags & NTF_PROXY) { |
1562 | err = pneigh_delete(tbl, net, nla_data(dst_attr), dev); | 1563 | err = pneigh_delete(tbl, net, nla_data(dst_attr), dev); |
1563 | goto out_dev_put; | 1564 | goto out; |
1564 | } | 1565 | } |
1565 | 1566 | ||
1566 | if (dev == NULL) | 1567 | if (dev == NULL) |
1567 | goto out_dev_put; | 1568 | goto out; |
1568 | 1569 | ||
1569 | neigh = neigh_lookup(tbl, nla_data(dst_attr), dev); | 1570 | neigh = neigh_lookup(tbl, nla_data(dst_attr), dev); |
1570 | if (neigh == NULL) { | 1571 | if (neigh == NULL) { |
1571 | err = -ENOENT; | 1572 | err = -ENOENT; |
1572 | goto out_dev_put; | 1573 | goto out; |
1573 | } | 1574 | } |
1574 | 1575 | ||
1575 | err = neigh_update(neigh, NULL, NUD_FAILED, | 1576 | err = neigh_update(neigh, NULL, NUD_FAILED, |
1576 | NEIGH_UPDATE_F_OVERRIDE | | 1577 | NEIGH_UPDATE_F_OVERRIDE | |
1577 | NEIGH_UPDATE_F_ADMIN); | 1578 | NEIGH_UPDATE_F_ADMIN); |
1578 | neigh_release(neigh); | 1579 | neigh_release(neigh); |
1579 | goto out_dev_put; | 1580 | goto out; |
1580 | } | 1581 | } |
1581 | read_unlock(&neigh_tbl_lock); | 1582 | read_unlock(&neigh_tbl_lock); |
1582 | err = -EAFNOSUPPORT; | 1583 | err = -EAFNOSUPPORT; |
1583 | 1584 | ||
1584 | out_dev_put: | ||
1585 | if (dev) | ||
1586 | dev_put(dev); | ||
1587 | out: | 1585 | out: |
1588 | return err; | 1586 | return err; |
1589 | } | 1587 | } |
@@ -1597,6 +1595,7 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1597 | struct net_device *dev = NULL; | 1595 | struct net_device *dev = NULL; |
1598 | int err; | 1596 | int err; |
1599 | 1597 | ||
1598 | ASSERT_RTNL(); | ||
1600 | err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); | 1599 | err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); |
1601 | if (err < 0) | 1600 | if (err < 0) |
1602 | goto out; | 1601 | goto out; |
@@ -1607,14 +1606,14 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1607 | 1606 | ||
1608 | ndm = nlmsg_data(nlh); | 1607 | ndm = nlmsg_data(nlh); |
1609 | if (ndm->ndm_ifindex) { | 1608 | if (ndm->ndm_ifindex) { |
1610 | dev = dev_get_by_index(net, ndm->ndm_ifindex); | 1609 | dev = __dev_get_by_index(net, ndm->ndm_ifindex); |
1611 | if (dev == NULL) { | 1610 | if (dev == NULL) { |
1612 | err = -ENODEV; | 1611 | err = -ENODEV; |
1613 | goto out; | 1612 | goto out; |
1614 | } | 1613 | } |
1615 | 1614 | ||
1616 | if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len) | 1615 | if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len) |
1617 | goto out_dev_put; | 1616 | goto out; |
1618 | } | 1617 | } |
1619 | 1618 | ||
1620 | read_lock(&neigh_tbl_lock); | 1619 | read_lock(&neigh_tbl_lock); |
@@ -1628,7 +1627,7 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1628 | read_unlock(&neigh_tbl_lock); | 1627 | read_unlock(&neigh_tbl_lock); |
1629 | 1628 | ||
1630 | if (nla_len(tb[NDA_DST]) < tbl->key_len) | 1629 | if (nla_len(tb[NDA_DST]) < tbl->key_len) |
1631 | goto out_dev_put; | 1630 | goto out; |
1632 | dst = nla_data(tb[NDA_DST]); | 1631 | dst = nla_data(tb[NDA_DST]); |
1633 | lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL; | 1632 | lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL; |
1634 | 1633 | ||
@@ -1641,29 +1640,29 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1641 | pn->flags = ndm->ndm_flags; | 1640 | pn->flags = ndm->ndm_flags; |
1642 | err = 0; | 1641 | err = 0; |
1643 | } | 1642 | } |
1644 | goto out_dev_put; | 1643 | goto out; |
1645 | } | 1644 | } |
1646 | 1645 | ||
1647 | if (dev == NULL) | 1646 | if (dev == NULL) |
1648 | goto out_dev_put; | 1647 | goto out; |
1649 | 1648 | ||
1650 | neigh = neigh_lookup(tbl, dst, dev); | 1649 | neigh = neigh_lookup(tbl, dst, dev); |
1651 | if (neigh == NULL) { | 1650 | if (neigh == NULL) { |
1652 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { | 1651 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { |
1653 | err = -ENOENT; | 1652 | err = -ENOENT; |
1654 | goto out_dev_put; | 1653 | goto out; |
1655 | } | 1654 | } |
1656 | 1655 | ||
1657 | neigh = __neigh_lookup_errno(tbl, dst, dev); | 1656 | neigh = __neigh_lookup_errno(tbl, dst, dev); |
1658 | if (IS_ERR(neigh)) { | 1657 | if (IS_ERR(neigh)) { |
1659 | err = PTR_ERR(neigh); | 1658 | err = PTR_ERR(neigh); |
1660 | goto out_dev_put; | 1659 | goto out; |
1661 | } | 1660 | } |
1662 | } else { | 1661 | } else { |
1663 | if (nlh->nlmsg_flags & NLM_F_EXCL) { | 1662 | if (nlh->nlmsg_flags & NLM_F_EXCL) { |
1664 | err = -EEXIST; | 1663 | err = -EEXIST; |
1665 | neigh_release(neigh); | 1664 | neigh_release(neigh); |
1666 | goto out_dev_put; | 1665 | goto out; |
1667 | } | 1666 | } |
1668 | 1667 | ||
1669 | if (!(nlh->nlmsg_flags & NLM_F_REPLACE)) | 1668 | if (!(nlh->nlmsg_flags & NLM_F_REPLACE)) |
@@ -1676,15 +1675,11 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1676 | } else | 1675 | } else |
1677 | err = neigh_update(neigh, lladdr, ndm->ndm_state, flags); | 1676 | err = neigh_update(neigh, lladdr, ndm->ndm_state, flags); |
1678 | neigh_release(neigh); | 1677 | neigh_release(neigh); |
1679 | goto out_dev_put; | 1678 | goto out; |
1680 | } | 1679 | } |
1681 | 1680 | ||
1682 | read_unlock(&neigh_tbl_lock); | 1681 | read_unlock(&neigh_tbl_lock); |
1683 | err = -EAFNOSUPPORT; | 1682 | err = -EAFNOSUPPORT; |
1684 | |||
1685 | out_dev_put: | ||
1686 | if (dev) | ||
1687 | dev_put(dev); | ||
1688 | out: | 1683 | out: |
1689 | return err; | 1684 | return err; |
1690 | } | 1685 | } |