static void print_linktype(FILE *fp, struct rtattr *tb) { struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct link_util *lu; char *kind; parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); if (!linkinfo[IFLA_INFO_KIND]) return; kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); fprintf(fp, "%s", _SL_); fprintf(fp, " %s ", kind); lu = get_link_kind(kind); if (!lu || !lu->print_opt) return; if (1) { struct rtattr *attr[lu->maxattr+1], **data = NULL; if (linkinfo[IFLA_INFO_DATA]) { parse_rtattr_nested(attr, lu->maxattr, linkinfo[IFLA_INFO_DATA]); data = attr; } lu->print_opt(lu, fp, data); if (linkinfo[IFLA_INFO_XSTATS] && show_stats && lu->print_xstats) lu->print_xstats(lu, fp, linkinfo[IFLA_INFO_XSTATS]); } }
int iplink_ifla_xstats(int argc, char **argv) { struct link_util *lu = NULL; __u32 filt_mask; if (!argc) { fprintf(stderr, "xstats: missing argument\n"); return -1; } if (matches(*argv, "type") == 0) { NEXT_ARG(); lu = get_link_kind(*argv); if (!lu) invarg("invalid type", *argv); } else if (matches(*argv, "help") == 0) { print_explain(stdout); return 0; } else { invarg("unknown argument", *argv); } if (!lu) { print_explain(stderr); return -1; } if (!lu->print_ifla_xstats) { fprintf(stderr, "xstats: link type %s doesn't support xstats\n", lu->id); return -1; } if (lu->parse_ifla_xstats && lu->parse_ifla_xstats(lu, argc-1, argv+1)) return -1; if (strstr(lu->id, "_slave")) filt_mask = IFLA_STATS_FILTER_BIT(IFLA_STATS_LINK_XSTATS_SLAVE); else filt_mask = IFLA_STATS_FILTER_BIT(IFLA_STATS_LINK_XSTATS); if (rtnl_wilddump_stats_req_filter(&rth, AF_UNSPEC, RTM_GETSTATS, filt_mask) < 0) { perror("Cannont send dump request"); return -1; } if (rtnl_dump_filter(&rth, lu->print_ifla_xstats, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); return -1; } return 0; }
static void print_linktype(FILE *fp, struct rtattr *tb) { struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct link_util *lu; struct link_util *slave_lu; char *kind; char *slave_kind; parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); if (linkinfo[IFLA_INFO_KIND]) { kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); fprintf(fp, "%s", _SL_); fprintf(fp, " %s ", kind); lu = get_link_kind(kind); if (lu && lu->print_opt) { struct rtattr *attr[lu->maxattr+1], **data = NULL; if (linkinfo[IFLA_INFO_DATA]) { parse_rtattr_nested(attr, lu->maxattr, linkinfo[IFLA_INFO_DATA]); data = attr; } lu->print_opt(lu, fp, data); if (linkinfo[IFLA_INFO_XSTATS] && show_stats && lu->print_xstats) lu->print_xstats(lu, fp, linkinfo[IFLA_INFO_XSTATS]); } } if (linkinfo[IFLA_INFO_SLAVE_KIND]) { slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); fprintf(fp, "%s", _SL_); fprintf(fp, " %s_slave ", slave_kind); slave_lu = get_link_slave_kind(slave_kind); if (slave_lu && slave_lu->print_opt) { struct rtattr *attr[slave_lu->maxattr+1], **data = NULL; if (linkinfo[IFLA_INFO_SLAVE_DATA]) { parse_rtattr_nested(attr, slave_lu->maxattr, linkinfo[IFLA_INFO_SLAVE_DATA]); data = attr; } slave_lu->print_opt(slave_lu, fp, data); } } }
static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) { int len; char *dev = NULL; char *name = NULL; char *link = NULL; char *type = NULL; int index = 0; int group; struct link_util *lu = NULL; struct iplink_req req; int ret; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.i.ifi_family = preferred_family; ret = iplink_parse(argc, argv, &req, &name, &type, &link, &dev, &group, &index); if (ret < 0) return ret; argc -= ret; argv += ret; if (group != -1) { if (dev) addattr_l(&req.n, sizeof(req), IFLA_GROUP, &group, sizeof(group)); else { if (argc) { fprintf(stderr, "Garbage instead of arguments " "\"%s ...\". Try \"ip link " "help\".\n", *argv); return -1; } if (flags & NLM_F_CREATE) { fprintf(stderr, "group cannot be used when " "creating devices.\n"); return -1; } req.i.ifi_index = 0; addattr32(&req.n, sizeof(req), IFLA_GROUP, group); if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) exit(2); return 0; } } if (!(flags & NLM_F_CREATE)) { if (!dev) { fprintf(stderr, "Not enough information: \"dev\" " "argument is required.\n"); exit(-1); } req.i.ifi_index = ll_name_to_index(dev); if (req.i.ifi_index == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", dev); return -1; } } else { /* Allow "ip link add dev" and "ip link add name" */ if (!name) name = dev; if (link) { int ifindex; ifindex = ll_name_to_index(link); if (ifindex == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", link); return -1; } addattr_l(&req.n, sizeof(req), IFLA_LINK, &ifindex, 4); } req.i.ifi_index = index; } if (name) { len = strlen(name) + 1; if (len == 1) invarg("\"\" is not a valid device identifier\n", "name"); if (len > IFNAMSIZ) invarg("\"name\" too long\n", name); addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, len); } if (type) { struct rtattr *linkinfo = NLMSG_TAIL(&req.n); addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type, strlen(type)); lu = get_link_kind(type); if (lu && argc) { struct rtattr * data = NLMSG_TAIL(&req.n); addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0); if (lu->parse_opt && lu->parse_opt(lu, argc, argv, &req.n)) return -1; data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; } else if (argc) { if (matches(*argv, "help") == 0) usage(); fprintf(stderr, "Garbage instead of arguments \"%s ...\". " "Try \"ip link help\".\n", *argv); return -1; } linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; } else if (flags & NLM_F_CREATE) { fprintf(stderr, "Not enough information: \"type\" argument " "is required\n"); return -1; } if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) exit(2); return 0; }