int set_ieee(char *ifname, struct ieee_ets *ets_data, struct ieee_pfc *pfc_data, struct dcb_app *app_data) { struct nlmsghdr *nlh; struct rtattr *ieee, *apptbl; nlh = start_msg(RTM_SETDCB, DCB_CMD_IEEE_SET); if (NULL == nlh) return -EIO; addattr_l(nlh, DCB_ATTR_IFNAME, ifname, strlen(ifname) + 1); ieee = addattr_nest(nlh, DCB_ATTR_IEEE); if (ets_data) addattr_l(nlh, DCB_ATTR_IEEE_ETS, ets_data, sizeof(*ets_data)); if (pfc_data) addattr_l(nlh, DCB_ATTR_IEEE_PFC, pfc_data, sizeof(*pfc_data)); if (app_data) { apptbl = addattr_nest(nlh, DCB_ATTR_IEEE_APP_TABLE); addattr_l(nlh, DCB_ATTR_IEEE_APP, app_data, sizeof(*app_data)); #if 1 app_data->protocol++; addattr_l(nlh, DCB_ATTR_IEEE_APP, app_data, sizeof(*app_data)); #endif addattr_nest_end(nlh, apptbl); } addattr_nest_end(nlh, ieee); if (send_msg(nlh)) return -EIO; return recv_msg(DCB_CMD_IEEE_SET, DCB_ATTR_IEEE); }
static int pedit_keys_ex_addattr(struct m_pedit_sel *sel, struct nlmsghdr *n) { struct m_pedit_key_ex *k = sel->keys_ex; struct rtattr *keys_start; int i; if (!sel->extended) return 0; keys_start = addattr_nest(n, MAX_MSG, TCA_PEDIT_KEYS_EX | NLA_F_NESTED); for (i = 0; i < sel->sel.nkeys; i++) { struct rtattr *key_start; key_start = addattr_nest(n, MAX_MSG, TCA_PEDIT_KEY_EX | NLA_F_NESTED); if (addattr16(n, MAX_MSG, TCA_PEDIT_KEY_EX_HTYPE, k->htype) || addattr16(n, MAX_MSG, TCA_PEDIT_KEY_EX_CMD, k->cmd)) { return -1; } addattr_nest_end(n, key_start); k++; } addattr_nest_end(n, keys_start); return 0; }
static int do_modify_nl(enum cmd c, enum macsec_nl_commands cmd, int ifindex, struct rxsc_desc *rxsc, struct sa_desc *sa) { struct rtattr *attr_sa; MACSEC_GENL_REQ(req, MACSEC_BUFLEN, cmd, NLM_F_REQUEST); addattr32(&req.n, MACSEC_BUFLEN, MACSEC_ATTR_IFINDEX, ifindex); if (rxsc) { struct rtattr *attr_rxsc; attr_rxsc = addattr_nest(&req.n, MACSEC_BUFLEN, MACSEC_ATTR_RXSC_CONFIG); addattr64(&req.n, MACSEC_BUFLEN, MACSEC_RXSC_ATTR_SCI, rxsc->sci); if (c != CMD_DEL && rxsc->active != 0xff) addattr8(&req.n, MACSEC_BUFLEN, MACSEC_RXSC_ATTR_ACTIVE, rxsc->active); addattr_nest_end(&req.n, attr_rxsc); } if (sa->an == 0xff) goto talk; attr_sa = addattr_nest(&req.n, MACSEC_BUFLEN, MACSEC_ATTR_SA_CONFIG); addattr8(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_AN, sa->an); if (c != CMD_DEL) { if (sa->pn) addattr32(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_PN, sa->pn); if (sa->key_len) { addattr_l(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_KEYID, sa->key_id, MACSEC_KEYID_LEN); addattr_l(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_KEY, sa->key, sa->key_len); } if (sa->active != 0xff) { addattr8(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_ACTIVE, sa->active); } } addattr_nest_end(&req.n, attr_sa); talk: if (rtnl_talk(&genl_rth, &req.n, NULL) < 0) return -2; return 0; }
static int parse_connmark(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { struct tc_connmark sel = {}; char **argv = *argv_p; int argc = *argc_p; int ok = 0; struct rtattr *tail; while (argc > 0) { if (matches(*argv, "connmark") == 0) { ok = 1; argc--; argv++; } else if (matches(*argv, "help") == 0) { usage(); } else { break; } } if (!ok) { explain(); return -1; } if (argc) { if (matches(*argv, "zone") == 0) { NEXT_ARG(); if (get_u16(&sel.zone, *argv, 10)) { fprintf(stderr, "simple: Illegal \"index\"\n"); return -1; } argc--; argv++; } } parse_action_control_dflt(&argc, &argv, &sel.action, false, TC_ACT_PIPE); if (argc) { if (matches(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&sel.index, *argv, 10)) { fprintf(stderr, "simple: Illegal \"index\"\n"); return -1; } argc--; argv++; } } tail = addattr_nest(n, MAX_MSG, tca_id); addattr_l(n, MAX_MSG, TCA_CONNMARK_PARMS, &sel, sizeof(sel)); addattr_nest_end(n, tail); *argc_p = argc; *argv_p = argv; return 0; }
static int codel_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { unsigned int limit = 0; unsigned int target = 0; unsigned int interval = 0; unsigned int ce_threshold = ~0U; int ecn = -1; struct rtattr *tail; while (argc > 0) { if (strcmp(*argv, "limit") == 0) { NEXT_ARG(); if (get_unsigned(&limit, *argv, 0)) { fprintf(stderr, "Illegal \"limit\"\n"); return -1; } } else if (strcmp(*argv, "target") == 0) { NEXT_ARG(); if (get_time(&target, *argv)) { fprintf(stderr, "Illegal \"target\"\n"); return -1; } } else if (strcmp(*argv, "ce_threshold") == 0) { NEXT_ARG(); if (get_time(&ce_threshold, *argv)) { fprintf(stderr, "Illegal \"ce_threshold\"\n"); return -1; } } else if (strcmp(*argv, "interval") == 0) { NEXT_ARG(); if (get_time(&interval, *argv)) { fprintf(stderr, "Illegal \"interval\"\n"); return -1; } } else if (strcmp(*argv, "ecn") == 0) { ecn = 1; } else if (strcmp(*argv, "noecn") == 0) { ecn = 0; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } tail = addattr_nest(n, 1024, TCA_OPTIONS); if (limit) addattr_l(n, 1024, TCA_CODEL_LIMIT, &limit, sizeof(limit)); if (interval) addattr_l(n, 1024, TCA_CODEL_INTERVAL, &interval, sizeof(interval)); if (target) addattr_l(n, 1024, TCA_CODEL_TARGET, &target, sizeof(target)); if (ecn != -1) addattr_l(n, 1024, TCA_CODEL_ECN, &ecn, sizeof(ecn)); if (ce_threshold != ~0U) addattr_l(n, 1024, TCA_CODEL_CE_THRESHOLD, &ce_threshold, sizeof(ce_threshold)); addattr_nest_end(n, tail); return 0; }
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; }
static int hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { struct tc_service_curve rsc = {}, fsc = {}, usc = {}; int rsc_ok = 0, fsc_ok = 0, usc_ok = 0; struct rtattr *tail; while (argc > 0) { if (matches(*argv, "rt") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &rsc, dev) < 0) { explain1("rt"); return -1; } rsc_ok = 1; } else if (matches(*argv, "ls") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &fsc, dev) < 0) { explain1("ls"); return -1; } fsc_ok = 1; } else if (matches(*argv, "sc") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &rsc, dev) < 0) { explain1("sc"); return -1; } memcpy(&fsc, &rsc, sizeof(fsc)); rsc_ok = 1; fsc_ok = 1; } else if (matches(*argv, "ul") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &usc, dev) < 0) { explain1("ul"); return -1; } usc_ok = 1; } else if (matches(*argv, "help") == 0) { explain_class(); return -1; } else { fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv); explain_class(); return -1; } argc--, argv++; } if (!(rsc_ok || fsc_ok || usc_ok)) { fprintf(stderr, "HFSC: no parameters given\n"); explain_class(); return -1; } if (usc_ok && !fsc_ok) { fprintf(stderr, "HFSC: Upper-limit Service Curve without Link-Share Service Curve\n"); explain_class(); return -1; } tail = addattr_nest(n, 1024, TCA_OPTIONS); if (rsc_ok) addattr_l(n, 1024, TCA_HFSC_RSC, &rsc, sizeof(rsc)); if (fsc_ok) addattr_l(n, 1024, TCA_HFSC_FSC, &fsc, sizeof(fsc)); if (usc_ok) addattr_l(n, 1024, TCA_HFSC_USC, &usc, sizeof(usc)); addattr_nest_end(n, tail); 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; }
static int vlan_modify(int cmd, int argc, char **argv) { struct { struct nlmsghdr n; struct ifinfomsg ifm; char buf[1024]; } req; char *d = NULL; short vid = -1; struct rtattr *afspec; struct bridge_vlan_info vinfo; unsigned short flags = 0; memset(&vinfo, 0, sizeof(vinfo)); 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 = cmd; req.ifm.ifi_family = PF_BRIDGE; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); d = *argv; } else if (strcmp(*argv, "vid") == 0) { NEXT_ARG(); vid = atoi(*argv); } else if (strcmp(*argv, "self") == 0) { flags |= BRIDGE_FLAGS_SELF; } else if (strcmp(*argv, "master") == 0) { flags |= BRIDGE_FLAGS_MASTER; } else if (strcmp(*argv, "pvid") == 0) { vinfo.flags |= BRIDGE_VLAN_INFO_PVID; } else if (strcmp(*argv, "untagged") == 0) { vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED; } else { if (matches(*argv, "help") == 0) { NEXT_ARG(); } } argc--; argv++; } if (d == NULL || vid == -1) { fprintf(stderr, "Device and VLAN ID are required arguments.\n"); exit(-1); } req.ifm.ifi_index = ll_name_to_index(d); if (req.ifm.ifi_index == 0) { fprintf(stderr, "Cannot find bridge device \"%s\"\n", d); return -1; } if (vid >= 4096) { fprintf(stderr, "Invalid VLAN ID \"%hu\"\n", vid); return -1; } vinfo.vid = vid; afspec = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC); if (flags) addattr16(&req.n, sizeof(req), IFLA_BRIDGE_FLAGS, flags); addattr_l(&req.n, sizeof(req), IFLA_BRIDGE_VLAN_INFO, &vinfo, sizeof(vinfo)); addattr_nest_end(&req.n, afspec); if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) exit(2); return 0; }
static int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { struct m_pedit_sel sel = {}; int argc = *argc_p; char **argv = *argv_p; int ok = 0, iok = 0; struct rtattr *tail; while (argc > 0) { if (pedit_debug > 1) fprintf(stderr, "while pedit (%d:%s)\n", argc, *argv); if (matches(*argv, "pedit") == 0) { NEXT_ARG(); ok++; if (matches(*argv, "ex") == 0) { if (ok > 1) { fprintf(stderr, "'ex' must be before first 'munge'\n"); explain(); return -1; } sel.extended = true; NEXT_ARG(); } continue; } else if (matches(*argv, "help") == 0) { usage(); } else if (matches(*argv, "munge") == 0) { if (!ok) { fprintf(stderr, "Bad pedit construct (%s)\n", *argv); explain(); return -1; } NEXT_ARG(); if (parse_munge(&argc, &argv, &sel)) { fprintf(stderr, "Bad pedit construct (%s)\n", *argv); explain(); return -1; } ok++; } else { break; } } if (!ok) { explain(); return -1; } parse_action_control_dflt(&argc, &argv, &sel.sel.action, false, TC_ACT_OK); if (argc) { if (matches(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&sel.sel.index, *argv, 10)) { fprintf(stderr, "Pedit: Illegal \"index\"\n"); return -1; } argc--; argv++; iok++; } } tail = addattr_nest(n, MAX_MSG, tca_id); if (!sel.extended) { addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS, &sel, sizeof(sel.sel) + sel.sel.nkeys * sizeof(struct tc_pedit_key)); } else { addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS_EX, &sel, sizeof(sel.sel) + sel.sel.nkeys * sizeof(struct tc_pedit_key)); pedit_keys_ex_addattr(&sel, n); } addattr_nest_end(n, tail); *argc_p = argc; *argv_p = argv; return 0; }
static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { unsigned int plimit; unsigned int flow_plimit; unsigned int quantum; unsigned int initial_quantum; unsigned int buckets = 0; unsigned int maxrate; unsigned int low_rate_threshold; unsigned int defrate; unsigned int refill_delay; unsigned int orphan_mask; unsigned int ce_threshold; bool set_plimit = false; bool set_flow_plimit = false; bool set_quantum = false; bool set_initial_quantum = false; bool set_maxrate = false; bool set_defrate = false; bool set_refill_delay = false; bool set_orphan_mask = false; bool set_low_rate_threshold = false; bool set_ce_threshold = false; int pacing = -1; struct rtattr *tail; while (argc > 0) { if (strcmp(*argv, "limit") == 0) { NEXT_ARG(); if (get_unsigned(&plimit, *argv, 0)) { fprintf(stderr, "Illegal \"limit\"\n"); return -1; } set_plimit = true; } else if (strcmp(*argv, "flow_limit") == 0) { NEXT_ARG(); if (get_unsigned(&flow_plimit, *argv, 0)) { fprintf(stderr, "Illegal \"flow_limit\"\n"); return -1; } set_flow_plimit = true; } else if (strcmp(*argv, "buckets") == 0) { NEXT_ARG(); if (get_unsigned(&buckets, *argv, 0)) { fprintf(stderr, "Illegal \"buckets\"\n"); return -1; } } else if (strcmp(*argv, "maxrate") == 0) { NEXT_ARG(); if (strchr(*argv, '%')) { if (get_percent_rate(&maxrate, *argv, dev)) { fprintf(stderr, "Illegal \"maxrate\"\n"); return -1; } } else if (get_rate(&maxrate, *argv)) { fprintf(stderr, "Illegal \"maxrate\"\n"); return -1; } set_maxrate = true; } else if (strcmp(*argv, "low_rate_threshold") == 0) { NEXT_ARG(); if (get_rate(&low_rate_threshold, *argv)) { fprintf(stderr, "Illegal \"low_rate_threshold\"\n"); return -1; } set_low_rate_threshold = true; } else if (strcmp(*argv, "ce_threshold") == 0) { NEXT_ARG(); if (get_time(&ce_threshold, *argv)) { fprintf(stderr, "Illegal \"ce_threshold\"\n"); return -1; } set_ce_threshold = true; } else if (strcmp(*argv, "defrate") == 0) { NEXT_ARG(); if (strchr(*argv, '%')) { if (get_percent_rate(&defrate, *argv, dev)) { fprintf(stderr, "Illegal \"defrate\"\n"); return -1; } } else if (get_rate(&defrate, *argv)) { fprintf(stderr, "Illegal \"defrate\"\n"); return -1; } set_defrate = true; } else if (strcmp(*argv, "quantum") == 0) { NEXT_ARG(); if (get_unsigned(&quantum, *argv, 0)) { fprintf(stderr, "Illegal \"quantum\"\n"); return -1; } set_quantum = true; } else if (strcmp(*argv, "initial_quantum") == 0) { NEXT_ARG(); if (get_unsigned(&initial_quantum, *argv, 0)) { fprintf(stderr, "Illegal \"initial_quantum\"\n"); return -1; } set_initial_quantum = true; } else if (strcmp(*argv, "orphan_mask") == 0) { NEXT_ARG(); if (get_unsigned(&orphan_mask, *argv, 0)) { fprintf(stderr, "Illegal \"initial_quantum\"\n"); return -1; } set_orphan_mask = true; } else if (strcmp(*argv, "refill_delay") == 0) { NEXT_ARG(); if (get_time(&refill_delay, *argv)) { fprintf(stderr, "Illegal \"refill_delay\"\n"); return -1; } set_refill_delay = true; } else if (strcmp(*argv, "pacing") == 0) { pacing = 1; } else if (strcmp(*argv, "nopacing") == 0) { pacing = 0; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } tail = addattr_nest(n, 1024, TCA_OPTIONS); if (buckets) { unsigned int log = ilog2(buckets); addattr_l(n, 1024, TCA_FQ_BUCKETS_LOG, &log, sizeof(log)); } if (set_plimit) addattr_l(n, 1024, TCA_FQ_PLIMIT, &plimit, sizeof(plimit)); if (set_flow_plimit) addattr_l(n, 1024, TCA_FQ_FLOW_PLIMIT, &flow_plimit, sizeof(flow_plimit)); if (set_quantum) addattr_l(n, 1024, TCA_FQ_QUANTUM, &quantum, sizeof(quantum)); if (set_initial_quantum) addattr_l(n, 1024, TCA_FQ_INITIAL_QUANTUM, &initial_quantum, sizeof(initial_quantum)); if (pacing != -1) addattr_l(n, 1024, TCA_FQ_RATE_ENABLE, &pacing, sizeof(pacing)); if (set_maxrate) addattr_l(n, 1024, TCA_FQ_FLOW_MAX_RATE, &maxrate, sizeof(maxrate)); if (set_low_rate_threshold) addattr_l(n, 1024, TCA_FQ_LOW_RATE_THRESHOLD, &low_rate_threshold, sizeof(low_rate_threshold)); if (set_defrate) addattr_l(n, 1024, TCA_FQ_FLOW_DEFAULT_RATE, &defrate, sizeof(defrate)); if (set_refill_delay) addattr_l(n, 1024, TCA_FQ_FLOW_REFILL_DELAY, &refill_delay, sizeof(refill_delay)); if (set_orphan_mask) addattr_l(n, 1024, TCA_FQ_ORPHAN_MASK, &orphan_mask, sizeof(refill_delay)); if (set_ce_threshold) addattr_l(n, 1024, TCA_FQ_CE_THRESHOLD, &ce_threshold, sizeof(ce_threshold)); addattr_nest_end(n, tail); return 0; }
static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { int dist_size = 0; struct rtattr *tail; struct tc_netem_qopt opt = { .limit = 1000 }; struct tc_netem_corr cor; struct tc_netem_reorder reorder; struct tc_netem_corrupt corrupt; struct tc_netem_gimodel gimodel; struct tc_netem_gemodel gemodel; struct tc_netem_rate rate; __s16 *dist_data = NULL; __u16 loss_type = NETEM_LOSS_UNSPEC; int present[__TCA_NETEM_MAX]; __u64 rate64 = 0; memset(&cor, 0, sizeof(cor)); memset(&reorder, 0, sizeof(reorder)); memset(&corrupt, 0, sizeof(corrupt)); memset(&rate, 0, sizeof(rate)); memset(present, 0, sizeof(present)); for( ; argc > 0; --argc, ++argv) { if (matches(*argv, "limit") == 0) { NEXT_ARG(); if (get_size(&opt.limit, *argv)) { explain1("limit"); return -1; } } else if (matches(*argv, "latency") == 0 || matches(*argv, "delay") == 0) { NEXT_ARG(); if (get_ticks(&opt.latency, *argv)) { explain1("latency"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); if (get_ticks(&opt.jitter, *argv)) { explain1("latency"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); ++present[TCA_NETEM_CORR]; if (get_percent(&cor.delay_corr, *argv)) { explain1("latency"); return -1; } } } } else if (matches(*argv, "loss") == 0 || matches(*argv, "drop") == 0) { if (opt.loss > 0 || loss_type != NETEM_LOSS_UNSPEC) { explain1("duplicate loss argument\n"); return -1; } NEXT_ARG(); /* Old (deprecated) random loss model syntax */ if (isdigit(argv[0][0])) goto random_loss_model; if (!strcmp(*argv, "random")) { NEXT_ARG(); random_loss_model: if (get_percent(&opt.loss, *argv)) { explain1("loss percent"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); ++present[TCA_NETEM_CORR]; if (get_percent(&cor.loss_corr, *argv)) { explain1("loss correllation"); return -1; } } } else if (!strcmp(*argv, "state")) { double p13; NEXT_ARG(); if (parse_percent(&p13, *argv)) { explain1("loss p13"); return -1; } /* set defaults */ set_percent(&gimodel.p13, p13); set_percent(&gimodel.p31, 1. - p13); set_percent(&gimodel.p32, 0); set_percent(&gimodel.p23, 1.); set_percent(&gimodel.p14, 0); loss_type = NETEM_LOSS_GI; if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gimodel.p31, *argv)) { explain1("loss p31"); return -1; } if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gimodel.p32, *argv)) { explain1("loss p32"); return -1; } if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gimodel.p23, *argv)) { explain1("loss p23"); return -1; } if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gimodel.p14, *argv)) { explain1("loss p14"); return -1; } } else if (!strcmp(*argv, "gemodel")) { NEXT_ARG(); if (get_percent(&gemodel.p, *argv)) { explain1("loss gemodel p"); return -1; } /* set defaults */ set_percent(&gemodel.r, 1.); set_percent(&gemodel.h, 0); set_percent(&gemodel.k1, 0); loss_type = NETEM_LOSS_GE; if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gemodel.r, *argv)) { explain1("loss gemodel r"); return -1; } if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gemodel.h, *argv)) { explain1("loss gemodel h"); return -1; } /* netem option is "1-h" but kernel * expects "h". */ gemodel.h = max_percent_value - gemodel.h; if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gemodel.k1, *argv)) { explain1("loss gemodel k"); return -1; } } else { fprintf(stderr, "Unknown loss parameter: %s\n", *argv); return -1; } } else if (matches(*argv, "ecn") == 0) { present[TCA_NETEM_ECN] = 1; } else if (matches(*argv, "reorder") == 0) { NEXT_ARG(); present[TCA_NETEM_REORDER] = 1; if (get_percent(&reorder.probability, *argv)) { explain1("reorder"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); ++present[TCA_NETEM_CORR]; if (get_percent(&reorder.correlation, *argv)) { explain1("reorder"); return -1; } } } else if (matches(*argv, "corrupt") == 0) { NEXT_ARG(); present[TCA_NETEM_CORRUPT] = 1; if (get_percent(&corrupt.probability, *argv)) { explain1("corrupt"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); ++present[TCA_NETEM_CORR]; if (get_percent(&corrupt.correlation, *argv)) { explain1("corrupt"); return -1; } } } else if (matches(*argv, "gap") == 0) { NEXT_ARG(); if (get_u32(&opt.gap, *argv, 0)) { explain1("gap"); return -1; } } else if (matches(*argv, "duplicate") == 0) { NEXT_ARG(); if (get_percent(&opt.duplicate, *argv)) { explain1("duplicate"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); if (get_percent(&cor.dup_corr, *argv)) { explain1("duplicate"); return -1; } } } else if (matches(*argv, "distribution") == 0) { NEXT_ARG(); dist_data = calloc(sizeof(dist_data[0]), MAX_DIST); dist_size = get_distribution(*argv, dist_data, MAX_DIST); if (dist_size <= 0) { free(dist_data); return -1; } } else if (matches(*argv, "rate") == 0) { ++present[TCA_NETEM_RATE]; NEXT_ARG(); if (get_rate64(&rate64, *argv)) { explain1("rate"); return -1; } if (NEXT_IS_SIGNED_NUMBER()) { NEXT_ARG(); if (get_s32(&rate.packet_overhead, *argv, 0)) { explain1("rate"); return -1; } } if (NEXT_IS_NUMBER()) { NEXT_ARG(); if (get_u32(&rate.cell_size, *argv, 0)) { explain1("rate"); return -1; } } if (NEXT_IS_SIGNED_NUMBER()) { NEXT_ARG(); if (get_s32(&rate.cell_overhead, *argv, 0)) { explain1("rate"); return -1; } } } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } } tail = NLMSG_TAIL(n); if (reorder.probability) { if (opt.latency == 0) { fprintf(stderr, "reordering not possible without specifying some delay\n"); explain(); return -1; } if (opt.gap == 0) opt.gap = 1; } else if (opt.gap > 0) { fprintf(stderr, "gap specified without reorder probability\n"); explain(); return -1; } if (present[TCA_NETEM_ECN]) { if (opt.loss <= 0 && loss_type == NETEM_LOSS_UNSPEC) { fprintf(stderr, "ecn requested without loss model\n"); explain(); return -1; } } if (dist_data && (opt.latency == 0 || opt.jitter == 0)) { fprintf(stderr, "distribution specified but no latency and jitter values\n"); explain(); return -1; } if (addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)) < 0) return -1; if (present[TCA_NETEM_CORR] && addattr_l(n, 1024, TCA_NETEM_CORR, &cor, sizeof(cor)) < 0) return -1; if (present[TCA_NETEM_REORDER] && addattr_l(n, 1024, TCA_NETEM_REORDER, &reorder, sizeof(reorder)) < 0) return -1; if (present[TCA_NETEM_ECN] && addattr_l(n, 1024, TCA_NETEM_ECN, &present[TCA_NETEM_ECN], sizeof(present[TCA_NETEM_ECN])) < 0) return -1; if (present[TCA_NETEM_CORRUPT] && addattr_l(n, 1024, TCA_NETEM_CORRUPT, &corrupt, sizeof(corrupt)) < 0) return -1; if (loss_type != NETEM_LOSS_UNSPEC) { struct rtattr *start; start = addattr_nest(n, 1024, TCA_NETEM_LOSS | NLA_F_NESTED); if (loss_type == NETEM_LOSS_GI) { if (addattr_l(n, 1024, NETEM_LOSS_GI, &gimodel, sizeof(gimodel)) < 0) return -1; } else if (loss_type == NETEM_LOSS_GE) { if (addattr_l(n, 1024, NETEM_LOSS_GE, &gemodel, sizeof(gemodel)) < 0) return -1; } else { fprintf(stderr, "loss in the weeds!\n"); return -1; } addattr_nest_end(n, start); } if (present[TCA_NETEM_RATE]) { if (rate64 >= (1ULL << 32)) { if (addattr_l(n, 1024, TCA_NETEM_RATE64, &rate64, sizeof(rate64)) < 0) return -1; rate.rate = ~0U; } else { rate.rate = rate64; } if (addattr_l(n, 1024, TCA_NETEM_RATE, &rate, sizeof(rate)) < 0) return -1; } if (dist_data) { if (addattr_l(n, MAX_DIST * sizeof(dist_data[0]), TCA_NETEM_DELAY_DIST, dist_data, dist_size * sizeof(dist_data[0])) < 0) return -1; free(dist_data); } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; } static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) { const struct tc_netem_corr *cor = NULL; const struct tc_netem_reorder *reorder = NULL; const struct tc_netem_corrupt *corrupt = NULL; const struct tc_netem_gimodel *gimodel = NULL; const struct tc_netem_gemodel *gemodel = NULL; int *ecn = NULL; struct tc_netem_qopt qopt; const struct tc_netem_rate *rate = NULL; int len = RTA_PAYLOAD(opt) - sizeof(qopt); __u64 rate64 = 0; SPRINT_BUF(b1); if (opt == NULL) return 0; if (len < 0) { fprintf(stderr, "options size error\n"); return -1; } memcpy(&qopt, RTA_DATA(opt), sizeof(qopt)); if (len > 0) { struct rtattr *tb[TCA_NETEM_MAX+1]; parse_rtattr(tb, TCA_NETEM_MAX, RTA_DATA(opt) + sizeof(qopt), len); if (tb[TCA_NETEM_CORR]) { if (RTA_PAYLOAD(tb[TCA_NETEM_CORR]) < sizeof(*cor)) return -1; cor = RTA_DATA(tb[TCA_NETEM_CORR]); } if (tb[TCA_NETEM_REORDER]) { if (RTA_PAYLOAD(tb[TCA_NETEM_REORDER]) < sizeof(*reorder)) return -1; reorder = RTA_DATA(tb[TCA_NETEM_REORDER]); } if (tb[TCA_NETEM_CORRUPT]) { if (RTA_PAYLOAD(tb[TCA_NETEM_CORRUPT]) < sizeof(*corrupt)) return -1; corrupt = RTA_DATA(tb[TCA_NETEM_CORRUPT]); } if (tb[TCA_NETEM_LOSS]) { struct rtattr *lb[NETEM_LOSS_MAX + 1]; parse_rtattr_nested(lb, NETEM_LOSS_MAX, tb[TCA_NETEM_LOSS]); if (lb[NETEM_LOSS_GI]) gimodel = RTA_DATA(lb[NETEM_LOSS_GI]); if (lb[NETEM_LOSS_GE]) gemodel = RTA_DATA(lb[NETEM_LOSS_GE]); } if (tb[TCA_NETEM_RATE]) { if (RTA_PAYLOAD(tb[TCA_NETEM_RATE]) < sizeof(*rate)) return -1; rate = RTA_DATA(tb[TCA_NETEM_RATE]); } if (tb[TCA_NETEM_ECN]) { if (RTA_PAYLOAD(tb[TCA_NETEM_ECN]) < sizeof(*ecn)) return -1; ecn = RTA_DATA(tb[TCA_NETEM_ECN]); } if (tb[TCA_NETEM_RATE64]) { if (RTA_PAYLOAD(tb[TCA_NETEM_RATE64]) < sizeof(rate64)) return -1; rate64 = rta_getattr_u64(tb[TCA_NETEM_RATE64]); } } fprintf(f, "limit %d", qopt.limit); if (qopt.latency) { fprintf(f, " delay %s", sprint_ticks(qopt.latency, b1)); if (qopt.jitter) { fprintf(f, " %s", sprint_ticks(qopt.jitter, b1)); if (cor && cor->delay_corr) fprintf(f, " %s", sprint_percent(cor->delay_corr, b1)); } } if (qopt.loss) { fprintf(f, " loss %s", sprint_percent(qopt.loss, b1)); if (cor && cor->loss_corr) fprintf(f, " %s", sprint_percent(cor->loss_corr, b1)); } if (gimodel) { fprintf(f, " loss state p13 %s", sprint_percent(gimodel->p13, b1)); fprintf(f, " p31 %s", sprint_percent(gimodel->p31, b1)); fprintf(f, " p32 %s", sprint_percent(gimodel->p32, b1)); fprintf(f, " p23 %s", sprint_percent(gimodel->p23, b1)); fprintf(f, " p14 %s", sprint_percent(gimodel->p14, b1)); } if (gemodel) { fprintf(f, " loss gemodel p %s", sprint_percent(gemodel->p, b1)); fprintf(f, " r %s", sprint_percent(gemodel->r, b1)); fprintf(f, " 1-h %s", sprint_percent(max_percent_value - gemodel->h, b1)); fprintf(f, " 1-k %s", sprint_percent(gemodel->k1, b1)); } if (qopt.duplicate) { fprintf(f, " duplicate %s", sprint_percent(qopt.duplicate, b1)); if (cor && cor->dup_corr) fprintf(f, " %s", sprint_percent(cor->dup_corr, b1)); } if (reorder && reorder->probability) { fprintf(f, " reorder %s", sprint_percent(reorder->probability, b1)); if (reorder->correlation) fprintf(f, " %s", sprint_percent(reorder->correlation, b1)); } if (corrupt && corrupt->probability) { fprintf(f, " corrupt %s", sprint_percent(corrupt->probability, b1)); if (corrupt->correlation) fprintf(f, " %s", sprint_percent(corrupt->correlation, b1)); } if (rate && rate->rate) { if (rate64) fprintf(f, " rate %s", sprint_rate(rate64, b1)); else fprintf(f, " rate %s", sprint_rate(rate->rate, b1)); if (rate->packet_overhead) fprintf(f, " packetoverhead %d", rate->packet_overhead); if (rate->cell_size) fprintf(f, " cellsize %u", rate->cell_size); if (rate->cell_overhead) fprintf(f, " celloverhead %d", rate->cell_overhead); } if (ecn) fprintf(f, " ecn "); if (qopt.gap) fprintf(f, " gap %lu", (unsigned long)qopt.gap); return 0; } struct qdisc_util netem_qdisc_util = { .id = "netem", .parse_qopt = netem_parse_opt, .print_qopt = netem_print_opt, };
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; 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; }
static int brlink_modify(int argc, char **argv) { struct { struct nlmsghdr n; struct ifinfomsg ifm; char buf[512]; } req; char *d = NULL; __s8 learning = -1; __s8 learning_sync = -1; __s8 flood = -1; __s8 hairpin = -1; __s8 bpdu_guard = -1; __s8 fast_leave = -1; __s8 root_block = -1; __u32 cost = 0; __s16 priority = -1; __s8 state = -1; __s16 mode = -1; __u16 flags = 0; struct rtattr *nest; 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_SETLINK; req.ifm.ifi_family = PF_BRIDGE; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); d = *argv; } else if (strcmp(*argv, "guard") == 0) { NEXT_ARG(); if (!on_off("guard", &bpdu_guard, *argv)) exit(-1); } else if (strcmp(*argv, "hairpin") == 0) { NEXT_ARG(); if (!on_off("hairping", &hairpin, *argv)) exit(-1); } else if (strcmp(*argv, "fastleave") == 0) { NEXT_ARG(); if (!on_off("fastleave", &fast_leave, *argv)) exit(-1); } else if (strcmp(*argv, "root_block") == 0) { NEXT_ARG(); if (!on_off("root_block", &root_block, *argv)) exit(-1); } else if (strcmp(*argv, "learning") == 0) { NEXT_ARG(); if (!on_off("learning", &learning, *argv)) exit(-1); } else if (strcmp(*argv, "learning_sync") == 0) { NEXT_ARG(); if (!on_off("learning_sync", &learning_sync, *argv)) exit(-1); } else if (strcmp(*argv, "flood") == 0) { NEXT_ARG(); if (!on_off("flood", &flood, *argv)) exit(-1); } else if (strcmp(*argv, "cost") == 0) { NEXT_ARG(); cost = atoi(*argv); } else if (strcmp(*argv, "priority") == 0) { NEXT_ARG(); priority = atoi(*argv); } else if (strcmp(*argv, "state") == 0) { NEXT_ARG(); char *endptr; size_t nstates = sizeof(port_states) / sizeof(*port_states); state = strtol(*argv, &endptr, 10); if (!(**argv != '\0' && *endptr == '\0')) { for (state = 0; state < nstates; state++) if (strcmp(port_states[state], *argv) == 0) break; if (state == nstates) { fprintf(stderr, "Error: invalid STP port state\n"); exit(-1); } } } else if (strcmp(*argv, "hwmode") == 0) { NEXT_ARG(); flags = BRIDGE_FLAGS_SELF; if (strcmp(*argv, "vepa") == 0) mode = BRIDGE_MODE_VEPA; else if (strcmp(*argv, "veb") == 0) mode = BRIDGE_MODE_VEB; else { fprintf(stderr, "Mode argument must be \"vepa\" or " "\"veb\".\n"); exit(-1); } } else if (strcmp(*argv, "self") == 0) { flags = BRIDGE_FLAGS_SELF; } else { usage(); } argc--; argv++; } if (d == NULL) { fprintf(stderr, "Device is a required argument.\n"); exit(-1); } req.ifm.ifi_index = ll_name_to_index(d); if (req.ifm.ifi_index == 0) { fprintf(stderr, "Cannot find bridge device \"%s\"\n", d); exit(-1); } /* Nested PROTINFO attribute. Contains: port flags, cost, priority and * state. */ nest = addattr_nest(&req.n, sizeof(req), IFLA_PROTINFO | NLA_F_NESTED); /* Flags first */ if (bpdu_guard >= 0) addattr8(&req.n, sizeof(req), IFLA_BRPORT_GUARD, bpdu_guard); if (hairpin >= 0) addattr8(&req.n, sizeof(req), IFLA_BRPORT_MODE, hairpin); if (fast_leave >= 0) addattr8(&req.n, sizeof(req), IFLA_BRPORT_FAST_LEAVE, fast_leave); if (root_block >= 0) addattr8(&req.n, sizeof(req), IFLA_BRPORT_PROTECT, root_block); if (flood >= 0) addattr8(&req.n, sizeof(req), IFLA_BRPORT_UNICAST_FLOOD, flood); if (learning >= 0) addattr8(&req.n, sizeof(req), IFLA_BRPORT_LEARNING, learning); if (learning_sync >= 0) addattr8(&req.n, sizeof(req), IFLA_BRPORT_LEARNING_SYNC, learning_sync); if (cost > 0) addattr32(&req.n, sizeof(req), IFLA_BRPORT_COST, cost); if (priority >= 0) addattr16(&req.n, sizeof(req), IFLA_BRPORT_PRIORITY, priority); if (state >= 0) addattr8(&req.n, sizeof(req), IFLA_BRPORT_STATE, state); addattr_nest_end(&req.n, nest); /* IFLA_AF_SPEC nested attribute. Contains IFLA_BRIDGE_FLAGS that * designates master or self operation and IFLA_BRIDGE_MODE * for hw 'vepa' or 'veb' operation modes. The hwmodes are * only valid in 'self' mode on some devices so far. */ if (mode >= 0 || flags > 0) { nest = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC); if (flags > 0) addattr16(&req.n, sizeof(req), IFLA_BRIDGE_FLAGS, flags); if (mode >= 0) addattr16(&req.n, sizeof(req), IFLA_BRIDGE_MODE, mode); addattr_nest_end(&req.n, nest); } if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) exit(2); return 0; }
static int parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { int argc = *argc_p; char **argv = *argv_p; int ok = 0; struct rtattr *tail; unsigned int tmp; __u16 queue_mapping, ptype; __u32 flags = 0, priority, mark; struct tc_skbedit sel = { 0 }; if (matches(*argv, "skbedit") != 0) return -1; NEXT_ARG(); while (argc > 0) { if (matches(*argv, "queue_mapping") == 0) { flags |= SKBEDIT_F_QUEUE_MAPPING; NEXT_ARG(); if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) { fprintf(stderr, "Illegal queue_mapping\n"); return -1; } queue_mapping = tmp; ok++; } else if (matches(*argv, "priority") == 0) { flags |= SKBEDIT_F_PRIORITY; NEXT_ARG(); if (get_tc_classid(&priority, *argv)) { fprintf(stderr, "Illegal priority\n"); return -1; } ok++; } else if (matches(*argv, "mark") == 0) { flags |= SKBEDIT_F_MARK; NEXT_ARG(); if (get_u32(&mark, *argv, 0)) { fprintf(stderr, "Illegal mark\n"); return -1; } ok++; } else if (matches(*argv, "ptype") == 0) { NEXT_ARG(); if (matches(*argv, "host") == 0) { ptype = PACKET_HOST; } else if (matches(*argv, "broadcast") == 0) { ptype = PACKET_BROADCAST; } else if (matches(*argv, "multicast") == 0) { ptype = PACKET_MULTICAST; } else if (matches(*argv, "otherhost") == 0) { ptype = PACKET_OTHERHOST; } else { fprintf(stderr, "Illegal ptype (%s)\n", *argv); return -1; } flags |= SKBEDIT_F_PTYPE; ok++; } else if (matches(*argv, "help") == 0) { usage(); } else { break; } argc--; argv++; } parse_action_control_dflt(&argc, &argv, &sel.action, false, TC_ACT_PIPE); if (argc) { if (matches(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&sel.index, *argv, 10)) { fprintf(stderr, "Pedit: Illegal \"index\"\n"); return -1; } argc--; argv++; ok++; } } if (!ok) { explain(); return -1; } tail = addattr_nest(n, MAX_MSG, tca_id); addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel)); if (flags & SKBEDIT_F_QUEUE_MAPPING) addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING, &queue_mapping, sizeof(queue_mapping)); if (flags & SKBEDIT_F_PRIORITY) addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY, &priority, sizeof(priority)); if (flags & SKBEDIT_F_MARK) addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK, &mark, sizeof(mark)); if (flags & SKBEDIT_F_PTYPE) addattr_l(n, MAX_MSG, TCA_SKBEDIT_PTYPE, &ptype, sizeof(ptype)); addattr_nest_end(n, tail); *argc_p = argc; *argv_p = argv; return 0; }
static int parse_direction(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { int argc = *argc_p; char **argv = *argv_p; int ok = 0, iok = 0, mirror = 0, redir = 0, ingress = 0, egress = 0; struct tc_mirred p = {}; struct rtattr *tail; char d[IFNAMSIZ] = {}; while (argc > 0) { if (matches(*argv, "action") == 0) { NEXT_ARG(); break; } else if (!egress && matches(*argv, "egress") == 0) { egress = 1; if (ingress) { fprintf(stderr, "Can't have both egress and ingress\n"); return -1; } NEXT_ARG(); ok++; continue; } else if (!ingress && matches(*argv, "ingress") == 0) { ingress = 1; if (egress) { fprintf(stderr, "Can't have both ingress and egress\n"); return -1; } NEXT_ARG(); ok++; continue; } else { if (matches(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&p.index, *argv, 10)) { fprintf(stderr, "Illegal \"index\"\n"); return -1; } iok++; if (!ok) { argc--; argv++; break; } } else if (!ok) { fprintf(stderr, "was expecting egress or ingress (%s)\n", *argv); break; } else if (!mirror && matches(*argv, "mirror") == 0) { mirror = 1; if (redir) { fprintf(stderr, "Can't have both mirror and redir\n"); return -1; } p.eaction = egress ? TCA_EGRESS_MIRROR : TCA_INGRESS_MIRROR; p.action = TC_ACT_PIPE; ok++; } else if (!redir && matches(*argv, "redirect") == 0) { redir = 1; if (mirror) { fprintf(stderr, "Can't have both mirror and redir\n"); return -1; } p.eaction = egress ? TCA_EGRESS_REDIR : TCA_INGRESS_REDIR; p.action = TC_ACT_STOLEN; ok++; } else if ((redir || mirror) && matches(*argv, "dev") == 0) { NEXT_ARG(); if (strlen(d)) duparg("dev", *argv); strncpy(d, *argv, sizeof(d)-1); argc--; argv++; break; } } NEXT_ARG(); } if (!ok && !iok) return -1; if (d[0]) { int idx; ll_init_map(&rth); idx = ll_name_to_index(d); if (!idx) return nodev(d); p.ifindex = idx; } if (p.eaction == TCA_EGRESS_MIRROR || p.eaction == TCA_INGRESS_MIRROR) parse_action_control(&argc, &argv, &p.action, false); if (argc) { if (iok && matches(*argv, "index") == 0) { fprintf(stderr, "mirred: Illegal double index\n"); return -1; } if (matches(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&p.index, *argv, 10)) { fprintf(stderr, "mirred: Illegal \"index\"\n"); return -1; } argc--; argv++; } } tail = addattr_nest(n, MAX_MSG, tca_id); addattr_l(n, MAX_MSG, TCA_MIRRED_PARMS, &p, sizeof(p)); addattr_nest_end(n, tail); *argc_p = argc; *argv_p = argv; 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; }
static int parse_ipt(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { struct xtables_target *m = NULL; struct ipt_entry fw; struct rtattr *tail; int c; int rargc = *argc_p; char **argv = *argv_p; int argc = 0, iargc = 0; char k[FILTER_NAMESZ]; int size = 0; int iok = 0, ok = 0; __u32 hook = 0, index = 0; set_lib_dir(); { int i; for (i = 0; i < rargc; i++) { if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) { break; } } iargc = argc = i; } if (argc <= 2) { fprintf(stderr, "bad arguments to ipt %d vs %d\n", argc, rargc); return -1; } while (1) { c = getopt_long(argc, argv, "j:", opts, NULL); if (c == -1) break; switch (c) { case 'j': m = find_target(optarg, TRY_LOAD); if (m != NULL) { if (build_st(m, NULL) < 0) { printf(" %s error\n", m->name); return -1; } opts = merge_options(opts, m->extra_opts, &m->option_offset); } else { fprintf(stderr, " failed to find target %s\n\n", optarg); return -1; } ok++; break; default: memset(&fw, 0, sizeof(fw)); if (m) { m->parse(c - m->option_offset, argv, 0, &m->tflags, NULL, &m->t); } else { fprintf(stderr, " failed to find target %s\n\n", optarg); return -1; } ok++; break; } } if (iargc > optind) { if (matches(argv[optind], "index") == 0) { if (get_u32(&index, argv[optind + 1], 10)) { fprintf(stderr, "Illegal \"index\"\n"); free_opts(opts); return -1; } iok++; optind += 2; } } if (!ok && !iok) { fprintf(stderr, " ipt Parser BAD!! (%s)\n", *argv); return -1; } /* check that we passed the correct parameters to the target */ if (m) m->final_check(m->tflags); { struct tcmsg *t = NLMSG_DATA(n); if (t->tcm_parent != TC_H_ROOT && t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) { hook = NF_IP_PRE_ROUTING; } else { hook = NF_IP_POST_ROUTING; } } tail = addattr_nest(n, MAX_MSG, tca_id); fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]); fprintf(stdout, "\ttarget: "); if (m) m->print(NULL, m->t, 0); fprintf(stdout, " index %d\n", index); if (strlen(tname) > 16) { size = 16; k[15] = 0; } else { size = 1 + strlen(tname); } strncpy(k, tname, size); addattr_l(n, MAX_MSG, TCA_IPT_TABLE, k, size); addattr_l(n, MAX_MSG, TCA_IPT_HOOK, &hook, 4); addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4); if (m) addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size); addattr_nest_end(n, tail); argc -= optind; argv += optind; *argc_p = rargc - iargc; *argv_p = argv; optind = 0; free_opts(opts); /* Clear flags if target will be used again */ m->tflags = 0; m->used = 0; /* Free allocated memory */ if (m->t) free(m->t); return 0; }
static int vlan_modify(int cmd, int argc, char **argv) { struct { struct nlmsghdr n; struct ifinfomsg ifm; char buf[1024]; } req = { .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), .n.nlmsg_flags = NLM_F_REQUEST, .n.nlmsg_type = cmd, .ifm.ifi_family = PF_BRIDGE, }; char *d = NULL; short vid = -1; short vid_end = -1; struct rtattr *afspec; struct bridge_vlan_info vinfo = {}; unsigned short flags = 0; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); d = *argv; } else if (strcmp(*argv, "vid") == 0) { char *p; NEXT_ARG(); p = strchr(*argv, '-'); if (p) { *p = '\0'; p++; vid = atoi(*argv); vid_end = atoi(p); vinfo.flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN; } else { vid = atoi(*argv); } } else if (strcmp(*argv, "self") == 0) { flags |= BRIDGE_FLAGS_SELF; } else if (strcmp(*argv, "master") == 0) { flags |= BRIDGE_FLAGS_MASTER; } else if (strcmp(*argv, "pvid") == 0) { vinfo.flags |= BRIDGE_VLAN_INFO_PVID; } else if (strcmp(*argv, "untagged") == 0) { vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED; } else { if (matches(*argv, "help") == 0) { NEXT_ARG(); } } argc--; argv++; } if (d == NULL || vid == -1) { fprintf(stderr, "Device and VLAN ID are required arguments.\n"); return -1; } req.ifm.ifi_index = ll_name_to_index(d); if (req.ifm.ifi_index == 0) { fprintf(stderr, "Cannot find bridge device \"%s\"\n", d); return -1; } if (vid >= 4096) { fprintf(stderr, "Invalid VLAN ID \"%hu\"\n", vid); return -1; } if (vinfo.flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) { if (vid_end == -1 || vid_end >= 4096 || vid >= vid_end) { fprintf(stderr, "Invalid VLAN range \"%hu-%hu\"\n", vid, vid_end); return -1; } if (vinfo.flags & BRIDGE_VLAN_INFO_PVID) { fprintf(stderr, "pvid cannot be configured for a vlan range\n"); return -1; } } afspec = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC); if (flags) addattr16(&req.n, sizeof(req), IFLA_BRIDGE_FLAGS, flags); vinfo.vid = vid; if (vid_end != -1) { /* send vlan range start */ addattr_l(&req.n, sizeof(req), IFLA_BRIDGE_VLAN_INFO, &vinfo, sizeof(vinfo)); vinfo.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN; /* Now send the vlan range end */ vinfo.flags |= BRIDGE_VLAN_INFO_RANGE_END; vinfo.vid = vid_end; addattr_l(&req.n, sizeof(req), IFLA_BRIDGE_VLAN_INFO, &vinfo, sizeof(vinfo)); } else { addattr_l(&req.n, sizeof(req), IFLA_BRIDGE_VLAN_INFO, &vinfo, sizeof(vinfo)); } addattr_nest_end(&req.n, afspec); if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) return -1; return 0; } /* In order to use this function for both filtering and non-filtering cases * we need to make it a tristate: * return -1 - if filtering we've gone over so don't continue * return 0 - skip entry and continue (applies to range start or to entries * which are less than filter_vlan) * return 1 - print the entry and continue */ static int filter_vlan_check(struct bridge_vlan_info *vinfo) { /* if we're filtering we should stop on the first greater entry */ if (filter_vlan && vinfo->vid > filter_vlan && !(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END)) return -1; if ((vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) || vinfo->vid < filter_vlan) return 0; return 1; } static void print_vlan_port(FILE *fp, int ifi_index) { if (jw_global) { jsonw_pretty(jw_global, 1); jsonw_name(jw_global, ll_index_to_name(ifi_index)); jsonw_start_array(jw_global); } else { fprintf(fp, "%s", ll_index_to_name(ifi_index)); } } static void start_json_vlan_flags_array(bool *vlan_flags) { if (*vlan_flags) return; jsonw_name(jw_global, "flags"); jsonw_start_array(jw_global); *vlan_flags = true; } static int print_vlan(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = arg; struct ifinfomsg *ifm = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[IFLA_MAX+1]; bool vlan_flags; if (n->nlmsg_type != RTM_NEWLINK) { fprintf(stderr, "Not RTM_NEWLINK: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } len -= NLMSG_LENGTH(sizeof(*ifm)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } if (ifm->ifi_family != AF_BRIDGE) return 0; if (filter_index && filter_index != ifm->ifi_index) return 0; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifm), len); /* if AF_SPEC isn't there, vlan table is not preset for this port */ if (!tb[IFLA_AF_SPEC]) { if (!filter_vlan) fprintf(fp, "%s\tNone\n", ll_index_to_name(ifm->ifi_index)); return 0; } else { struct rtattr *i, *list = tb[IFLA_AF_SPEC]; int rem = RTA_PAYLOAD(list); __u16 last_vid_start = 0; if (!filter_vlan) print_vlan_port(fp, ifm->ifi_index); for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { struct bridge_vlan_info *vinfo; int vcheck_ret; if (i->rta_type != IFLA_BRIDGE_VLAN_INFO) continue; vinfo = RTA_DATA(i); if (!(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END)) last_vid_start = vinfo->vid; vcheck_ret = filter_vlan_check(vinfo); if (vcheck_ret == -1) break; else if (vcheck_ret == 0) continue; if (filter_vlan) print_vlan_port(fp, ifm->ifi_index); if (jw_global) { jsonw_start_object(jw_global); jsonw_uint_field(jw_global, "vlan", last_vid_start); if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) continue; } else { fprintf(fp, "\t %hu", last_vid_start); } if (last_vid_start != vinfo->vid) { if (jw_global) jsonw_uint_field(jw_global, "vlanEnd", vinfo->vid); else fprintf(fp, "-%hu", vinfo->vid); } if (vinfo->flags & BRIDGE_VLAN_INFO_PVID) { if (jw_global) { start_json_vlan_flags_array(&vlan_flags); jsonw_string(jw_global, "PVID"); } else { fprintf(fp, " PVID"); } } if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED) { if (jw_global) { start_json_vlan_flags_array(&vlan_flags); jsonw_string(jw_global, "Egress Untagged"); } else { fprintf(fp, " Egress Untagged"); } } if (vlan_flags) { jsonw_end_array(jw_global); vlan_flags = false; } if (jw_global) jsonw_end_object(jw_global); else fprintf(fp, "\n"); } } if (!filter_vlan) { if (jw_global) jsonw_end_array(jw_global); else fprintf(fp, "\n"); } fflush(fp); return 0; }