aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/neighbour.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-10-04 00:27:36 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-05 17:54:35 -0400
commit110b2499370c401cdcc7c63e481084467291d556 (patch)
tree22c0c6ef4f1780a51c20a83e65cd7ce8b70f8b58 /net/core/neighbour.c
parentcaf586e5f23cebb2a68cbaf288d59dbbf2d74052 (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.c39
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
1584out_dev_put:
1585 if (dev)
1586 dev_put(dev);
1587out: 1585out:
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
1685out_dev_put:
1686 if (dev)
1687 dev_put(dev);
1688out: 1683out:
1689 return err; 1684 return err;
1690} 1685}