static int get_sci_portaddr(struct sci *sci, int *argcp, char ***argvp, bool port_only, bool optional) { int argc = *argcp; char **argv = *argvp; int ret; bool p = false, a = false, s = false; while (argc > 0) { if (strcmp(*argv, "sci") == 0) { if (p) invarg("expected address", *argv); if (a) invarg("expected port", *argv); NEXT_ARG(); ret = get_sci(&sci->sci, *argv); if (ret) invarg("expected sci", *argv); s = true; } else if (strcmp(*argv, "port") == 0) { NEXT_ARG(); ret = get_port(&sci->port, *argv); if (ret) invarg("expected port", *argv); if (sci->port == 0) invarg("expected port != 0", *argv); p = true; } else if (strcmp(*argv, "address") == 0) { NEXT_ARG(); ret = ll_addr_a2n(sci->abuf, sizeof(sci->abuf), *argv); if (ret < 0) invarg("expected lladdr", *argv); a = true; } else if (optional) { break; } else { invarg("expected sci, port, or address", *argv); } argv++; argc--; if (sci_complete(s, p, a, port_only)) break; } if (!optional && !sci_complete(s, p, a, port_only)) return -1; if (p && a) sci->sci = make_sci(sci->abuf, sci->port); *argvp = argv; *argcp = argc; return p || a || s; }
static int multiaddr_modify(int cmd, int argc, char **argv) { struct ifreq ifr; int fd; memset(&ifr, 0, sizeof(ifr)); if (cmd == RTM_NEWADDR) cmd = SIOCADDMULTI; else cmd = SIOCDELMULTI; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if (ifr.ifr_name[0]) duparg("dev", *argv); strncpy(ifr.ifr_name, *argv, IFNAMSIZ); } else { if (matches(*argv, "address") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (ifr.ifr_hwaddr.sa_data[0]) duparg("address", *argv); if (ll_addr_a2n(ifr.ifr_hwaddr.sa_data, 14, *argv) < 0) { fprintf(stderr, "Error: \"%s\" is not a legal ll address.\n", *argv); exit(1); } } argc--; argv++; } if (ifr.ifr_name[0] == 0) { fprintf(stderr, "Not enough information: \"dev\" is required.\n"); exit(-1); } fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("Cannot create socket"); exit(1); } if (ioctl(fd, cmd, (char*)&ifr) != 0) { perror("ioctl"); exit(1); } close(fd); exit(0); }
/* Exits on error */ static void parse_address(char *dev, int hatype, int halen, char *lla, struct ifreq *ifr) { int alen; memset(ifr, 0, sizeof(*ifr)); strncpy_IFNAMSIZ(ifr->ifr_name, dev); ifr->ifr_hwaddr.sa_family = hatype; alen = hatype == 1/*ARPHRD_ETHER*/ ? 14/*ETH_HLEN*/ : 19/*INFINIBAND_HLEN*/; alen = ll_addr_a2n((unsigned char *)(ifr->ifr_hwaddr.sa_data), alen, lla); if (alen < 0) exit(EXIT_FAILURE); if (alen != halen) { bb_error_msg_and_die("wrong address (%s) length: expected %d bytes", lla, halen); } }
static int parse_address(char *dev, int hatype, int halen, char *lla, struct ifreq *ifr) { int alen; memset(ifr, 0, sizeof(*ifr)); strcpy(ifr->ifr_name, dev); ifr->ifr_hwaddr.sa_family = hatype; alen = ll_addr_a2n(ifr->ifr_hwaddr.sa_data, 14, lla); if (alen < 0) return -1; if (alen != halen) { bb_error_msg("Wrong address (%s) length: expected %d bytes", lla, halen); return -1; } return 0; }
static int parse_address(const char *dev, int hatype, int halen, char *lla, struct ifreq *ifr) { int alen; memset(ifr, 0, sizeof(*ifr)); strncpy(ifr->ifr_name, dev, IFNAMSIZ); ifr->ifr_hwaddr.sa_family = hatype; alen = ll_addr_a2n(ifr->ifr_hwaddr.sa_data, 14, lla); if (alen < 0) return -1; if (alen != halen) { fprintf(stderr, "Wrong address (%s) length: expected %d bytes\n", lla, halen); return -1; } return 0; }
static int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type) { int argc = *argc_p; char **argv = *argv_p; if (argc <= 0) return -1; if (type == TINT) return get_integer((int *)val, *argv, 0); if (type == TU32) return get_u32(val, *argv, 0); if (type == TIPV4) { inet_prefix addr; if (get_prefix_1(&addr, *argv, AF_INET)) return -1; *val = addr.data[0]; return 0; } if (type == TIPV6) { inet_prefix addr; if (get_prefix_1(&addr, *argv, AF_INET6)) return -1; memcpy(val, addr.data, addr.bytelen); return 0; } if (type == TMAC) { #define MAC_ALEN 6 int ret = ll_addr_a2n((char *)val, MAC_ALEN, *argv); if (ret == MAC_ALEN) return 0; } return -1; }
static int bond_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { __u8 mode, use_carrier, primary_reselect, fail_over_mac; __u8 xmit_hash_policy, num_peer_notif, all_slaves_active; __u8 lacp_rate, ad_select, tlb_dynamic_lb; __u16 ad_user_port_key, ad_actor_sys_prio; __u32 miimon, updelay, downdelay, arp_interval, arp_validate; __u32 arp_all_targets, resend_igmp, min_links, lp_interval; __u32 packets_per_slave; unsigned ifindex; while (argc > 0) { if (matches(*argv, "mode") == 0) { NEXT_ARG(); if (get_index(mode_tbl, *argv) < 0) invarg("invalid mode", *argv); mode = get_index(mode_tbl, *argv); addattr8(n, 1024, IFLA_BOND_MODE, mode); } else if (matches(*argv, "active_slave") == 0) { NEXT_ARG(); ifindex = if_nametoindex(*argv); if (!ifindex) return -1; addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, ifindex); } else if (matches(*argv, "clear_active_slave") == 0) { addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0); } else if (matches(*argv, "miimon") == 0) { NEXT_ARG(); if (get_u32(&miimon, *argv, 0)) invarg("invalid miimon", *argv); addattr32(n, 1024, IFLA_BOND_MIIMON, miimon); } else if (matches(*argv, "updelay") == 0) { NEXT_ARG(); if (get_u32(&updelay, *argv, 0)) invarg("invalid updelay", *argv); addattr32(n, 1024, IFLA_BOND_UPDELAY, updelay); } else if (matches(*argv, "downdelay") == 0) { NEXT_ARG(); if (get_u32(&downdelay, *argv, 0)) invarg("invalid downdelay", *argv); addattr32(n, 1024, IFLA_BOND_DOWNDELAY, downdelay); } else if (matches(*argv, "use_carrier") == 0) { NEXT_ARG(); if (get_u8(&use_carrier, *argv, 0)) invarg("invalid use_carrier", *argv); addattr8(n, 1024, IFLA_BOND_USE_CARRIER, use_carrier); } else if (matches(*argv, "arp_interval") == 0) { NEXT_ARG(); if (get_u32(&arp_interval, *argv, 0)) invarg("invalid arp_interval", *argv); addattr32(n, 1024, IFLA_BOND_ARP_INTERVAL, arp_interval); } else if (matches(*argv, "arp_ip_target") == 0) { struct rtattr * nest = addattr_nest(n, 1024, IFLA_BOND_ARP_IP_TARGET); if (NEXT_ARG_OK()) { NEXT_ARG(); char *targets = strdupa(*argv); char *target = strtok(targets, ","); int i; for(i = 0; target && i < BOND_MAX_ARP_TARGETS; i++) { __u32 addr = get_addr32(target); addattr32(n, 1024, i, addr); target = strtok(NULL, ","); } addattr_nest_end(n, nest); } addattr_nest_end(n, nest); } else if (matches(*argv, "arp_validate") == 0) { NEXT_ARG(); if (get_index(arp_validate_tbl, *argv) < 0) invarg("invalid arp_validate", *argv); arp_validate = get_index(arp_validate_tbl, *argv); addattr32(n, 1024, IFLA_BOND_ARP_VALIDATE, arp_validate); } else if (matches(*argv, "arp_all_targets") == 0) { NEXT_ARG(); if (get_index(arp_all_targets_tbl, *argv) < 0) invarg("invalid arp_all_targets", *argv); arp_all_targets = get_index(arp_all_targets_tbl, *argv); addattr32(n, 1024, IFLA_BOND_ARP_ALL_TARGETS, arp_all_targets); } else if (matches(*argv, "primary") == 0) { NEXT_ARG(); ifindex = if_nametoindex(*argv); if (!ifindex) return -1; addattr32(n, 1024, IFLA_BOND_PRIMARY, ifindex); } else if (matches(*argv, "primary_reselect") == 0) { NEXT_ARG(); if (get_index(primary_reselect_tbl, *argv) < 0) invarg("invalid primary_reselect", *argv); primary_reselect = get_index(primary_reselect_tbl, *argv); addattr8(n, 1024, IFLA_BOND_PRIMARY_RESELECT, primary_reselect); } else if (matches(*argv, "fail_over_mac") == 0) { NEXT_ARG(); if (get_index(fail_over_mac_tbl, *argv) < 0) invarg("invalid fail_over_mac", *argv); fail_over_mac = get_index(fail_over_mac_tbl, *argv); addattr8(n, 1024, IFLA_BOND_FAIL_OVER_MAC, fail_over_mac); } else if (matches(*argv, "xmit_hash_policy") == 0) { NEXT_ARG(); if (get_index(xmit_hash_policy_tbl, *argv) < 0) invarg("invalid xmit_hash_policy", *argv); xmit_hash_policy = get_index(xmit_hash_policy_tbl, *argv); addattr8(n, 1024, IFLA_BOND_XMIT_HASH_POLICY, xmit_hash_policy); } else if (matches(*argv, "resend_igmp") == 0) { NEXT_ARG(); if (get_u32(&resend_igmp, *argv, 0)) invarg("invalid resend_igmp", *argv); addattr32(n, 1024, IFLA_BOND_RESEND_IGMP, resend_igmp); } else if (matches(*argv, "num_grat_arp") == 0 || matches(*argv, "num_unsol_na") == 0) { NEXT_ARG(); if (get_u8(&num_peer_notif, *argv, 0)) invarg("invalid num_grat_arp|num_unsol_na", *argv); addattr8(n, 1024, IFLA_BOND_NUM_PEER_NOTIF, num_peer_notif); } else if (matches(*argv, "all_slaves_active") == 0) { NEXT_ARG(); if (get_u8(&all_slaves_active, *argv, 0)) invarg("invalid all_slaves_active", *argv); addattr8(n, 1024, IFLA_BOND_ALL_SLAVES_ACTIVE, all_slaves_active); } else if (matches(*argv, "min_links") == 0) { NEXT_ARG(); if (get_u32(&min_links, *argv, 0)) invarg("invalid min_links", *argv); addattr32(n, 1024, IFLA_BOND_MIN_LINKS, min_links); } else if (matches(*argv, "lp_interval") == 0) { NEXT_ARG(); if (get_u32(&lp_interval, *argv, 0)) invarg("invalid lp_interval", *argv); addattr32(n, 1024, IFLA_BOND_LP_INTERVAL, lp_interval); } else if (matches(*argv, "packets_per_slave") == 0) { NEXT_ARG(); if (get_u32(&packets_per_slave, *argv, 0)) invarg("invalid packets_per_slave", *argv); addattr32(n, 1024, IFLA_BOND_PACKETS_PER_SLAVE, packets_per_slave); } else if (matches(*argv, "lacp_rate") == 0) { NEXT_ARG(); if (get_index(lacp_rate_tbl, *argv) < 0) invarg("invalid lacp_rate", *argv); lacp_rate = get_index(lacp_rate_tbl, *argv); addattr8(n, 1024, IFLA_BOND_AD_LACP_RATE, lacp_rate); } else if (matches(*argv, "ad_select") == 0) { NEXT_ARG(); if (get_index(ad_select_tbl, *argv) < 0) invarg("invalid ad_select", *argv); ad_select = get_index(ad_select_tbl, *argv); addattr8(n, 1024, IFLA_BOND_AD_SELECT, ad_select); } else if (matches(*argv, "ad_user_port_key") == 0) { NEXT_ARG(); if (get_u16(&ad_user_port_key, *argv, 0)) invarg("invalid ad_user_port_key", *argv); addattr16(n, 1024, IFLA_BOND_AD_USER_PORT_KEY, ad_user_port_key); } else if (matches(*argv, "ad_actor_sys_prio") == 0) { NEXT_ARG(); if (get_u16(&ad_actor_sys_prio, *argv, 0)) invarg("invalid ad_actor_sys_prio", *argv); addattr16(n, 1024, IFLA_BOND_AD_ACTOR_SYS_PRIO, ad_actor_sys_prio); } else if (matches(*argv, "ad_actor_system") == 0) { int len; char abuf[32]; NEXT_ARG(); len = ll_addr_a2n(abuf, sizeof(abuf), *argv); if (len < 0) return -1; addattr_l(n, 1024, IFLA_BOND_AD_ACTOR_SYSTEM, abuf, len); } else if (matches(*argv, "tlb_dynamic_lb") == 0) { NEXT_ARG(); if (get_u8(&tlb_dynamic_lb, *argv, 0)) { invarg("invalid tlb_dynamic_lb", *argv); return -1; } addattr8(n, 1024, IFLA_BOND_TLB_DYNAMIC_LB, tlb_dynamic_lb); } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv); explain(); return -1; } argc--, argv++; } return 0; }
/* Return value becomes exitcode. It's okay to not return at all */ static int do_add_or_delete(char **argv, const unsigned rtm) { static const char keywords[] ALIGN1 = "link\0""name\0""type\0""dev\0""address\0"; enum { ARG_link, ARG_name, ARG_type, ARG_dev, ARG_address, }; struct rtnl_handle rth; struct { struct nlmsghdr n; struct ifinfomsg i; char buf[1024]; } req; smalluint arg; char *name_str = NULL; char *link_str = NULL; char *type_str = NULL; char *dev_str = NULL; char *address_str = NULL; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = rtm; req.i.ifi_family = preferred_family; if (rtm == RTM_NEWLINK) req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; while (*argv) { arg = index_in_substrings(keywords, *argv); if (arg == ARG_type) { NEXT_ARG(); type_str = *argv++; dbg("type_str:'%s'", type_str); break; } if (arg == ARG_link) { NEXT_ARG(); link_str = *argv; dbg("link_str:'%s'", link_str); } else if (arg == ARG_name) { NEXT_ARG(); name_str = *argv; dbg("name_str:'%s'", name_str); } else if (arg == ARG_address) { NEXT_ARG(); address_str = *argv; dbg("address_str:'%s'", name_str); } else { if (arg == ARG_dev) { if (dev_str) duparg(*argv, "dev"); NEXT_ARG(); } dev_str = *argv; dbg("dev_str:'%s'", dev_str); } argv++; } xrtnl_open(&rth); ll_init_map(&rth); if (type_str) { 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_str, strlen(type_str)); if (*argv) { struct rtattr *data = NLMSG_TAIL(&req.n); addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0); if (strcmp(type_str, "vlan") == 0) vlan_parse_opt(argv, &req.n, sizeof(req)); data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; } linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; } if (rtm != RTM_NEWLINK) { if (!dev_str) return 1; /* Need a device to delete */ req.i.ifi_index = xll_name_to_index(dev_str); } else { if (!name_str) name_str = dev_str; if (link_str) { int idx = xll_name_to_index(link_str); addattr_l(&req.n, sizeof(req), IFLA_LINK, &idx, 4); } if (address_str) { unsigned char abuf[32]; int len = ll_addr_a2n(abuf, sizeof(abuf), address_str); dbg("address len:%d", len); if (len < 0) return -1; addattr_l(&req.n, sizeof(req), IFLA_ADDRESS, abuf, len); } } if (name_str) { const size_t name_len = strlen(name_str) + 1; if (name_len < 2 || name_len > IFNAMSIZ) invarg(name_str, "name"); addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name_str, name_len); } if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) return 2; return 0; }
static int ipneigh_modify(int cmd, int flags, int argc, char **argv) { struct { struct nlmsghdr n; struct ndmsg ndm; char buf[256]; } req = { .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)), .n.nlmsg_flags = NLM_F_REQUEST | flags, .n.nlmsg_type = cmd, .ndm.ndm_family = preferred_family, .ndm.ndm_state = NUD_PERMANENT, }; char *dev = NULL; int dst_ok = 0; int dev_ok = 0; int lladdr_ok = 0; char *lla = NULL; inet_prefix dst; while (argc > 0) { if (matches(*argv, "lladdr") == 0) { NEXT_ARG(); if (lladdr_ok) duparg("lladdr", *argv); lla = *argv; lladdr_ok = 1; } else if (strcmp(*argv, "nud") == 0) { unsigned int state; NEXT_ARG(); if (nud_state_a2n(&state, *argv)) invarg("nud state is bad", *argv); req.ndm.ndm_state = state; } else if (matches(*argv, "proxy") == 0) { NEXT_ARG(); if (matches(*argv, "help") == 0) usage(); if (dst_ok) duparg("address", *argv); get_addr(&dst, *argv, preferred_family); dst_ok = 1; dev_ok = 1; req.ndm.ndm_flags |= NTF_PROXY; } else if (strcmp(*argv, "router") == 0) { req.ndm.ndm_flags |= NTF_ROUTER; } else if (matches(*argv, "extern_learn") == 0) { req.ndm.ndm_flags |= NTF_EXT_LEARNED; } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); dev = *argv; dev_ok = 1; } else if (matches(*argv, "protocol") == 0) { __u32 proto; NEXT_ARG(); if (rtnl_rtprot_a2n(&proto, *argv)) invarg("\"protocol\" value is invalid\n", *argv); if (addattr8(&req.n, sizeof(req), NDA_PROTOCOL, proto)) return -1; } else { if (strcmp(*argv, "to") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) { NEXT_ARG(); } if (dst_ok) duparg2("to", *argv); get_addr(&dst, *argv, preferred_family); dst_ok = 1; } argc--; argv++; } if (!dev_ok || !dst_ok || dst.family == AF_UNSPEC) { fprintf(stderr, "Device and destination are required arguments.\n"); exit(-1); } req.ndm.ndm_family = dst.family; if (addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen) < 0) return -1; if (lla && strcmp(lla, "null")) { char llabuf[20]; int l; l = ll_addr_a2n(llabuf, sizeof(llabuf), lla); if (l < 0) return -1; if (addattr_l(&req.n, sizeof(req), NDA_LLADDR, llabuf, l) < 0) return -1; } ll_init_map(&rth); if (dev) { req.ndm.ndm_ifindex = ll_name_to_index(dev); if (!req.ndm.ndm_ifindex) return nodev(dev); } if (rtnl_talk(&rth, &req.n, NULL) < 0) exit(2); return 0; } static void print_cacheinfo(const struct nda_cacheinfo *ci) { static int hz; if (!hz) hz = get_user_hz(); if (ci->ndm_refcnt) print_uint(PRINT_ANY, "refcnt", " ref %u", ci->ndm_refcnt); print_uint(PRINT_ANY, "used", " used %u", ci->ndm_used / hz); print_uint(PRINT_ANY, "confirmed", "/%u", ci->ndm_confirmed / hz); print_uint(PRINT_ANY, "updated", "/%u", ci->ndm_updated / hz); } static void print_neigh_state(unsigned int nud) { open_json_array(PRINT_JSON, is_json_context() ? "state" : ""); #define PRINT_FLAG(f) \ if (nud & NUD_##f) { \ nud &= ~NUD_##f; \ print_string(PRINT_ANY, NULL, " %s", #f); \ } PRINT_FLAG(INCOMPLETE); PRINT_FLAG(REACHABLE); PRINT_FLAG(STALE); PRINT_FLAG(DELAY); PRINT_FLAG(PROBE); PRINT_FLAG(FAILED); PRINT_FLAG(NOARP); PRINT_FLAG(PERMANENT); #undef PRINT_FLAG close_json_array(PRINT_JSON, NULL); }
static int ipneigh_modify(int cmd, int flags, int argc, char **argv) { struct { struct nlmsghdr n; struct ndmsg ndm; char buf[256]; } req; char *d = NULL; int dst_ok = 0; int lladdr_ok = 0; char * lla = NULL; inet_prefix dst; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.ndm.ndm_family = preferred_family; req.ndm.ndm_state = NUD_PERMANENT; while (argc > 0) { if (matches(*argv, "lladdr") == 0) { NEXT_ARG(); if (lladdr_ok) duparg("lladdr", *argv); lla = *argv; lladdr_ok = 1; } else if (strcmp(*argv, "nud") == 0) { unsigned state; NEXT_ARG(); if (nud_state_a2n(&state, *argv)) invarg("nud state is bad", *argv); req.ndm.ndm_state = state; } else if (matches(*argv, "proxy") == 0) { NEXT_ARG(); if (matches(*argv, "help") == 0) usage(); if (dst_ok) duparg("address", *argv); get_addr(&dst, *argv, preferred_family); dst_ok = 1; req.ndm.ndm_flags |= NTF_PROXY; } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); d = *argv; } else { if (strcmp(*argv, "to") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) { NEXT_ARG(); } if (dst_ok) duparg2("to", *argv); get_addr(&dst, *argv, preferred_family); dst_ok = 1; } argc--; argv++; } if (d == NULL || !dst_ok || dst.family == AF_UNSPEC) { fprintf(stderr, "Device and destination are required arguments.\n"); exit(-1); } req.ndm.ndm_family = dst.family; addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen); if (lla && strcmp(lla, "null")) { char llabuf[20]; int l; l = ll_addr_a2n(llabuf, sizeof(llabuf), lla); addattr_l(&req.n, sizeof(req), NDA_LLADDR, llabuf, l); } ll_init_map(&rth); if ((req.ndm.ndm_ifindex = ll_name_to_index(d)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", d); return -1; } if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) exit(2); return 0; }
static int iplink_parse_vf(int vf, int *argcp, char ***argvp, struct iplink_req *req, int dev_index) { char new_rate_api = 0, count = 0, override_legacy_rate = 0; struct ifla_vf_rate tivt; int len, argc = *argcp; char **argv = *argvp; struct rtattr *vfinfo; tivt.min_tx_rate = -1; tivt.max_tx_rate = -1; vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO); while (NEXT_ARG_OK()) { NEXT_ARG(); count++; if (!matches(*argv, "max_tx_rate")) { /* new API in use */ new_rate_api = 1; /* override legacy rate */ override_legacy_rate = 1; } else if (!matches(*argv, "min_tx_rate")) { /* new API in use */ new_rate_api = 1; } } while (count--) { /* rewind arg */ PREV_ARG(); } while (NEXT_ARG_OK()) { NEXT_ARG(); if (matches(*argv, "mac") == 0) { struct ifla_vf_mac ivm; NEXT_ARG(); ivm.vf = vf; len = ll_addr_a2n((char *)ivm.mac, 32, *argv); if (len < 0) return -1; addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm, sizeof(ivm)); } else if (matches(*argv, "vlan") == 0) { struct ifla_vf_vlan ivv; NEXT_ARG(); if (get_unsigned(&ivv.vlan, *argv, 0)) { invarg("Invalid \"vlan\" value\n", *argv); } ivv.vf = vf; ivv.qos = 0; if (NEXT_ARG_OK()) { NEXT_ARG(); if (matches(*argv, "qos") == 0) { NEXT_ARG(); if (get_unsigned(&ivv.qos, *argv, 0)) { invarg("Invalid \"qos\" value\n", *argv); } } else { /* rewind arg */ PREV_ARG(); } } addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv, sizeof(ivv)); } else if (matches(*argv, "rate") == 0) { struct ifla_vf_tx_rate ivt; NEXT_ARG(); if (get_unsigned(&ivt.rate, *argv, 0)) { invarg("Invalid \"rate\" value\n", *argv); } ivt.vf = vf; if (!new_rate_api) addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE, &ivt, sizeof(ivt)); else if (!override_legacy_rate) tivt.max_tx_rate = ivt.rate; } else if (matches(*argv, "max_tx_rate") == 0) { NEXT_ARG(); if (get_unsigned(&tivt.max_tx_rate, *argv, 0)) invarg("Invalid \"max tx rate\" value\n", *argv); tivt.vf = vf; } else if (matches(*argv, "min_tx_rate") == 0) { NEXT_ARG(); if (get_unsigned(&tivt.min_tx_rate, *argv, 0)) invarg("Invalid \"min tx rate\" value\n", *argv); tivt.vf = vf; } else if (matches(*argv, "spoofchk") == 0) { struct ifla_vf_spoofchk ivs; NEXT_ARG(); if (matches(*argv, "on") == 0) ivs.setting = 1; else if (matches(*argv, "off") == 0) ivs.setting = 0; else invarg("Invalid \"spoofchk\" value\n", *argv); ivs.vf = vf; addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs)); } else if (matches(*argv, "state") == 0) { struct ifla_vf_link_state ivl; NEXT_ARG(); if (matches(*argv, "auto") == 0) ivl.link_state = IFLA_VF_LINK_STATE_AUTO; else if (matches(*argv, "enable") == 0) ivl.link_state = IFLA_VF_LINK_STATE_ENABLE; else if (matches(*argv, "disable") == 0) ivl.link_state = IFLA_VF_LINK_STATE_DISABLE; else invarg("Invalid \"state\" value\n", *argv); ivl.vf = vf; addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE, &ivl, sizeof(ivl)); } else { /* rewind arg */ PREV_ARG(); break; } } if (new_rate_api) { int tmin, tmax; if (tivt.min_tx_rate == -1 || tivt.max_tx_rate == -1) { ipaddr_get_vf_rate(tivt.vf, &tmin, &tmax, dev_index); if (tivt.min_tx_rate == -1) tivt.min_tx_rate = tmin; if (tivt.max_tx_rate == -1) tivt.max_tx_rate = tmax; } addattr_l(&req->n, sizeof(*req), IFLA_VF_RATE, &tivt, sizeof(tivt)); } if (argc == *argcp) incomplete_command(); addattr_nest_end(&req->n, vfinfo); *argcp = argc; *argvp = argv; return 0; }
int get_addr_1(inet_prefix *addr, const char *name, int family) { memset(addr, 0, sizeof(*addr)); if (strcmp(name, "default") == 0 || strcmp(name, "all") == 0 || strcmp(name, "any") == 0) { if ((family == AF_DECnet) || (family == AF_MPLS)) return -1; addr->family = family; addr->bytelen = (family == AF_INET6 ? 16 : 4); addr->bitlen = -1; return 0; } if (family == AF_PACKET) { int len; len = ll_addr_a2n((char *)&addr->data, sizeof(addr->data), name); if (len < 0) return -1; addr->family = AF_PACKET; addr->bytelen = len; addr->bitlen = len * 8; return 0; } if (strchr(name, ':')) { addr->family = AF_INET6; if (family != AF_UNSPEC && family != AF_INET6) return -1; if (inet_pton(AF_INET6, name, addr->data) <= 0) return -1; addr->bytelen = 16; addr->bitlen = -1; return 0; } if (family == AF_DECnet) { struct dn_naddr dna; addr->family = AF_DECnet; if (dnet_pton(AF_DECnet, name, &dna) <= 0) return -1; memcpy(addr->data, dna.a_addr, 2); addr->bytelen = 2; addr->bitlen = -1; return 0; } if (family == AF_MPLS) { int i; addr->family = AF_MPLS; if (mpls_pton(AF_MPLS, name, addr->data) <= 0) return -1; addr->bytelen = 4; addr->bitlen = 20; /* How many bytes do I need? */ for (i = 0; i < 8; i++) { if (ntohl(addr->data[i]) & MPLS_LS_S_MASK) { addr->bytelen = (i + 1)*4; break; } } return 0; } addr->family = AF_INET; if (family != AF_UNSPEC && family != AF_INET) return -1; if (get_addr_ipv4((__u8 *)addr->data, name) <= 0) return -1; addr->bytelen = 4; addr->bitlen = -1; return 0; }
int main(int argc, char **argv) { int opt; int do_list = 0; char *do_load = NULL; while ((opt = getopt(argc, argv, "h?b:lf:a:n:p:kR:B:")) != EOF) { switch (opt) { case 'b': dbname = optarg; break; case 'f': if (do_load) { fprintf(stderr, "Duplicate option -f\n"); usage(); } do_load = optarg; break; case 'l': do_list = 1; break; case 'a': active_probing = atoi(optarg); break; case 'n': negative_timeout = atoi(optarg); break; case 'k': no_kernel_broadcasts = 1; break; case 'p': if ((poll_timeout = 1000 * strtod(optarg, NULL)) < 100) { fprintf(stderr,"Invalid poll timeout\n"); exit(-1); } break; case 'R': if ((broadcast_rate = atoi(optarg)) <= 0 || (broadcast_rate = 1000/broadcast_rate) <= 0) { fprintf(stderr, "Invalid ARP rate\n"); exit(-1); } break; case 'B': if ((broadcast_burst = atoi(optarg)) <= 0 || (broadcast_burst = 1000*broadcast_burst) <= 0) { fprintf(stderr, "Invalid ARP burst\n"); exit(-1); } break; case 'h': case '?': default: usage(); } } argc -= optind; argv += optind; if (argc > 0) { ifnum = argc; ifnames = argv; ifvec = malloc(argc*sizeof(int)); if (!ifvec) { perror("malloc"); exit(-1); } } if ((udp_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(-1); } if (ifnum) { int i; struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); for (i=0; i<ifnum; i++) { strncpy(ifr.ifr_name, ifnames[i], IFNAMSIZ); if (ioctl(udp_sock, SIOCGIFINDEX, &ifr)) { perror("ioctl(SIOCGIFINDEX)"); exit(-1);; } ifvec[i] = ifr.ifr_ifindex; } } dbase = dbopen(dbname, O_CREAT|O_RDWR, 0644, DB_HASH, NULL); if (dbase == NULL) { perror("db_open"); exit(-1); } if (do_load) { char buf[128]; FILE *fp; struct dbkey k; DBT dbkey, dbdat; dbkey.data = &k; dbkey.size = sizeof(k); if (strcmp(do_load, "-") == 0 || strcmp(do_load, "--") == 0) { fp = stdin; } else if ((fp = fopen(do_load, "r")) == NULL) { perror("fopen"); goto do_abort; } buf[sizeof(buf)-1] = 0; while (fgets(buf, sizeof(buf)-1, fp)) { __u8 b1[6]; char ipbuf[128]; char macbuf[128]; if (buf[0] == '#') continue; if (sscanf(buf, "%u%s%s", &k.iface, ipbuf, macbuf) != 3) { fprintf(stderr, "Wrong format of input file \"%s\"\n", do_load); goto do_abort; } if (strncmp(macbuf, "FAILED:", 7) == 0) continue; if (!inet_aton(ipbuf, (struct in_addr*)&k.addr)) { fprintf(stderr, "Invalid IP address: \"%s\"\n", ipbuf); goto do_abort; } if (ll_addr_a2n((char *) b1, 6, macbuf) != 6) goto do_abort; dbdat.size = 6; if (dbase->put(dbase, &dbkey, &dbdat, 0)) { perror("hash->put"); goto do_abort; } } dbase->sync(dbase, 0); if (fp != stdin) fclose(fp); } if (do_list) { DBT dbkey, dbdat; printf("%-8s %-15s %s\n", "#Ifindex", "IP", "MAC"); while (dbase->seq(dbase, &dbkey, &dbdat, R_NEXT) == 0) { struct dbkey *key = dbkey.data; if (handle_if(key->iface)) { if (!IS_NEG(dbdat.data)) { char b1[18]; printf("%-8d %-15s %s\n", key->iface, inet_ntoa(*(struct in_addr*)&key->addr), ll_addr_n2a(dbdat.data, 6, ARPHRD_ETHER, b1, 18)); } else { printf("%-8d %-15s FAILED: %dsec ago\n", key->iface, inet_ntoa(*(struct in_addr*)&key->addr), NEG_AGE(dbdat.data)); } } } } if (do_load || do_list) goto out; pset[0].fd = socket(PF_PACKET, SOCK_DGRAM, 0); if (pset[0].fd < 0) { perror("socket"); exit(-1); } if (1) { struct sockaddr_ll sll; memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_protocol = htons(ETH_P_ARP); sll.sll_ifindex = (ifnum == 1 ? ifvec[0] : 0); if (bind(pset[0].fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) { perror("bind"); goto do_abort; } } if (rtnl_open(&rth, RTMGRP_NEIGH) < 0) { perror("rtnl_open"); goto do_abort; } pset[1].fd = rth.fd; load_initial_table(); if (daemon(0, 0)) { perror("arpd: daemon"); goto do_abort; } openlog("arpd", LOG_PID | LOG_CONS, LOG_DAEMON); catch_signal(SIGINT, sig_exit); catch_signal(SIGTERM, sig_exit); catch_signal(SIGHUP, sig_sync); catch_signal(SIGUSR1, sig_stats); #define EVENTS (POLLIN|POLLPRI|POLLERR|POLLHUP) pset[0].events = EVENTS; pset[0].revents = 0; pset[1].events = EVENTS; pset[1].revents = 0; sigsetjmp(env, 1); for (;;) { in_poll = 1; if (do_exit) break; if (do_sync) { in_poll = 0; dbase->sync(dbase, 0); do_sync = 0; in_poll = 1; } if (do_stats) send_stats(); if (poll(pset, 2, poll_timeout) > 0) { in_poll = 0; if (pset[0].revents&EVENTS) get_arp_pkt(); if (pset[1].revents&EVENTS) get_kern_msg(); } else { do_sync = 1; } } undo_sysctl_adjustments(); out: dbase->close(dbase); exit(0); do_abort: dbase->close(dbase); exit(-1); }
static int iplink_parse_vf(int vf, int *argcp, char ***argvp, struct iplink_req *req) { int len, argc = *argcp; char **argv = *argvp; struct rtattr *vfinfo; vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO); while (NEXT_ARG_OK()) { NEXT_ARG(); if (matches(*argv, "mac") == 0) { struct ifla_vf_mac ivm; NEXT_ARG(); ivm.vf = vf; len = ll_addr_a2n((char *)ivm.mac, 32, *argv); if (len < 0) return -1; addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm, sizeof(ivm)); } else if (matches(*argv, "vlan") == 0) { struct ifla_vf_vlan ivv; NEXT_ARG(); if (get_unsigned(&ivv.vlan, *argv, 0)) { invarg("Invalid \"vlan\" value\n", *argv); } ivv.vf = vf; ivv.qos = 0; if (NEXT_ARG_OK()) { NEXT_ARG(); if (matches(*argv, "qos") == 0) { NEXT_ARG(); if (get_unsigned(&ivv.qos, *argv, 0)) { invarg("Invalid \"qos\" value\n", *argv); } } else { /* rewind arg */ PREV_ARG(); } } addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv, sizeof(ivv)); } else if (matches(*argv, "rate") == 0) { struct ifla_vf_tx_rate ivt; NEXT_ARG(); if (get_unsigned(&ivt.rate, *argv, 0)) { invarg("Invalid \"rate\" value\n", *argv); } ivt.vf = vf; addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE, &ivt, sizeof(ivt)); } else if (matches(*argv, "spoofchk") == 0) { struct ifla_vf_spoofchk ivs; NEXT_ARG(); if (matches(*argv, "on") == 0) ivs.setting = 1; else if (matches(*argv, "off") == 0) ivs.setting = 0; else invarg("Invalid \"spoofchk\" value\n", *argv); ivs.vf = vf; addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs)); } else { /* rewind arg */ PREV_ARG(); break; } } if (argc == *argcp) incomplete_command(); addattr_nest_end(&req->n, vfinfo); *argcp = argc; *argvp = argv; return 0; }
int iplink_parse(int argc, char **argv, struct iplink_req *req, char **name, char **type, char **link, char **dev) { int ret, len; char abuf[32]; int qlen = -1; int mtu = -1; int netns = -1; ret = argc; while (argc > 0) { if (strcmp(*argv, "up") == 0) { req->i.ifi_change |= IFF_UP; req->i.ifi_flags |= IFF_UP; } else if (strcmp(*argv, "down") == 0) { req->i.ifi_change |= IFF_UP; req->i.ifi_flags &= ~IFF_UP; } else if (strcmp(*argv, "name") == 0) { NEXT_ARG(); *name = *argv; } else if (matches(*argv, "link") == 0) { NEXT_ARG(); *link = *argv; } else if (matches(*argv, "address") == 0) { NEXT_ARG(); len = ll_addr_a2n(abuf, sizeof(abuf), *argv); if (len < 0) return -1; addattr_l(&req->n, sizeof(*req), IFLA_ADDRESS, abuf, len); } else if (matches(*argv, "broadcast") == 0 || strcmp(*argv, "brd") == 0) { NEXT_ARG(); len = ll_addr_a2n(abuf, sizeof(abuf), *argv); if (len < 0) return -1; addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len); } else if (matches(*argv, "txqueuelen") == 0 || strcmp(*argv, "qlen") == 0 || matches(*argv, "txqlen") == 0) { NEXT_ARG(); if (qlen != -1) duparg("txqueuelen", *argv); if (get_integer(&qlen, *argv, 0)) invarg("Invalid \"txqueuelen\" value\n", *argv); addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4); } else if (strcmp(*argv, "mtu") == 0) { NEXT_ARG(); if (mtu != -1) duparg("mtu", *argv); if (get_integer(&mtu, *argv, 0)) invarg("Invalid \"mtu\" value\n", *argv); addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4); } else if (strcmp(*argv, "netns") == 0) { NEXT_ARG(); if (netns != -1) duparg("netns", *argv); if (get_integer(&netns, *argv, 0)) invarg("Invalid \"netns\" value\n", *argv); addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4); } else if (strcmp(*argv, "multicast") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_MULTICAST; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_MULTICAST; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_MULTICAST; } else return on_off("multicast"); } else if (strcmp(*argv, "allmulticast") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_ALLMULTI; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_ALLMULTI; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_ALLMULTI; } else return on_off("allmulticast"); } else if (strcmp(*argv, "promisc") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_PROMISC; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_PROMISC; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_PROMISC; } else return on_off("promisc"); } else if (strcmp(*argv, "trailers") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_NOTRAILERS; if (strcmp(*argv, "off") == 0) { req->i.ifi_flags |= IFF_NOTRAILERS; } else if (strcmp(*argv, "on") == 0) { req->i.ifi_flags &= ~IFF_NOTRAILERS; } else return on_off("trailers"); } else if (strcmp(*argv, "arp") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_NOARP; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags &= ~IFF_NOARP; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags |= IFF_NOARP; } else return on_off("noarp"); #ifdef IFF_DYNAMIC } else if (matches(*argv, "dynamic") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_DYNAMIC; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_DYNAMIC; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_DYNAMIC; } else return on_off("dynamic"); #endif } else if (matches(*argv, "type") == 0) { NEXT_ARG(); *type = *argv; argc--; argv++; break; } else if (matches(*argv, "alias") == 0) { NEXT_ARG(); addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS, *argv, strlen(*argv)); argc--; argv++; break; } else { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (*dev) duparg2("dev", *argv); *dev = *argv; } argc--; argv++; } return ret - argc; }
static int bridge_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { __u32 val; while (argc > 0) { if (matches(*argv, "forward_delay") == 0) { NEXT_ARG(); if (get_u32(&val, *argv, 0)) invarg("invalid forward_delay", *argv); addattr32(n, 1024, IFLA_BR_FORWARD_DELAY, val); } else if (matches(*argv, "hello_time") == 0) { NEXT_ARG(); if (get_u32(&val, *argv, 0)) invarg("invalid hello_time", *argv); addattr32(n, 1024, IFLA_BR_HELLO_TIME, val); } else if (matches(*argv, "max_age") == 0) { NEXT_ARG(); if (get_u32(&val, *argv, 0)) invarg("invalid max_age", *argv); addattr32(n, 1024, IFLA_BR_MAX_AGE, val); } else if (matches(*argv, "ageing_time") == 0) { NEXT_ARG(); if (get_u32(&val, *argv, 0)) invarg("invalid ageing_time", *argv); addattr32(n, 1024, IFLA_BR_AGEING_TIME, val); } else if (matches(*argv, "stp_state") == 0) { NEXT_ARG(); if (get_u32(&val, *argv, 0)) invarg("invalid stp_state", *argv); addattr32(n, 1024, IFLA_BR_STP_STATE, val); } else if (matches(*argv, "priority") == 0) { __u16 prio; NEXT_ARG(); if (get_u16(&prio, *argv, 0)) invarg("invalid priority", *argv); addattr16(n, 1024, IFLA_BR_PRIORITY, prio); } else if (matches(*argv, "vlan_filtering") == 0) { __u8 vlan_filter; NEXT_ARG(); if (get_u8(&vlan_filter, *argv, 0)) invarg("invalid vlan_filtering", *argv); addattr8(n, 1024, IFLA_BR_VLAN_FILTERING, vlan_filter); } else if (matches(*argv, "vlan_protocol") == 0) { __u16 vlan_proto; NEXT_ARG(); if (ll_proto_a2n(&vlan_proto, *argv)) invarg("invalid vlan_protocol", *argv); addattr16(n, 1024, IFLA_BR_VLAN_PROTOCOL, vlan_proto); } else if (matches(*argv, "group_fwd_mask") == 0) { __u16 fwd_mask; NEXT_ARG(); if (get_u16(&fwd_mask, *argv, 0)) invarg("invalid group_fwd_mask", *argv); addattr16(n, 1024, IFLA_BR_GROUP_FWD_MASK, fwd_mask); } else if (matches(*argv, "group_address") == 0) { char llabuf[32]; int len; NEXT_ARG(); len = ll_addr_a2n(llabuf, sizeof(llabuf), *argv); if (len < 0) return -1; addattr_l(n, 1024, IFLA_BR_GROUP_ADDR, llabuf, len); } else if (matches(*argv, "vlan_default_pvid") == 0) { __u16 default_pvid; NEXT_ARG(); if (get_u16(&default_pvid, *argv, 0)) invarg("invalid vlan_default_pvid", *argv); addattr16(n, 1024, IFLA_BR_VLAN_DEFAULT_PVID, default_pvid); } else if (matches(*argv, "mcast_router") == 0) { __u8 mcast_router; NEXT_ARG(); if (get_u8(&mcast_router, *argv, 0)) invarg("invalid mcast_router", *argv); addattr8(n, 1024, IFLA_BR_MCAST_ROUTER, mcast_router); } else if (matches(*argv, "mcast_snooping") == 0) { __u8 mcast_snoop; NEXT_ARG(); if (get_u8(&mcast_snoop, *argv, 0)) invarg("invalid mcast_snooping", *argv); addattr8(n, 1024, IFLA_BR_MCAST_SNOOPING, mcast_snoop); } else if (matches(*argv, "mcast_query_use_ifaddr") == 0) { __u8 mcast_qui; NEXT_ARG(); if (get_u8(&mcast_qui, *argv, 0)) invarg("invalid mcast_query_use_ifaddr", *argv); addattr8(n, 1024, IFLA_BR_MCAST_QUERY_USE_IFADDR, mcast_qui); } else if (matches(*argv, "mcast_querier") == 0) { __u8 mcast_querier; NEXT_ARG(); if (get_u8(&mcast_querier, *argv, 0)) invarg("invalid mcast_querier", *argv); addattr8(n, 1024, IFLA_BR_MCAST_QUERIER, mcast_querier); } else if (matches(*argv, "mcast_hash_elasticity") == 0) { __u32 mcast_hash_el; NEXT_ARG(); if (get_u32(&mcast_hash_el, *argv, 0)) invarg("invalid mcast_hash_elasticity", *argv); addattr32(n, 1024, IFLA_BR_MCAST_HASH_ELASTICITY, mcast_hash_el); } else if (matches(*argv, "mcast_hash_max") == 0) { __u32 mcast_hash_max; NEXT_ARG(); if (get_u32(&mcast_hash_max, *argv, 0)) invarg("invalid mcast_hash_max", *argv); addattr32(n, 1024, IFLA_BR_MCAST_HASH_MAX, mcast_hash_max); } else if (matches(*argv, "mcast_last_member_count") == 0) { __u32 mcast_lmc; NEXT_ARG(); if (get_u32(&mcast_lmc, *argv, 0)) invarg("invalid mcast_last_member_count", *argv); addattr32(n, 1024, IFLA_BR_MCAST_LAST_MEMBER_CNT, mcast_lmc); } else if (matches(*argv, "mcast_startup_query_count") == 0) { __u32 mcast_sqc; NEXT_ARG(); if (get_u32(&mcast_sqc, *argv, 0)) invarg("invalid mcast_startup_query_count", *argv); addattr32(n, 1024, IFLA_BR_MCAST_STARTUP_QUERY_CNT, mcast_sqc); } else if (matches(*argv, "mcast_last_member_interval") == 0) { __u64 mcast_last_member_intvl; NEXT_ARG(); if (get_u64(&mcast_last_member_intvl, *argv, 0)) invarg("invalid mcast_last_member_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_LAST_MEMBER_INTVL, mcast_last_member_intvl); } else if (matches(*argv, "mcast_membership_interval") == 0) { __u64 mcast_membership_intvl; NEXT_ARG(); if (get_u64(&mcast_membership_intvl, *argv, 0)) invarg("invalid mcast_membership_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_MEMBERSHIP_INTVL, mcast_membership_intvl); } else if (matches(*argv, "mcast_querier_interval") == 0) { __u64 mcast_querier_intvl; NEXT_ARG(); if (get_u64(&mcast_querier_intvl, *argv, 0)) invarg("invalid mcast_querier_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_QUERIER_INTVL, mcast_querier_intvl); } else if (matches(*argv, "mcast_query_interval") == 0) { __u64 mcast_query_intvl; NEXT_ARG(); if (get_u64(&mcast_query_intvl, *argv, 0)) invarg("invalid mcast_query_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_QUERY_INTVL, mcast_query_intvl); } else if (!matches(*argv, "mcast_query_response_interval")) { __u64 mcast_query_resp_intvl; NEXT_ARG(); if (get_u64(&mcast_query_resp_intvl, *argv, 0)) invarg("invalid mcast_query_response_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, mcast_query_resp_intvl); } else if (!matches(*argv, "mcast_startup_query_interval")) { __u64 mcast_startup_query_intvl; NEXT_ARG(); if (get_u64(&mcast_startup_query_intvl, *argv, 0)) invarg("invalid mcast_startup_query_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_STARTUP_QUERY_INTVL, mcast_startup_query_intvl); } else if (matches(*argv, "nf_call_iptables") == 0) { __u8 nf_call_ipt; NEXT_ARG(); if (get_u8(&nf_call_ipt, *argv, 0)) invarg("invalid nf_call_iptables", *argv); addattr8(n, 1024, IFLA_BR_NF_CALL_IPTABLES, nf_call_ipt); } else if (matches(*argv, "nf_call_ip6tables") == 0) { __u8 nf_call_ip6t; NEXT_ARG(); if (get_u8(&nf_call_ip6t, *argv, 0)) invarg("invalid nf_call_ip6tables", *argv); addattr8(n, 1024, IFLA_BR_NF_CALL_IP6TABLES, nf_call_ip6t); } else if (matches(*argv, "nf_call_arptables") == 0) { __u8 nf_call_arpt; NEXT_ARG(); if (get_u8(&nf_call_arpt, *argv, 0)) invarg("invalid nf_call_arptables", *argv); addattr8(n, 1024, IFLA_BR_NF_CALL_ARPTABLES, nf_call_arpt); } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "bridge: unknown command \"%s\"?\n", *argv); explain(); return -1; } argc--, argv++; } return 0; }
int iplink_parse(int argc, char **argv, struct iplink_req *req, char **name, char **type, char **link, char **dev, int *group, int *index) { int ret, len; char abuf[32]; int qlen = -1; int mtu = -1; int netns = -1; int vf = -1; int numtxqueues = -1; int numrxqueues = -1; int dev_index = 0; *group = -1; ret = argc; while (argc > 0) { if (strcmp(*argv, "up") == 0) { req->i.ifi_change |= IFF_UP; req->i.ifi_flags |= IFF_UP; } else if (strcmp(*argv, "down") == 0) { req->i.ifi_change |= IFF_UP; req->i.ifi_flags &= ~IFF_UP; } else if (strcmp(*argv, "name") == 0) { NEXT_ARG(); *name = *argv; } else if (strcmp(*argv, "index") == 0) { NEXT_ARG(); *index = atoi(*argv); } else if (matches(*argv, "link") == 0) { NEXT_ARG(); *link = *argv; } else if (matches(*argv, "address") == 0) { NEXT_ARG(); len = ll_addr_a2n(abuf, sizeof(abuf), *argv); if (len < 0) return -1; addattr_l(&req->n, sizeof(*req), IFLA_ADDRESS, abuf, len); } else if (matches(*argv, "broadcast") == 0 || strcmp(*argv, "brd") == 0) { NEXT_ARG(); len = ll_addr_a2n(abuf, sizeof(abuf), *argv); if (len < 0) return -1; addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len); } else if (matches(*argv, "txqueuelen") == 0 || strcmp(*argv, "qlen") == 0 || matches(*argv, "txqlen") == 0) { NEXT_ARG(); if (qlen != -1) duparg("txqueuelen", *argv); if (get_integer(&qlen, *argv, 0)) invarg("Invalid \"txqueuelen\" value\n", *argv); addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4); } else if (strcmp(*argv, "mtu") == 0) { NEXT_ARG(); if (mtu != -1) duparg("mtu", *argv); if (get_integer(&mtu, *argv, 0)) invarg("Invalid \"mtu\" value\n", *argv); addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4); } else if (strcmp(*argv, "netns") == 0) { NEXT_ARG(); if (netns != -1) duparg("netns", *argv); if ((netns = get_netns_fd(*argv)) >= 0) addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4); else if (get_integer(&netns, *argv, 0) == 0) addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4); else invarg("Invalid \"netns\" value\n", *argv); } else if (strcmp(*argv, "multicast") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_MULTICAST; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_MULTICAST; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_MULTICAST; } else return on_off("multicast", *argv); } else if (strcmp(*argv, "allmulticast") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_ALLMULTI; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_ALLMULTI; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_ALLMULTI; } else return on_off("allmulticast", *argv); } else if (strcmp(*argv, "promisc") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_PROMISC; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_PROMISC; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_PROMISC; } else return on_off("promisc", *argv); } else if (strcmp(*argv, "trailers") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_NOTRAILERS; if (strcmp(*argv, "off") == 0) { req->i.ifi_flags |= IFF_NOTRAILERS; } else if (strcmp(*argv, "on") == 0) { req->i.ifi_flags &= ~IFF_NOTRAILERS; } else return on_off("trailers", *argv); } else if (strcmp(*argv, "arp") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_NOARP; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags &= ~IFF_NOARP; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags |= IFF_NOARP; } else return on_off("noarp", *argv); } else if (strcmp(*argv, "vf") == 0) { struct rtattr *vflist; NEXT_ARG(); if (get_integer(&vf, *argv, 0)) { invarg("Invalid \"vf\" value\n", *argv); } vflist = addattr_nest(&req->n, sizeof(*req), IFLA_VFINFO_LIST); if (dev_index == 0) missarg("dev"); len = iplink_parse_vf(vf, &argc, &argv, req, dev_index); if (len < 0) return -1; addattr_nest_end(&req->n, vflist); } else if (matches(*argv, "master") == 0) { int ifindex; NEXT_ARG(); ifindex = ll_name_to_index(*argv); if (!ifindex) invarg("Device does not exist\n", *argv); addattr_l(&req->n, sizeof(*req), IFLA_MASTER, &ifindex, 4); } else if (matches(*argv, "nomaster") == 0) { int ifindex = 0; addattr_l(&req->n, sizeof(*req), IFLA_MASTER, &ifindex, 4); } else if (matches(*argv, "dynamic") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_DYNAMIC; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_DYNAMIC; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_DYNAMIC; } else return on_off("dynamic", *argv); } else if (matches(*argv, "type") == 0) { NEXT_ARG(); *type = *argv; argc--; argv++; break; } else if (matches(*argv, "alias") == 0) { NEXT_ARG(); addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS, *argv, strlen(*argv)); argc--; argv++; break; } else if (strcmp(*argv, "group") == 0) { NEXT_ARG(); if (*group != -1) duparg("group", *argv); if (rtnl_group_a2n(group, *argv)) invarg("Invalid \"group\" value\n", *argv); } else if (strcmp(*argv, "mode") == 0) { int mode; NEXT_ARG(); mode = get_link_mode(*argv); if (mode < 0) invarg("Invalid link mode\n", *argv); addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode); } else if (strcmp(*argv, "state") == 0) { int state; NEXT_ARG(); state = get_operstate(*argv); if (state < 0) invarg("Invalid operstate\n", *argv); addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state); } else if (matches(*argv, "numtxqueues") == 0) { NEXT_ARG(); if (numtxqueues != -1) duparg("numtxqueues", *argv); if (get_integer(&numtxqueues, *argv, 0)) invarg("Invalid \"numtxqueues\" value\n", *argv); addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES, &numtxqueues, 4); } else if (matches(*argv, "numrxqueues") == 0) { NEXT_ARG(); if (numrxqueues != -1) duparg("numrxqueues", *argv); if (get_integer(&numrxqueues, *argv, 0)) invarg("Invalid \"numrxqueues\" value\n", *argv); addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES, &numrxqueues, 4); } else { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (*dev) duparg2("dev", *argv); *dev = *argv; dev_index = ll_name_to_index(*dev); if (dev_index == 0) invarg("Unknown device", *argv); } argc--; argv++; } return ret - argc; }
int iplink_parse(int argc, char **argv, struct iplink_req *req, char **name, char **type, char **link, char **dev) { int ret, len; char abuf[32]; int qlen = -1; int mtu = -1; int netns = -1; int vf = -1; ret = argc; while (argc > 0) { if (strcmp(*argv, "up") == 0) { req->i.ifi_change |= IFF_UP; req->i.ifi_flags |= IFF_UP; } else if (strcmp(*argv, "down") == 0) { req->i.ifi_change |= IFF_UP; req->i.ifi_flags &= ~IFF_UP; } else if (strcmp(*argv, "name") == 0) { NEXT_ARG(); *name = *argv; } else if (matches(*argv, "link") == 0) { NEXT_ARG(); *link = *argv; } else if (matches(*argv, "address") == 0) { NEXT_ARG(); len = ll_addr_a2n(abuf, sizeof(abuf), *argv); if (len < 0) return -1; addattr_l(&req->n, sizeof(*req), IFLA_ADDRESS, abuf, len); } else if (matches(*argv, "broadcast") == 0 || strcmp(*argv, "brd") == 0) { NEXT_ARG(); len = ll_addr_a2n(abuf, sizeof(abuf), *argv); if (len < 0) return -1; addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len); } else if (matches(*argv, "txqueuelen") == 0 || strcmp(*argv, "qlen") == 0 || matches(*argv, "txqlen") == 0) { NEXT_ARG(); if (qlen != -1) duparg("txqueuelen", *argv); if (get_integer(&qlen, *argv, 0)) invarg("Invalid \"txqueuelen\" value\n", *argv); addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4); } else if (strcmp(*argv, "mtu") == 0) { NEXT_ARG(); if (mtu != -1) duparg("mtu", *argv); if (get_integer(&mtu, *argv, 0)) invarg("Invalid \"mtu\" value\n", *argv); addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4); } else if (strcmp(*argv, "netns") == 0) { NEXT_ARG(); if (netns != -1) duparg("netns", *argv); if (get_integer(&netns, *argv, 0)) invarg("Invalid \"netns\" value\n", *argv); addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4); } else if (strcmp(*argv, "multicast") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_MULTICAST; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_MULTICAST; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_MULTICAST; } else return on_off("multicast"); } else if (strcmp(*argv, "allmulticast") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_ALLMULTI; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_ALLMULTI; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_ALLMULTI; } else return on_off("allmulticast"); } else if (strcmp(*argv, "multipath") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_NOMULTIPATH; req->i.ifi_change |= IFF_MPBACKUP; req->i.ifi_change |= IFF_MPHANDOVER; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags &= ~IFF_NOMULTIPATH; req->i.ifi_flags &= ~IFF_MPBACKUP; req->i.ifi_flags &= ~IFF_MPHANDOVER; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags |= IFF_NOMULTIPATH; } else if (strcmp(*argv, "backup") == 0) { req->i.ifi_flags &= ~IFF_NOMULTIPATH; req->i.ifi_flags |= IFF_MPBACKUP; } else if (strcmp(*argv, "handover") == 0) { req->i.ifi_flags &= ~IFF_NOMULTIPATH; req->i.ifi_flags |= IFF_MPHANDOVER; } else { fprintf(stderr, "Error: argument of \"multipath\" must be" "\"on\", \"off\", \"backup\" or \"handover\"\n"); return -1; } } else if (strcmp(*argv, "promisc") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_PROMISC; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_PROMISC; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_PROMISC; } else return on_off("promisc"); } else if (strcmp(*argv, "trailers") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_NOTRAILERS; if (strcmp(*argv, "off") == 0) { req->i.ifi_flags |= IFF_NOTRAILERS; } else if (strcmp(*argv, "on") == 0) { req->i.ifi_flags &= ~IFF_NOTRAILERS; } else return on_off("trailers"); } else if (strcmp(*argv, "arp") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_NOARP; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags &= ~IFF_NOARP; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags |= IFF_NOARP; } else return on_off("noarp"); } else if (strcmp(*argv, "vf") == 0) { struct rtattr *vflist; NEXT_ARG(); if (get_integer(&vf, *argv, 0)) { invarg("Invalid \"vf\" value\n", *argv); } vflist = addattr_nest(&req->n, sizeof(*req), IFLA_VFINFO_LIST); len = iplink_parse_vf(vf, &argc, &argv, req); if (len < 0) return -1; addattr_nest_end(&req->n, vflist); #ifdef IFF_DYNAMIC } else if (matches(*argv, "dynamic") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_DYNAMIC; if (strcmp(*argv, "on") == 0) { req->i.ifi_flags |= IFF_DYNAMIC; } else if (strcmp(*argv, "off") == 0) { req->i.ifi_flags &= ~IFF_DYNAMIC; } else return on_off("dynamic"); #endif } else if (matches(*argv, "type") == 0) { NEXT_ARG(); *type = *argv; argc--; argv++; break; } else if (matches(*argv, "alias") == 0) { NEXT_ARG(); addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS, *argv, strlen(*argv)); argc--; argv++; break; } else { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (*dev) duparg2("dev", *argv); *dev = *argv; } argc--; argv++; } return ret - argc; }