static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) { int count = 0; char medium[IFNAMSIZ]; memset(p, 0, sizeof(*p)); memset(&medium, 0, sizeof(medium)); p->iph.version = 4; p->iph.ihl = 5; #ifndef IP_DF #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ #endif p->iph.frag_off = htons(IP_DF); while (argc > 0) { if (strcmp(*argv, "mode") == 0) { NEXT_ARG(); if (strcmp(*argv, "ipip") == 0 || strcmp(*argv, "ip/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPIP; } else if (strcmp(*argv, "gre") == 0 || strcmp(*argv, "gre/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_GRE; } else if (strcmp(*argv, "sit") == 0 || strcmp(*argv, "ipv6/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPV6; } else { fprintf(stderr,"Cannot guess tunnel mode.\n"); exit(-1); } } else if (strcmp(*argv, "key") == 0) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->i_key = p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value of \"key\"\n"); exit(-1); } p->i_key = p->o_key = htonl(uval); } } else if (strcmp(*argv, "ikey") == 0) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; if (strchr(*argv, '.')) p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value of \"ikey\"\n"); exit(-1); } p->i_key = htonl(uval); } } else if (strcmp(*argv, "okey") == 0) { unsigned uval; NEXT_ARG(); p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value of \"okey\"\n"); exit(-1); } p->o_key = htonl(uval); } } else if (strcmp(*argv, "seq") == 0) { p->i_flags |= GRE_SEQ; p->o_flags |= GRE_SEQ; } else if (strcmp(*argv, "iseq") == 0) { p->i_flags |= GRE_SEQ; } else if (strcmp(*argv, "oseq") == 0) { p->o_flags |= GRE_SEQ; } else if (strcmp(*argv, "csum") == 0) { p->i_flags |= GRE_CSUM; p->o_flags |= GRE_CSUM; } else if (strcmp(*argv, "icsum") == 0) { p->i_flags |= GRE_CSUM; } else if (strcmp(*argv, "ocsum") == 0) { p->o_flags |= GRE_CSUM; } else if (strcmp(*argv, "nopmtudisc") == 0) { p->iph.frag_off = 0; } else if (strcmp(*argv, "pmtudisc") == 0) { p->iph.frag_off = htons(IP_DF); } else if (strcmp(*argv, "remote") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) p->iph.daddr = get_addr32(*argv); } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) p->iph.saddr = get_addr32(*argv); } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); strncpy(medium, *argv, IFNAMSIZ-1); } else if (strcmp(*argv, "ttl") == 0) { unsigned uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_unsigned(&uval, *argv, 0)) invarg("invalid TTL\n", *argv); if (uval > 255) invarg("TTL must be <=255\n", *argv); p->iph.ttl = uval; } } else if (strcmp(*argv, "tos") == 0 || matches(*argv, "dsfield") == 0) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg("bad TOS value", *argv); p->iph.tos = uval; } else p->iph.tos = 1; } else { if (strcmp(*argv, "name") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (p->name[0]) duparg2("name", *argv); strncpy(p->name, *argv, IFNAMSIZ); if (cmd == SIOCCHGTUNNEL && count == 0) { struct ip_tunnel_parm old_p; memset(&old_p, 0, sizeof(old_p)); if (tnl_get_ioctl(*argv, &old_p)) return -1; *p = old_p; } } count++; argc--; argv++; } if (p->iph.protocol == 0) { if (memcmp(p->name, "gre", 3) == 0) p->iph.protocol = IPPROTO_GRE; else if (memcmp(p->name, "ipip", 4) == 0) p->iph.protocol = IPPROTO_IPIP; else if (memcmp(p->name, "sit", 3) == 0) p->iph.protocol = IPPROTO_IPV6; } if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) { if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) { fprintf(stderr, "Keys are not allowed with ipip and sit.\n"); return -1; } } if (medium[0]) { p->link = tnl_ioctl_get_ifindex(medium); if (p->link == 0) return -1; } if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->i_key = p->iph.daddr; p->i_flags |= GRE_KEY; } if (p->o_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->o_key = p->iph.daddr; p->o_flags |= GRE_KEY; } if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) { fprintf(stderr, "Broadcast tunnel requires a source address.\n"); return -1; } return 0; }
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ static int gred_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { int ok=0; struct tc_gred_qopt opt; unsigned burst = 0; unsigned avpkt = 0; double probability = 0.02; unsigned rate = 0; int wlog; __u8 sbuf[256]; struct rtattr *tail; memset(&opt, 0, sizeof(opt)); while (argc > 0) { if (strcmp(*argv, "limit") == 0) { NEXT_ARG(); if (get_size(&opt.limit, *argv)) { my_printf("Illegal \"limit\"\n"); return -1; } ok++; } else if (strcmp(*argv, "setup") == 0) { if (ok) { my_printf("Illegal \"setup\"\n"); return -1; } return init_gred(qu,argc-1, argv+1,n); } else if (strcmp(*argv, "min") == 0) { NEXT_ARG(); if (get_size(&opt.qth_min, *argv)) { my_printf("Illegal \"min\"\n"); return -1; } ok++; } else if (strcmp(*argv, "max") == 0) { NEXT_ARG(); if (get_size(&opt.qth_max, *argv)) { my_printf("Illegal \"max\"\n"); return -1; } ok++; } else if (strcmp(*argv, "DP") == 0) { NEXT_ARG(); opt.DP=strtol(*argv, (char **)NULL, 10); DPRINTF ("\n ******* DP =%u\n",opt.DP); if (opt.DP >MAX_DPs) { /* need a better error check */ my_printf("DP =%u \n",opt.DP); my_printf("Illegal \"DP\"\n"); my_printf("GRED: only %d DPs are currently supported\n",MAX_DPs); return -1; } ok++; } else if (strcmp(*argv, "burst") == 0) { NEXT_ARG(); if (get_unsigned(&burst, *argv, 0)) { my_printf("Illegal \"burst\"\n"); return -1; } ok++; } else if (strcmp(*argv, "avpkt") == 0) { NEXT_ARG(); if (get_size(&avpkt, *argv)) { my_printf("Illegal \"avpkt\"\n"); return -1; } ok++; } else if (strcmp(*argv, "probability") == 0) { NEXT_ARG(); if (sscanf(*argv, "%lg", &probability) != 1) { my_printf("Illegal \"probability\"\n"); return -1; } ok++; } else if (strcmp(*argv, "prio") == 0) { NEXT_ARG(); opt.prio=strtol(*argv, (char **)NULL, 10); /* some error check here */ ok++; } else if (strcmp(*argv, "bandwidth") == 0) { NEXT_ARG(); if (get_rate(&rate, *argv)) { my_printf("Illegal \"bandwidth\"\n"); return -1; } ok++; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { my_printf("What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } if (!ok) return 0; if (rate == 0) get_rate(&rate, "10Mbit"); if (!opt.qth_min || !opt.qth_max || !burst || !opt.limit || !avpkt || (opt.DP<0)) { my_printf("Required parameter (min, max, burst, limit, " "avpket, DP) is missing\n"); return -1; } if ((wlog = tc_red_eval_ewma(opt.qth_min, burst, avpkt)) < 0) { my_printf("GRED: failed to calculate EWMA constant.\n"); return -1; } if (wlog >= 10) my_printf("GRED: WARNING. Burst %d seems to be to " "large.\n", burst); opt.Wlog = wlog; if ((wlog = tc_red_eval_P(opt.qth_min, opt.qth_max, probability)) < 0) { my_printf("GRED: failed to calculate probability.\n"); return -1; } opt.Plog = wlog; if ((wlog = tc_red_eval_idle_damping(opt.Wlog, avpkt, rate, sbuf)) < 0) { my_printf("GRED: failed to calculate idle damping " "table.\n"); return -1; } opt.Scell_log = wlog; tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); addattr_l(n, 1024, TCA_GRED_PARMS, &opt, sizeof(opt)); addattr_l(n, 1024, TCA_GRED_STAB, sbuf, 256); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
/* Dies on error */ static void parse_args(char **argv, int cmd, struct ip_tunnel_parm *p) { static const char keywords[] ALIGN1 = "mode\0""ipip\0""ip/ip\0""gre\0""gre/ip\0""sit\0""ipv6/ip\0" "key\0""ikey\0""okey\0""seq\0""iseq\0""oseq\0" "csum\0""icsum\0""ocsum\0""nopmtudisc\0""pmtudisc\0" "remote\0""any\0""local\0""dev\0" "ttl\0""inherit\0""tos\0""dsfield\0" "name\0"; enum { ARG_mode, ARG_ipip, ARG_ip_ip, ARG_gre, ARG_gre_ip, ARG_sit, ARG_ip6_ip, ARG_key, ARG_ikey, ARG_okey, ARG_seq, ARG_iseq, ARG_oseq, ARG_csum, ARG_icsum, ARG_ocsum, ARG_nopmtudisc, ARG_pmtudisc, ARG_remote, ARG_any, ARG_local, ARG_dev, ARG_ttl, ARG_inherit, ARG_tos, ARG_dsfield, ARG_name }; int count = 0; char medium[IFNAMSIZ]; int key; memset(p, 0, sizeof(*p)); medium[0] = '\0'; p->iph.version = 4; p->iph.ihl = 5; #ifndef IP_DF #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ #endif p->iph.frag_off = htons(IP_DF); while (*argv) { key = index_in_strings(keywords, *argv); if (key == ARG_mode) { NEXT_ARG(); key = index_in_strings(keywords, *argv); if (key == ARG_ipip || key == ARG_ip_ip) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) { bb_error_msg_and_die("%s tunnel mode", "you managed to ask for more than one"); } p->iph.protocol = IPPROTO_IPIP; } else if (key == ARG_gre || key == ARG_gre_ip) { if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) { bb_error_msg_and_die("%s tunnel mode", "you managed to ask for more than one"); } p->iph.protocol = IPPROTO_GRE; } else if (key == ARG_sit || key == ARG_ip6_ip) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) { bb_error_msg_and_die("%s tunnel mode", "you managed to ask for more than one"); } p->iph.protocol = IPPROTO_IPV6; } else { bb_error_msg_and_die("%s tunnel mode", "cannot guess"); } } else if (key == ARG_key) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->i_key = p->o_key = get_addr32(*argv); else { uval = get_unsigned(*argv, "key"); p->i_key = p->o_key = htonl(uval); } } else if (key == ARG_ikey) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; if (strchr(*argv, '.')) p->o_key = get_addr32(*argv); else { uval = get_unsigned(*argv, "ikey"); p->i_key = htonl(uval); } } else if (key == ARG_okey) { unsigned uval; NEXT_ARG(); p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->o_key = get_addr32(*argv); else { uval = get_unsigned(*argv, "okey"); p->o_key = htonl(uval); } } else if (key == ARG_seq) { p->i_flags |= GRE_SEQ; p->o_flags |= GRE_SEQ; } else if (key == ARG_iseq) { p->i_flags |= GRE_SEQ; } else if (key == ARG_oseq) { p->o_flags |= GRE_SEQ; } else if (key == ARG_csum) { p->i_flags |= GRE_CSUM; p->o_flags |= GRE_CSUM; } else if (key == ARG_icsum) { p->i_flags |= GRE_CSUM; } else if (key == ARG_ocsum) { p->o_flags |= GRE_CSUM; } else if (key == ARG_nopmtudisc) { p->iph.frag_off = 0; } else if (key == ARG_pmtudisc) { p->iph.frag_off = htons(IP_DF); } else if (key == ARG_remote) { NEXT_ARG(); key = index_in_strings(keywords, *argv); if (key != ARG_any) p->iph.daddr = get_addr32(*argv); } else if (key == ARG_local) { NEXT_ARG(); key = index_in_strings(keywords, *argv); if (key != ARG_any) p->iph.saddr = get_addr32(*argv); } else if (key == ARG_dev) { NEXT_ARG(); strncpy_IFNAMSIZ(medium, *argv); } else if (key == ARG_ttl) { unsigned uval; NEXT_ARG(); key = index_in_strings(keywords, *argv); if (key != ARG_inherit) { uval = get_unsigned(*argv, "TTL"); if (uval > 255) invarg(*argv, "TTL must be <=255"); p->iph.ttl = uval; } } else if (key == ARG_tos || key == ARG_dsfield) { uint32_t uval; NEXT_ARG(); key = index_in_strings(keywords, *argv); if (key != ARG_inherit) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg(*argv, "TOS"); p->iph.tos = uval; } else p->iph.tos = 1; } else { if (key == ARG_name) { NEXT_ARG(); } if (p->name[0]) duparg2("name", *argv); strncpy_IFNAMSIZ(p->name, *argv); if (cmd == SIOCCHGTUNNEL && count == 0) { struct ip_tunnel_parm old_p; memset(&old_p, 0, sizeof(old_p)); if (do_get_ioctl(*argv, &old_p)) exit(EXIT_FAILURE); *p = old_p; } } count++; argv++; } if (p->iph.protocol == 0) { if (memcmp(p->name, "gre", 3) == 0) p->iph.protocol = IPPROTO_GRE; else if (memcmp(p->name, "ipip", 4) == 0) p->iph.protocol = IPPROTO_IPIP; else if (memcmp(p->name, "sit", 3) == 0) p->iph.protocol = IPPROTO_IPV6; } if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) { if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) { bb_error_msg_and_die("keys are not allowed with ipip and sit"); } } if (medium[0]) { p->link = do_ioctl_get_ifindex(medium); } if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->i_key = p->iph.daddr; p->i_flags |= GRE_KEY; } if (p->o_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->o_key = p->iph.daddr; p->o_flags |= GRE_KEY; } if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) { bb_error_msg_and_die("broadcast tunnel requires a source address"); } }
static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { int wrr_ok=0, fopt_ok=0; struct tc_ratespec r; struct tc_cbq_lssopt lss; struct tc_cbq_wrropt wrr; struct tc_cbq_fopt fopt; struct tc_cbq_ovl ovl; __u32 rtab[256]; unsigned mpu=0; int cell_log=-1; int ewma_log=-1; unsigned bndw = 0; unsigned minburst=0, maxburst=0; unsigned short overhead=0; unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */ struct rtattr *tail; memset(&r, 0, sizeof(r)); memset(&lss, 0, sizeof(lss)); memset(&wrr, 0, sizeof(wrr)); memset(&fopt, 0, sizeof(fopt)); memset(&ovl, 0, sizeof(ovl)); while (argc > 0) { if (matches(*argv, "rate") == 0) { NEXT_ARG(); if (get_rate(&r.rate, *argv)) { explain1("rate"); return -1; } } else if (matches(*argv, "bandwidth") == 0) { NEXT_ARG(); if (get_rate(&bndw, *argv)) { explain1("bandwidth"); return -1; } } else if (matches(*argv, "minidle") == 0) { NEXT_ARG(); if (get_u32(&lss.minidle, *argv, 0)) { explain1("minidle"); return -1; } lss.change |= TCF_CBQ_LSS_MINIDLE; } else if (matches(*argv, "minburst") == 0) { NEXT_ARG(); if (get_u32(&minburst, *argv, 0)) { explain1("minburst"); return -1; } lss.change |= TCF_CBQ_LSS_OFFTIME; } else if (matches(*argv, "maxburst") == 0) { NEXT_ARG(); if (get_u32(&maxburst, *argv, 0)) { explain1("maxburst"); return -1; } lss.change |= TCF_CBQ_LSS_MAXIDLE; } else if (matches(*argv, "bounded") == 0) { lss.flags |= TCF_CBQ_LSS_BOUNDED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (matches(*argv, "borrow") == 0) { lss.flags &= ~TCF_CBQ_LSS_BOUNDED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (matches(*argv, "isolated") == 0) { lss.flags |= TCF_CBQ_LSS_ISOLATED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (matches(*argv, "sharing") == 0) { lss.flags &= ~TCF_CBQ_LSS_ISOLATED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (matches(*argv, "ewma") == 0) { NEXT_ARG(); if (get_integer(&ewma_log, *argv, 0)) { explain1("ewma"); return -1; } if (ewma_log > 31) { fprintf(stderr, "ewma_log must be < 32\n"); return -1; } lss.change |= TCF_CBQ_LSS_EWMA; } else if (matches(*argv, "cell") == 0) { unsigned cell; int i; NEXT_ARG(); if (get_size(&cell, *argv)) { explain1("cell"); return -1; } for (i=0; i<32; i++) if ((1<<i) == cell) break; if (i>=32) { fprintf(stderr, "cell must be 2^n\n"); return -1; } cell_log = i; } else if (matches(*argv, "prio") == 0) { unsigned prio; NEXT_ARG(); if (get_u32(&prio, *argv, 0)) { explain1("prio"); return -1; } if (prio > TC_CBQ_MAXPRIO) { fprintf(stderr, "\"prio\" must be number in the range 1...%d\n", TC_CBQ_MAXPRIO); return -1; } wrr.priority = prio; wrr_ok++; } else if (matches(*argv, "allot") == 0) { NEXT_ARG(); if (get_size(&wrr.allot, *argv)) { explain1("allot"); return -1; } } else if (matches(*argv, "avpkt") == 0) { NEXT_ARG(); if (get_size(&lss.avpkt, *argv)) { explain1("avpkt"); return -1; } lss.change |= TCF_CBQ_LSS_AVPKT; } else if (matches(*argv, "mpu") == 0) { NEXT_ARG(); if (get_size(&mpu, *argv)) { explain1("mpu"); return -1; } } else if (matches(*argv, "weight") == 0) { NEXT_ARG(); if (get_size(&wrr.weight, *argv)) { explain1("weight"); return -1; } wrr_ok++; } else if (matches(*argv, "split") == 0) { NEXT_ARG(); if (get_tc_classid(&fopt.split, *argv)) { fprintf(stderr, "Invalid split node ID.\n"); return -1; } fopt_ok++; } else if (matches(*argv, "defmap") == 0) { int err; NEXT_ARG(); err = sscanf(*argv, "%08x/%08x", &fopt.defmap, &fopt.defchange); if (err < 1) { fprintf(stderr, "Invalid defmap, should be MASK32[/MASK]\n"); return -1; } if (err == 1) fopt.defchange = ~0; fopt_ok++; } else if (matches(*argv, "overhead") == 0) { NEXT_ARG(); if (get_u16(&overhead, *argv, 10)) { explain1("overhead"); return -1; } } else if (matches(*argv, "linklayer") == 0) { NEXT_ARG(); if (get_linklayer(&linklayer, *argv)) { explain1("linklayer"); return -1; } } else if (matches(*argv, "help") == 0) { explain_class(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain_class(); return -1; } argc--; argv++; } /* OK. All options are parsed. */ /* 1. Prepare link sharing scheduler parameters */ if (r.rate) { unsigned pktsize = wrr.allot; if (wrr.allot < (lss.avpkt*3)/2) wrr.allot = (lss.avpkt*3)/2; r.mpu = mpu; r.overhead = overhead; if (tc_calc_rtable(&r, rtab, cell_log, pktsize, linklayer) < 0) { fprintf(stderr, "CBQ: failed to calculate rate table.\n"); return -1; } } if (ewma_log < 0) ewma_log = TC_CBQ_DEF_EWMA; lss.ewma_log = ewma_log; if (lss.change&(TCF_CBQ_LSS_OFFTIME|TCF_CBQ_LSS_MAXIDLE)) { if (lss.avpkt == 0) { fprintf(stderr, "CBQ: avpkt is required for max/minburst.\n"); return -1; } if (bndw==0 || r.rate == 0) { fprintf(stderr, "CBQ: bandwidth&rate are required for max/minburst.\n"); return -1; } } if (wrr.priority == 0 && (n->nlmsg_flags&NLM_F_EXCL)) { wrr_ok = 1; wrr.priority = TC_CBQ_MAXPRIO; if (wrr.allot == 0) wrr.allot = (lss.avpkt*3)/2; } if (wrr_ok) { if (wrr.weight == 0) wrr.weight = (wrr.priority == TC_CBQ_MAXPRIO) ? 1 : r.rate; if (wrr.allot == 0) { fprintf(stderr, "CBQ: \"allot\" is required to set WRR parameters.\n"); return -1; } } if (lss.change&TCF_CBQ_LSS_MAXIDLE) { lss.maxidle = tc_cbq_calc_maxidle(bndw, r.rate, lss.avpkt, ewma_log, maxburst); lss.change |= TCF_CBQ_LSS_MAXIDLE; lss.change |= TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT; } if (lss.change&TCF_CBQ_LSS_OFFTIME) { lss.offtime = tc_cbq_calc_offtime(bndw, r.rate, lss.avpkt, ewma_log, minburst); lss.change |= TCF_CBQ_LSS_OFFTIME; lss.change |= TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT; } if (lss.change&TCF_CBQ_LSS_MINIDLE) { lss.minidle <<= lss.ewma_log; lss.change |= TCF_CBQ_LSS_EWMA; } tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); if (lss.change) { lss.change |= TCF_CBQ_LSS_FLAGS; addattr_l(n, 1024, TCA_CBQ_LSSOPT, &lss, sizeof(lss)); } if (wrr_ok) addattr_l(n, 1024, TCA_CBQ_WRROPT, &wrr, sizeof(wrr)); if (fopt_ok) addattr_l(n, 1024, TCA_CBQ_FOPT, &fopt, sizeof(fopt)); if (r.rate) { addattr_l(n, 1024, TCA_CBQ_RATE, &r, sizeof(r)); addattr_l(n, 3024, TCA_CBQ_RTAB, rtab, 1024); if (show_raw) { int i; for (i=0; i<256; i++) printf("%u ", rtab[i]); printf("\n"); } } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
int do_ipmonitor(int argc, char **argv) { struct rtnl_handle rth; char *file = NULL; unsigned groups = ~RTMGRP_TC; int llink=0; int laddr=0; int lroute=0; ipaddr_reset_filter(1); iproute_reset_filter(); ipneigh_reset_filter(); while (argc > 0) { if (matches(*argv, "file") == 0) { NEXT_ARG(); file = *argv; } else if (matches(*argv, "link") == 0) { llink=1; groups = 0; } else if (matches(*argv, "address") == 0) { laddr=1; groups = 0; } else if (matches(*argv, "route") == 0) { lroute=1; groups = 0; } else if (strcmp(*argv, "all") == 0) { groups = ~RTMGRP_TC; } else if (matches(*argv, "help") == 0) { usage(); } else { fprintf(stderr, "Argument \"%s\" is unknown, try \"ip monitor help\".\n", *argv); exit(-1); } argc--; argv++; } if (llink) groups |= RTMGRP_LINK; if (laddr) { if (!preferred_family || preferred_family == AF_INET) groups |= RTMGRP_IPV4_IFADDR; if (!preferred_family || preferred_family == AF_INET6) groups |= RTMGRP_IPV6_IFADDR; } if (lroute) { if (!preferred_family || preferred_family == AF_INET) groups |= RTMGRP_IPV4_ROUTE; if (!preferred_family || preferred_family == AF_INET6) groups |= RTMGRP_IPV6_ROUTE; } if (file) { FILE *fp; fp = fopen(file, "r"); if (fp == NULL) { perror("Cannot fopen"); exit(-1); } return rtnl_from_file(fp, accept_msg, (void*)stdout); } if (rtnl_open(&rth, groups) < 0) exit(1); ll_init_map(&rth); if (rtnl_listen(&rth, accept_msg, (void*)stdout) < 0) exit(2); exit(0); }
static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) { struct rtnl_handle rth; struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; char mxbuf[256]; struct rtattr * mxrta = (void*)mxbuf; unsigned mxlock = 0; char *d = NULL; int gw_ok = 0; int dst_ok = 0; int proto_ok = 0; int type_ok = 0; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.r.rtm_family = preferred_family; req.r.rtm_table = RT_TABLE_MAIN; req.r.rtm_scope = RT_SCOPE_NOWHERE; if (cmd != RTM_DELROUTE) { req.r.rtm_protocol = RTPROT_BOOT; req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_type = RTN_UNICAST; } mxrta->rta_type = RTA_METRICS; mxrta->rta_len = RTA_LENGTH(0); while (argc > 0) { if (strcmp(*argv, "src") == 0) { inet_prefix addr; NEXT_ARG(); get_addr(&addr, *argv, req.r.rtm_family); if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = addr.family; } addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &addr.data, addr.bytelen); } else if (strcmp(*argv, "via") == 0) { inet_prefix addr; gw_ok = 1; NEXT_ARG(); get_addr(&addr, *argv, req.r.rtm_family); if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = addr.family; } addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen); } else if (strcmp(*argv, "mtu") == 0) { unsigned mtu; NEXT_ARG(); if (strcmp(*argv, "lock") == 0) { mxlock |= (1<<RTAX_MTU); NEXT_ARG(); } if (get_unsigned(&mtu, *argv, 0)) { invarg("\"mtu\" value is invalid\n", *argv); } rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu); } else if (matches(*argv, "protocol") == 0) { int prot; NEXT_ARG(); if (rtnl_rtprot_a2n(&prot, *argv)) invarg("\"protocol\" value is invalid\n", *argv); req.r.rtm_protocol = prot; proto_ok =1; } else if (strcmp(*argv, "dev") == 0 || strcmp(*argv, "oif") == 0) { NEXT_ARG(); d = *argv; } else { int type; inet_prefix dst; if (strcmp(*argv, "to") == 0) { NEXT_ARG(); } if ((**argv < '0' || **argv > '9') && rtnl_rtntype_a2n(&type, *argv) == 0) { NEXT_ARG(); req.r.rtm_type = type; type_ok = 1; } if (dst_ok) { duparg2("to", *argv); } get_prefix(&dst, *argv, req.r.rtm_family); if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = dst.family; } req.r.rtm_dst_len = dst.bitlen; dst_ok = 1; if (dst.bytelen) { addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); } } argc--; argv++; } if (rtnl_open(&rth, 0) < 0) { exit(1); } if (d) { int idx; ll_init_map(&rth); if (d) { if ((idx = ll_name_to_index(d)) == 0) { bb_error_msg("Cannot find device \"%s\"", d); return -1; } addattr32(&req.n, sizeof(req), RTA_OIF, idx); } } if (mxrta->rta_len > RTA_LENGTH(0)) { if (mxlock) { rta_addattr32(mxrta, sizeof(mxbuf), RTAX_LOCK, mxlock); } addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta)); } if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = AF_INET; } if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) { exit(2); } return 0; }
static int iproute_get(int argc, char **argv) { struct rtnl_handle rth; struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; char *idev = NULL; char *odev = NULL; int connected = 0; int from_ok = 0; const char *options[] = { "from", "iif", "oif", "dev", "notify", "connected", "to", 0 }; memset(&req, 0, sizeof(req)); iproute_reset_filter(); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETROUTE; req.r.rtm_family = preferred_family; req.r.rtm_table = 0; req.r.rtm_protocol = 0; req.r.rtm_scope = 0; req.r.rtm_type = 0; req.r.rtm_src_len = 0; req.r.rtm_dst_len = 0; req.r.rtm_tos = 0; while (argc > 0) { switch (compare_string_array(options, *argv)) { case 0: /* from */ { inet_prefix addr; NEXT_ARG(); from_ok = 1; get_prefix(&addr, *argv, req.r.rtm_family); if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = addr.family; } if (addr.bytelen) { addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen); } req.r.rtm_src_len = addr.bitlen; break; } case 1: /* iif */ NEXT_ARG(); idev = *argv; break; case 2: /* oif */ case 3: /* dev */ NEXT_ARG(); odev = *argv; break; case 4: /* notify */ req.r.rtm_flags |= RTM_F_NOTIFY; break; case 5: /* connected */ connected = 1; break; case 6: /* to */ NEXT_ARG(); default: { inet_prefix addr; get_prefix(&addr, *argv, req.r.rtm_family); if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = addr.family; } if (addr.bytelen) { addattr_l(&req.n, sizeof(req), RTA_DST, &addr.data, addr.bytelen); } req.r.rtm_dst_len = addr.bitlen; } argc--; argv++; } } if (req.r.rtm_dst_len == 0) { bb_error_msg_and_die("need at least destination address"); } if (rtnl_open(&rth, 0) < 0) exit(1); ll_init_map(&rth); if (idev || odev) { int idx; if (idev) { if ((idx = ll_name_to_index(idev)) == 0) { bb_error_msg("Cannot find device \"%s\"", idev); return -1; } addattr32(&req.n, sizeof(req), RTA_IIF, idx); } if (odev) { if ((idx = ll_name_to_index(odev)) == 0) { bb_error_msg("Cannot find device \"%s\"", odev); return -1; } addattr32(&req.n, sizeof(req), RTA_OIF, idx); } } if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = AF_INET; } if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) { exit(2); } if (connected && !from_ok) { struct rtmsg *r = NLMSG_DATA(&req.n); int len = req.n.nlmsg_len; struct rtattr * tb[RTA_MAX+1]; if (print_route(NULL, &req.n, (void*)stdout) < 0) { bb_error_msg_and_die("An error :-)"); } if (req.n.nlmsg_type != RTM_NEWROUTE) { bb_error_msg("Not a route?"); return -1; } len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) { bb_error_msg("Wrong len %d", len); return -1; } memset(tb, 0, sizeof(tb)); parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); if (tb[RTA_PREFSRC]) { tb[RTA_PREFSRC]->rta_type = RTA_SRC; r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]); } else if (!tb[RTA_SRC]) { bb_error_msg("Failed to connect the route"); return -1; } if (!odev && tb[RTA_OIF]) { tb[RTA_OIF]->rta_type = 0; } if (tb[RTA_GATEWAY]) { tb[RTA_GATEWAY]->rta_type = 0; } if (!idev && tb[RTA_IIF]) { tb[RTA_IIF]->rta_type = 0; } req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETROUTE; if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) { exit(2); } } if (print_route(NULL, &req.n, (void*)stdout) < 0) { bb_error_msg_and_die("An error :-)"); } exit(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"; enum { ARG_link, ARG_name, ARG_type, ARG_dev, }; struct rtnl_handle rth; struct { struct nlmsghdr n; struct ifinfomsg i; char buf[1024]; } req; smalluint arg; char *name_str = NULL, *link_str = NULL, *type_str = NULL, *dev_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++; break; } if (arg == ARG_link) { NEXT_ARG(); link_str = *argv; } else if (arg == ARG_name) { NEXT_ARG(); name_str = *argv; } else { if (arg == ARG_dev) { if (dev_str) duparg(*argv, "dev"); NEXT_ARG(); } dev_str = *argv; } 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 (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; }
int do_show_or_flush(int argc, char **argv, int flush) { char *filter_dev = NULL; int state_given = 0; struct ndmsg ndm = { 0 }; ipneigh_reset_filter(); if (!filter.family) filter.family = preferred_family; if (flush) { if (argc <= 0) { fprintf(stderr, "Flush requires arguments.\n"); return -1; } filter.state = ~(NUD_PERMANENT|NUD_NOARP); } else filter.state = 0xFF & ~NUD_NOARP; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if (filter_dev) duparg("dev", *argv); filter_dev = *argv; } else if (strcmp(*argv, "unused") == 0) { filter.unused_only = 1; } else if (strcmp(*argv, "nud") == 0) { unsigned state; NEXT_ARG(); if (!state_given) { state_given = 1; filter.state = 0; } if (nud_state_a2n(&state, *argv)) { if (strcmp(*argv, "all") != 0) invarg("nud state is bad", *argv); state = ~0; if (flush) state &= ~NUD_NOARP; } if (state == 0) state = 0x100; filter.state |= state; } else if (strcmp(*argv, "proxy") == 0) ndm.ndm_flags = NTF_PROXY; else { if (strcmp(*argv, "to") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); get_prefix(&filter.pfx, *argv, filter.family); if (filter.family == AF_UNSPEC) filter.family = filter.pfx.family; } argc--; argv++; } ll_init_map(&rth); if (filter_dev) { if ((filter.index = ll_name_to_index(filter_dev)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", filter_dev); return -1; } } if (flush) { int round = 0; char flushb[4096-512]; filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); filter.state &= ~NUD_FAILED; while (round < MAX_ROUNDS) { ndm.ndm_family = filter.family; if (rtnl_dump_request(&rth, RTM_GETNEIGH, &ndm, sizeof(struct ndmsg)) < 0) { perror("Cannot send dump request"); exit(1); } filter.flushed = 0; if (rtnl_dump_filter(&rth, print_neigh, stdout, NULL, NULL) < 0) { fprintf(stderr, "Flush terminated\n"); exit(1); } if (filter.flushed == 0) { if (show_stats) { if (round == 0) printf("Nothing to flush.\n"); else printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":""); } fflush(stdout); return 0; } round++; if (flush_update() < 0) exit(1); if (show_stats) { printf("\n*** Round %d, deleting %d entries ***\n", round, filter.flushed); fflush(stdout); } } printf("*** Flush not complete bailing out after %d rounds\n", MAX_ROUNDS); return 1; } ndm.ndm_family = filter.family; if (rtnl_dump_request(&rth, RTM_GETNEIGH, &ndm, sizeof(struct ndmsg)) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, print_neigh, stdout, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } return 0; }
/* Return value becomes exitcode. It's okay to not return at all */ static int do_set(char **argv) { char *dev = NULL; uint32_t mask = 0; uint32_t flags = 0; int qlen = -1; int mtu = -1; char *newaddr = NULL; char *newbrd = NULL; struct ifreq ifr0, ifr1; char *newname = NULL; int htype, halen; static const char keywords[] ALIGN1 = "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" "arp\0""address\0""dev\0"; enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, ARG_arp, ARG_addr, ARG_dev }; static const char str_on_off[] ALIGN1 = "on\0""off\0"; enum { PARM_on = 0, PARM_off }; smalluint key; while (*argv) { /* substring search ensures that e.g. "addr" and "address" * are both accepted */ key = index_in_substrings(keywords, *argv); if (key == ARG_up) { mask |= IFF_UP; flags |= IFF_UP; } else if (key == ARG_down) { mask |= IFF_UP; flags &= ~IFF_UP; } else if (key == ARG_name) { NEXT_ARG(); newname = *argv; } else if (key == ARG_mtu) { NEXT_ARG(); if (mtu != -1) duparg("mtu", *argv); mtu = get_unsigned(*argv, "mtu"); } else if (key == ARG_qlen) { NEXT_ARG(); if (qlen != -1) duparg("qlen", *argv); qlen = get_unsigned(*argv, "qlen"); } else if (key == ARG_addr) { NEXT_ARG(); newaddr = *argv; } else if (key >= ARG_dev) { if (key == ARG_dev) { NEXT_ARG(); } if (dev) duparg2("dev", *argv); dev = *argv; } else { int param; NEXT_ARG(); param = index_in_strings(str_on_off, *argv); if (key == ARG_multicast) { if (param < 0) die_must_be_on_off("multicast"); mask |= IFF_MULTICAST; if (param == PARM_on) flags |= IFF_MULTICAST; else flags &= ~IFF_MULTICAST; } else if (key == ARG_arp) { if (param < 0) die_must_be_on_off("arp"); mask |= IFF_NOARP; if (param == PARM_on) flags &= ~IFF_NOARP; else flags |= IFF_NOARP; } } argv++; } if (!dev) { bb_error_msg_and_die(bb_msg_requires_arg, "\"dev\""); } if (newaddr || newbrd) { halen = get_address(dev, &htype); if (newaddr) { parse_address(dev, htype, halen, newaddr, &ifr0); set_address(&ifr0, 0); } if (newbrd) { parse_address(dev, htype, halen, newbrd, &ifr1); set_address(&ifr1, 1); } } if (newname && strcmp(dev, newname)) { do_changename(dev, newname); dev = newname; } if (qlen != -1) { set_qlen(dev, qlen); } if (mtu != -1) { set_mtu(dev, mtu); } if (mask) do_chflags(dev, flags, mask); return 0; }
static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size) { static const char keywords[] ALIGN1 = "id\0" "protocol\0" "reorder_hdr\0" "gvrp\0" "mvrp\0" "loose_binding\0" ; static const char protocols[] ALIGN1 = "802.1q\0" "802.1ad\0" ; static const char str_on_off[] ALIGN1 = "on\0" "off\0" ; enum { ARG_id = 0, ARG_reorder_hdr, ARG_gvrp, ARG_mvrp, ARG_loose_binding, ARG_protocol, }; enum { PROTO_8021Q = 0, PROTO_8021AD, }; enum { PARM_on = 0, PARM_off }; int arg; uint16_t id, proto; struct ifla_vlan_flags flags = {}; while (*argv) { arg = index_in_substrings(keywords, *argv); if (arg < 0) invarg(*argv, "type vlan"); NEXT_ARG(); if (arg == ARG_id) { id = get_u16(*argv, "id"); addattr_l(n, size, IFLA_VLAN_ID, &id, sizeof(id)); } else if (arg == ARG_protocol) { arg = index_in_substrings(protocols, *argv); if (arg == PROTO_8021Q) proto = ETH_P_8021Q; else if (arg == PROTO_8021AD) proto = ETH_P_8021AD; else bb_error_msg_and_die("unknown VLAN encapsulation protocol '%s'", *argv); addattr_l(n, size, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto)); } else { int param = index_in_strings(str_on_off, *argv); if (param < 0) die_must_be_on_off(nth_string(keywords, arg)); if (arg == ARG_reorder_hdr) { flags.mask |= VLAN_FLAG_REORDER_HDR; flags.flags &= ~VLAN_FLAG_REORDER_HDR; if (param == PARM_on) flags.flags |= VLAN_FLAG_REORDER_HDR; } else if (arg == ARG_gvrp) { flags.mask |= VLAN_FLAG_GVRP; flags.flags &= ~VLAN_FLAG_GVRP; if (param == PARM_on) flags.flags |= VLAN_FLAG_GVRP; } else if (arg == ARG_mvrp) { flags.mask |= VLAN_FLAG_MVRP; flags.flags &= ~VLAN_FLAG_MVRP; if (param == PARM_on) flags.flags |= VLAN_FLAG_MVRP; } else { /*if (arg == ARG_loose_binding) */ flags.mask |= VLAN_FLAG_LOOSE_BINDING; flags.flags &= ~VLAN_FLAG_LOOSE_BINDING; if (param == PARM_on) flags.flags |= VLAN_FLAG_LOOSE_BINDING; } } argv++; } if (flags.mask) addattr_l(n, size, IFLA_VLAN_FLAGS, &flags, sizeof(flags)); }
static int ipntable_modify(int cmd, int flags, int argc, char **argv) { struct { struct nlmsghdr n; struct ndtmsg ndtm; char buf[1024]; } req; char *namep = NULL; char *threshsp = NULL; char *gc_intp = NULL; char parms_buf[1024]; struct rtattr *parms_rta = (struct rtattr *)parms_buf; int parms_change = 0; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.ndtm.ndtm_family = preferred_family; req.ndtm.ndtm_pad1 = 0; req.ndtm.ndtm_pad2 = 0; memset(&parms_buf, 0, sizeof(parms_buf)); parms_rta->rta_type = NDTA_PARMS; parms_rta->rta_len = RTA_LENGTH(0); while (argc > 0) { if (strcmp(*argv, "name") == 0) { int len; NEXT_ARG(); if (namep) duparg("NAME", *argv); namep = *argv; len = strlen(namep) + 1; addattr_l(&req.n, sizeof(req), NDTA_NAME, namep, len); } else if (strcmp(*argv, "thresh1") == 0) { __u32 thresh1; NEXT_ARG(); threshsp = *argv; if (get_u32(&thresh1, *argv, 0)) invarg("\"thresh1\" value is invalid", *argv); addattr32(&req.n, sizeof(req), NDTA_THRESH1, thresh1); } else if (strcmp(*argv, "thresh2") == 0) { __u32 thresh2; NEXT_ARG(); threshsp = *argv; if (get_u32(&thresh2, *argv, 0)) invarg("\"thresh2\" value is invalid", *argv); addattr32(&req.n, sizeof(req), NDTA_THRESH2, thresh2); } else if (strcmp(*argv, "thresh3") == 0) { __u32 thresh3; NEXT_ARG(); threshsp = *argv; if (get_u32(&thresh3, *argv, 0)) invarg("\"thresh3\" value is invalid", *argv); addattr32(&req.n, sizeof(req), NDTA_THRESH3, thresh3); } else if (strcmp(*argv, "gc_int") == 0) { __u64 gc_int; NEXT_ARG(); gc_intp = *argv; if (get_u64(&gc_int, *argv, 0)) invarg("\"gc_int\" value is invalid", *argv); addattr_l(&req.n, sizeof(req), NDTA_GC_INTERVAL, &gc_int, sizeof(gc_int)); } else if (strcmp(*argv, "dev") == 0) { __u32 ifindex; NEXT_ARG(); ifindex = ll_name_to_index(*argv); if (ifindex == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", *argv); return -1; } rta_addattr32(parms_rta, sizeof(parms_buf), NDTPA_IFINDEX, ifindex); } else if (strcmp(*argv, "base_reachable") == 0) { __u64 breachable; NEXT_ARG(); if (get_u64(&breachable, *argv, 0)) invarg("\"base_reachable\" value is invalid", *argv); rta_addattr_l(parms_rta, sizeof(parms_buf), NDTPA_BASE_REACHABLE_TIME, &breachable, sizeof(breachable)); parms_change = 1; } else if (strcmp(*argv, "retrans") == 0) { __u64 retrans; NEXT_ARG(); if (get_u64(&retrans, *argv, 0)) invarg("\"retrans\" value is invalid", *argv); rta_addattr_l(parms_rta, sizeof(parms_buf), NDTPA_RETRANS_TIME, &retrans, sizeof(retrans)); parms_change = 1; } else if (strcmp(*argv, "gc_stale") == 0) { __u64 gc_stale; NEXT_ARG(); if (get_u64(&gc_stale, *argv, 0)) invarg("\"gc_stale\" value is invalid", *argv); rta_addattr_l(parms_rta, sizeof(parms_buf), NDTPA_GC_STALETIME, &gc_stale, sizeof(gc_stale)); parms_change = 1; } else if (strcmp(*argv, "delay_probe") == 0) { __u64 delay_probe; NEXT_ARG(); if (get_u64(&delay_probe, *argv, 0)) invarg("\"delay_probe\" value is invalid", *argv); rta_addattr_l(parms_rta, sizeof(parms_buf), NDTPA_DELAY_PROBE_TIME, &delay_probe, sizeof(delay_probe)); parms_change = 1; } else if (strcmp(*argv, "queue") == 0) { __u32 queue; NEXT_ARG(); if (get_u32(&queue, *argv, 0)) invarg("\"queue\" value is invalid", *argv); if (!parms_rta) parms_rta = (struct rtattr *)&parms_buf; rta_addattr32(parms_rta, sizeof(parms_buf), NDTPA_QUEUE_LEN, queue); parms_change = 1; } else if (strcmp(*argv, "app_probes") == 0) { __u32 aprobe; NEXT_ARG(); if (get_u32(&aprobe, *argv, 0)) invarg("\"app_probes\" value is invalid", *argv); rta_addattr32(parms_rta, sizeof(parms_buf), NDTPA_APP_PROBES, aprobe); parms_change = 1; } else if (strcmp(*argv, "ucast_probes") == 0) { __u32 uprobe; NEXT_ARG(); if (get_u32(&uprobe, *argv, 0)) invarg("\"ucast_probes\" value is invalid", *argv); rta_addattr32(parms_rta, sizeof(parms_buf), NDTPA_UCAST_PROBES, uprobe); parms_change = 1; } else if (strcmp(*argv, "mcast_probes") == 0) { __u32 mprobe; NEXT_ARG(); if (get_u32(&mprobe, *argv, 0)) invarg("\"mcast_probes\" value is invalid", *argv); rta_addattr32(parms_rta, sizeof(parms_buf), NDTPA_MCAST_PROBES, mprobe); parms_change = 1; } else if (strcmp(*argv, "anycast_delay") == 0) { __u64 anycast_delay; NEXT_ARG(); if (get_u64(&anycast_delay, *argv, 0)) invarg("\"anycast_delay\" value is invalid", *argv); rta_addattr_l(parms_rta, sizeof(parms_buf), NDTPA_ANYCAST_DELAY, &anycast_delay, sizeof(anycast_delay)); parms_change = 1; } else if (strcmp(*argv, "proxy_delay") == 0) { __u64 proxy_delay; NEXT_ARG(); if (get_u64(&proxy_delay, *argv, 0)) invarg("\"proxy_delay\" value is invalid", *argv); rta_addattr_l(parms_rta, sizeof(parms_buf), NDTPA_PROXY_DELAY, &proxy_delay, sizeof(proxy_delay)); parms_change = 1; } else if (strcmp(*argv, "proxy_queue") == 0) { __u32 pqueue; NEXT_ARG(); if (get_u32(&pqueue, *argv, 0)) invarg("\"proxy_queue\" value is invalid", *argv); rta_addattr32(parms_rta, sizeof(parms_buf), NDTPA_PROXY_QLEN, pqueue); parms_change = 1; } else if (strcmp(*argv, "locktime") == 0) { __u64 locktime; NEXT_ARG(); if (get_u64(&locktime, *argv, 0)) invarg("\"locktime\" value is invalid", *argv); rta_addattr_l(parms_rta, sizeof(parms_buf), NDTPA_LOCKTIME, &locktime, sizeof(locktime)); parms_change = 1; } else { invarg("unknown", *argv); } argc--; argv++; } if (!namep) missarg("NAME"); if (!threshsp && !gc_intp && !parms_change) { fprintf(stderr, "Not enough information: changeable attributes required.\n"); exit(-1); } if (parms_rta->rta_len > RTA_LENGTH(0)) { addattr_l(&req.n, sizeof(req), NDTA_PARMS, RTA_DATA(parms_rta), RTA_PAYLOAD(parms_rta)); } if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) exit(2); return 0; }
static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { __u32 vni = 0; int vni_set = 0; __u32 daddr = 0; struct in6_addr daddr6 = IN6ADDR_ANY_INIT; __u32 label = 0; __u8 ttl = 0; __u8 tos = 0; __u16 dstport = 0; bool metadata = 0; __u8 udpcsum = 0; bool udpcsum_set = false; __u8 udp6zerocsumtx = 0; bool udp6zerocsumtx_set = false; __u8 udp6zerocsumrx = 0; bool udp6zerocsumrx_set = false; while (argc > 0) { if (!matches(*argv, "id") || !matches(*argv, "vni")) { NEXT_ARG(); if (get_u32(&vni, *argv, 0) || vni >= 1u << 24) invarg("invalid id", *argv); vni_set = 1; } else if (!matches(*argv, "remote")) { NEXT_ARG(); if (!inet_get_addr(*argv, &daddr, &daddr6)) { fprintf(stderr, "Invalid address \"%s\"\n", *argv); return -1; } if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr))) invarg("invalid remote address", *argv); } else if (!matches(*argv, "ttl") || !matches(*argv, "hoplimit")) { unsigned int uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_unsigned(&uval, *argv, 0)) invarg("invalid TTL", *argv); if (uval > 255) invarg("TTL must be <= 255", *argv); ttl = uval; } } else if (!matches(*argv, "tos") || !matches(*argv, "dsfield")) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg("bad TOS value", *argv); tos = uval; } else tos = 1; } else if (!matches(*argv, "label") || !matches(*argv, "flowlabel")) { __u32 uval; NEXT_ARG(); if (get_u32(&uval, *argv, 0) || (uval & ~LABEL_MAX_MASK)) invarg("invalid flowlabel", *argv); label = htonl(uval); } else if (!matches(*argv, "dstport")) { NEXT_ARG(); if (get_u16(&dstport, *argv, 0)) invarg("dstport", *argv); } else if (!matches(*argv, "external")) { metadata = true; } else if (!matches(*argv, "noexternal")) { metadata = false; } else if (!matches(*argv, "udpcsum")) { udpcsum = 1; udpcsum_set = true; } else if (!matches(*argv, "noudpcsum")) { udpcsum = 0; udpcsum_set = true; } else if (!matches(*argv, "udp6zerocsumtx")) { udp6zerocsumtx = 1; udp6zerocsumtx_set = true; } else if (!matches(*argv, "noudp6zerocsumtx")) { udp6zerocsumtx = 0; udp6zerocsumtx_set = true; } else if (!matches(*argv, "udp6zerocsumrx")) { udp6zerocsumrx = 1; udp6zerocsumrx_set = true; } else if (!matches(*argv, "noudp6zerocsumrx")) { udp6zerocsumrx = 0; udp6zerocsumrx_set = true; } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "geneve: unknown command \"%s\"?\n", *argv); explain(); return -1; } argc--, argv++; } if (metadata && vni_set) { fprintf(stderr, "geneve: both 'external' and vni cannot be specified\n"); return -1; } if (!metadata) { /* parameter checking make sense only for full geneve tunnels */ if (!vni_set) { fprintf(stderr, "geneve: missing virtual network identifier\n"); return -1; } if (!daddr && IN6_IS_ADDR_UNSPECIFIED(&daddr6)) { fprintf(stderr, "geneve: remote link partner not specified\n"); return -1; } } addattr32(n, 1024, IFLA_GENEVE_ID, vni); if (daddr) addattr_l(n, 1024, IFLA_GENEVE_REMOTE, &daddr, 4); if (!IN6_IS_ADDR_UNSPECIFIED(&daddr6)) addattr_l(n, 1024, IFLA_GENEVE_REMOTE6, &daddr6, sizeof(struct in6_addr)); addattr32(n, 1024, IFLA_GENEVE_LABEL, label); addattr8(n, 1024, IFLA_GENEVE_TTL, ttl); addattr8(n, 1024, IFLA_GENEVE_TOS, tos); if (dstport) addattr16(n, 1024, IFLA_GENEVE_PORT, htons(dstport)); if (metadata) addattr(n, 1024, IFLA_GENEVE_COLLECT_METADATA); if (udpcsum_set) addattr8(n, 1024, IFLA_GENEVE_UDP_CSUM, udpcsum); if (udp6zerocsumtx_set) addattr8(n, 1024, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, udp6zerocsumtx); if (udp6zerocsumrx_set) addattr8(n, 1024, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, udp6zerocsumrx); return 0; }
int do_xfrm_monitor(int argc, char **argv) { char *file = NULL; unsigned groups = ~((unsigned)0); /* XXX */ int lacquire=0; int lexpire=0; int laevent=0; int lpolicy=0; int lsa=0; int lreport=0; rtnl_close(&rth); while (argc > 0) { if (matches(*argv, "file") == 0) { NEXT_ARG(); file = *argv; } else if (matches(*argv, "acquire") == 0) { lacquire=1; groups = 0; } else if (matches(*argv, "expire") == 0) { lexpire=1; groups = 0; } else if (matches(*argv, "SA") == 0) { lsa=1; groups = 0; } else if (matches(*argv, "aevent") == 0) { laevent=1; groups = 0; } else if (matches(*argv, "policy") == 0) { lpolicy=1; groups = 0; } else if (matches(*argv, "report") == 0) { lreport=1; groups = 0; } else if (matches(*argv, "help") == 0) { usage(); } else { fprintf(stderr, "Argument \"%s\" is unknown, try \"ip xfrm monitor help\".\n", *argv); exit(-1); } argc--; argv++; } if (lacquire) groups |= nl_mgrp(XFRMNLGRP_ACQUIRE); if (lexpire) groups |= nl_mgrp(XFRMNLGRP_EXPIRE); if (lsa) groups |= nl_mgrp(XFRMNLGRP_SA); if (lpolicy) groups |= nl_mgrp(XFRMNLGRP_POLICY); if (laevent) groups |= nl_mgrp(XFRMNLGRP_AEVENTS); if (lreport) groups |= nl_mgrp(XFRMNLGRP_REPORT); if (file) { FILE *fp; fp = fopen(file, "r"); if (fp == NULL) { perror("Cannot fopen"); exit(-1); } return rtnl_from_file(fp, xfrm_accept_msg, (void*)stdout); } //ll_init_map(&rth); if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0) exit(1); if (rtnl_listen(&rth, xfrm_accept_msg, (void*)stdout) < 0) exit(2); return 0; }
static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv) { struct rtnl_handle rth; struct { struct nlmsghdr n; struct xfrm_userpolicy_info xpinfo; char buf[RTA_BUF_SIZE]; } req; char *dirp = NULL; char *selp = NULL; char *ptypep = NULL; char *sctxp = NULL; struct xfrm_userpolicy_type upt; char tmpls_buf[XFRM_TMPLS_BUF_SIZE]; int tmpls_len = 0; struct xfrm_mark mark = {0, 0}; struct { struct xfrm_user_sec_ctx sctx; char str[CTX_BUF_SIZE]; } ctx; memset(&req, 0, sizeof(req)); memset(&upt, 0, sizeof(upt)); memset(&tmpls_buf, 0, sizeof(tmpls_buf)); memset(&ctx, 0, sizeof(ctx)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.xpinfo.sel.family = preferred_family; req.xpinfo.lft.soft_byte_limit = XFRM_INF; req.xpinfo.lft.hard_byte_limit = XFRM_INF; req.xpinfo.lft.soft_packet_limit = XFRM_INF; req.xpinfo.lft.hard_packet_limit = XFRM_INF; while (argc > 0) { if (strcmp(*argv, "dir") == 0) { if (dirp) duparg("dir", *argv); dirp = *argv; NEXT_ARG(); xfrm_policy_dir_parse(&req.xpinfo.dir, &argc, &argv); } else if (strcmp(*argv, "ctx") == 0) { char *context; if (sctxp) duparg("ctx", *argv); sctxp = *argv; NEXT_ARG(); context = *argv; xfrm_sctx_parse((char *)&ctx.str, context, &ctx.sctx); } else if (strcmp(*argv, "mark") == 0) { xfrm_parse_mark(&mark, &argc, &argv); } else if (strcmp(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&req.xpinfo.index, *argv, 0)) invarg("INDEX value is invalid", *argv); } else if (strcmp(*argv, "ptype") == 0) { if (ptypep) duparg("ptype", *argv); ptypep = *argv; NEXT_ARG(); xfrm_policy_ptype_parse(&upt.type, &argc, &argv); } else if (strcmp(*argv, "action") == 0) { NEXT_ARG(); if (strcmp(*argv, "allow") == 0) req.xpinfo.action = XFRM_POLICY_ALLOW; else if (strcmp(*argv, "block") == 0) req.xpinfo.action = XFRM_POLICY_BLOCK; else invarg("ACTION value is invalid\n", *argv); } else if (strcmp(*argv, "priority") == 0) { NEXT_ARG(); if (get_u32(&req.xpinfo.priority, *argv, 0)) invarg("PRIORITY value is invalid", *argv); } else if (strcmp(*argv, "flag") == 0) { NEXT_ARG(); xfrm_policy_flag_parse(&req.xpinfo.flags, &argc, &argv); } else if (strcmp(*argv, "limit") == 0) { NEXT_ARG(); xfrm_lifetime_cfg_parse(&req.xpinfo.lft, &argc, &argv); } else if (strcmp(*argv, "tmpl") == 0) { struct xfrm_user_tmpl *tmpl; if (tmpls_len + sizeof(*tmpl) > sizeof(tmpls_buf)) { fprintf(stderr, "Too many tmpls: buffer overflow\n"); exit(1); } tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len); tmpl->family = preferred_family; tmpl->aalgos = (~(__u32)0); tmpl->ealgos = (~(__u32)0); tmpl->calgos = (~(__u32)0); NEXT_ARG(); xfrm_tmpl_parse(tmpl, &argc, &argv); tmpls_len += sizeof(*tmpl); } else { if (selp) duparg("unknown", *argv); selp = *argv; xfrm_selector_parse(&req.xpinfo.sel, &argc, &argv); if (preferred_family == AF_UNSPEC) preferred_family = req.xpinfo.sel.family; } argc--; argv++; } if (!dirp) { fprintf(stderr, "Not enough information: DIR is required.\n"); exit(1); } if (ptypep) { addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE, (void *)&upt, sizeof(upt)); } if (tmpls_len > 0) { addattr_l(&req.n, sizeof(req), XFRMA_TMPL, (void *)tmpls_buf, tmpls_len); } if (mark.m) { int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK, (void *)&mark, sizeof(mark)); if (r < 0) { fprintf(stderr, "%s: XFRMA_MARK failed\n",__func__); exit(1); } } if (sctxp) { addattr_l(&req.n, sizeof(req), XFRMA_SEC_CTX, (void *)&ctx, ctx.sctx.len); } if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) exit(1); if (req.xpinfo.sel.family == AF_UNSPEC) req.xpinfo.sel.family = AF_INET; if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) exit(2); rtnl_close(&rth); 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; 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, NULL, NULL) < 0) exit(2); return 0; }
static int xfrm_policy_list_or_deleteall(int argc, char **argv, int deleteall) { char *selp = NULL; struct rtnl_handle rth; if (argc > 0) filter.use = 1; filter.xpinfo.sel.family = preferred_family; while (argc > 0) { if (strcmp(*argv, "dir") == 0) { NEXT_ARG(); xfrm_policy_dir_parse(&filter.xpinfo.dir, &argc, &argv); filter.dir_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&filter.xpinfo.index, *argv, 0)) invarg("INDEX value is invalid", *argv); filter.index_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "ptype") == 0) { NEXT_ARG(); xfrm_policy_ptype_parse(&filter.ptype, &argc, &argv); filter.ptype_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "action") == 0) { NEXT_ARG(); if (strcmp(*argv, "allow") == 0) filter.xpinfo.action = XFRM_POLICY_ALLOW; else if (strcmp(*argv, "block") == 0) filter.xpinfo.action = XFRM_POLICY_BLOCK; else invarg("ACTION value is invalid\n", *argv); filter.action_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "priority") == 0) { NEXT_ARG(); if (get_u32(&filter.xpinfo.priority, *argv, 0)) invarg("PRIORITY value is invalid", *argv); filter.priority_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "flag") == 0) { NEXT_ARG(); xfrm_policy_flag_parse(&filter.xpinfo.flags, &argc, &argv); filter.policy_flags_mask = XFRM_FILTER_MASK_FULL; } else { if (selp) invarg("unknown", *argv); selp = *argv; xfrm_selector_parse(&filter.xpinfo.sel, &argc, &argv); if (preferred_family == AF_UNSPEC) preferred_family = filter.xpinfo.sel.family; } argc--; argv++; } if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) exit(1); if (deleteall) { struct xfrm_buffer xb; char buf[NLMSG_DELETEALL_BUF_SIZE]; int i; xb.buf = buf; xb.size = sizeof(buf); xb.rth = &rth; for (i = 0; ; i++) { struct { struct nlmsghdr n; char buf[NLMSG_BUF_SIZE]; } req = { .n.nlmsg_len = NLMSG_HDRLEN, .n.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, .n.nlmsg_type = XFRM_MSG_GETPOLICY, .n.nlmsg_seq = rth.dump = ++rth.seq, }; xb.offset = 0; xb.nlmsg_count = 0; if (show_stats > 1) fprintf(stderr, "Delete-all round = %d\n", i); if (rtnl_send(&rth, (void *)&req, req.n.nlmsg_len) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, xfrm_policy_keep, &xb) < 0) { fprintf(stderr, "Delete-all terminated\n"); exit(1); } if (xb.nlmsg_count == 0) { if (show_stats > 1) fprintf(stderr, "Delete-all completed\n"); break; } if (rtnl_send_check(&rth, xb.buf, xb.offset) < 0) { perror("Failed to send delete-all request"); exit(1); } if (show_stats > 1) fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count); xb.offset = 0; xb.nlmsg_count = 0; } } else { struct { struct nlmsghdr n; char buf[NLMSG_BUF_SIZE]; } req = { .n.nlmsg_len = NLMSG_HDRLEN, .n.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, .n.nlmsg_type = XFRM_MSG_GETPOLICY, .n.nlmsg_seq = rth.dump = ++rth.seq, }; if (rtnl_send(&rth, (void *)&req, req.n.nlmsg_len) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, xfrm_policy_print, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } } rtnl_close(&rth); exit(0); } static int print_spdinfo( struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; __u32 *f = NLMSG_DATA(n); struct rtattr * tb[XFRMA_SPD_MAX+1]; struct rtattr * rta; int len = n->nlmsg_len; len -= NLMSG_LENGTH(sizeof(__u32)); if (len < 0) { fprintf(stderr, "SPDinfo: Wrong len %d\n", len); return -1; } rta = XFRMSAPD_RTA(f); parse_rtattr(tb, XFRMA_SPD_MAX, rta, len); fprintf(fp,"\t SPD"); if (tb[XFRMA_SPD_INFO]) { struct xfrmu_spdinfo *si; if (RTA_PAYLOAD(tb[XFRMA_SPD_INFO]) < sizeof(*si)) { fprintf(stderr, "SPDinfo: Wrong len %d\n", len); return -1; } si = RTA_DATA(tb[XFRMA_SPD_INFO]); fprintf(fp," IN %d", si->incnt); fprintf(fp," OUT %d", si->outcnt); fprintf(fp," FWD %d", si->fwdcnt); if (show_stats) { fprintf(fp," (Sock:"); fprintf(fp," IN %d", si->inscnt); fprintf(fp," OUT %d", si->outscnt); fprintf(fp," FWD %d", si->fwdscnt); fprintf(fp,")"); } fprintf(fp, "%s", _SL_); } if (show_stats > 1) { struct xfrmu_spdhinfo *sh; if (tb[XFRMA_SPD_HINFO]) { if (RTA_PAYLOAD(tb[XFRMA_SPD_HINFO]) < sizeof(*sh)) { fprintf(stderr, "SPDinfo: Wrong len %d\n", len); return -1; } sh = RTA_DATA(tb[XFRMA_SPD_HINFO]); fprintf(fp,"\t SPD buckets:"); fprintf(fp," count %d", sh->spdhcnt); fprintf(fp," Max %d", sh->spdhmcnt); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_SPD_IPV4_HTHRESH]) { struct xfrmu_spdhthresh *th; if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV4_HTHRESH]) < sizeof(*th)) { fprintf(stderr, "SPDinfo: Wrong len %d\n", len); return -1; } th = RTA_DATA(tb[XFRMA_SPD_IPV4_HTHRESH]); fprintf(fp,"\t SPD IPv4 thresholds:"); fprintf(fp," local %d", th->lbits); fprintf(fp," remote %d", th->rbits); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_SPD_IPV6_HTHRESH]) { struct xfrmu_spdhthresh *th; if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV6_HTHRESH]) < sizeof(*th)) { fprintf(stderr, "SPDinfo: Wrong len %d\n", len); return -1; } th = RTA_DATA(tb[XFRMA_SPD_IPV6_HTHRESH]); fprintf(fp,"\t SPD IPv6 thresholds:"); fprintf(fp," local %d", th->lbits); fprintf(fp," remote %d", th->rbits); fprintf(fp, "%s", _SL_); } } if (oneline) fprintf(fp, "\n"); return 0; }
static int iprule_modify(int cmd, int argc, char **argv) { int table_ok = 0; struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; memset(&req, 0, sizeof(req)); req.n.nlmsg_type = cmd; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.r.rtm_family = preferred_family; req.r.rtm_protocol = RTPROT_BOOT; req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_table = 0; req.r.rtm_type = RTN_UNSPEC; req.r.rtm_flags = 0; if (cmd == RTM_NEWRULE) { req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; req.r.rtm_type = RTN_UNICAST; } while (argc > 0) { if (strcmp(*argv, "not") == 0) { req.r.rtm_flags |= FIB_RULE_INVERT; } else if (strcmp(*argv, "from") == 0) { inet_prefix dst; NEXT_ARG(); get_prefix(&dst, *argv, req.r.rtm_family); req.r.rtm_src_len = dst.bitlen; addattr_l(&req.n, sizeof(req), FRA_SRC, &dst.data, dst.bytelen); } else if (strcmp(*argv, "to") == 0) { inet_prefix dst; NEXT_ARG(); get_prefix(&dst, *argv, req.r.rtm_family); req.r.rtm_dst_len = dst.bitlen; addattr_l(&req.n, sizeof(req), FRA_DST, &dst.data, dst.bytelen); } else if (matches(*argv, "preference") == 0 || matches(*argv, "order") == 0 || matches(*argv, "priority") == 0) { __u32 pref; NEXT_ARG(); if (get_u32(&pref, *argv, 0)) invarg("preference value is invalid\n", *argv); addattr32(&req.n, sizeof(req), FRA_PRIORITY, pref); } else if (strcmp(*argv, "tos") == 0 || matches(*argv, "dsfield") == 0) { __u32 tos; NEXT_ARG(); if (rtnl_dsfield_a2n(&tos, *argv)) invarg("TOS value is invalid\n", *argv); req.r.rtm_tos = tos; } else if (strcmp(*argv, "fwmark") == 0) { char *slash; __u32 fwmark, fwmask; NEXT_ARG(); if ((slash = strchr(*argv, '/')) != NULL) *slash = '\0'; if (get_u32(&fwmark, *argv, 0)) invarg("fwmark value is invalid\n", *argv); addattr32(&req.n, sizeof(req), FRA_FWMARK, fwmark); if (slash) { if (get_u32(&fwmask, slash+1, 0)) invarg("fwmask value is invalid\n", slash+1); addattr32(&req.n, sizeof(req), FRA_FWMASK, fwmask); } } else if (matches(*argv, "realms") == 0) { __u32 realm; NEXT_ARG(); if (get_rt_realms_or_raw(&realm, *argv)) invarg("invalid realms\n", *argv); addattr32(&req.n, sizeof(req), FRA_FLOW, realm); } else if (matches(*argv, "table") == 0 || strcmp(*argv, "lookup") == 0) { __u32 tid; NEXT_ARG(); if (rtnl_rttable_a2n(&tid, *argv)) invarg("invalid table ID\n", *argv); if (tid < 256) req.r.rtm_table = tid; else { req.r.rtm_table = RT_TABLE_UNSPEC; addattr32(&req.n, sizeof(req), FRA_TABLE, tid); } table_ok = 1; } else if (matches(*argv, "suppress_prefixlength") == 0 || strcmp(*argv, "sup_pl") == 0) { int pl; NEXT_ARG(); if (get_s32(&pl, *argv, 0) || pl < 0) invarg("suppress_prefixlength value is invalid\n", *argv); addattr32(&req.n, sizeof(req), FRA_SUPPRESS_PREFIXLEN, pl); } else if (matches(*argv, "suppress_ifgroup") == 0 || strcmp(*argv, "sup_group") == 0) { NEXT_ARG(); int group; if (rtnl_group_a2n(&group, *argv)) invarg("Invalid \"suppress_ifgroup\" value\n", *argv); addattr32(&req.n, sizeof(req), FRA_SUPPRESS_IFGROUP, group); } else if (strcmp(*argv, "dev") == 0 || strcmp(*argv, "iif") == 0) { NEXT_ARG(); addattr_l(&req.n, sizeof(req), FRA_IFNAME, *argv, strlen(*argv)+1); } else if (strcmp(*argv, "oif") == 0) { NEXT_ARG(); addattr_l(&req.n, sizeof(req), FRA_OIFNAME, *argv, strlen(*argv)+1); } else if (strcmp(*argv, "nat") == 0 || matches(*argv, "map-to") == 0) { NEXT_ARG(); fprintf(stderr, "Warning: route NAT is deprecated\n"); addattr32(&req.n, sizeof(req), RTA_GATEWAY, get_addr32(*argv)); req.r.rtm_type = RTN_NAT; } else { int type; if (strcmp(*argv, "type") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); else if (matches(*argv, "goto") == 0) { __u32 target; type = FR_ACT_GOTO; NEXT_ARG(); if (get_u32(&target, *argv, 0)) invarg("invalid target\n", *argv); addattr32(&req.n, sizeof(req), FRA_GOTO, target); } else if (matches(*argv, "nop") == 0) type = FR_ACT_NOP; else if (rtnl_rtntype_a2n(&type, *argv)) invarg("Failed to parse rule type", *argv); req.r.rtm_type = type; table_ok = 1; } argc--; argv++; } if (req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = AF_INET; if (!table_ok && cmd == RTM_NEWRULE) req.r.rtm_table = RT_TABLE_MAIN; if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) return -2; return 0; }
static int iproute_list_or_flush(int argc, char **argv, int flush) { int do_ipv6 = preferred_family; struct rtnl_handle rth; char *id = NULL; char *od = NULL; iproute_reset_filter(); filter.tb = RT_TABLE_MAIN; if (flush && argc <= 0) { fprintf(stderr, "\"ip route flush\" requires arguments.\n"); return -1; } while (argc > 0) { if (matches(*argv, "protocol") == 0) { int prot = 0; NEXT_ARG(); filter.protocolmask = -1; if (rtnl_rtprot_a2n(&prot, *argv)) { if (strcmp(*argv, "all") != 0) { invarg("invalid \"protocol\"\n", *argv); } prot = 0; filter.protocolmask = 0; } filter.protocol = prot; } else if (strcmp(*argv, "dev") == 0 || strcmp(*argv, "oif") == 0) { NEXT_ARG(); od = *argv; } else if (strcmp(*argv, "iif") == 0) { NEXT_ARG(); id = *argv; } else if (matches(*argv, "from") == 0) { NEXT_ARG(); if (matches(*argv, "root") == 0) { NEXT_ARG(); get_prefix(&filter.rsrc, *argv, do_ipv6); } else if (matches(*argv, "match") == 0) { NEXT_ARG(); get_prefix(&filter.msrc, *argv, do_ipv6); } else { if (matches(*argv, "exact") == 0) { NEXT_ARG(); } get_prefix(&filter.msrc, *argv, do_ipv6); filter.rsrc = filter.msrc; } } else { if (matches(*argv, "to") == 0) { NEXT_ARG(); } if (matches(*argv, "root") == 0) { NEXT_ARG(); get_prefix(&filter.rdst, *argv, do_ipv6); } else if (matches(*argv, "match") == 0) { NEXT_ARG(); get_prefix(&filter.mdst, *argv, do_ipv6); } else { if (matches(*argv, "exact") == 0) { NEXT_ARG(); } get_prefix(&filter.mdst, *argv, do_ipv6); filter.rdst = filter.mdst; } } argc--; argv++; } if (do_ipv6 == AF_UNSPEC && filter.tb) { do_ipv6 = AF_INET; } if (rtnl_open(&rth, 0) < 0) { exit(1); } ll_init_map(&rth); if (id || od) { int idx; if (id) { if ((idx = ll_name_to_index(id)) == 0) { bb_error_msg("Cannot find device \"%s\"", id); return -1; } filter.iif = idx; filter.iifmask = -1; } if (od) { if ((idx = ll_name_to_index(od)) == 0) { bb_error_msg("Cannot find device \"%s\"", od); } filter.oif = idx; filter.oifmask = -1; } } if (flush) { int round = 0; char flushb[4096-512]; if (filter.tb == -1) { if (do_ipv6 != AF_INET6) iproute_flush_cache(); if (do_ipv6 == AF_INET) return 0; } filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); filter.rth = &rth; for (;;) { if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { perror("Cannot send dump request"); return -1; } filter.flushed = 0; if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) { bb_error_msg("Flush terminated\n"); return -1; } if (filter.flushed == 0) { if (round == 0) { if (filter.tb != -1 || do_ipv6 == AF_INET6) fprintf(stderr, "Nothing to flush.\n"); } fflush(stdout); return 0; } round++; if (flush_update() < 0) exit(1); } } if (filter.tb != -1) { if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { bb_perror_msg_and_die("Cannot send dump request"); } } else { if (rtnl_rtcache_request(&rth, do_ipv6) < 0) { bb_perror_msg_and_die("Cannot send dump request"); } } if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) { bb_error_msg_and_die("Dump terminated"); } exit(0); }
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 tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { int ok=0; struct tc_tbf_qopt opt; __u32 rtab[256]; __u32 ptab[256]; unsigned buffer=0, mtu=0, mpu=0, latency=0; int Rcell_log=-1, Pcell_log = -1; struct rtattr *tail; memset(&opt, 0, sizeof(opt)); while (argc > 0) { if (matches(*argv, "limit") == 0) { NEXT_ARG(); if (opt.limit || latency) { fprintf(stderr, "Double \"limit/latency\" spec\n"); return -1; } if (get_size(&opt.limit, *argv)) { explain1("limit"); return -1; } ok++; } else if (matches(*argv, "latency") == 0) { NEXT_ARG(); if (opt.limit || latency) { fprintf(stderr, "Double \"limit/latency\" spec\n"); return -1; } if (get_usecs(&latency, *argv)) { explain1("latency"); return -1; } ok++; } else if (matches(*argv, "burst") == 0 || strcmp(*argv, "buffer") == 0 || strcmp(*argv, "maxburst") == 0) { NEXT_ARG(); if (buffer) { fprintf(stderr, "Double \"buffer/burst\" spec\n"); return -1; } if (get_size_and_cell(&buffer, &Rcell_log, *argv) < 0) { explain1("buffer"); return -1; } ok++; } else if (strcmp(*argv, "mtu") == 0 || strcmp(*argv, "minburst") == 0) { NEXT_ARG(); if (mtu) { fprintf(stderr, "Double \"mtu/minburst\" spec\n"); return -1; } if (get_size_and_cell(&mtu, &Pcell_log, *argv) < 0) { explain1("mtu"); return -1; } ok++; } else if (strcmp(*argv, "mpu") == 0) { NEXT_ARG(); if (mpu) { fprintf(stderr, "Double \"mpu\" spec\n"); return -1; } if (get_size(&mpu, *argv)) { explain1("mpu"); return -1; } ok++; } else if (strcmp(*argv, "rate") == 0) { NEXT_ARG(); if (opt.rate.rate) { fprintf(stderr, "Double \"rate\" spec\n"); return -1; } if (get_rate(&opt.rate.rate, *argv)) { explain1("rate"); return -1; } ok++; } else if (matches(*argv, "peakrate") == 0) { NEXT_ARG(); if (opt.peakrate.rate) { fprintf(stderr, "Double \"peakrate\" spec\n"); return -1; } if (get_rate(&opt.peakrate.rate, *argv)) { explain1("peakrate"); return -1; } ok++; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } if (!ok) return 0; if (opt.rate.rate == 0 || !buffer) { fprintf(stderr, "Both \"rate\" and \"burst\" are required.\n"); return -1; } if (opt.peakrate.rate) { if (!mtu) { fprintf(stderr, "\"mtu\" is required, if \"peakrate\" is requested.\n"); return -1; } } if (opt.limit == 0 && latency == 0) { fprintf(stderr, "Either \"limit\" or \"latency\" are required.\n"); return -1; } if (opt.limit == 0) { double lim = opt.rate.rate*(double)latency/1000000 + buffer; if (opt.peakrate.rate) { double lim2 = opt.peakrate.rate*(double)latency/1000000 + mtu; if (lim2 < lim) lim = lim2; } opt.limit = lim; } if ((Rcell_log = tc_calc_rtable(opt.rate.rate, rtab, Rcell_log, mtu, mpu)) < 0) { fprintf(stderr, "TBF: failed to calculate rate table.\n"); return -1; } opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer); opt.rate.cell_log = Rcell_log; opt.rate.mpu = mpu; if (opt.peakrate.rate) { if ((Pcell_log = tc_calc_rtable(opt.peakrate.rate, ptab, Pcell_log, mtu, mpu)) < 0) { fprintf(stderr, "TBF: failed to calculate peak rate table.\n"); return -1; } opt.mtu = tc_calc_xmittime(opt.peakrate.rate, mtu); opt.peakrate.cell_log = Pcell_log; opt.peakrate.mpu = mpu; } tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); addattr_l(n, 2024, TCA_TBF_PARMS, &opt, sizeof(opt)); addattr_l(n, 3024, TCA_TBF_RTAB, rtab, 1024); if (opt.peakrate.rate) addattr_l(n, 4096, TCA_TBF_PTAB, ptab, 1024); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
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 { /* rewind arg */ PREV_ARG(); break; } } if (argc == *argcp) incomplete_command(); addattr_nest_end(&req->n, vfinfo); *argcp = argc; *argvp = argv; return 0; }
static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct tc_ratespec r; struct tc_cbq_lssopt lss; __u32 rtab[256]; unsigned mpu=0, avpkt=0, allot=0; unsigned short overhead=0; unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */ int cell_log=-1; int ewma_log=-1; struct rtattr *tail; memset(&lss, 0, sizeof(lss)); memset(&r, 0, sizeof(r)); while (argc > 0) { if (matches(*argv, "bandwidth") == 0 || matches(*argv, "rate") == 0) { NEXT_ARG(); if (get_rate(&r.rate, *argv)) { explain1("bandwidth"); return -1; } } else if (matches(*argv, "ewma") == 0) { NEXT_ARG(); if (get_integer(&ewma_log, *argv, 0)) { explain1("ewma"); return -1; } if (ewma_log > 31) { fprintf(stderr, "ewma_log must be < 32\n"); return -1; } } else if (matches(*argv, "cell") == 0) { unsigned cell; int i; NEXT_ARG(); if (get_size(&cell, *argv)) { explain1("cell"); return -1; } for (i=0; i<32; i++) if ((1<<i) == cell) break; if (i>=32) { fprintf(stderr, "cell must be 2^n\n"); return -1; } cell_log = i; } else if (matches(*argv, "avpkt") == 0) { NEXT_ARG(); if (get_size(&avpkt, *argv)) { explain1("avpkt"); return -1; } } else if (matches(*argv, "mpu") == 0) { NEXT_ARG(); if (get_size(&mpu, *argv)) { explain1("mpu"); return -1; } } else if (matches(*argv, "allot") == 0) { NEXT_ARG(); /* Accept and ignore "allot" for backward compatibility */ if (get_size(&allot, *argv)) { explain1("allot"); return -1; } } else if (matches(*argv, "overhead") == 0) { NEXT_ARG(); if (get_u16(&overhead, *argv, 10)) { explain1("overhead"); return -1; } } else if (matches(*argv, "linklayer") == 0) { NEXT_ARG(); if (get_linklayer(&linklayer, *argv)) { explain1("linklayer"); return -1; } } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } /* OK. All options are parsed. */ if (r.rate == 0) { fprintf(stderr, "CBQ: bandwidth is required parameter.\n"); return -1; } if (avpkt == 0) { fprintf(stderr, "CBQ: \"avpkt\" is required.\n"); return -1; } if (allot < (avpkt*3)/2) allot = (avpkt*3)/2; r.mpu = mpu; r.overhead = overhead; if (tc_calc_rtable(&r, rtab, cell_log, allot, linklayer) < 0) { fprintf(stderr, "CBQ: failed to calculate rate table.\n"); return -1; } if (ewma_log < 0) ewma_log = TC_CBQ_DEF_EWMA; lss.ewma_log = ewma_log; lss.maxidle = tc_calc_xmittime(r.rate, avpkt); lss.change = TCF_CBQ_LSS_MAXIDLE|TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT; lss.avpkt = avpkt; tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); addattr_l(n, 1024, TCA_CBQ_RATE, &r, sizeof(r)); addattr_l(n, 1024, TCA_CBQ_LSSOPT, &lss, sizeof(lss)); addattr_l(n, 3024, TCA_CBQ_RTAB, rtab, 1024); if (show_raw) { int i; for (i=0; i<256; i++) printf("%u ", rtab[i]); printf("\n"); } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; 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 tcpm_do_cmd(int cmd, int argc, char **argv) { TCPM_REQUEST(req, 1024, TCP_METRICS_CMD_GET, NLM_F_REQUEST); int atype = -1, stype = -1; int ack; memset(&f, 0, sizeof(f)); f.daddr.bitlen = -1; f.daddr.family = preferred_family; f.saddr.bitlen = -1; f.saddr.family = preferred_family; switch (preferred_family) { case AF_UNSPEC: case AF_INET: case AF_INET6: break; default: fprintf(stderr, "Unsupported protocol family: %d\n", preferred_family); return -1; } for (; argc > 0; argc--, argv++) { if (strcmp(*argv, "src") == 0 || strcmp(*argv, "source") == 0) { char *who = *argv; NEXT_ARG(); if (matches(*argv, "help") == 0) usage(); if (f.saddr.bitlen >= 0) duparg2(who, *argv); get_prefix(&f.saddr, *argv, preferred_family); if (f.saddr.bytelen && f.saddr.bytelen * 8 == f.saddr.bitlen) { if (f.saddr.family == AF_INET) stype = TCP_METRICS_ATTR_SADDR_IPV4; else if (f.saddr.family == AF_INET6) stype = TCP_METRICS_ATTR_SADDR_IPV6; } if (stype < 0) { fprintf(stderr, "Error: a specific IP address is expected rather than \"%s\"\n", *argv); return -1; } } else { char *who = "address"; if (strcmp(*argv, "addr") == 0 || strcmp(*argv, "address") == 0) { who = *argv; NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (f.daddr.bitlen >= 0) duparg2(who, *argv); get_prefix(&f.daddr, *argv, preferred_family); if (f.daddr.bytelen && f.daddr.bytelen * 8 == f.daddr.bitlen) { if (f.daddr.family == AF_INET) atype = TCP_METRICS_ATTR_ADDR_IPV4; else if (f.daddr.family == AF_INET6) atype = TCP_METRICS_ATTR_ADDR_IPV6; } if ((CMD_DEL & cmd) && atype < 0) { fprintf(stderr, "Error: a specific IP address is expected rather than \"%s\"\n", *argv); return -1; } } argc--; argv++; } if (cmd == CMD_DEL && atype < 0) missarg("address"); /* flush for exact address ? Single del */ if (cmd == CMD_FLUSH && atype >= 0) cmd = CMD_DEL; /* flush for all addresses ? Single del without address */ if (cmd == CMD_FLUSH && f.daddr.bitlen <= 0 && f.saddr.bitlen <= 0 && preferred_family == AF_UNSPEC) { cmd = CMD_DEL; req.g.cmd = TCP_METRICS_CMD_DEL; ack = 1; } else if (cmd == CMD_DEL) { req.g.cmd = TCP_METRICS_CMD_DEL; ack = 1; } else { /* CMD_FLUSH, CMD_LIST */ ack = 0; } if (genl_family < 0) { if (rtnl_open_byproto(&grth, 0, NETLINK_GENERIC) < 0) { fprintf(stderr, "Cannot open generic netlink socket\n"); exit(1); } genl_family = genl_resolve_family(&grth, TCP_METRICS_GENL_NAME); if (genl_family < 0) exit(1); req.n.nlmsg_type = genl_family; } if (!(cmd & CMD_FLUSH) && (atype >= 0 || (cmd & CMD_DEL))) { if (ack) req.n.nlmsg_flags |= NLM_F_ACK; if (atype >= 0) addattr_l(&req.n, sizeof(req), atype, &f.daddr.data, f.daddr.bytelen); if (stype >= 0) addattr_l(&req.n, sizeof(req), stype, &f.saddr.data, f.saddr.bytelen); } else { req.n.nlmsg_flags |= NLM_F_DUMP; } f.cmd = cmd; if (cmd & CMD_FLUSH) { int round = 0; char flushb[4096-512]; f.flushb = flushb; f.flushp = 0; f.flushe = sizeof(flushb); for (;;) { req.n.nlmsg_seq = grth.dump = ++grth.seq; if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) { perror("Failed to send flush request"); exit(1); } f.flushed = 0; if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) { fprintf(stderr, "Flush terminated\n"); exit(1); } if (f.flushed == 0) { if (round == 0) { fprintf(stderr, "Nothing to flush.\n"); } else if (show_stats) printf("*** Flush is complete after %d round%s ***\n", round, round > 1 ? "s" : ""); fflush(stdout); return 0; } round++; if (flush_update() < 0) exit(1); if (show_stats) { printf("\n*** Round %d, deleting %d entries ***\n", round, f.flushed); fflush(stdout); } } return 0; } if (ack) { if (rtnl_talk(&grth, &req.n, NULL, 0) < 0) return -2; } else if (atype >= 0) { if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0) return -2; if (process_msg(NULL, &req.n, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } } else { req.n.nlmsg_seq = grth.dump = ++grth.seq; if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) { perror("Failed to send dump request"); exit(1); } if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } } return 0; }
static int do_set(int argc, char **argv) { char *dev = NULL; __u32 mask = 0; __u32 flags = 0; int qlen = -1; int mtu = -1; char *newaddr = NULL; char *newbrd = NULL; struct ifreq ifr0, ifr1; char *newname = NULL; int htype, halen; while (argc > 0) { if (strcmp(*argv, "up") == 0) { mask |= IFF_UP; flags |= IFF_UP; } else if (strcmp(*argv, "down") == 0) { mask |= IFF_UP; flags &= ~IFF_UP; } else if (strcmp(*argv, "name") == 0) { NEXT_ARG(); newname = *argv; } else if (matches(*argv, "address") == 0) { NEXT_ARG(); newaddr = *argv; } else if (matches(*argv, "broadcast") == 0 || strcmp(*argv, "brd") == 0) { NEXT_ARG(); newbrd = *argv; } 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); } 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); } else if (strcmp(*argv, "multicast") == 0) { NEXT_ARG(); mask |= IFF_MULTICAST; if (strcmp(*argv, "on") == 0) { flags |= IFF_MULTICAST; } else if (strcmp(*argv, "off") == 0) { flags &= ~IFF_MULTICAST; } else return on_off("multicast"); } else if (strcmp(*argv, "allmulticast") == 0) { NEXT_ARG(); mask |= IFF_ALLMULTI; if (strcmp(*argv, "on") == 0) { flags |= IFF_ALLMULTI; } else if (strcmp(*argv, "off") == 0) { flags &= ~IFF_ALLMULTI; } else return on_off("allmulticast"); } else if (strcmp(*argv, "multipath") == 0) { NEXT_ARG(); mask |= IFF_NOMULTIPATH; mask |= IFF_MPBACKUP; mask |= IFF_MPHANDOVER; if (strcmp(*argv, "on") == 0) { flags &= ~IFF_NOMULTIPATH; } else if (strcmp(*argv, "off") == 0) { flags |= IFF_NOMULTIPATH; } else if (strcmp(*argv, "backup") == 0) { flags |= IFF_MPBACKUP; } else if (strcmp(*argv, "handover") == 0) { flags |= IFF_MPHANDOVER; } else return on_off("multipath"); } else if (strcmp(*argv, "promisc") == 0) { NEXT_ARG(); mask |= IFF_PROMISC; if (strcmp(*argv, "on") == 0) { flags |= IFF_PROMISC; } else if (strcmp(*argv, "off") == 0) { flags &= ~IFF_PROMISC; } else return on_off("promisc"); } else if (strcmp(*argv, "trailers") == 0) { NEXT_ARG(); mask |= IFF_NOTRAILERS; if (strcmp(*argv, "off") == 0) { flags |= IFF_NOTRAILERS; } else if (strcmp(*argv, "on") == 0) { flags &= ~IFF_NOTRAILERS; } else return on_off("trailers"); } else if (strcmp(*argv, "arp") == 0) { NEXT_ARG(); mask |= IFF_NOARP; if (strcmp(*argv, "on") == 0) { flags &= ~IFF_NOARP; } else if (strcmp(*argv, "off") == 0) { flags |= IFF_NOARP; } else return on_off("noarp"); #ifdef IFF_DYNAMIC } else if (matches(*argv, "dynamic") == 0) { NEXT_ARG(); mask |= IFF_DYNAMIC; if (strcmp(*argv, "on") == 0) { flags |= IFF_DYNAMIC; } else if (strcmp(*argv, "off") == 0) { flags &= ~IFF_DYNAMIC; } else return on_off("dynamic"); #endif } else { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (dev) duparg2("dev", *argv); dev = *argv; } argc--; argv++; } if (!dev) { fprintf(stderr, "Not enough of information: \"dev\" argument is required.\n"); exit(-1); } if (newaddr || newbrd) { halen = get_address(dev, &htype); if (halen < 0) return -1; if (newaddr) { if (parse_address(dev, htype, halen, newaddr, &ifr0) < 0) return -1; } if (newbrd) { if (parse_address(dev, htype, halen, newbrd, &ifr1) < 0) return -1; } } if (newname && strcmp(dev, newname)) { if (strlen(newname) == 0) invarg("\"\" is not a valid device identifier\n", "name"); if (do_changename(dev, newname) < 0) return -1; dev = newname; } if (qlen != -1) { if (set_qlen(dev, qlen) < 0) return -1; } if (mtu != -1) { if (set_mtu(dev, mtu) < 0) return -1; } if (newaddr || newbrd) { if (newbrd) { if (set_address(&ifr1, 1) < 0) return -1; } if (newaddr) { if (set_address(&ifr0, 0) < 0) return -1; } } if (mask) return do_chflags(dev, flags, mask); return 0; }
static int init_gred(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct rtattr *tail; struct tc_gred_sopt opt; memset(&opt, 0, sizeof(struct tc_gred_sopt)); while (argc > 0) { DPRINTF(stderr,"init_gred: invoked with %s\n",*argv); if (strcmp(*argv, "DPs") == 0) { NEXT_ARG(); DPRINTF(stderr,"init_gred: next_arg with %s\n",*argv); opt.DPs=strtol(*argv, (char **)NULL, 10); if (opt.DPs >MAX_DPs) { /* need a better error check */ my_printf("DPs =%u \n",opt.DPs); my_printf("Illegal \"DPs\"\n"); my_printf("GRED: only %d DPs are " "currently supported\n",MAX_DPs); return -1; } } else if (strcmp(*argv, "default") == 0) { NEXT_ARG(); opt.def_DP=strtol(*argv, (char **)NULL, 10); if (!opt.DPs) { my_printf("\"default DP\" must be " "defined after DPs\n"); return -1; } if (opt.def_DP>opt.DPs) { /* my_printf("\"default DP\" must be less than %d\nNote: DP runs from 0 to %d for %d DPs\n",opt.DPs,opt.DPs-1,opt.DPs); */ my_printf("\"default DP\" must be less than %d\n",opt.DPs); return -1; } } else if (strcmp(*argv, "grio") == 0) { opt.grio=1; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { my_printf("What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } if ((!opt.DPs) || (!opt.def_DP)) { my_printf("Illegal gred setup parameters \n"); return -1; } DPRINTF("TC_GRED: sending DPs=%d default=%d\n",opt.DPs,opt.def_DP); n->nlmsg_flags|=NLM_F_CREATE; tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); addattr_l(n, 1024, TCA_GRED_DPS, &opt, sizeof(struct tc_gred_sopt)); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
static int xfrm_spd_setinfo(int argc, char **argv) { struct rtnl_handle rth; struct { struct nlmsghdr n; __u32 flags; char buf[RTA_BUF_SIZE]; } req; char *thr4 = NULL; char *thr6 = NULL; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(__u32)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = XFRM_MSG_NEWSPDINFO; req.flags = 0XFFFFFFFF; while (argc > 0) { if (strcmp(*argv, "hthresh4") == 0) { struct xfrmu_spdhthresh thr; if (thr4) duparg("hthresh4", *argv); thr4 = *argv; NEXT_ARG(); if (get_u8(&thr.lbits, *argv, 0) || thr.lbits > 32) invarg("hthresh4 LBITS value is invalid", *argv); NEXT_ARG(); if (get_u8(&thr.rbits, *argv, 0) || thr.rbits > 32) invarg("hthresh4 RBITS value is invalid", *argv); addattr_l(&req.n, sizeof(req), XFRMA_SPD_IPV4_HTHRESH, (void *)&thr, sizeof(thr)); } else if (strcmp(*argv, "hthresh6") == 0) { struct xfrmu_spdhthresh thr; if (thr6) duparg("hthresh6", *argv); thr6 = *argv; NEXT_ARG(); if (get_u8(&thr.lbits, *argv, 0) || thr.lbits > 128) invarg("hthresh6 LBITS value is invalid", *argv); NEXT_ARG(); if (get_u8(&thr.rbits, *argv, 0) || thr.rbits > 128) invarg("hthresh6 RBITS value is invalid", *argv); addattr_l(&req.n, sizeof(req), XFRMA_SPD_IPV6_HTHRESH, (void *)&thr, sizeof(thr)); } else { invarg("unknown", *argv); } argc--; argv++; } if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) exit(1); if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) exit(2); rtnl_close(&rth); return 0; }
static int ipaddrlabel_modify(int cmd, int argc, char **argv) { struct { struct nlmsghdr n; struct ifaddrlblmsg ifal; char buf[1024]; } req; inet_prefix prefix; uint32_t label = 0xffffffffUL; char *p = NULL; char *l = NULL; memset(&req, 0, sizeof(req)); memset(&prefix, 0, sizeof(prefix)); req.n.nlmsg_type = cmd; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrlblmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.ifal.ifal_family = preferred_family; req.ifal.ifal_prefixlen = 0; req.ifal.ifal_index = 0; if (cmd == RTM_NEWADDRLABEL) { req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; } while (argc > 0) { if (strcmp(*argv, "prefix") == 0) { NEXT_ARG(); p = *argv; get_prefix(&prefix, *argv, preferred_family); } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if ((req.ifal.ifal_index = ll_name_to_index(*argv)) == 0) invarg("dev is invalid\n", *argv); } else if (strcmp(*argv, "label") == 0) { NEXT_ARG(); l = *argv; if (get_u32(&label, *argv, 0) || label == 0xffffffffUL) invarg("label is invalid\n", *argv); } argc--; argv++; } if (p == NULL) { fprintf(stderr, "Not enough information: \"prefix\" argument is required.\n"); return -1; } if (l == NULL) { fprintf(stderr, "Not enough information: \"label\" argument is required.\n"); return -1; } addattr32(&req.n, sizeof(req), IFAL_LABEL, label); addattr_l(&req.n, sizeof(req), IFAL_ADDRESS, &prefix.data, prefix.bytelen); req.ifal.ifal_prefixlen = prefix.bitlen; if (req.ifal.ifal_family == AF_UNSPEC) req.ifal.ifal_family = AF_INET6; if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) return -2; return 0; }
static int prio_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { int pmap_mode = 0; int idx = 0; struct tc_prio_qopt opt = {3, { 1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 } }; struct rtattr *nest; unsigned char mq = 0; while (argc > 0) { if (strcmp(*argv, "bands") == 0) { if (pmap_mode) explain(); NEXT_ARG(); if (get_integer(&opt.bands, *argv, 10)) { fprintf(stderr, "Illegal \"bands\"\n"); return -1; } } else if (strcmp(*argv, "priomap") == 0) { if (pmap_mode) { fprintf(stderr, "Error: duplicate priomap\n"); return -1; } pmap_mode = 1; } else if (strcmp(*argv, "multiqueue") == 0) { mq = 1; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { unsigned int band; if (!pmap_mode) { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } if (get_unsigned(&band, *argv, 10)) { fprintf(stderr, "Illegal \"priomap\" element\n"); return -1; } if (band >= opt.bands) { fprintf(stderr, "\"priomap\" element is out of bands\n"); return -1; } if (idx > TC_PRIO_MAX) { fprintf(stderr, "\"priomap\" index > TC_PRIO_MAX=%u\n", TC_PRIO_MAX); return -1; } opt.priomap[idx++] = band; } argc--; argv++; } /* if (pmap_mode) { for (; idx < TC_PRIO_MAX; idx++) opt.priomap[idx] = opt.priomap[TC_PRIO_BESTEFFORT]; } */ nest = addattr_nest_compat(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)); if (mq) addattr_l(n, 1024, TCA_PRIO_MQ, NULL, 0); addattr_nest_compat_end(n, nest); return 0; }