diff options
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 113 |
1 files changed, 61 insertions, 52 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 120eecc0f5a4..d4ff41739b0f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -822,6 +822,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, | |||
822 | + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */ | 822 | + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */ |
823 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 823 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
824 | + nla_total_size(1) /* IFLA_LINKMODE */ | 824 | + nla_total_size(1) /* IFLA_LINKMODE */ |
825 | + nla_total_size(4) /* IFLA_CARRIER_CHANGES */ | ||
825 | + nla_total_size(ext_filter_mask | 826 | + nla_total_size(ext_filter_mask |
826 | & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ | 827 | & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ |
827 | + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ | 828 | + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ |
@@ -970,7 +971,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
970 | (dev->qdisc && | 971 | (dev->qdisc && |
971 | nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) || | 972 | nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) || |
972 | (dev->ifalias && | 973 | (dev->ifalias && |
973 | nla_put_string(skb, IFLA_IFALIAS, dev->ifalias))) | 974 | nla_put_string(skb, IFLA_IFALIAS, dev->ifalias)) || |
975 | nla_put_u32(skb, IFLA_CARRIER_CHANGES, | ||
976 | atomic_read(&dev->carrier_changes))) | ||
974 | goto nla_put_failure; | 977 | goto nla_put_failure; |
975 | 978 | ||
976 | if (1) { | 979 | if (1) { |
@@ -1121,56 +1124,7 @@ nla_put_failure: | |||
1121 | return -EMSGSIZE; | 1124 | return -EMSGSIZE; |
1122 | } | 1125 | } |
1123 | 1126 | ||
1124 | static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | 1127 | static const struct nla_policy ifla_policy[IFLA_MAX+1] = { |
1125 | { | ||
1126 | struct net *net = sock_net(skb->sk); | ||
1127 | int h, s_h; | ||
1128 | int idx = 0, s_idx; | ||
1129 | struct net_device *dev; | ||
1130 | struct hlist_head *head; | ||
1131 | struct nlattr *tb[IFLA_MAX+1]; | ||
1132 | u32 ext_filter_mask = 0; | ||
1133 | |||
1134 | s_h = cb->args[0]; | ||
1135 | s_idx = cb->args[1]; | ||
1136 | |||
1137 | rcu_read_lock(); | ||
1138 | cb->seq = net->dev_base_seq; | ||
1139 | |||
1140 | if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, | ||
1141 | ifla_policy) >= 0) { | ||
1142 | |||
1143 | if (tb[IFLA_EXT_MASK]) | ||
1144 | ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); | ||
1145 | } | ||
1146 | |||
1147 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { | ||
1148 | idx = 0; | ||
1149 | head = &net->dev_index_head[h]; | ||
1150 | hlist_for_each_entry_rcu(dev, head, index_hlist) { | ||
1151 | if (idx < s_idx) | ||
1152 | goto cont; | ||
1153 | if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, | ||
1154 | NETLINK_CB(cb->skb).portid, | ||
1155 | cb->nlh->nlmsg_seq, 0, | ||
1156 | NLM_F_MULTI, | ||
1157 | ext_filter_mask) <= 0) | ||
1158 | goto out; | ||
1159 | |||
1160 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | ||
1161 | cont: | ||
1162 | idx++; | ||
1163 | } | ||
1164 | } | ||
1165 | out: | ||
1166 | rcu_read_unlock(); | ||
1167 | cb->args[1] = idx; | ||
1168 | cb->args[0] = h; | ||
1169 | |||
1170 | return skb->len; | ||
1171 | } | ||
1172 | |||
1173 | const struct nla_policy ifla_policy[IFLA_MAX+1] = { | ||
1174 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, | 1128 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, |
1175 | [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | 1129 | [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, |
1176 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | 1130 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, |
@@ -1196,8 +1150,8 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
1196 | [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, | 1150 | [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, |
1197 | [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, | 1151 | [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, |
1198 | [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN }, | 1152 | [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN }, |
1153 | [IFLA_CARRIER_CHANGES] = { .type = NLA_U32 }, /* ignored */ | ||
1199 | }; | 1154 | }; |
1200 | EXPORT_SYMBOL(ifla_policy); | ||
1201 | 1155 | ||
1202 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | 1156 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { |
1203 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, | 1157 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, |
@@ -1235,6 +1189,61 @@ static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { | |||
1235 | [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, | 1189 | [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, |
1236 | }; | 1190 | }; |
1237 | 1191 | ||
1192 | static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | ||
1193 | { | ||
1194 | struct net *net = sock_net(skb->sk); | ||
1195 | int h, s_h; | ||
1196 | int idx = 0, s_idx; | ||
1197 | struct net_device *dev; | ||
1198 | struct hlist_head *head; | ||
1199 | struct nlattr *tb[IFLA_MAX+1]; | ||
1200 | u32 ext_filter_mask = 0; | ||
1201 | |||
1202 | s_h = cb->args[0]; | ||
1203 | s_idx = cb->args[1]; | ||
1204 | |||
1205 | rcu_read_lock(); | ||
1206 | cb->seq = net->dev_base_seq; | ||
1207 | |||
1208 | if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, | ||
1209 | ifla_policy) >= 0) { | ||
1210 | |||
1211 | if (tb[IFLA_EXT_MASK]) | ||
1212 | ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); | ||
1213 | } | ||
1214 | |||
1215 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { | ||
1216 | idx = 0; | ||
1217 | head = &net->dev_index_head[h]; | ||
1218 | hlist_for_each_entry_rcu(dev, head, index_hlist) { | ||
1219 | if (idx < s_idx) | ||
1220 | goto cont; | ||
1221 | if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, | ||
1222 | NETLINK_CB(cb->skb).portid, | ||
1223 | cb->nlh->nlmsg_seq, 0, | ||
1224 | NLM_F_MULTI, | ||
1225 | ext_filter_mask) <= 0) | ||
1226 | goto out; | ||
1227 | |||
1228 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | ||
1229 | cont: | ||
1230 | idx++; | ||
1231 | } | ||
1232 | } | ||
1233 | out: | ||
1234 | rcu_read_unlock(); | ||
1235 | cb->args[1] = idx; | ||
1236 | cb->args[0] = h; | ||
1237 | |||
1238 | return skb->len; | ||
1239 | } | ||
1240 | |||
1241 | int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len) | ||
1242 | { | ||
1243 | return nla_parse(tb, IFLA_MAX, head, len, ifla_policy); | ||
1244 | } | ||
1245 | EXPORT_SYMBOL(rtnl_nla_parse_ifla); | ||
1246 | |||
1238 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) | 1247 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) |
1239 | { | 1248 | { |
1240 | struct net *net; | 1249 | struct net *net; |