if (is_json_context())
print_uint(PRINT_JSON, "operstate_index", NULL, state);
else
- print_0xhex(PRINT_FP, NULL, "state %#x", state);
+ print_0xhex(PRINT_FP, NULL, "state %#llx", state);
} else if (brief) {
print_color_string(PRINT_ANY,
oper_state_color(state),
return;
}
- parse_rtattr_nested(vf, IFLA_VF_MAX, vfstats);
+ parse_rtattr_nested(vf, IFLA_VF_STATS_MAX, vfstats);
if (is_json_context()) {
open_json_object("stats");
}
/* Mapping from argument to address flag mask */
-struct {
+static const struct {
const char *name;
unsigned long value;
} ifa_flag_names[] = {
static int get_filter(const char *arg)
{
+ bool inv = false;
unsigned int i;
+ if (arg[0] == '-') {
+ inv = true;
+ arg++;
+ }
+
/* Special cases */
if (strcmp(arg, "dynamic") == 0) {
- filter.flags &= ~IFA_F_PERMANENT;
- filter.flagmask |= IFA_F_PERMANENT;
+ inv = !inv;
+ arg = "permanent";
} else if (strcmp(arg, "primary") == 0) {
- filter.flags &= ~IFA_F_SECONDARY;
- filter.flagmask |= IFA_F_SECONDARY;
- } else if (*arg == '-') {
- for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
- if (strcmp(arg + 1, ifa_flag_names[i].name))
- continue;
+ inv = !inv;
+ arg = "secondary";
+ }
- filter.flags &= ifa_flag_names[i].value;
- filter.flagmask |= ifa_flag_names[i].value;
- return 0;
- }
+ for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
+ if (strcmp(arg, ifa_flag_names[i].name))
+ continue;
- return -1;
- } else {
- for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
- if (strcmp(arg, ifa_flag_names[i].name))
- continue;
+ if (inv)
+ filter.flags &= ~ifa_flag_names[i].value;
+ else
filter.flags |= ifa_flag_names[i].value;
- filter.flagmask |= ifa_flag_names[i].value;
- return 0;
- }
- return -1;
+ filter.flagmask |= ifa_flag_names[i].value;
+ return 0;
}
-
- return 0;
+ return -1;
}
static int ifa_label_match_rta(int ifindex, const struct rtattr *rta)
}
}
+static int ipaddr_dump_filter(struct nlmsghdr *nlh, int reqlen)
+{
+ struct ifaddrmsg *ifa = NLMSG_DATA(nlh);
+
+ ifa->ifa_index = filter.ifindex;
+
+ return 0;
+}
+
static int ipaddr_flush(void)
{
int round = 0;
filter.flushe = sizeof(flushb);
while ((max_flush_loops == 0) || (round < max_flush_loops)) {
- if (rtnl_addrdump_req(&rth, filter.family) < 0) {
+ if (rtnl_addrdump_req(&rth, filter.family,
+ ipaddr_dump_filter) < 0) {
perror("Cannot send dump request");
exit(1);
}
return 0;
}
+static int ipaddr_link_get(int index, struct nlmsg_chain *linfo)
+{
+ struct iplink_req req = {
+ .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+ .n.nlmsg_flags = NLM_F_REQUEST,
+ .n.nlmsg_type = RTM_GETLINK,
+ .i.ifi_family = filter.family,
+ .i.ifi_index = index,
+ };
+ __u32 filt_mask = RTEXT_FILTER_VF;
+ struct nlmsghdr *answer;
+
+ if (!show_stats)
+ filt_mask |= RTEXT_FILTER_SKIP_STATS;
+
+ addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
+
+ if (rtnl_talk(&rth, &req.n, &answer) < 0) {
+ perror("Cannot send link request");
+ return 1;
+ }
+
+ if (store_nlmsg(answer, linfo) < 0) {
+ fprintf(stderr, "Failed to process link information\n");
+ return 1;
+ }
+
+ return 0;
+}
+
/* fills in linfo with link data and optionally ainfo with address info
* caller can walk lists as desired and must call free_nlmsg_chain for
* both when done
*/
-int ip_linkaddr_list(int family, req_filter_fn_t filter_fn,
- struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
+int ip_link_list(req_filter_fn_t filter_fn, struct nlmsg_chain *linfo)
{
if (rtnl_linkdump_req_filter_fn(&rth, preferred_family,
filter_fn) < 0) {
return 1;
}
- if (ainfo) {
- if (rtnl_addrdump_req(&rth, family) < 0) {
- perror("Cannot send dump request");
- return 1;
- }
+ return 0;
+}
- if (rtnl_dump_filter(&rth, store_nlmsg, ainfo) < 0) {
- fprintf(stderr, "Dump terminated\n");
- return 1;
- }
+static int ip_addr_list(struct nlmsg_chain *ainfo)
+{
+ if (rtnl_addrdump_req(&rth, filter.family, ipaddr_dump_filter) < 0) {
+ perror("Cannot send dump request");
+ return 1;
+ }
+
+ if (rtnl_dump_filter(&rth, store_nlmsg, ainfo) < 0) {
+ fprintf(stderr, "Dump terminated\n");
+ return 1;
}
return 0;
static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
{
struct nlmsg_chain linfo = { NULL, NULL};
- struct nlmsg_chain _ainfo = { NULL, NULL}, *ainfo = NULL;
+ struct nlmsg_chain _ainfo = { NULL, NULL}, *ainfo = &_ainfo;
struct nlmsg_list *l;
char *filter_dev = NULL;
int no_link = 0;
if (ipadd_save_prep())
exit(1);
- if (rtnl_addrdump_req(&rth, preferred_family) < 0) {
+ if (rtnl_addrdump_req(&rth, preferred_family,
+ ipaddr_dump_filter) < 0) {
perror("Cannot send dump request");
exit(1);
}
goto out;
}
- if (filter.family != AF_PACKET) {
- ainfo = &_ainfo;
+ if (filter.ifindex) {
+ if (ipaddr_link_get(filter.ifindex, &linfo) != 0)
+ goto out;
+ } else {
+ if (ip_link_list(iplink_filter_req, &linfo) != 0)
+ goto out;
+ }
+ if (filter.family != AF_PACKET) {
if (filter.oneline)
no_link = 1;
- }
- if (ip_linkaddr_list(filter.family, iplink_filter_req,
- &linfo, ainfo) != 0)
- goto out;
+ if (ip_addr_list(ainfo) != 0)
+ goto out;
- if (filter.family != AF_PACKET)
ipaddr_filter(&linfo, ainfo);
+ }
for (l = linfo.head; l; l = l->next) {
struct nlmsghdr *n = &l->h;
fflush(stdout);
out:
- if (ainfo)
- free_nlmsg_chain(ainfo);
+ free_nlmsg_chain(ainfo);
free_nlmsg_chain(&linfo);
delete_json_obj();
return 0;