aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c69
1 files changed, 57 insertions, 12 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 2d56cb9b0b94..99d9e953fe39 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -56,9 +56,11 @@
56struct rtnl_link { 56struct rtnl_link {
57 rtnl_doit_func doit; 57 rtnl_doit_func doit;
58 rtnl_dumpit_func dumpit; 58 rtnl_dumpit_func dumpit;
59 rtnl_calcit_func calcit;
59}; 60};
60 61
61static DEFINE_MUTEX(rtnl_mutex); 62static DEFINE_MUTEX(rtnl_mutex);
63static u16 min_ifinfo_dump_size;
62 64
63void rtnl_lock(void) 65void rtnl_lock(void)
64{ 66{
@@ -144,12 +146,28 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
144 return tab ? tab[msgindex].dumpit : NULL; 146 return tab ? tab[msgindex].dumpit : NULL;
145} 147}
146 148
149static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
150{
151 struct rtnl_link *tab;
152
153 if (protocol <= RTNL_FAMILY_MAX)
154 tab = rtnl_msg_handlers[protocol];
155 else
156 tab = NULL;
157
158 if (tab == NULL || tab[msgindex].calcit == NULL)
159 tab = rtnl_msg_handlers[PF_UNSPEC];
160
161 return tab ? tab[msgindex].calcit : NULL;
162}
163
147/** 164/**
148 * __rtnl_register - Register a rtnetlink message type 165 * __rtnl_register - Register a rtnetlink message type
149 * @protocol: Protocol family or PF_UNSPEC 166 * @protocol: Protocol family or PF_UNSPEC
150 * @msgtype: rtnetlink message type 167 * @msgtype: rtnetlink message type
151 * @doit: Function pointer called for each request message 168 * @doit: Function pointer called for each request message
152 * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message 169 * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message
170 * @calcit: Function pointer to calc size of dump message
153 * 171 *
154 * Registers the specified function pointers (at least one of them has 172 * Registers the specified function pointers (at least one of them has
155 * to be non-NULL) to be called whenever a request message for the 173 * to be non-NULL) to be called whenever a request message for the
@@ -162,7 +180,8 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
162 * Returns 0 on success or a negative error code. 180 * Returns 0 on success or a negative error code.
163 */ 181 */
164int __rtnl_register(int protocol, int msgtype, 182int __rtnl_register(int protocol, int msgtype,
165 rtnl_doit_func doit, rtnl_dumpit_func dumpit) 183 rtnl_doit_func doit, rtnl_dumpit_func dumpit,
184 rtnl_calcit_func calcit)
166{ 185{
167 struct rtnl_link *tab; 186 struct rtnl_link *tab;
168 int msgindex; 187 int msgindex;
@@ -185,6 +204,9 @@ int __rtnl_register(int protocol, int msgtype,
185 if (dumpit) 204 if (dumpit)
186 tab[msgindex].dumpit = dumpit; 205 tab[msgindex].dumpit = dumpit;
187 206
207 if (calcit)
208 tab[msgindex].calcit = calcit;
209
188 return 0; 210 return 0;
189} 211}
190EXPORT_SYMBOL_GPL(__rtnl_register); 212EXPORT_SYMBOL_GPL(__rtnl_register);
@@ -199,9 +221,10 @@ EXPORT_SYMBOL_GPL(__rtnl_register);
199 * of memory implies no sense in continuing. 221 * of memory implies no sense in continuing.
200 */ 222 */
201void rtnl_register(int protocol, int msgtype, 223void rtnl_register(int protocol, int msgtype,
202 rtnl_doit_func doit, rtnl_dumpit_func dumpit) 224 rtnl_doit_func doit, rtnl_dumpit_func dumpit,
225 rtnl_calcit_func calcit)
203{ 226{
204 if (__rtnl_register(protocol, msgtype, doit, dumpit) < 0) 227 if (__rtnl_register(protocol, msgtype, doit, dumpit, calcit) < 0)
205 panic("Unable to register rtnetlink message handler, " 228 panic("Unable to register rtnetlink message handler, "
206 "protocol = %d, message type = %d\n", 229 "protocol = %d, message type = %d\n",
207 protocol, msgtype); 230 protocol, msgtype);
@@ -1009,6 +1032,8 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1009 s_idx = cb->args[1]; 1032 s_idx = cb->args[1];
1010 1033
1011 rcu_read_lock(); 1034 rcu_read_lock();
1035 cb->seq = net->dev_base_seq;
1036
1012 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { 1037 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
1013 idx = 0; 1038 idx = 0;
1014 head = &net->dev_index_head[h]; 1039 head = &net->dev_index_head[h];
@@ -1020,6 +1045,8 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1020 cb->nlh->nlmsg_seq, 0, 1045 cb->nlh->nlmsg_seq, 0,
1021 NLM_F_MULTI) <= 0) 1046 NLM_F_MULTI) <= 0)
1022 goto out; 1047 goto out;
1048
1049 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
1023cont: 1050cont:
1024 idx++; 1051 idx++;
1025 } 1052 }
@@ -1046,6 +1073,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
1046 [IFLA_LINKMODE] = { .type = NLA_U8 }, 1073 [IFLA_LINKMODE] = { .type = NLA_U8 },
1047 [IFLA_LINKINFO] = { .type = NLA_NESTED }, 1074 [IFLA_LINKINFO] = { .type = NLA_NESTED },
1048 [IFLA_NET_NS_PID] = { .type = NLA_U32 }, 1075 [IFLA_NET_NS_PID] = { .type = NLA_U32 },
1076 [IFLA_NET_NS_FD] = { .type = NLA_U32 },
1049 [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, 1077 [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 },
1050 [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, 1078 [IFLA_VFINFO_LIST] = {. type = NLA_NESTED },
1051 [IFLA_VF_PORTS] = { .type = NLA_NESTED }, 1079 [IFLA_VF_PORTS] = { .type = NLA_NESTED },
@@ -1094,6 +1122,8 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
1094 */ 1122 */
1095 if (tb[IFLA_NET_NS_PID]) 1123 if (tb[IFLA_NET_NS_PID])
1096 net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); 1124 net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
1125 else if (tb[IFLA_NET_NS_FD])
1126 net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD]));
1097 else 1127 else
1098 net = get_net(src_net); 1128 net = get_net(src_net);
1099 return net; 1129 return net;
@@ -1224,7 +1254,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1224 int send_addr_notify = 0; 1254 int send_addr_notify = 0;
1225 int err; 1255 int err;
1226 1256
1227 if (tb[IFLA_NET_NS_PID]) { 1257 if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) {
1228 struct net *net = rtnl_link_get_net(dev_net(dev), tb); 1258 struct net *net = rtnl_link_get_net(dev_net(dev), tb);
1229 if (IS_ERR(net)) { 1259 if (IS_ERR(net)) {
1230 err = PTR_ERR(net); 1260 err = PTR_ERR(net);
@@ -1815,6 +1845,11 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1815 return err; 1845 return err;
1816} 1846}
1817 1847
1848static u16 rtnl_calcit(struct sk_buff *skb)
1849{
1850 return min_ifinfo_dump_size;
1851}
1852
1818static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) 1853static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
1819{ 1854{
1820 int idx; 1855 int idx;
@@ -1844,11 +1879,14 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
1844 struct net *net = dev_net(dev); 1879 struct net *net = dev_net(dev);
1845 struct sk_buff *skb; 1880 struct sk_buff *skb;
1846 int err = -ENOBUFS; 1881 int err = -ENOBUFS;
1882 size_t if_info_size;
1847 1883
1848 skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); 1884 skb = nlmsg_new((if_info_size = if_nlmsg_size(dev)), GFP_KERNEL);
1849 if (skb == NULL) 1885 if (skb == NULL)
1850 goto errout; 1886 goto errout;
1851 1887
1888 min_ifinfo_dump_size = max_t(u16, if_info_size, min_ifinfo_dump_size);
1889
1852 err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0); 1890 err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0);
1853 if (err < 0) { 1891 if (err < 0) {
1854 /* -EMSGSIZE implies BUG in if_nlmsg_size() */ 1892 /* -EMSGSIZE implies BUG in if_nlmsg_size() */
@@ -1899,14 +1937,20 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1899 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { 1937 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
1900 struct sock *rtnl; 1938 struct sock *rtnl;
1901 rtnl_dumpit_func dumpit; 1939 rtnl_dumpit_func dumpit;
1940 rtnl_calcit_func calcit;
1941 u16 min_dump_alloc = 0;
1902 1942
1903 dumpit = rtnl_get_dumpit(family, type); 1943 dumpit = rtnl_get_dumpit(family, type);
1904 if (dumpit == NULL) 1944 if (dumpit == NULL)
1905 return -EOPNOTSUPP; 1945 return -EOPNOTSUPP;
1946 calcit = rtnl_get_calcit(family, type);
1947 if (calcit)
1948 min_dump_alloc = calcit(skb);
1906 1949
1907 __rtnl_unlock(); 1950 __rtnl_unlock();
1908 rtnl = net->rtnl; 1951 rtnl = net->rtnl;
1909 err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); 1952 err = netlink_dump_start(rtnl, skb, nlh, dumpit,
1953 NULL, min_dump_alloc);
1910 rtnl_lock(); 1954 rtnl_lock();
1911 return err; 1955 return err;
1912 } 1956 }
@@ -2016,12 +2060,13 @@ void __init rtnetlink_init(void)
2016 netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); 2060 netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
2017 register_netdevice_notifier(&rtnetlink_dev_notifier); 2061 register_netdevice_notifier(&rtnetlink_dev_notifier);
2018 2062
2019 rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo); 2063 rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink,
2020 rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL); 2064 rtnl_dump_ifinfo, rtnl_calcit);
2021 rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL); 2065 rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL);
2022 rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL); 2066 rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL);
2067 rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL);
2023 2068
2024 rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all); 2069 rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL);
2025 rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); 2070 rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL);
2026} 2071}
2027 2072