static int veth_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *hdr) { char *name = NULL; char *type = NULL; char *link = NULL; char *dev = NULL; int err, len; struct rtattr * data; if (strcmp(argv[0], "peer") != 0) { usage(); return -1; } data = NLMSG_TAIL(hdr); addattr_l(hdr, 1024, VETH_INFO_PEER, NULL, 0); hdr->nlmsg_len += sizeof(struct ifinfomsg); err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)hdr, &name, &type, &link, &dev); if (err < 0) return err; if (name) { len = strlen(name) + 1; if (len > IFNAMSIZ) invarg("\"name\" too long\n", *argv); addattr_l(hdr, 1024, IFLA_IFNAME, name, len); } data->rta_len = (void *)NLMSG_TAIL(hdr) - (void *)data; return argc - 1 - err; }
static int veth_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *hdr) { char *dev = NULL; char *name = NULL; char *link = NULL; char *type = NULL; int index = 0; int err, len; struct rtattr * data; int group; struct ifinfomsg *ifm, *peer_ifm; unsigned int ifi_flags, ifi_change; if (strcmp(argv[0], "peer") != 0) { usage(); return -1; } ifm = NLMSG_DATA(hdr); ifi_flags = ifm->ifi_flags; ifi_change = ifm->ifi_change; ifm->ifi_flags = 0; ifm->ifi_change = 0; data = NLMSG_TAIL(hdr); addattr_l(hdr, 1024, VETH_INFO_PEER, NULL, 0); hdr->nlmsg_len += sizeof(struct ifinfomsg); err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)hdr, &name, &type, &link, &dev, &group, &index); if (err < 0) return err; if (name) { len = strlen(name) + 1; if (len > IFNAMSIZ) invarg("\"name\" too long\n", *argv); addattr_l(hdr, 1024, IFLA_IFNAME, name, len); } peer_ifm = RTA_DATA(data); peer_ifm->ifi_index = index; peer_ifm->ifi_flags = ifm->ifi_flags; peer_ifm->ifi_change = ifm->ifi_change; ifm->ifi_flags = ifi_flags; ifm->ifi_change = ifi_change; if (group != -1) addattr32(hdr, 1024, IFLA_GROUP, group); data->rta_len = (void *)NLMSG_TAIL(hdr) - (void *)data; return argc - 1 - err; }
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; }