예제 #1
0
static int rr_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
	int ok = 0;
	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;
			}
			ok++;
		} else if (strcmp(*argv, "priomap") == 0) {
			if (pmap_mode) {
				fprintf(stderr, "Error: duplicate priomap\n");
				return -1;
			}
			pmap_mode = 1;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else if (strcmp(*argv, "multiqueue") == 0) {
			mq = 1;
		} else {
			unsigned 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_RR_MAX=%u\n", TC_PRIO_MAX);
				return -1;
			}
			opt.priomap[idx++] = band;
		}
		argc--; argv++;
	}

	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;
}
예제 #2
0
파일: ipneigh.c 프로젝트: eworm-de/iproute2
static int nud_state_a2n(unsigned int *state, const char *arg)
{
	if (matches(arg, "permanent") == 0)
		*state = NUD_PERMANENT;
	else if (matches(arg, "reachable") == 0)
		*state = NUD_REACHABLE;
	else if (strcmp(arg, "noarp") == 0)
		*state = NUD_NOARP;
	else if (strcmp(arg, "none") == 0)
		*state = NUD_NONE;
	else if (strcmp(arg, "stale") == 0)
		*state = NUD_STALE;
	else if (strcmp(arg, "incomplete") == 0)
		*state = NUD_INCOMPLETE;
	else if (strcmp(arg, "delay") == 0)
		*state = NUD_DELAY;
	else if (strcmp(arg, "probe") == 0)
		*state = NUD_PROBE;
	else if (matches(arg, "failed") == 0)
		*state = NUD_FAILED;
	else {
		if (get_unsigned(state, arg, 0))
			return -1;
		if (*state >= 0x100 || (*state&((*state)-1)))
			return -1;
	}
	return 0;
}
예제 #3
0
int parse_one_nh(struct rtattr *rta, struct rtnexthop *rtnh, int *argcp, char *argvp)
{
	int argc = *argcp;
	char *argv = argvp;

	while(++argv, --argc > 0) {
		if(strcmp(argv, "via") == 0) {
			NEXT_ARG();
			rta_addattr32(rta, 4096, RTA_GATEWAY, get_addr32(argv));
			rtnh->rtnh_len += sizeof(struct rtattr) + 4;
		} else if(strcmp(argv, "dev") == 0) {
			NEXT_ARG();
			if((rtnh->rtnh_ifindex = ll_name_to_index(argv)) == 0) {
				fprintf(stderr, "Cannot find device \"%s\"\n", argv);
				exit(1);
			}
		} else if(strcmp(argv, "weight") == 0) {
			unsigned w;
			NEXT_ARG();
			if(get_unsigned(&w, argv, 0) || w == 0 || w > 256) {
				invarg("\"weight\" is invalid\n", argv);
            }
			rtnh->rtnh_hops = w - 1;
		} else if(strcmp(argv, "onlink") == 0) {
			rtnh->rtnh_flags |= RTNH_F_ONLINK;
		} else
			break;
	}
	*argcp = argc;
	argvp = argv;
	return 0;
}
예제 #4
0
static int prio_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
	int ok=0;
	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 }};

	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;
			}
			ok++;
		} else if (strcmp(*argv, "priomap") == 0) {
			if (pmap_mode) {
				fprintf(stderr, "Error: duplicate priomap\n");
				return -1;
			}
			pmap_mode = 1;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			unsigned 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];
	}
*/
	addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
	return 0;
}
예제 #5
0
파일: q_codel.c 프로젝트: AllardJ/Tomato
static int codel_parse_opt(struct qdisc_util *qu, int argc, char **argv,
			   struct nlmsghdr *n)
{
	unsigned limit = 0;
	unsigned target = 0;
	unsigned interval = 0;
	int ecn = -1;
	struct rtattr *tail;

	while (argc > 0) {
		if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_unsigned(&limit, *argv, 0)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "target") == 0) {
			NEXT_ARG();
			if (get_time(&target, *argv)) {
				fprintf(stderr, "Illegal \"target\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "interval") == 0) {
			NEXT_ARG();
			if (get_time(&interval, *argv)) {
				fprintf(stderr, "Illegal \"interval\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "ecn") == 0) {
			ecn = 1;
		} else if (strcmp(*argv, "noecn") == 0) {
			ecn = 0;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	tail = NLMSG_TAIL(n);
	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	if (limit)
		addattr_l(n, 1024, TCA_CODEL_LIMIT, &limit, sizeof(limit));
	if (interval)
		addattr_l(n, 1024, TCA_CODEL_INTERVAL, &interval, sizeof(interval));
	if (target)
		addattr_l(n, 1024, TCA_CODEL_TARGET, &target, sizeof(target));
	if (ecn != -1)
		addattr_l(n, 1024, TCA_CODEL_ECN, &ecn, sizeof(ecn));
	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	return 0;
}
예제 #6
0
파일: mpls.c 프로젝트: MichaelQQ/Quagga-PE
//void
//mpls_parse_label (struct mpls_label *label, int *pargc, char ***pargv) {
int
mpls_parse_label (struct mpls_label *label, int *pargc, char ***pargv) {
	unsigned int l1, l2;
	char *value;
	int argc = *pargc;
	char **argv = *pargv;

	if (strncmp(*argv, "fr", 2) == 0) {
		label->ml_type = MPLS_LABEL_FR;
	} else if (strncmp(*argv, "atm", 3) == 0) {
		label->ml_type = MPLS_LABEL_ATM;
	} else if (strncmp(*argv, "gen", 3) == 0) {
		label->ml_type = MPLS_LABEL_GEN;
	} else {
		invarg(*argv, "invalid mpls label type");
	}

	NEXT_ARG();
	value = *argv;

	switch (label->ml_type) {
		case MPLS_LABEL_GEN:
			if (get_unsigned(&l1, value, 0) || l1 > 1048575)
				invarg(value, "invalid label value");
			label->u.ml_gen = l1;
			break;
		case MPLS_LABEL_ATM:
			if (sscanf(value, "%u/%d", &l1, &l2) != 2)
				invarg(value, "invalid label value");
			label->u.ml_atm.mla_vpi = l1;
			label->u.ml_atm.mla_vci = l2;
		case MPLS_LABEL_FR:
			if (get_unsigned(&l1, value, 0) || l1 > 1023)
				invarg(value, "invalid label value");
			label->u.ml_fr = l1;
		default:
			fprintf(stderr, "Invalid label type!\n");
			//exit(-1);
			return -1;
	}
	*pargc = argc;
	*pargv = argv;
}
예제 #7
0
int get_prefix_1(inet_prefix *dst, char *arg, int family)
{
	int err;
	unsigned plen;
	char *slash;

	memset(dst, 0, sizeof(*dst));

	if (strcmp(arg, "default") == 0 ||
	    strcmp(arg, "any") == 0 ||
	    strcmp(arg, "all") == 0) {
		if (family == AF_DECnet)
			return -1;
		dst->family = family;
		dst->bytelen = 0;
		dst->bitlen = 0;
		return 0;
	}

	slash = strchr(arg, '/');
	if (slash)
		*slash = 0;

	err = get_addr_1(dst, arg, family);
	if (err == 0) {
		switch(dst->family) {
			case AF_INET6:
				dst->bitlen = 128;
				break;
			case AF_DECnet:
				dst->bitlen = 16;
				break;
			default:
			case AF_INET:
				dst->bitlen = 32;
		}
		if (slash) {
			if (get_unsigned(&plen, slash+1, 0) || plen > dst->bitlen) {
				err = -1;
				goto done;
			}
			dst->flags |= PREFIXLEN_SPECIFIED;
			dst->bitlen = plen;
		}
	}
done:
	if (slash)
		*slash = '/';
	return err;
}
예제 #8
0
파일: mpls.c 프로젝트: MichaelQQ/Quagga-PE
int
mpls_labelspace_modify(int cmd, unsigned flags, int argc, char **argv)
{
	__u32 labelspace = -2;
	struct genlmsghdr		*ghdr;
	struct {
		struct nlmsghdr 	n;
		char			buf[4096];
	} req;
	struct mpls_labelspace_req 	ls;

	memset(&req, 0, sizeof(req));
	memset(&ls, 0, sizeof(ls));

	req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
	req.n.nlmsg_flags = NLM_F_REQUEST|flags;
	req.n.nlmsg_type = PF_MPLS;

	ghdr = NLMSG_DATA(&req.n);
	ghdr->cmd = cmd;

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			ls.mls_ifindex = ll_name_to_index(*argv);
		} else if (strcmp(*argv, "labelspace") == 0) {
			NEXT_ARG();
			if (get_unsigned(&labelspace, *argv, 0))
				invarg(*argv, "invalid labelspace");
			ls.mls_labelspace = labelspace;
		} else {
			usage();
		}
		argc--; argv++;
	}

	if (ls.mls_ifindex == 0 || ls.mls_labelspace == -2) {
		fprintf(stderr, "Invalid arguments\n");
		//exit(1);
		return 1;
	}

	addattr_l(&req.n, sizeof(req), MPLS_ATTR_LABELSPACE, &ls, sizeof(ls));

	if (rtnl_talk(&rth2, &req.n, 0, 0, NULL, NULL, NULL) < 0)
		return 2;
		//exit(2);

	return 0;
}
예제 #9
0
static int get_netmask(unsigned *val, const char *arg, int base)
{
	inet_prefix addr;

	if (!get_unsigned(val, arg, base))
		return 0;

	/* try coverting dotted quad to CIDR */
	if (!get_addr_1(&addr, arg, AF_INET) && addr.family == AF_INET) {
		int b = mask2bits(addr.data[0]);
		
		if (b >= 0) {
			*val = b;
			return 0;
		}
	}

	return -1;
}
예제 #10
0
파일: flag_o.c 프로젝트: Radugr7/ls
int		compute_o_flag(va_list *ap, t_arg args)
{
	char	*text;

	if (args.mod_l)
		text = get_unsigned_long(ap, 8, "0123456789");
	else if (args.mod_ll)
		text = get_unsigned_longlong(ap, 8, "0123456789");
	else if (args.mod_hh)
		text = get_unsigned_hh(ap, 8, "0123456789");
	else if (args.mod_h)
		text = get_unsigned_h(ap, 8, "0123456789");
	else if (args.mod_z)
		text = get_unsigned_size_t(ap, 8, "0123456789");
	else if (args.mod_j)
		text = get_unsigned_intmax_t(ap, 8, "0123456789");
	else
		text = get_unsigned(ap, 8, "0123456789");
	return (ft_print_str(text, args, 4));
}
예제 #11
0
파일: mpls.c 프로젝트: MichaelQQ/Quagga-PE
int
mpls_tunnel_modify(int cmd, int argc, char **argv)
{
	unsigned int key = -2;
	struct ifreq ifr;
	int err;
	int fd;

	memset(&ifr, 0, sizeof(ifr));

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			strncpy(ifr.ifr_name, *argv, IFNAMSIZ);
		} else if (strcmp(*argv, "nhlfe") == 0) {
			NEXT_ARG();
			if (get_unsigned(&key, *argv, 0))
				invarg(*argv, "invalid NHLFE key");
			ifr.ifr_ifru.ifru_ivalue = key;
		} else {
			usage();
		}
		argc--; argv++;
	}

	if (!strlen(ifr.ifr_name)) {
		fprintf(stderr, "You must specify a interface name\n");
		//exit(1);
		return 1;
	}

	fd = socket(AF_INET, SOCK_DGRAM, 0);
	err = ioctl(fd, cmd, &ifr);
	if (err)
		perror("ioctl");

	return 0;
}
예제 #12
0
static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm2 *p)
{
	int count = 0;
	char medium[IFNAMSIZ];

	memset(medium, 0, sizeof(medium));

	while (argc > 0) {
		if (strcmp(*argv, "mode") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "ipv6/ipv6") == 0 ||
			    strcmp(*argv, "ip6ip6") == 0)
				p->proto = IPPROTO_IPV6;
			else if (strcmp(*argv, "ip/ipv6") == 0 ||
				 strcmp(*argv, "ipv4/ipv6") == 0 ||
				 strcmp(*argv, "ipip6") == 0 ||
				 strcmp(*argv, "ip4ip6") == 0)
				p->proto = IPPROTO_IPIP;
			else if (strcmp(*argv, "ip6gre") == 0 ||
				 strcmp(*argv, "gre/ipv6") == 0)
				p->proto = IPPROTO_GRE;
			else if (strcmp(*argv, "any/ipv6") == 0 ||
				 strcmp(*argv, "any") == 0)
				p->proto = 0;
			else {
                                fprintf(stderr,"Unknown tunnel mode \"%s\"\n", *argv);
                                exit(-1);
                        }
                } else if (strcmp(*argv, "remote") == 0) {
			inet_prefix raddr;
			NEXT_ARG();
			get_prefix(&raddr, *argv, preferred_family);
			if (raddr.family == AF_UNSPEC)
				invarg("\"remote\" address family is AF_UNSPEC", *argv);
			memcpy(&p->raddr, &raddr.data, sizeof(p->raddr));
		} else if (strcmp(*argv, "local") == 0) {
			inet_prefix laddr;
			NEXT_ARG();
			get_prefix(&laddr, *argv, preferred_family);
			if (laddr.family == AF_UNSPEC)
				invarg("\"local\" address family is AF_UNSPEC", *argv);
			memcpy(&p->laddr, &laddr.data, sizeof(p->laddr));
		} else if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			strncpy(medium, *argv, IFNAMSIZ - 1);
		} else if (strcmp(*argv, "encaplimit") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "none") == 0) {
				p->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT;
			} else {
				__u8 uval;
				if (get_u8(&uval, *argv, 0) < -1)
					invarg("invalid ELIM", *argv);
				p->encap_limit = uval;
				p->flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
			}
		} else if (strcmp(*argv, "hoplimit") == 0 ||
			   strcmp(*argv, "ttl") == 0 ||
			   strcmp(*argv, "hlim") == 0) {
			__u8 uval;
			NEXT_ARG();
			if (get_u8(&uval, *argv, 0))
				invarg("invalid TTL", *argv);
			p->hop_limit = uval;
		} else if (strcmp(*argv, "tclass") == 0 ||
			   strcmp(*argv, "tc") == 0 ||
			   strcmp(*argv, "tos") == 0 ||
			   matches(*argv, "dsfield") == 0) {
			__u8 uval;
			NEXT_ARG();
			p->flowinfo &= ~IP6_FLOWINFO_TCLASS;
			if (strcmp(*argv, "inherit") == 0)
				p->flags |= IP6_TNL_F_USE_ORIG_TCLASS;
			else {
				if (get_u8(&uval, *argv, 16))
					invarg("invalid TClass", *argv);
				p->flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS;
				p->flags &= ~IP6_TNL_F_USE_ORIG_TCLASS;
			}
		} else if (strcmp(*argv, "flowlabel") == 0 ||
			   strcmp(*argv, "fl") == 0) {
			__u32 uval;
			NEXT_ARG();
			p->flowinfo &= ~IP6_FLOWINFO_FLOWLABEL;
			if (strcmp(*argv, "inherit") == 0)
				p->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
			else {
				if (get_u32(&uval, *argv, 16))
					invarg("invalid Flowlabel", *argv);
				if (uval > 0xFFFFF)
					invarg("invalid Flowlabel", *argv);
				p->flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL;
				p->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
			}
		} else if (strcmp(*argv, "dscp") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "inherit") != 0)
				invarg("not inherit", *argv);
			p->flags |= IP6_TNL_F_RCV_DSCP_COPY;
		} 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->i_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, "name") == 0) {
				NEXT_ARG();
			}
			if (matches(*argv, "help") == 0)
				usage();
			if (p->name[0])
				duparg2("name", *argv);
			strncpy(p->name, *argv, IFNAMSIZ - 1);
			if (cmd == SIOCCHGTUNNEL && count == 0) {
				struct ip6_tnl_parm2 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 (medium[0]) {
		p->link = ll_name_to_index(medium);
		if (p->link == 0)
			return -1;
	}
	return 0;
}
예제 #13
0
파일: q_codel.c 프로젝트: dtaht/tc-adv
static int codel_parse_opt(struct qdisc_util *qu, int argc, char **argv,
			   struct nlmsghdr *n, const char *dev)
{
	unsigned int limit = 0;
	unsigned int target = 0;
	unsigned int interval = 0;
	unsigned int ce_threshold = ~0U;
	int ecn = -1;
	struct rtattr *tail;

	while (argc > 0) {
		if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_unsigned(&limit, *argv, 0)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "target") == 0) {
			NEXT_ARG();
			if (get_time(&target, *argv)) {
				fprintf(stderr, "Illegal \"target\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "ce_threshold") == 0) {
			NEXT_ARG();
			if (get_time(&ce_threshold, *argv)) {
				fprintf(stderr, "Illegal \"ce_threshold\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "interval") == 0) {
			NEXT_ARG();
			if (get_time(&interval, *argv)) {
				fprintf(stderr, "Illegal \"interval\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "ecn") == 0) {
			ecn = 1;
		} else if (strcmp(*argv, "noecn") == 0) {
			ecn = 0;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	tail = addattr_nest(n, 1024, TCA_OPTIONS);
	if (limit)
		addattr_l(n, 1024, TCA_CODEL_LIMIT, &limit, sizeof(limit));
	if (interval)
		addattr_l(n, 1024, TCA_CODEL_INTERVAL, &interval, sizeof(interval));
	if (target)
		addattr_l(n, 1024, TCA_CODEL_TARGET, &target, sizeof(target));
	if (ecn != -1)
		addattr_l(n, 1024, TCA_CODEL_ECN, &ecn, sizeof(ecn));
	if (ce_threshold != ~0U)
		addattr_l(n, 1024, TCA_CODEL_CE_THRESHOLD,
			  &ce_threshold, sizeof(ce_threshold));

	addattr_nest_end(n, tail);
	return 0;
}
예제 #14
0
파일: q_red.c 프로젝트: Azzik/iproute2
static int red_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
	struct tc_red_qopt opt;
	unsigned burst = 0;
	unsigned avpkt = 0;
	double probability = 0.02;
	__u64 rate = 0;
	int wlog;
	__u8 sbuf[256];
	__u32 max_P;
	struct rtattr *tail;

	memset(&opt, 0, sizeof(opt));

	while (argc > 0) {
		if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_size(&opt.limit, *argv)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "min") == 0) {
			NEXT_ARG();
			if (get_size(&opt.qth_min, *argv)) {
				fprintf(stderr, "Illegal \"min\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "max") == 0) {
			NEXT_ARG();
			if (get_size(&opt.qth_max, *argv)) {
				fprintf(stderr, "Illegal \"max\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "burst") == 0) {
			NEXT_ARG();
			if (get_unsigned(&burst, *argv, 0)) {
				fprintf(stderr, "Illegal \"burst\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "avpkt") == 0) {
			NEXT_ARG();
			if (get_size(&avpkt, *argv)) {
				fprintf(stderr, "Illegal \"avpkt\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "probability") == 0) {
			NEXT_ARG();
			if (sscanf(*argv, "%lg", &probability) != 1) {
				fprintf(stderr, "Illegal \"probability\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "bandwidth") == 0) {
			NEXT_ARG();
			if (get_rate(&rate, *argv)) {
				fprintf(stderr, "Illegal \"bandwidth\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "ecn") == 0) {
			opt.flags |= TC_RED_ECN;
		} else if (strcmp(*argv, "harddrop") == 0) {
			opt.flags |= TC_RED_HARDDROP;
		} else if (strcmp(*argv, "adaptative") == 0) {
			opt.flags |= TC_RED_ADAPTATIVE;
		} else if (strcmp(*argv, "adaptive") == 0) {
			opt.flags |= TC_RED_ADAPTATIVE;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	if (rate == 0)
		get_rate(&rate, "10Mbit");

	if (!opt.limit || !avpkt) {
		fprintf(stderr, "RED: Required parameter (limit, avpkt) is missing\n");
		return -1;
	}
	/* Compute default min/max thresholds based on
	 * Sally Floyd's recommendations:
	 * http://www.icir.org/floyd/REDparameters.txt
	 */
	if (!opt.qth_max)
		opt.qth_max = opt.qth_min ? opt.qth_min * 3 : opt.limit / 4;
	if (!opt.qth_min)
		opt.qth_min = opt.qth_max / 3;
	if (!burst)
		burst = (2 * opt.qth_min + opt.qth_max) / (3 * avpkt);
	if ((wlog = tc_red_eval_ewma(opt.qth_min, burst, avpkt)) < 0) {
		fprintf(stderr, "RED: failed to calculate EWMA constant.\n");
		return -1;
	}
	if (wlog >= 10)
		fprintf(stderr, "RED: WARNING. Burst %d seems to be too large.\n", burst);
	opt.Wlog = wlog;
	if ((wlog = tc_red_eval_P(opt.qth_min, opt.qth_max, probability)) < 0) {
		fprintf(stderr, "RED: failed to calculate probability.\n");
		return -1;
	}
	opt.Plog = wlog;
	if ((wlog = tc_red_eval_idle_damping(opt.Wlog, avpkt, rate, sbuf)) < 0) {
		fprintf(stderr, "RED: 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_RED_PARMS, &opt, sizeof(opt));
	addattr_l(n, 1024, TCA_RED_STAB, sbuf, 256);
	max_P = probability * pow(2, 32);
	addattr_l(n, 1024, TCA_RED_MAX_P, &max_P, sizeof(max_P));
	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	return 0;
}
예제 #15
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""multicast\0"
		"arp\0""address\0""dev\0";
	enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, 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;
		}
		if (key == ARG_down) {
			mask |= IFF_UP;
			flags &= ~IFF_UP;
		}
		if (key == ARG_name) {
			NEXT_ARG();
			newname = *argv;
		}
		if (key == ARG_mtu) {
			NEXT_ARG();
			if (mtu != -1)
				duparg("mtu", *argv);
			mtu = get_unsigned(*argv, "mtu");
		}
		if (key == ARG_multicast) {
			int param;
			NEXT_ARG();
			mask |= IFF_MULTICAST;
			param = index_in_strings(str_on_off, *argv);
			if (param < 0)
				die_must_be_on_off("multicast");
			if (param == PARM_on)
				flags |= IFF_MULTICAST;
			else
				flags &= ~IFF_MULTICAST;
		}
		if (key == ARG_arp) {
			int param;
			NEXT_ARG();
			mask |= IFF_NOARP;
			param = index_in_strings(str_on_off, *argv);
			if (param < 0)
				die_must_be_on_off("arp");
			if (param == PARM_on)
				flags &= ~IFF_NOARP;
			else
				flags |= IFF_NOARP;
		}
		if (key == ARG_addr) {
			NEXT_ARG();
			newaddr = *argv;
		}
		if (key >= ARG_dev) {
			if (key == ARG_dev) {
				NEXT_ARG();
			}
			if (dev)
				duparg2("dev", *argv);
			dev = *argv;
		}
		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);
		}
		if (newbrd) {
			parse_address(dev, htype, halen, newbrd, &ifr1);
		}
	}

	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 (newaddr || newbrd) {
		if (newbrd) {
			set_address(&ifr1, 1);
		}
		if (newaddr) {
			set_address(&ifr0, 0);
		}
	}
	if (mask)
		do_chflags(dev, flags, mask);
	return 0;
}
예제 #16
0
파일: q_fq.c 프로젝트: eworm-de/iproute2
static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv,
			struct nlmsghdr *n, const char *dev)
{
	unsigned int plimit;
	unsigned int flow_plimit;
	unsigned int quantum;
	unsigned int initial_quantum;
	unsigned int buckets = 0;
	unsigned int maxrate;
	unsigned int low_rate_threshold;
	unsigned int defrate;
	unsigned int refill_delay;
	unsigned int orphan_mask;
	unsigned int ce_threshold;
	bool set_plimit = false;
	bool set_flow_plimit = false;
	bool set_quantum = false;
	bool set_initial_quantum = false;
	bool set_maxrate = false;
	bool set_defrate = false;
	bool set_refill_delay = false;
	bool set_orphan_mask = false;
	bool set_low_rate_threshold = false;
	bool set_ce_threshold = false;
	int pacing = -1;
	struct rtattr *tail;

	while (argc > 0) {
		if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_unsigned(&plimit, *argv, 0)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
			set_plimit = true;
		} else if (strcmp(*argv, "flow_limit") == 0) {
			NEXT_ARG();
			if (get_unsigned(&flow_plimit, *argv, 0)) {
				fprintf(stderr, "Illegal \"flow_limit\"\n");
				return -1;
			}
			set_flow_plimit = true;
		} else if (strcmp(*argv, "buckets") == 0) {
			NEXT_ARG();
			if (get_unsigned(&buckets, *argv, 0)) {
				fprintf(stderr, "Illegal \"buckets\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "maxrate") == 0) {
			NEXT_ARG();
			if (strchr(*argv, '%')) {
				if (get_percent_rate(&maxrate, *argv, dev)) {
					fprintf(stderr, "Illegal \"maxrate\"\n");
					return -1;
				}
			} else if (get_rate(&maxrate, *argv)) {
				fprintf(stderr, "Illegal \"maxrate\"\n");
				return -1;
			}
			set_maxrate = true;
		} else if (strcmp(*argv, "low_rate_threshold") == 0) {
			NEXT_ARG();
			if (get_rate(&low_rate_threshold, *argv)) {
				fprintf(stderr, "Illegal \"low_rate_threshold\"\n");
				return -1;
			}
			set_low_rate_threshold = true;
		} else if (strcmp(*argv, "ce_threshold") == 0) {
			NEXT_ARG();
			if (get_time(&ce_threshold, *argv)) {
				fprintf(stderr, "Illegal \"ce_threshold\"\n");
				return -1;
			}
			set_ce_threshold = true;
		} else if (strcmp(*argv, "defrate") == 0) {
			NEXT_ARG();
			if (strchr(*argv, '%')) {
				if (get_percent_rate(&defrate, *argv, dev)) {
					fprintf(stderr, "Illegal \"defrate\"\n");
					return -1;
				}
			} else if (get_rate(&defrate, *argv)) {
				fprintf(stderr, "Illegal \"defrate\"\n");
				return -1;
			}
			set_defrate = true;
		} else if (strcmp(*argv, "quantum") == 0) {
			NEXT_ARG();
			if (get_unsigned(&quantum, *argv, 0)) {
				fprintf(stderr, "Illegal \"quantum\"\n");
				return -1;
			}
			set_quantum = true;
		} else if (strcmp(*argv, "initial_quantum") == 0) {
			NEXT_ARG();
			if (get_unsigned(&initial_quantum, *argv, 0)) {
				fprintf(stderr, "Illegal \"initial_quantum\"\n");
				return -1;
			}
			set_initial_quantum = true;
		} else if (strcmp(*argv, "orphan_mask") == 0) {
			NEXT_ARG();
			if (get_unsigned(&orphan_mask, *argv, 0)) {
				fprintf(stderr, "Illegal \"initial_quantum\"\n");
				return -1;
			}
			set_orphan_mask = true;
		} else if (strcmp(*argv, "refill_delay") == 0) {
			NEXT_ARG();
			if (get_time(&refill_delay, *argv)) {
				fprintf(stderr, "Illegal \"refill_delay\"\n");
				return -1;
			}
			set_refill_delay = true;
		} else if (strcmp(*argv, "pacing") == 0) {
			pacing = 1;
		} else if (strcmp(*argv, "nopacing") == 0) {
			pacing = 0;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	tail = addattr_nest(n, 1024, TCA_OPTIONS);
	if (buckets) {
		unsigned int log = ilog2(buckets);

		addattr_l(n, 1024, TCA_FQ_BUCKETS_LOG,
			  &log, sizeof(log));
	}
	if (set_plimit)
		addattr_l(n, 1024, TCA_FQ_PLIMIT,
			  &plimit, sizeof(plimit));
	if (set_flow_plimit)
		addattr_l(n, 1024, TCA_FQ_FLOW_PLIMIT,
			  &flow_plimit, sizeof(flow_plimit));
	if (set_quantum)
		addattr_l(n, 1024, TCA_FQ_QUANTUM, &quantum, sizeof(quantum));
	if (set_initial_quantum)
		addattr_l(n, 1024, TCA_FQ_INITIAL_QUANTUM,
			  &initial_quantum, sizeof(initial_quantum));
	if (pacing != -1)
		addattr_l(n, 1024, TCA_FQ_RATE_ENABLE,
			  &pacing, sizeof(pacing));
	if (set_maxrate)
		addattr_l(n, 1024, TCA_FQ_FLOW_MAX_RATE,
			  &maxrate, sizeof(maxrate));
	if (set_low_rate_threshold)
		addattr_l(n, 1024, TCA_FQ_LOW_RATE_THRESHOLD,
			  &low_rate_threshold, sizeof(low_rate_threshold));
	if (set_defrate)
		addattr_l(n, 1024, TCA_FQ_FLOW_DEFAULT_RATE,
			  &defrate, sizeof(defrate));
	if (set_refill_delay)
		addattr_l(n, 1024, TCA_FQ_FLOW_REFILL_DELAY,
			  &refill_delay, sizeof(refill_delay));
	if (set_orphan_mask)
		addattr_l(n, 1024, TCA_FQ_ORPHAN_MASK,
			  &orphan_mask, sizeof(refill_delay));
	if (set_ce_threshold)
		addattr_l(n, 1024, TCA_FQ_CE_THRESHOLD,
			  &ce_threshold, sizeof(ce_threshold));
	addattr_nest_end(n, tail);
	return 0;
}
예제 #17
0
static int xfrm_selector_upspec_parse(struct xfrm_selector *sel,
				      int *argcp, char ***argvp)
{
	int argc = *argcp;
	char **argv = *argvp;
	char *sportp = NULL;
	char *dportp = NULL;
	char *typep = NULL;
	char *codep = NULL;
	char *grekey = NULL;

	while (1) {
		if (strcmp(*argv, "proto") == 0) {
			__u8 upspec;

			NEXT_ARG();

			if (strcmp(*argv, "any") == 0)
				upspec = 0;
			else {
				struct protoent *pp;
				pp = getprotobyname(*argv);
				if (pp)
					upspec = pp->p_proto;
				else {
					if (get_u8(&upspec, *argv, 0))
						invarg("PROTO value is invalid", *argv);
				}
			}
			sel->proto = upspec;

			filter.upspec_proto_mask = XFRM_FILTER_MASK_FULL;

		} else if (strcmp(*argv, "sport") == 0) {
			sportp = *argv;

			NEXT_ARG();

			if (get_u16(&sel->sport, *argv, 0))
				invarg("value after \"sport\" is invalid", *argv);
			sel->sport = htons(sel->sport);
			if (sel->sport)
				sel->sport_mask = ~((__u16)0);

			filter.upspec_sport_mask = XFRM_FILTER_MASK_FULL;

		} else if (strcmp(*argv, "dport") == 0) {
			dportp = *argv;

			NEXT_ARG();

			if (get_u16(&sel->dport, *argv, 0))
				invarg("value after \"dport\" is invalid", *argv);
			sel->dport = htons(sel->dport);
			if (sel->dport)
				sel->dport_mask = ~((__u16)0);

			filter.upspec_dport_mask = XFRM_FILTER_MASK_FULL;

		} else if (strcmp(*argv, "type") == 0) {
			typep = *argv;

			NEXT_ARG();

			if (get_u16(&sel->sport, *argv, 0) ||
			    (sel->sport & ~((__u16)0xff)))
				invarg("value after \"type\" is invalid", *argv);
			sel->sport = htons(sel->sport);
			sel->sport_mask = ~((__u16)0);

			filter.upspec_sport_mask = XFRM_FILTER_MASK_FULL;


		} else if (strcmp(*argv, "code") == 0) {
			codep = *argv;

			NEXT_ARG();

			if (get_u16(&sel->dport, *argv, 0) ||
			    (sel->dport & ~((__u16)0xff)))
				invarg("value after \"code\" is invalid", *argv);
			sel->dport = htons(sel->dport);
			sel->dport_mask = ~((__u16)0);

			filter.upspec_dport_mask = XFRM_FILTER_MASK_FULL;

		} else if (strcmp(*argv, "key") == 0) {
			unsigned uval;

			grekey = *argv;

			NEXT_ARG();

			if (strchr(*argv, '.'))
				uval = htonl(get_addr32(*argv));
			else {
				if (get_unsigned(&uval, *argv, 0)<0) {
					fprintf(stderr, "value after \"key\" is invalid\n");
					exit(-1);
				}
			}

			sel->sport = htons(uval >> 16);
			sel->dport = htons(uval & 0xffff);
			sel->sport_mask = ~((__u16)0);
			sel->dport_mask = ~((__u16)0);

			filter.upspec_dport_mask = XFRM_FILTER_MASK_FULL;

		} else {
예제 #18
0
파일: ip.c 프로젝트: Distrotech/iproute2
int main(int argc, char **argv)
{
	char *basename;
	char *batch_file = NULL;

	basename = strrchr(argv[0], '/');
	if (basename == NULL)
		basename = argv[0];
	else
		basename++;

	while (argc > 1) {
		char *opt = argv[1];
		if (strcmp(opt,"--") == 0) {
			argc--; argv++;
			break;
		}
		if (opt[0] != '-')
			break;
		if (opt[1] == '-')
			opt++;
		if (matches(opt, "-loops") == 0) {
			argc--;
			argv++;
			if (argc <= 1)
				usage();
                        max_flush_loops = atoi(argv[1]);
                } else if (matches(opt, "-family") == 0) {
			argc--;
			argv++;
			if (argc <= 1)
				usage();
			if (strcmp(argv[1], "help") == 0)
				usage();
			else
				preferred_family = read_family(argv[1]);
			if (preferred_family == AF_UNSPEC)
				invarg("invalid protocol family", argv[1]);
		} else if (strcmp(opt, "-4") == 0) {
			preferred_family = AF_INET;
		} else if (strcmp(opt, "-6") == 0) {
			preferred_family = AF_INET6;
		} else if (strcmp(opt, "-0") == 0) {
			preferred_family = AF_PACKET;
		} else if (strcmp(opt, "-I") == 0) {
			preferred_family = AF_IPX;
		} else if (strcmp(opt, "-D") == 0) {
			preferred_family = AF_DECnet;
		} else if (strcmp(opt, "-M") == 0) {
			preferred_family = AF_MPLS;
		} else if (strcmp(opt, "-B") == 0) {
			preferred_family = AF_BRIDGE;
		} else if (matches(opt, "-human") == 0 ||
			   matches(opt, "-human-readable") == 0) {
			++human_readable;
		} else if (matches(opt, "-iec") == 0) {
			++use_iec;
		} else if (matches(opt, "-stats") == 0 ||
			   matches(opt, "-statistics") == 0) {
			++show_stats;
		} else if (matches(opt, "-details") == 0) {
			++show_details;
		} else if (matches(opt, "-resolve") == 0) {
			++resolve_hosts;
		} else if (matches(opt, "-oneline") == 0) {
			++oneline;
		} else if (matches(opt, "-timestamp") == 0) {
			++timestamp;
		} else if (matches(opt, "-tshort") == 0) {
			++timestamp;
			++timestamp_short;
#if 0
		} else if (matches(opt, "-numeric") == 0) {
			rtnl_names_numeric++;
#endif
		} else if (matches(opt, "-Version") == 0) {
			printf("ip utility, iproute2-ss%s\n", SNAPSHOT);
			exit(0);
		} else if (matches(opt, "-force") == 0) {
			++force;
		} else if (matches(opt, "-batch") == 0) {
			argc--;
			argv++;
			if (argc <= 1)
				usage();
			batch_file = argv[1];
		} else if (matches(opt, "-rcvbuf") == 0) {
			unsigned int size;

			argc--;
			argv++;
			if (argc <= 1)
				usage();
			if (get_unsigned(&size, argv[1], 0)) {
				fprintf(stderr, "Invalid rcvbuf size '%s'\n",
					argv[1]);
				exit(-1);
			}
			rcvbuf = size;
		} else if (matches(opt, "-color") == 0) {
			enable_color();
		} else if (matches(opt, "-help") == 0) {
			usage();
		} else if (matches(opt, "-netns") == 0) {
			NEXT_ARG();
			if (netns_switch(argv[1]))
				exit(-1);
		} else if (matches(opt, "-all") == 0) {
			do_all = true;
		} else {
			fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt);
			exit(-1);
		}
		argc--;	argv++;
	}

	_SL_ = oneline ? "\\" : "\n" ;

	if (batch_file)
		return batch(batch_file);

	if (rtnl_open(&rth, 0) < 0)
		exit(1);

	if (strlen(basename) > 2)
		return do_cmd(basename+2, argc, argv);

	if (argc > 1)
		return do_cmd(argv[1], argc-1, argv+1);

	rtnl_close(&rth);
	usage();
}
예제 #19
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", "can't 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");
	}
}
예제 #20
0
static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
{
	int count = 0;
	char medium[IFNAMSIZ];
	int isatap = 0;

	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 if (strcmp(*argv, "isatap") == 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;
				isatap++;
			} else if (strcmp(*argv, "vti") == 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;
				p->i_flags |= VTI_ISVTI;
			} else {
				fprintf(stderr,"Unknown tunnel mode \"%s\"\n", *argv);
				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 for \"key\": \"%s\"; it should be an unsigned integer\n", *argv);
					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->i_key = get_addr32(*argv);
			else {
				if (get_unsigned(&uval, *argv, 0)<0) {
					fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv);
					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 for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv);
					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 ||
			   strcmp(*argv, "hoplimit") == 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 ||
			   strcmp(*argv, "tclass") == 0 ||
			   matches(*argv, "dsfield") == 0) {
			char *dsfield;
			__u32 uval;
			NEXT_ARG();
			dsfield = *argv;
			strsep(&dsfield, "/");
			if (strcmp(*argv, "inherit") != 0) {
				dsfield = *argv;
				p->iph.tos = 0;
			} else
				p->iph.tos = 1;
			if (dsfield) {
				if (rtnl_dsfield_a2n(&uval, dsfield))
					invarg("bad TOS value", *argv);
				p->iph.tos |= uval;
			}
		} else {
			if (strcmp(*argv, "name") == 0) {
				NEXT_ARG();
			} else 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;
		else if (memcmp(p->name, "isatap", 6) == 0) {
			p->iph.protocol = IPPROTO_IPV6;
			isatap++;
		} else if (memcmp(p->name, "vti", 3) == 0) {
			p->iph.protocol = IPPROTO_IPIP;
			p->i_flags |= VTI_ISVTI;
		}
	}

	if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) {
		if (!(p->i_flags & VTI_ISVTI) &&
		    (p->iph.protocol != IPPROTO_GRE)) {
			fprintf(stderr, "Keys are not allowed with ipip and sit tunnels\n");
			return -1;
		}
	}

	if (medium[0]) {
		p->link = if_nametoindex(medium);
		if (p->link == 0) {
			fprintf(stderr, "Cannot find device \"%s\"\n",
				medium);
			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, "A broadcast tunnel requires a source address\n");
		return -1;
	}
	if (isatap)
		p->i_flags |= SIT_ISATAP;

	return 0;
}
예제 #21
0
static int fq_pie_parse_opt(struct qdisc_util *qu, int argc, char **argv,
			      struct nlmsghdr *n)
{
	unsigned limit = 0;
	unsigned flows = 0;
	unsigned target = 0;
	unsigned quantum = 0;
	unsigned tupdate = 0;
	unsigned alpha   = 0;
	unsigned beta    = 0;
	int ecn = -1;
	int bytemode = -1;
	struct rtattr *tail;

	while (argc > 0) {
		if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_unsigned(&limit, *argv, 0)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "flows") == 0) {
			NEXT_ARG();
			if (get_unsigned(&flows, *argv, 0)) {
				fprintf(stderr, "Illegal \"flows\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "quantum") == 0) {
			NEXT_ARG();
			if (get_unsigned(&quantum, *argv, 0)) {
				fprintf(stderr, "Illegal \"quantum\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "target") == 0) {
			NEXT_ARG();
			if (get_time(&target, *argv)) {
				fprintf(stderr, "Illegal \"target\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "tupdate") == 0) {
			NEXT_ARG();
			if (get_time(&tupdate, *argv)) {
				fprintf(stderr, "Illegal \"tupdate\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "alpha") == 0) {
			NEXT_ARG();
			if (get_unsigned(&alpha, *argv, 0) ||
			    (alpha > ALPHA_MAX) || (alpha < ALPHA_MIN)) {
				fprintf(stderr, "Illegal \"alpha\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "beta") == 0) {
			NEXT_ARG();
			if (get_unsigned(&beta, *argv, 0) ||
			    (beta > BETA_MAX) || (beta < BETA_MIN)) {
				fprintf(stderr, "Illegal \"beta\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "ecn") == 0) {
			ecn = 1;
		} else if (strcmp(*argv, "noecn") == 0) {
			ecn = 0;
		} else if (strcmp(*argv, "bytemode") == 0) {
			bytemode = 1;
		} else if (strcmp(*argv, "nobytemode") == 0) {
			bytemode = 0;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--;
		argv++;
	}

	tail = NLMSG_TAIL(n);
	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	if (limit)
		addattr_l(n, 1024, TCA_FQ_PIE_LIMIT, &limit, sizeof(limit));
	if (flows)
		addattr_l(n, 1024, TCA_FQ_PIE_FLOWS, &flows, sizeof(flows));
	if (quantum)
		addattr_l(n, 1024, TCA_FQ_PIE_QUANTUM, &quantum, sizeof(quantum));
	if (tupdate)
		addattr_l(n, 1024, TCA_FQ_PIE_TUPDATE, &tupdate, sizeof(tupdate));
	if (target)
		addattr_l(n, 1024, TCA_FQ_PIE_TARGET, &target, sizeof(target));
	if (alpha)
		addattr_l(n, 1024, TCA_FQ_PIE_ALPHA, &alpha, sizeof(alpha));
	if (beta)
		addattr_l(n, 1024, TCA_FQ_PIE_BETA, &beta, sizeof(beta));
	if (ecn != -1)
		addattr_l(n, 1024, TCA_FQ_PIE_ECN, &ecn, sizeof(ecn));
	if (bytemode != -1)
		addattr_l(n, 1024, TCA_FQ_PIE_BYTEMODE, &bytemode,
			  sizeof(bytemode));
	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	return 0;
}
예제 #22
0
파일: q_gred.c 프로젝트: 6WIND/iproute2
static int init_gred(struct qdisc_util *qu, int argc, char **argv,
		     struct nlmsghdr *n)
{

	struct rtattr *tail;
	struct tc_gred_sopt opt = { 0 };
	__u32 limit = 0;

	opt.def_DP = MAX_DPs;

	while (argc > 0) {
		DPRINTF(stderr, "init_gred: invoked with %s\n", *argv);
		if (strcmp(*argv, "vqs") == 0 ||
		    strcmp(*argv, "DPs") == 0) {
			NEXT_ARG();
			if (get_unsigned(&opt.DPs, *argv, 10)) {
				fprintf(stderr, "Illegal \"vqs\"\n");
				return -1;
			} else if (opt.DPs > MAX_DPs) {
				fprintf(stderr, "GRED: only %u VQs are currently supported\n",
					MAX_DPs);
				return -1;
			}
		} else if (strcmp(*argv, "default") == 0) {
			if (opt.DPs == 0) {
				fprintf(stderr, "\"default\" must be defined after \"vqs\"\n");
				return -1;
			}
			NEXT_ARG();
			if (get_unsigned(&opt.def_DP, *argv, 10)) {
				fprintf(stderr, "Illegal \"default\"\n");
				return -1;
			} else if (opt.def_DP >= opt.DPs) {
				fprintf(stderr, "\"default\" must be less than \"vqs\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "grio") == 0) {
			opt.grio = 1;
		} else if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_size(&limit, *argv)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	if (!opt.DPs || opt.def_DP == MAX_DPs) {
		fprintf(stderr, "Illegal gred setup parameters\n");
		return -1;
	}

	DPRINTF("TC_GRED: sending DPs=%u def_DP=%u\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));
	if (limit)
		addattr32(n, 1024, TCA_GRED_LIMIT, limit);
	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	return 0;
}
예제 #23
0
파일: q_gred.c 프로젝트: 6WIND/iproute2
/*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*/
static int gred_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
	int ok = 0;
	struct tc_gred_qopt opt = { 0 };
	unsigned int burst = 0;
	unsigned int avpkt = 0;
	double probability = 0.02;
	unsigned int rate = 0;
	int parm;
	__u8 sbuf[256];
	struct rtattr *tail;
	__u32 max_P;

	opt.DP = MAX_DPs;

	while (argc > 0) {
		if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_size(&opt.limit, *argv)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "setup") == 0) {
			if (ok) {
				fprintf(stderr, "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)) {
				fprintf(stderr, "Illegal \"min\"\n");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "max") == 0) {
			NEXT_ARG();
			if (get_size(&opt.qth_max, *argv)) {
				fprintf(stderr, "Illegal \"max\"\n");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "vq") == 0 ||
			   strcmp(*argv, "DP") == 0) {
			NEXT_ARG();
			if (get_unsigned(&opt.DP, *argv, 10)) {
				fprintf(stderr, "Illegal \"vq\"\n");
				return -1;
			} else if (opt.DP >= MAX_DPs) {
				fprintf(stderr, "GRED: only %u VQs are currently supported\n",
					MAX_DPs);
				return -1;
			} /* need a better error check */
			ok++;
		} else if (strcmp(*argv, "burst") == 0) {
			NEXT_ARG();
			if (get_unsigned(&burst, *argv, 0)) {
				fprintf(stderr, "Illegal \"burst\"\n");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "avpkt") == 0) {
			NEXT_ARG();
			if (get_size(&avpkt, *argv)) {
				fprintf(stderr, "Illegal \"avpkt\"\n");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "probability") == 0) {
			NEXT_ARG();
			if (sscanf(*argv, "%lg", &probability) != 1) {
				fprintf(stderr, "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)) {
				fprintf(stderr, "Illegal \"bandwidth\"\n");
				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) {
		explain();
		return -1;
	}
	if (opt.DP == MAX_DPs || !opt.limit || !opt.qth_min || !opt.qth_max ||
	    !avpkt) {
		fprintf(stderr, "Required parameter (vq, limit, min, max, avpkt) is missing\n");
		return -1;
	}
	if (!burst) {
		burst = (2 * opt.qth_min + opt.qth_max) / (3 * avpkt);
		fprintf(stderr, "GRED: set burst to %u\n", burst);
	}
	if (!rate) {
		get_rate(&rate, "10Mbit");
		fprintf(stderr, "GRED: set bandwidth to 10Mbit\n");
	}
	if ((parm = tc_red_eval_ewma(opt.qth_min, burst, avpkt)) < 0) {
		fprintf(stderr, "GRED: failed to calculate EWMA constant.\n");
		return -1;
	}
	if (parm >= 10)
		fprintf(stderr, "GRED: WARNING. Burst %u seems to be too large.\n",
		    burst);
	opt.Wlog = parm;
	if ((parm = tc_red_eval_P(opt.qth_min, opt.qth_max, probability)) < 0) {
		fprintf(stderr, "GRED: failed to calculate probability.\n");
		return -1;
	}
	opt.Plog = parm;
	if ((parm = tc_red_eval_idle_damping(opt.Wlog, avpkt, rate, sbuf)) < 0)
	    {
		fprintf(stderr, "GRED: failed to calculate idle damping table.\n");
		return -1;
	}
	opt.Scell_log = parm;

	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);
	max_P = probability * pow(2, 32);
	addattr32(n, 1024, TCA_GRED_MAX_P, max_P);
	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	return 0;
}
예제 #24
0
파일: q_gred.c 프로젝트: NieHao/R7000
/*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*/
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)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "setup") == 0) {
			if (ok) {
				fprintf(stderr, "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)) {
				fprintf(stderr, "Illegal \"min\"\n");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "max") == 0) {
			NEXT_ARG();
			if (get_size(&opt.qth_max, *argv)) {
				fprintf(stderr, "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 */
				fprintf(stderr, "DP =%u \n",opt.DP);
				fprintf(stderr, "Illegal \"DP\"\n");
				fprintf(stderr, "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)) {
				fprintf(stderr, "Illegal \"burst\"\n");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "avpkt") == 0) {
			NEXT_ARG();
			if (get_size(&avpkt, *argv)) {
				fprintf(stderr, "Illegal \"avpkt\"\n");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "probability") == 0) {
			NEXT_ARG();
			if (sscanf(*argv, "%lg", &probability) != 1) {
				fprintf(stderr, "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)) {
				fprintf(stderr, "Illegal \"bandwidth\"\n");
				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 (rate == 0)
		get_rate(&rate, "10Mbit");

	if (!opt.qth_min || !opt.qth_max || !burst || !opt.limit || !avpkt ||
	    (opt.DP<0)) {
		fprintf(stderr, "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) {
		fprintf(stderr, "GRED: failed to calculate EWMA constant.\n");
		return -1;
	}
	if (wlog >= 10)
		fprintf(stderr, "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) {
		fprintf(stderr, "GRED: failed to calculate probability.\n");
		return -1;
	}
	opt.Plog = wlog;
	if ((wlog = tc_red_eval_idle_damping(opt.Wlog, avpkt, rate, sbuf)) < 0)
	    {
		fprintf(stderr, "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;
}
예제 #25
0
파일: m_skbedit.c 프로젝트: dtaht/tc-adv
static int
parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
	      struct nlmsghdr *n)
{
	int argc = *argc_p;
	char **argv = *argv_p;
	int ok = 0;
	struct rtattr *tail;
	unsigned int tmp;
	__u16 queue_mapping, ptype;
	__u32 flags = 0, priority, mark;
	struct tc_skbedit sel = { 0 };

	if (matches(*argv, "skbedit") != 0)
		return -1;

	NEXT_ARG();

	while (argc > 0) {
		if (matches(*argv, "queue_mapping") == 0) {
			flags |= SKBEDIT_F_QUEUE_MAPPING;
			NEXT_ARG();
			if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) {
				fprintf(stderr, "Illegal queue_mapping\n");
				return -1;
			}
			queue_mapping = tmp;
			ok++;
		} else if (matches(*argv, "priority") == 0) {
			flags |= SKBEDIT_F_PRIORITY;
			NEXT_ARG();
			if (get_tc_classid(&priority, *argv)) {
				fprintf(stderr, "Illegal priority\n");
				return -1;
			}
			ok++;
		} else if (matches(*argv, "mark") == 0) {
			flags |= SKBEDIT_F_MARK;
			NEXT_ARG();
			if (get_u32(&mark, *argv, 0)) {
				fprintf(stderr, "Illegal mark\n");
				return -1;
			}
			ok++;
		} else if (matches(*argv, "ptype") == 0) {

			NEXT_ARG();
			if (matches(*argv, "host") == 0) {
				ptype = PACKET_HOST;
			} else if (matches(*argv, "broadcast") == 0) {
				ptype = PACKET_BROADCAST;
			} else if (matches(*argv, "multicast") == 0) {
				ptype = PACKET_MULTICAST;
			} else if (matches(*argv, "otherhost") == 0) {
				ptype = PACKET_OTHERHOST;
			} else {
				fprintf(stderr, "Illegal ptype (%s)\n",
					*argv);
				return -1;
			}
			flags |= SKBEDIT_F_PTYPE;
			ok++;
		} else if (matches(*argv, "help") == 0) {
			usage();
		} else {
			break;
		}
		argc--;
		argv++;
	}

	parse_action_control_dflt(&argc, &argv, &sel.action,
				  false, TC_ACT_PIPE);

	if (argc) {
		if (matches(*argv, "index") == 0) {
			NEXT_ARG();
			if (get_u32(&sel.index, *argv, 10)) {
				fprintf(stderr, "Pedit: Illegal \"index\"\n");
				return -1;
			}
			argc--;
			argv++;
			ok++;
		}
	}

	if (!ok) {
		explain();
		return -1;
	}


	tail = addattr_nest(n, MAX_MSG, tca_id);
	addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel));
	if (flags & SKBEDIT_F_QUEUE_MAPPING)
		addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING,
			  &queue_mapping, sizeof(queue_mapping));
	if (flags & SKBEDIT_F_PRIORITY)
		addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY,
			  &priority, sizeof(priority));
	if (flags & SKBEDIT_F_MARK)
		addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK,
			  &mark, sizeof(mark));
	if (flags & SKBEDIT_F_PTYPE)
		addattr_l(n, MAX_MSG, TCA_SKBEDIT_PTYPE,
			  &ptype, sizeof(ptype));
	addattr_nest_end(n, tail);

	*argc_p = argc;
	*argv_p = argv;
	return 0;
}
예제 #26
0
int main(int argc, char **argv)
{
	char *basename;

	basename = strrchr(argv[0], '/');
	if (basename == NULL)
		basename = argv[0];
	else
		basename++;

	while (argc > 1) {
		char *opt = argv[1];
		if (strcmp(opt,"--") == 0) {
			argc--; argv++;
			break;
		}
		if (opt[0] != '-')
			break;
		if (opt[1] == '-')
			opt++;
		if (matches(opt, "-family") == 0) {
			argc--;
			argv++;
			if (argc <= 1)
				usage();
			if (strcmp(argv[1], "inet") == 0)
				preferred_family = AF_INET;
			else if (strcmp(argv[1], "inet6") == 0)
				preferred_family = AF_INET6;
			else if (strcmp(argv[1], "dnet") == 0)
				preferred_family = AF_DECnet;
			else if (strcmp(argv[1], "link") == 0)
				preferred_family = AF_PACKET;
			else if (strcmp(argv[1], "ipx") == 0)
				preferred_family = AF_IPX;
			else if (strcmp(argv[1], "help") == 0)
				usage();
			else
				invarg(argv[1], "invalid protocol family");
		} else if (strcmp(opt, "-4") == 0) {
			preferred_family = AF_INET;
		} else if (strcmp(opt, "-6") == 0) {
			preferred_family = AF_INET6;
		} else if (strcmp(opt, "-0") == 0) {
			preferred_family = AF_PACKET;
		} else if (strcmp(opt, "-I") == 0) {
			preferred_family = AF_IPX;
		} else if (strcmp(opt, "-D") == 0) {
			preferred_family = AF_DECnet;
		} else if (matches(opt, "-stats") == 0 ||
			   matches(opt, "-statistics") == 0) {
			++show_stats;
		} else if (matches(opt, "-details") == 0) {
			++show_details;
		} else if (matches(opt, "-resolve") == 0) {
			++resolve_hosts;
		} else if (matches(opt, "-oneline") == 0) {
			++oneline;
		} else if (matches(opt, "-timestamp") == 0) {
			++timestamp;
#if 0
		} else if (matches(opt, "-numeric") == 0) {
			rtnl_names_numeric++;
#endif
		} else if (matches(opt, "-Version") == 0) {
			printf("ip utility, iproute2-ss%s\n", SNAPSHOT);
			exit(0);
#ifndef ANDROID
		} else if (matches(opt, "-force") == 0) {
			++force;
		} else if (matches(opt, "-batch") == 0) {
			argc--;
			argv++;
			if (argc <= 1)
				usage();
			batch_file = argv[1];
#endif
		} else if (matches(opt, "-rcvbuf") == 0) {
			unsigned int size;

			argc--;
			argv++;
			if (argc <= 1)
				usage();
			if (get_unsigned(&size, argv[1], 0)) {
				fprintf(stderr, "Invalid rcvbuf size '%s'\n",
					argv[1]);
				exit(-1);
			}
			rcvbuf = size;
		} else if (matches(opt, "-help") == 0) {
			usage();
		} else {
			fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt);
			exit(-1);
		}
		argc--;	argv++;
	}

	_SL_ = oneline ? "\\" : "\n" ;

#ifndef ANDROID
	if (batch_file)
		return batch(batch_file);
#endif

	if (rtnl_open(&rth, 0) < 0)
		exit(1);

	if (strlen(basename) > 2)
		return do_cmd(basename+2, argc, argv);

	if (argc > 1)
		return do_cmd(argv[1], argc-1, argv+1);

	rtnl_close(&rth);
	usage();
}
예제 #27
0
static int rsvp_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
{
    int family = strcmp(qu->id, "rsvp") == 0 ? AF_INET : AF_INET6;
    struct tc_rsvp_pinfo pinfo;
    struct tc_police tp;
    struct tcmsg *t = NLMSG_DATA(n);
    int pinfo_ok = 0;
    struct rtattr *tail;

    memset(&pinfo, 0, sizeof(pinfo));
    memset(&tp, 0, sizeof(tp));

    if (handle) {
        if (get_u32(&t->tcm_handle, handle, 0)) {
            my_printf("Illegal \"handle\"\n");
            return -1;
        }
    }

    if (argc == 0)
        return 0;

    tail = NLMSG_TAIL(n);
    addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);

    while (argc > 0) {
        if (matches(*argv, "session") == 0) {
            inet_prefix addr;
            NEXT_ARG();
            if (get_addr_and_pi(&argc, &argv, &addr, &pinfo, 1, family)) {
                my_printf("Illegal \"session\"\n");
                return -1;
            }
            addattr_l(n, 4096, TCA_RSVP_DST, &addr.data, addr.bytelen);
            if (pinfo.dpi.mask || pinfo.protocol)
                pinfo_ok++;
            continue;
        } else if (matches(*argv, "sender") == 0 ||
                   matches(*argv, "flowspec") == 0) {
            inet_prefix addr;
            NEXT_ARG();
            if (get_addr_and_pi(&argc, &argv, &addr, &pinfo, 0, family)) {
                my_printf("Illegal \"sender\"\n");
                return -1;
            }
            addattr_l(n, 4096, TCA_RSVP_SRC, &addr.data, addr.bytelen);
            if (pinfo.spi.mask || pinfo.protocol)
                pinfo_ok++;
            continue;
        } else if (matches("ipproto", *argv) == 0) {
            int num;
            NEXT_ARG();
            num = inet_proto_a2n(*argv);
            if (num < 0) {
                my_printf("Illegal \"ipproto\"\n");
                return -1;
            }
            pinfo.protocol = num;
            pinfo_ok++;
        } else if (matches(*argv, "classid") == 0 ||
                   strcmp(*argv, "flowid") == 0) {
            unsigned handle;
            NEXT_ARG();
            if (get_tc_classid(&handle, *argv)) {
                my_printf("Illegal \"classid\"\n");
                return -1;
            }
            addattr_l(n, 4096, TCA_RSVP_CLASSID, &handle, 4);
        } else if (strcmp(*argv, "tunnelid") == 0) {
            unsigned tid;
            NEXT_ARG();
            if (get_unsigned(&tid, *argv, 0)) {
                my_printf("Illegal \"tunnelid\"\n");
                return -1;
            }
            pinfo.tunnelid = tid;
            pinfo_ok++;
        } else if (strcmp(*argv, "tunnel") == 0) {
            unsigned tid;
            NEXT_ARG();
            if (get_unsigned(&tid, *argv, 0)) {
                my_printf("Illegal \"tunnel\"\n");
                return -1;
            }
            addattr_l(n, 4096, TCA_RSVP_CLASSID, &tid, 4);
            NEXT_ARG();
            if (strcmp(*argv, "skip") == 0) {
                NEXT_ARG();
            }
            if (get_unsigned(&tid, *argv, 0)) {
                my_printf("Illegal \"skip\"\n");
                return -1;
            }
            pinfo.tunnelhdr = tid;
            pinfo_ok++;
        } else if (matches(*argv, "police") == 0) {
            NEXT_ARG();
            if (parse_police(&argc, &argv, TCA_RSVP_POLICE, n)) {
                my_printf("Illegal \"police\"\n");
                return -1;
            }
            continue;
        } else if (strcmp(*argv, "help") == 0) {
            explain();
            return -1;
        } else {
            my_printf("What is \"%s\"?\n", *argv);
            explain();
            return -1;
        }
        argc--;
        argv++;
    }

    if (pinfo_ok)
        addattr_l(n, 4096, TCA_RSVP_PINFO, &pinfo, sizeof(pinfo));
    tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
    return 0;
}
예제 #28
0
static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
			   struct iplink_req *req, int dev_index)
{
	char new_rate_api = 0, count = 0, override_legacy_rate = 0;
	struct ifla_vf_rate tivt;
	int len, argc = *argcp;
	char **argv = *argvp;
	struct rtattr *vfinfo;

	tivt.min_tx_rate = -1;
	tivt.max_tx_rate = -1;

	vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);

	while (NEXT_ARG_OK()) {
		NEXT_ARG();
		count++;
		if (!matches(*argv, "max_tx_rate")) {
			/* new API in use */
			new_rate_api = 1;
			/* override legacy rate */
			override_legacy_rate = 1;
		} else if (!matches(*argv, "min_tx_rate")) {
			/* new API in use */
			new_rate_api = 1;
		}
	}

	while (count--) {
		/* rewind arg */
		PREV_ARG();
	}

	while (NEXT_ARG_OK()) {
		NEXT_ARG();
		if (matches(*argv, "mac") == 0) {
			struct ifla_vf_mac ivm;
			NEXT_ARG();
			ivm.vf = vf;
			len = ll_addr_a2n((char *)ivm.mac, 32, *argv);
			if (len < 0)
				return -1;
			addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm, sizeof(ivm));
		} else if (matches(*argv, "vlan") == 0) {
			struct ifla_vf_vlan ivv;
			NEXT_ARG();
			if (get_unsigned(&ivv.vlan, *argv, 0)) {
				invarg("Invalid \"vlan\" value\n", *argv);
			}
			ivv.vf = vf;
			ivv.qos = 0;
			if (NEXT_ARG_OK()) {
				NEXT_ARG();
				if (matches(*argv, "qos") == 0) {
					NEXT_ARG();
					if (get_unsigned(&ivv.qos, *argv, 0)) {
						invarg("Invalid \"qos\" value\n", *argv);
					}
				} else {
					/* rewind arg */
					PREV_ARG();
				}
			}
			addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv, sizeof(ivv));
		} else if (matches(*argv, "rate") == 0) {
			struct ifla_vf_tx_rate ivt;
			NEXT_ARG();
			if (get_unsigned(&ivt.rate, *argv, 0)) {
				invarg("Invalid \"rate\" value\n", *argv);
			}
			ivt.vf = vf;
			if (!new_rate_api)
				addattr_l(&req->n, sizeof(*req),
					  IFLA_VF_TX_RATE, &ivt, sizeof(ivt));
			else if (!override_legacy_rate)
				tivt.max_tx_rate = ivt.rate;

		} else if (matches(*argv, "max_tx_rate") == 0) {
			NEXT_ARG();
			if (get_unsigned(&tivt.max_tx_rate, *argv, 0))
				invarg("Invalid \"max tx rate\" value\n",
				       *argv);
			tivt.vf = vf;

		} else if (matches(*argv, "min_tx_rate") == 0) {
			NEXT_ARG();
			if (get_unsigned(&tivt.min_tx_rate, *argv, 0))
				invarg("Invalid \"min tx rate\" value\n",
				       *argv);
			tivt.vf = vf;

		} else if (matches(*argv, "spoofchk") == 0) {
			struct ifla_vf_spoofchk ivs;
			NEXT_ARG();
			if (matches(*argv, "on") == 0)
				ivs.setting = 1;
			else if (matches(*argv, "off") == 0)
				ivs.setting = 0;
			else
				invarg("Invalid \"spoofchk\" value\n", *argv);
			ivs.vf = vf;
			addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs));

		} else if (matches(*argv, "state") == 0) {
			struct ifla_vf_link_state ivl;
			NEXT_ARG();
			if (matches(*argv, "auto") == 0)
				ivl.link_state = IFLA_VF_LINK_STATE_AUTO;
			else if (matches(*argv, "enable") == 0)
				ivl.link_state = IFLA_VF_LINK_STATE_ENABLE;
			else if (matches(*argv, "disable") == 0)
				ivl.link_state = IFLA_VF_LINK_STATE_DISABLE;
			else
				invarg("Invalid \"state\" value\n", *argv);
			ivl.vf = vf;
			addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE, &ivl, sizeof(ivl));
		} else {
			/* rewind arg */
			PREV_ARG();
			break;
		}
	}

	if (new_rate_api) {
		int tmin, tmax;

		if (tivt.min_tx_rate == -1 || tivt.max_tx_rate == -1) {
			ipaddr_get_vf_rate(tivt.vf, &tmin, &tmax, dev_index);
			if (tivt.min_tx_rate == -1)
				tivt.min_tx_rate = tmin;
			if (tivt.max_tx_rate == -1)
				tivt.max_tx_rate = tmax;
		}
		addattr_l(&req->n, sizeof(*req), IFLA_VF_RATE, &tivt,
			  sizeof(tivt));
	}

	if (argc == *argcp)
		incomplete_command();

	addattr_nest_end(&req->n, vfinfo);

	*argcp = argc;
	*argvp = argv;
	return 0;
}
예제 #29
0
파일: link_gre6.c 프로젝트: AllardJ/Tomato
static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
			 struct nlmsghdr *n)
{
	struct {
		struct nlmsghdr n;
		struct ifinfomsg i;
		char buf[1024];
	} req;
	struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
	struct rtattr *tb[IFLA_MAX + 1];
	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
	struct rtattr *greinfo[IFLA_GRE_MAX + 1];
	__u16 iflags = 0;
	__u16 oflags = 0;
	unsigned ikey = 0;
	unsigned okey = 0;
	struct in6_addr raddr = IN6ADDR_ANY_INIT;
	struct in6_addr laddr = IN6ADDR_ANY_INIT;
	unsigned link = 0;
	unsigned flowinfo = 0;
	unsigned flags = 0;
	__u8 hop_limit = DEFAULT_TNL_HOP_LIMIT;
	__u8 encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
	int len;

	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
		memset(&req, 0, sizeof(req));

		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
		req.n.nlmsg_flags = NLM_F_REQUEST;
		req.n.nlmsg_type = RTM_GETLINK;
		req.i.ifi_family = preferred_family;
		req.i.ifi_index = ifi->ifi_index;

		if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
get_failed:
			fprintf(stderr,
				"Failed to get existing tunnel info.\n");
			return -1;
		}

		len = req.n.nlmsg_len;
		len -= NLMSG_LENGTH(sizeof(*ifi));
		if (len < 0)
			goto get_failed;

		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);

		if (!tb[IFLA_LINKINFO])
			goto get_failed;

		parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);

		if (!linkinfo[IFLA_INFO_DATA])
			goto get_failed;

		parse_rtattr_nested(greinfo, IFLA_GRE_MAX,
				    linkinfo[IFLA_INFO_DATA]);

		if (greinfo[IFLA_GRE_IKEY])
			ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]);

		if (greinfo[IFLA_GRE_OKEY])
			okey = rta_getattr_u32(greinfo[IFLA_GRE_OKEY]);

		if (greinfo[IFLA_GRE_IFLAGS])
			iflags = rta_getattr_u16(greinfo[IFLA_GRE_IFLAGS]);

		if (greinfo[IFLA_GRE_OFLAGS])
			oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]);

		if (greinfo[IFLA_GRE_LOCAL])
			memcpy(&laddr, RTA_DATA(greinfo[IFLA_GRE_LOCAL]), sizeof(laddr));

		if (greinfo[IFLA_GRE_REMOTE])
			memcpy(&raddr, RTA_DATA(greinfo[IFLA_GRE_REMOTE]), sizeof(raddr));

		if (greinfo[IFLA_GRE_TTL])
			hop_limit = rta_getattr_u8(greinfo[IFLA_GRE_TTL]);

		if (greinfo[IFLA_GRE_LINK])
			link = rta_getattr_u32(greinfo[IFLA_GRE_LINK]);

		if (greinfo[IFLA_GRE_ENCAP_LIMIT])
			encap_limit = rta_getattr_u8(greinfo[IFLA_GRE_ENCAP_LIMIT]);

		if (greinfo[IFLA_GRE_FLOWINFO])
			flowinfo = rta_getattr_u32(greinfo[IFLA_GRE_FLOWINFO]);

		if (greinfo[IFLA_GRE_FLAGS])
			flags = rta_getattr_u32(greinfo[IFLA_GRE_FLAGS]);
	}

	while (argc > 0) {
		if (!matches(*argv, "key")) {
			unsigned uval;

			NEXT_ARG();
			iflags |= GRE_KEY;
			oflags |= GRE_KEY;
			if (strchr(*argv, '.'))
				uval = get_addr32(*argv);
			else {
				if (get_unsigned(&uval, *argv, 0) < 0) {
					fprintf(stderr,
						"Invalid value for \"key\"\n");
					exit(-1);
				}
				uval = htonl(uval);
			}

			ikey = okey = uval;
		} else if (!matches(*argv, "ikey")) {
			unsigned uval;

			NEXT_ARG();
			iflags |= GRE_KEY;
			if (strchr(*argv, '.'))
				uval = get_addr32(*argv);
			else {
				if (get_unsigned(&uval, *argv, 0)<0) {
					fprintf(stderr, "invalid value of \"ikey\"\n");
					exit(-1);
				}
				uval = htonl(uval);
			}
			ikey = uval;
		} else if (!matches(*argv, "okey")) {
			unsigned uval;

			NEXT_ARG();
			oflags |= GRE_KEY;
			if (strchr(*argv, '.'))
				uval = get_addr32(*argv);
			else {
				if (get_unsigned(&uval, *argv, 0)<0) {
					fprintf(stderr, "invalid value of \"okey\"\n");
					exit(-1);
				}
				uval = htonl(uval);
			}
			okey = uval;
		} else if (!matches(*argv, "seq")) {
			iflags |= GRE_SEQ;
			oflags |= GRE_SEQ;
		} else if (!matches(*argv, "iseq")) {
			iflags |= GRE_SEQ;
		} else if (!matches(*argv, "oseq")) {
			oflags |= GRE_SEQ;
		} else if (!matches(*argv, "csum")) {
			iflags |= GRE_CSUM;
			oflags |= GRE_CSUM;
		} else if (!matches(*argv, "icsum")) {
			iflags |= GRE_CSUM;
		} else if (!matches(*argv, "ocsum")) {
			oflags |= GRE_CSUM;
		} else if (!matches(*argv, "remote")) {
			inet_prefix addr;
			NEXT_ARG();
			get_prefix(&addr, *argv, preferred_family);
			if (addr.family == AF_UNSPEC)
				invarg("\"remote\" address family is AF_UNSPEC", *argv);
			memcpy(&raddr, &addr.data, sizeof(raddr));
		} else if (!matches(*argv, "local")) {
			inet_prefix addr;
			NEXT_ARG();
			get_prefix(&addr, *argv, preferred_family);
			if (addr.family == AF_UNSPEC)
				invarg("\"local\" address family is AF_UNSPEC", *argv);
			memcpy(&laddr, &addr.data, sizeof(laddr));
		} else if (!matches(*argv, "dev")) {
			NEXT_ARG();
			link = if_nametoindex(*argv);
			if (link == 0) {
				fprintf(stderr, "Cannot find device \"%s\"\n",
					*argv);
				exit(-1);
			}
		} else if (!matches(*argv, "ttl") ||
			   !matches(*argv, "hoplimit")) {
			__u8 uval;
			NEXT_ARG();
			if (get_u8(&uval, *argv, 0))
				invarg("invalid TTL", *argv);
			hop_limit = uval;
		} else if (!matches(*argv, "tos") ||
			   !matches(*argv, "tclass") ||
			   !matches(*argv, "dsfield")) {
			__u8 uval;
			NEXT_ARG();
			if (strcmp(*argv, "inherit") == 0)
				flags |= IP6_TNL_F_USE_ORIG_TCLASS;
			else {
				if (get_u8(&uval, *argv, 16))
					invarg("invalid TClass", *argv);
				flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS;
				flags &= ~IP6_TNL_F_USE_ORIG_TCLASS;
			}
		} else if (strcmp(*argv, "flowlabel") == 0 ||
			   strcmp(*argv, "fl") == 0) {
			__u32 uval;
			NEXT_ARG();
			if (strcmp(*argv, "inherit") == 0)
				flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
			else {
				if (get_u32(&uval, *argv, 16))
					invarg("invalid Flowlabel", *argv);
				if (uval > 0xFFFFF)
					invarg("invalid Flowlabel", *argv);
				flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL;
				flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
			}
		} else if (strcmp(*argv, "dscp") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "inherit") != 0)
				invarg("not inherit", *argv);
			flags |= IP6_TNL_F_RCV_DSCP_COPY;
		} else
			usage();
		argc--; argv++;
	}

	addattr32(n, 1024, IFLA_GRE_IKEY, ikey);
	addattr32(n, 1024, IFLA_GRE_OKEY, okey);
	addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2);
	addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2);
	addattr_l(n, 1024, IFLA_GRE_LOCAL, &laddr, sizeof(laddr));
	addattr_l(n, 1024, IFLA_GRE_REMOTE, &raddr, sizeof(raddr));
	if (link)
		addattr32(n, 1024, IFLA_GRE_LINK, link);
	addattr_l(n, 1024, IFLA_GRE_TTL, &hop_limit, 1);
	addattr_l(n, 1024, IFLA_GRE_ENCAP_LIMIT, &encap_limit, 1);
	addattr_l(n, 1024, IFLA_GRE_FLOWINFO, &flowinfo, 4);
	addattr_l(n, 1024, IFLA_GRE_FLAGS, &flowinfo, 4);

	return 0;
}
예제 #30
0
static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
			 struct nlmsghdr *n)
{
	struct {
		struct nlmsghdr n;
		struct ifinfomsg i;
		char buf[16384];
	} req;
	struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
	struct rtattr *tb[IFLA_MAX + 1];
	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
	struct rtattr *greinfo[IFLA_GRE_MAX + 1];
	__u16 iflags = 0;
	__u16 oflags = 0;
	unsigned ikey = 0;
	unsigned okey = 0;
	unsigned saddr = 0;
	unsigned daddr = 0;
	unsigned link = 0;
	__u8 pmtudisc = 1;
	__u8 ttl = 0;
	__u8 tos = 0;
	int len;
	__u16 encaptype = 0;
	__u16 encapflags = 0;
	__u16 encapsport = 0;
	__u16 encapdport = 0;

	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
		memset(&req, 0, sizeof(req));

		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
		req.n.nlmsg_flags = NLM_F_REQUEST;
		req.n.nlmsg_type = RTM_GETLINK;
		req.i.ifi_family = preferred_family;
		req.i.ifi_index = ifi->ifi_index;

		if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
get_failed:
			fprintf(stderr,
				"Failed to get existing tunnel info.\n");
			return -1;
		}

		len = req.n.nlmsg_len;
		len -= NLMSG_LENGTH(sizeof(*ifi));
		if (len < 0)
			goto get_failed;

		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);

		if (!tb[IFLA_LINKINFO])
			goto get_failed;

		parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);

		if (!linkinfo[IFLA_INFO_DATA])
			goto get_failed;

		parse_rtattr_nested(greinfo, IFLA_GRE_MAX,
				    linkinfo[IFLA_INFO_DATA]);

		if (greinfo[IFLA_GRE_IKEY])
			ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]);

		if (greinfo[IFLA_GRE_OKEY])
			okey = rta_getattr_u32(greinfo[IFLA_GRE_OKEY]);

		if (greinfo[IFLA_GRE_IFLAGS])
			iflags = rta_getattr_u16(greinfo[IFLA_GRE_IFLAGS]);

		if (greinfo[IFLA_GRE_OFLAGS])
			oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]);

		if (greinfo[IFLA_GRE_LOCAL])
			saddr = rta_getattr_u32(greinfo[IFLA_GRE_LOCAL]);

		if (greinfo[IFLA_GRE_REMOTE])
			daddr = rta_getattr_u32(greinfo[IFLA_GRE_REMOTE]);

		if (greinfo[IFLA_GRE_PMTUDISC])
			pmtudisc = rta_getattr_u8(
				greinfo[IFLA_GRE_PMTUDISC]);

		if (greinfo[IFLA_GRE_TTL])
			ttl = rta_getattr_u8(greinfo[IFLA_GRE_TTL]);

		if (greinfo[IFLA_GRE_TOS])
			tos = rta_getattr_u8(greinfo[IFLA_GRE_TOS]);

		if (greinfo[IFLA_GRE_LINK])
			link = rta_getattr_u8(greinfo[IFLA_GRE_LINK]);

		if (greinfo[IFLA_GRE_ENCAP_TYPE])
			encaptype = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_TYPE]);
		if (greinfo[IFLA_GRE_ENCAP_FLAGS])
			encapflags = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_FLAGS]);
		if (greinfo[IFLA_GRE_ENCAP_SPORT])
			encapsport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_SPORT]);
		if (greinfo[IFLA_GRE_ENCAP_DPORT])
			encapdport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_DPORT]);
	}

	while (argc > 0) {
		if (!matches(*argv, "key")) {
			unsigned uval;

			NEXT_ARG();
			iflags |= GRE_KEY;
			oflags |= GRE_KEY;
			if (strchr(*argv, '.'))
				uval = get_addr32(*argv);
			else {
				if (get_unsigned(&uval, *argv, 0) < 0) {
					fprintf(stderr,
						"Invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv);
					exit(-1);
				}
				uval = htonl(uval);
			}

			ikey = okey = uval;
		} else if (!matches(*argv, "ikey")) {
			unsigned uval;

			NEXT_ARG();
			iflags |= GRE_KEY;
			if (strchr(*argv, '.'))
				uval = get_addr32(*argv);
			else {
				if (get_unsigned(&uval, *argv, 0)<0) {
					fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv);
					exit(-1);
				}
				uval = htonl(uval);
			}
			ikey = uval;
		} else if (!matches(*argv, "okey")) {
			unsigned uval;

			NEXT_ARG();
			oflags |= GRE_KEY;
			if (strchr(*argv, '.'))
				uval = get_addr32(*argv);
			else {
				if (get_unsigned(&uval, *argv, 0)<0) {
					fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv);
					exit(-1);
				}
				uval = htonl(uval);
			}
			okey = uval;
		} else if (!matches(*argv, "seq")) {
			iflags |= GRE_SEQ;
			oflags |= GRE_SEQ;
		} else if (!matches(*argv, "iseq")) {
			iflags |= GRE_SEQ;
		} else if (!matches(*argv, "oseq")) {
			oflags |= GRE_SEQ;
		} else if (!matches(*argv, "csum")) {
			iflags |= GRE_CSUM;
			oflags |= GRE_CSUM;
		} else if (!matches(*argv, "icsum")) {
			iflags |= GRE_CSUM;
		} else if (!matches(*argv, "ocsum")) {
			oflags |= GRE_CSUM;
		} else if (!matches(*argv, "nopmtudisc")) {
			pmtudisc = 0;
		} else if (!matches(*argv, "pmtudisc")) {
			pmtudisc = 1;
		} else if (!matches(*argv, "remote")) {
			NEXT_ARG();
			if (strcmp(*argv, "any"))
				daddr = get_addr32(*argv);
		} else if (!matches(*argv, "local")) {
			NEXT_ARG();
			if (strcmp(*argv, "any"))
				saddr = get_addr32(*argv);
		} else if (!matches(*argv, "dev")) {
			NEXT_ARG();
			link = if_nametoindex(*argv);
			if (link == 0) {
				fprintf(stderr, "Cannot find device \"%s\"\n",
					*argv);
				exit(-1);
			}
		} else if (!matches(*argv, "ttl") ||
			   !matches(*argv, "hoplimit")) {
			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);
				ttl = uval;
			}
		} else if (!matches(*argv, "tos") ||
			   !matches(*argv, "tclass") ||
			   !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 (strcmp(*argv, "noencap") == 0) {
			encaptype = TUNNEL_ENCAP_NONE;
		} else if (strcmp(*argv, "encap") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "fou") == 0)
				encaptype = TUNNEL_ENCAP_FOU;
			else if (strcmp(*argv, "gue") == 0)
				encaptype = TUNNEL_ENCAP_GUE;
			else if (strcmp(*argv, "none") == 0)
				encaptype = TUNNEL_ENCAP_NONE;
			else
				invarg("Invalid encap type.", *argv);
		} else if (strcmp(*argv, "encap-sport") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "auto") == 0)
				encapsport = 0;
			else if (get_u16(&encapsport, *argv, 0))
				invarg("Invalid source port.", *argv);
		} else if (strcmp(*argv, "encap-dport") == 0) {
			NEXT_ARG();
			if (get_u16(&encapdport, *argv, 0))
				invarg("Invalid destination port.", *argv);
		} else if (strcmp(*argv, "encap-csum") == 0) {
			encapflags |= TUNNEL_ENCAP_FLAG_CSUM;
		} else if (strcmp(*argv, "noencap-csum") == 0) {
			encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM;
		} else if (strcmp(*argv, "encap-udp6-csum") == 0) {
			encapflags |= TUNNEL_ENCAP_FLAG_CSUM6;
		} else if (strcmp(*argv, "noencap-udp6-csum") == 0) {
			encapflags |= ~TUNNEL_ENCAP_FLAG_CSUM6;
		} else if (strcmp(*argv, "encap-remcsum") == 0) {
			encapflags |= TUNNEL_ENCAP_FLAG_REMCSUM;
		} else if (strcmp(*argv, "noencap-remcsum") == 0) {
			encapflags |= ~TUNNEL_ENCAP_FLAG_REMCSUM;
		} else
			usage();
		argc--; argv++;
	}

	if (!ikey && IN_MULTICAST(ntohl(daddr))) {
		ikey = daddr;
		iflags |= GRE_KEY;
	}
	if (!okey && IN_MULTICAST(ntohl(daddr))) {
		okey = daddr;
		oflags |= GRE_KEY;
	}
	if (IN_MULTICAST(ntohl(daddr)) && !saddr) {
		fprintf(stderr, "A broadcast tunnel requires a source address.\n");
		return -1;
	}

	addattr32(n, 1024, IFLA_GRE_IKEY, ikey);
	addattr32(n, 1024, IFLA_GRE_OKEY, okey);
	addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2);
	addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2);
	addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4);
	addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4);
	addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1);
	if (link)
		addattr32(n, 1024, IFLA_GRE_LINK, link);
	addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1);
	addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1);

	addattr16(n, 1024, IFLA_GRE_ENCAP_TYPE, encaptype);
	addattr16(n, 1024, IFLA_GRE_ENCAP_FLAGS, encapflags);
	addattr16(n, 1024, IFLA_GRE_ENCAP_SPORT, htons(encapsport));
	addattr16(n, 1024, IFLA_GRE_ENCAP_DPORT, htons(encapdport));

	return 0;
}