Example #1
0
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;
}
Example #2
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;
}
Example #3
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);
}
Example #6
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;
}
Example #7
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);
}
Example #8
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;
}
Example #9
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;
}
Example #10
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;
}
Example #11
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));
}
Example #12
0
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;
}
Example #14
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;
}
Example #15
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;
}
Example #16
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;
}
Example #17
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;
}
Example #18
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;
}
Example #19
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);
}
Example #20
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;
}
Example #21
0
File: q_tbf.c Project: NieHao/R7000
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;
}
Example #25
0
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;
}
Example #27
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;
}
Example #28
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;
}
Example #29
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;
}
Example #30
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;
}