+static int get_nlmsg_extended(const struct sockaddr_nl *who,
+ struct nlmsghdr *m, void *arg)
+{
+ struct if_stats_msg *ifsm = NLMSG_DATA(m);
+ struct rtattr *tb[IFLA_STATS_MAX+1];
+ int len = m->nlmsg_len;
+ struct ifstat_ent *n;
+
+ if (m->nlmsg_type != RTM_NEWSTATS)
+ return 0;
+
+ len -= NLMSG_LENGTH(sizeof(*ifsm));
+ if (len < 0)
+ return -1;
+
+ parse_rtattr(tb, IFLA_STATS_MAX, IFLA_STATS_RTA(ifsm), len);
+ if (tb[filter_type] == NULL)
+ return 0;
+
+ n = malloc(sizeof(*n));
+ if (!n)
+ abort();
+
+ n->ifindex = ifsm->ifindex;
+ n->name = strdup(ll_index_to_name(ifsm->ifindex));
+
+ if (sub_type == NO_SUB_TYPE) {
+ memcpy(&n->val, RTA_DATA(tb[filter_type]), sizeof(n->val));
+ } else {
+ struct rtattr *attr;
+
+ attr = parse_rtattr_one_nested(sub_type, tb[filter_type]);
+ if (attr == NULL)
+ return 0;
+ memcpy(&n->val, RTA_DATA(attr), sizeof(n->val));
+ }
+ memset(&n->rate, 0, sizeof(n->rate));
+ n->next = kern_db;
+ kern_db = n;
+ return 0;
+}
+