devinet.c (aaccf3c97418f169afdbb5855e9cbcbda34e90fd) | devinet.c (dac9c9790e542777079999900594fd069ba10489) |
---|---|
1/* 2 * NET3 IP device support routines. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * --- 86 unchanged lines hidden (view full) --- 95static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = { 96 [IFA_LOCAL] = { .type = NLA_U32 }, 97 [IFA_ADDRESS] = { .type = NLA_U32 }, 98 [IFA_BROADCAST] = { .type = NLA_U32 }, 99 [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, 100 [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) }, 101 [IFA_FLAGS] = { .type = NLA_U32 }, 102 [IFA_RT_PRIORITY] = { .type = NLA_U32 }, | 1/* 2 * NET3 IP device support routines. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * --- 86 unchanged lines hidden (view full) --- 95static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = { 96 [IFA_LOCAL] = { .type = NLA_U32 }, 97 [IFA_ADDRESS] = { .type = NLA_U32 }, 98 [IFA_BROADCAST] = { .type = NLA_U32 }, 99 [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, 100 [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) }, 101 [IFA_FLAGS] = { .type = NLA_U32 }, 102 [IFA_RT_PRIORITY] = { .type = NLA_U32 }, |
103 [IFA_TARGET_NETNSID] = { .type = NLA_S32 }, |
|
103}; 104 | 104}; 105 |
106struct inet_fill_args { 107 u32 portid; 108 u32 seq; 109 int event; 110 unsigned int flags; 111 int netnsid; 112}; 113 |
|
105#define IN4_ADDR_HSIZE_SHIFT 8 106#define IN4_ADDR_HSIZE (1U << IN4_ADDR_HSIZE_SHIFT) 107 108static struct hlist_head inet_addr_lst[IN4_ADDR_HSIZE]; 109 110static u32 inet_addr_hash(const struct net *net, __be32 addr) 111{ 112 u32 val = (__force u32) addr ^ net_hash_mix(net); --- 655 unchanged lines hidden (view full) --- 768 ifa->ifa_preferred_lft = timeout; 769 } 770 ifa->ifa_tstamp = jiffies; 771 if (!ifa->ifa_cstamp) 772 ifa->ifa_cstamp = ifa->ifa_tstamp; 773} 774 775static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh, | 114#define IN4_ADDR_HSIZE_SHIFT 8 115#define IN4_ADDR_HSIZE (1U << IN4_ADDR_HSIZE_SHIFT) 116 117static struct hlist_head inet_addr_lst[IN4_ADDR_HSIZE]; 118 119static u32 inet_addr_hash(const struct net *net, __be32 addr) 120{ 121 u32 val = (__force u32) addr ^ net_hash_mix(net); --- 655 unchanged lines hidden (view full) --- 777 ifa->ifa_preferred_lft = timeout; 778 } 779 ifa->ifa_tstamp = jiffies; 780 if (!ifa->ifa_cstamp) 781 ifa->ifa_cstamp = ifa->ifa_tstamp; 782} 783 784static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh, |
776 __u32 *pvalid_lft, __u32 *pprefered_lft) | 785 __u32 *pvalid_lft, __u32 *pprefered_lft, 786 struct netlink_ext_ack *extack) |
777{ 778 struct nlattr *tb[IFA_MAX+1]; 779 struct in_ifaddr *ifa; 780 struct ifaddrmsg *ifm; 781 struct net_device *dev; 782 struct in_device *in_dev; 783 int err; 784 785 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy, | 787{ 788 struct nlattr *tb[IFA_MAX+1]; 789 struct in_ifaddr *ifa; 790 struct ifaddrmsg *ifm; 791 struct net_device *dev; 792 struct in_device *in_dev; 793 int err; 794 795 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy, |
786 NULL); | 796 extack); |
787 if (err < 0) 788 goto errout; 789 790 ifm = nlmsg_data(nlh); 791 err = -EINVAL; 792 if (ifm->ifa_prefixlen > 32 || !tb[IFA_LOCAL]) 793 goto errout; 794 --- 88 unchanged lines hidden (view full) --- 883 struct net *net = sock_net(skb->sk); 884 struct in_ifaddr *ifa; 885 struct in_ifaddr *ifa_existing; 886 __u32 valid_lft = INFINITY_LIFE_TIME; 887 __u32 prefered_lft = INFINITY_LIFE_TIME; 888 889 ASSERT_RTNL(); 890 | 797 if (err < 0) 798 goto errout; 799 800 ifm = nlmsg_data(nlh); 801 err = -EINVAL; 802 if (ifm->ifa_prefixlen > 32 || !tb[IFA_LOCAL]) 803 goto errout; 804 --- 88 unchanged lines hidden (view full) --- 893 struct net *net = sock_net(skb->sk); 894 struct in_ifaddr *ifa; 895 struct in_ifaddr *ifa_existing; 896 __u32 valid_lft = INFINITY_LIFE_TIME; 897 __u32 prefered_lft = INFINITY_LIFE_TIME; 898 899 ASSERT_RTNL(); 900 |
891 ifa = rtm_to_ifaddr(net, nlh, &valid_lft, &prefered_lft); | 901 ifa = rtm_to_ifaddr(net, nlh, &valid_lft, &prefered_lft, extack); |
892 if (IS_ERR(ifa)) 893 return PTR_ERR(ifa); 894 895 ifa_existing = find_matching_ifa(ifa); 896 if (!ifa_existing) { 897 /* It would be best to check for !NLM_F_CREATE here but 898 * userspace already relies on not having to provide this. 899 */ --- 679 unchanged lines hidden (view full) --- 1579 ci.tstamp = cstamp_delta(tstamp); 1580 ci.ifa_prefered = preferred; 1581 ci.ifa_valid = valid; 1582 1583 return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci); 1584} 1585 1586static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, | 902 if (IS_ERR(ifa)) 903 return PTR_ERR(ifa); 904 905 ifa_existing = find_matching_ifa(ifa); 906 if (!ifa_existing) { 907 /* It would be best to check for !NLM_F_CREATE here but 908 * userspace already relies on not having to provide this. 909 */ --- 679 unchanged lines hidden (view full) --- 1589 ci.tstamp = cstamp_delta(tstamp); 1590 ci.ifa_prefered = preferred; 1591 ci.ifa_valid = valid; 1592 1593 return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci); 1594} 1595 1596static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, |
1587 u32 portid, u32 seq, int event, unsigned int flags) | 1597 struct inet_fill_args *args) |
1588{ 1589 struct ifaddrmsg *ifm; 1590 struct nlmsghdr *nlh; 1591 u32 preferred, valid; 1592 | 1598{ 1599 struct ifaddrmsg *ifm; 1600 struct nlmsghdr *nlh; 1601 u32 preferred, valid; 1602 |
1593 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*ifm), flags); | 1603 nlh = nlmsg_put(skb, args->portid, args->seq, args->event, sizeof(*ifm), 1604 args->flags); |
1594 if (!nlh) 1595 return -EMSGSIZE; 1596 1597 ifm = nlmsg_data(nlh); 1598 ifm->ifa_family = AF_INET; 1599 ifm->ifa_prefixlen = ifa->ifa_prefixlen; 1600 ifm->ifa_flags = ifa->ifa_flags; 1601 ifm->ifa_scope = ifa->ifa_scope; 1602 ifm->ifa_index = ifa->ifa_dev->dev->ifindex; 1603 | 1605 if (!nlh) 1606 return -EMSGSIZE; 1607 1608 ifm = nlmsg_data(nlh); 1609 ifm->ifa_family = AF_INET; 1610 ifm->ifa_prefixlen = ifa->ifa_prefixlen; 1611 ifm->ifa_flags = ifa->ifa_flags; 1612 ifm->ifa_scope = ifa->ifa_scope; 1613 ifm->ifa_index = ifa->ifa_dev->dev->ifindex; 1614 |
1615 if (args->netnsid >= 0 && 1616 nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid)) 1617 goto nla_put_failure; 1618 |
|
1604 if (!(ifm->ifa_flags & IFA_F_PERMANENT)) { 1605 preferred = ifa->ifa_preferred_lft; 1606 valid = ifa->ifa_valid_lft; 1607 if (preferred != INFINITY_LIFE_TIME) { 1608 long tval = (jiffies - ifa->ifa_tstamp) / HZ; 1609 1610 if (preferred > tval) 1611 preferred -= tval; --- 30 unchanged lines hidden (view full) --- 1642 1643nla_put_failure: 1644 nlmsg_cancel(skb, nlh); 1645 return -EMSGSIZE; 1646} 1647 1648static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) 1649{ | 1619 if (!(ifm->ifa_flags & IFA_F_PERMANENT)) { 1620 preferred = ifa->ifa_preferred_lft; 1621 valid = ifa->ifa_valid_lft; 1622 if (preferred != INFINITY_LIFE_TIME) { 1623 long tval = (jiffies - ifa->ifa_tstamp) / HZ; 1624 1625 if (preferred > tval) 1626 preferred -= tval; --- 30 unchanged lines hidden (view full) --- 1657 1658nla_put_failure: 1659 nlmsg_cancel(skb, nlh); 1660 return -EMSGSIZE; 1661} 1662 1663static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) 1664{ |
1665 struct inet_fill_args fillargs = { 1666 .portid = NETLINK_CB(cb->skb).portid, 1667 .seq = cb->nlh->nlmsg_seq, 1668 .event = RTM_NEWADDR, 1669 .flags = NLM_F_MULTI, 1670 .netnsid = -1, 1671 }; |
|
1650 struct net *net = sock_net(skb->sk); | 1672 struct net *net = sock_net(skb->sk); |
1673 struct nlattr *tb[IFA_MAX+1]; 1674 struct net *tgt_net = net; |
|
1651 int h, s_h; 1652 int idx, s_idx; 1653 int ip_idx, s_ip_idx; 1654 struct net_device *dev; 1655 struct in_device *in_dev; 1656 struct in_ifaddr *ifa; 1657 struct hlist_head *head; 1658 1659 s_h = cb->args[0]; 1660 s_idx = idx = cb->args[1]; 1661 s_ip_idx = ip_idx = cb->args[2]; 1662 | 1675 int h, s_h; 1676 int idx, s_idx; 1677 int ip_idx, s_ip_idx; 1678 struct net_device *dev; 1679 struct in_device *in_dev; 1680 struct in_ifaddr *ifa; 1681 struct hlist_head *head; 1682 1683 s_h = cb->args[0]; 1684 s_idx = idx = cb->args[1]; 1685 s_ip_idx = ip_idx = cb->args[2]; 1686 |
1687 if (nlmsg_parse(cb->nlh, sizeof(struct ifaddrmsg), tb, IFA_MAX, 1688 ifa_ipv4_policy, cb->extack) >= 0) { 1689 if (tb[IFA_TARGET_NETNSID]) { 1690 fillargs.netnsid = nla_get_s32(tb[IFA_TARGET_NETNSID]); 1691 1692 tgt_net = rtnl_get_net_ns_capable(skb->sk, 1693 fillargs.netnsid); 1694 if (IS_ERR(tgt_net)) 1695 return PTR_ERR(tgt_net); 1696 } 1697 } 1698 |
|
1663 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { 1664 idx = 0; | 1699 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { 1700 idx = 0; |
1665 head = &net->dev_index_head[h]; | 1701 head = &tgt_net->dev_index_head[h]; |
1666 rcu_read_lock(); | 1702 rcu_read_lock(); |
1667 cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^ 1668 net->dev_base_seq; | 1703 cb->seq = atomic_read(&tgt_net->ipv4.dev_addr_genid) ^ 1704 tgt_net->dev_base_seq; |
1669 hlist_for_each_entry_rcu(dev, head, index_hlist) { 1670 if (idx < s_idx) 1671 goto cont; 1672 if (h > s_h || idx > s_idx) 1673 s_ip_idx = 0; 1674 in_dev = __in_dev_get_rcu(dev); 1675 if (!in_dev) 1676 goto cont; 1677 1678 for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; 1679 ifa = ifa->ifa_next, ip_idx++) { 1680 if (ip_idx < s_ip_idx) 1681 continue; | 1705 hlist_for_each_entry_rcu(dev, head, index_hlist) { 1706 if (idx < s_idx) 1707 goto cont; 1708 if (h > s_h || idx > s_idx) 1709 s_ip_idx = 0; 1710 in_dev = __in_dev_get_rcu(dev); 1711 if (!in_dev) 1712 goto cont; 1713 1714 for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; 1715 ifa = ifa->ifa_next, ip_idx++) { 1716 if (ip_idx < s_ip_idx) 1717 continue; |
1682 if (inet_fill_ifaddr(skb, ifa, 1683 NETLINK_CB(cb->skb).portid, 1684 cb->nlh->nlmsg_seq, 1685 RTM_NEWADDR, NLM_F_MULTI) < 0) { | 1718 if (inet_fill_ifaddr(skb, ifa, &fillargs) < 0) { |
1686 rcu_read_unlock(); 1687 goto done; 1688 } 1689 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 1690 } 1691cont: 1692 idx++; 1693 } 1694 rcu_read_unlock(); 1695 } 1696 1697done: 1698 cb->args[0] = h; 1699 cb->args[1] = idx; 1700 cb->args[2] = ip_idx; | 1719 rcu_read_unlock(); 1720 goto done; 1721 } 1722 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 1723 } 1724cont: 1725 idx++; 1726 } 1727 rcu_read_unlock(); 1728 } 1729 1730done: 1731 cb->args[0] = h; 1732 cb->args[1] = idx; 1733 cb->args[2] = ip_idx; |
1734 if (fillargs.netnsid >= 0) 1735 put_net(tgt_net); |
|
1701 1702 return skb->len; 1703} 1704 1705static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh, 1706 u32 portid) 1707{ | 1736 1737 return skb->len; 1738} 1739 1740static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh, 1741 u32 portid) 1742{ |
1743 struct inet_fill_args fillargs = { 1744 .portid = portid, 1745 .seq = nlh ? nlh->nlmsg_seq : 0, 1746 .event = event, 1747 .flags = 0, 1748 .netnsid = -1, 1749 }; |
|
1708 struct sk_buff *skb; | 1750 struct sk_buff *skb; |
1709 u32 seq = nlh ? nlh->nlmsg_seq : 0; | |
1710 int err = -ENOBUFS; 1711 struct net *net; 1712 1713 net = dev_net(ifa->ifa_dev->dev); 1714 skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL); 1715 if (!skb) 1716 goto errout; 1717 | 1751 int err = -ENOBUFS; 1752 struct net *net; 1753 1754 net = dev_net(ifa->ifa_dev->dev); 1755 skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL); 1756 if (!skb) 1757 goto errout; 1758 |
1718 err = inet_fill_ifaddr(skb, ifa, portid, seq, event, 0); | 1759 err = inet_fill_ifaddr(skb, ifa, &fillargs); |
1719 if (err < 0) { 1720 /* -EMSGSIZE implies BUG in inet_nlmsg_size() */ 1721 WARN_ON(err == -EMSGSIZE); 1722 kfree_skb(skb); 1723 goto errout; 1724 } 1725 rtnl_notify(skb, net, portid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); 1726 return; --- 803 unchanged lines hidden --- | 1760 if (err < 0) { 1761 /* -EMSGSIZE implies BUG in inet_nlmsg_size() */ 1762 WARN_ON(err == -EMSGSIZE); 1763 kfree_skb(skb); 1764 goto errout; 1765 } 1766 rtnl_notify(skb, net, portid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); 1767 return; --- 803 unchanged lines hidden --- |