Example #1
0
static int xfrm_state_extra_flag_parse(__u32 *extra_flags, int *argcp, char ***argvp)
{
    int argc = *argcp;
    char **argv = *argvp;
    int len = strlen(*argv);

    if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
        __u32 val = 0;

        if (get_u32(&val, *argv, 16))
            invarg("\"EXTRA-FLAG\" is invalid", *argv);
        *extra_flags = val;
    } else {
        while (1) {
            if (strcmp(*argv, "dont-encap-dscp") == 0)
                *extra_flags |= XFRM_SA_XFLAG_DONT_ENCAP_DSCP;
            else {
                PREV_ARG(); /* back track */
                break;
            }

            if (!NEXT_ARG_OK())
                break;
            NEXT_ARG();
        }
    }

    *argcp = argc;
    *argvp = argv;

    return 0;
}
Example #2
0
static int xfrm_policy_flag_parse(__u8 *flags, int *argcp, char ***argvp)
{
	int argc = *argcp;
	char **argv = *argvp;
	int len = strlen(*argv);

	if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
		__u8 val = 0;

		if (get_u8(&val, *argv, 16))
			invarg("\"FLAG\" is invalid", *argv);
		*flags = val;
	} else {
		while (1) {
			if (strcmp(*argv, "localok") == 0)
				*flags |= XFRM_POLICY_LOCALOK;
			else {
				PREV_ARG(); /* back track */
				break;
			}

			if (!NEXT_ARG_OK())
				break;
			NEXT_ARG();
		}
	}

	*argcp = argc;
	*argvp = argv;

	return 0;
}
int xfrm_parse_mark(struct xfrm_mark *mark, int *argcp, char ***argvp)
{
	int argc = *argcp;
	char **argv = *argvp;

	NEXT_ARG();
	if (get_u32(&mark->v, *argv, 0)) {
		invarg("Illegal \"mark\" value\n", *argv);
	}
	if (argc > 1)
		NEXT_ARG();
	else { /* last entry on parse line */
		mark->m = 0xffffffff;
		goto done;
	}

	if (strcmp(*argv, "mask") == 0) {
		NEXT_ARG();
		if (get_u32(&mark->m, *argv, 0)) {
			invarg("Illegal \"mark\" mask\n", *argv);
		}
	} else {
		mark->m = 0xffffffff;
		PREV_ARG();
	}

done:
	*argcp = argc;
	*argvp = argv;

	return 0;
}
Example #4
0
static int xfrm_tmpl_parse(struct xfrm_user_tmpl *tmpl,
			   int *argcp, char ***argvp)
{
	int argc = *argcp;
	char **argv = *argvp;
	char *idp = NULL;

	while (1) {
		if (strcmp(*argv, "mode") == 0) {
			NEXT_ARG();
			xfrm_mode_parse(&tmpl->mode,  &argc, &argv);
		} else if (strcmp(*argv, "reqid") == 0) {
			NEXT_ARG();
			xfrm_reqid_parse(&tmpl->reqid, &argc, &argv);
		} else if (strcmp(*argv, "level") == 0) {
			NEXT_ARG();

			if (strcmp(*argv, "required") == 0)
				tmpl->optional = 0;
			else if (strcmp(*argv, "use") == 0)
				tmpl->optional = 1;
			else
				invarg("\"LEVEL\" is invalid\n", *argv);

		} else {
			if (idp) {
				PREV_ARG(); /* back track */
				break;
			}
			idp = *argv;
			xfrm_id_parse(&tmpl->saddr, &tmpl->id, &tmpl->family,
				      0, &argc, &argv);
			if (preferred_family == AF_UNSPEC)
				preferred_family = tmpl->family;
		}

		if (!NEXT_ARG_OK())
			break;

		NEXT_ARG();
	}
	if (argc == *argcp)
		missarg("TMPL");

	*argcp = argc;
	*argvp = argv;

	return 0;
}
Example #5
0
static int xfrm_state_flag_parse(__u8 *flags, int *argcp, char ***argvp)
{
	int argc = *argcp;
	char **argv = *argvp;
	int len = strlen(*argv);

	if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
		__u8 val = 0;

		if (get_u8(&val, *argv, 16))
			invarg("FLAG value is invalid", *argv);
		*flags = val;
	} else {
		while (1) {
			if (strcmp(*argv, "noecn") == 0)
				*flags |= XFRM_STATE_NOECN;
			else if (strcmp(*argv, "decap-dscp") == 0)
				*flags |= XFRM_STATE_DECAP_DSCP;
			else if (strcmp(*argv, "nopmtudisc") == 0)
				*flags |= XFRM_STATE_NOPMTUDISC;
			else if (strcmp(*argv, "wildrecv") == 0)
				*flags |= XFRM_STATE_WILDRECV;
			else if (strcmp(*argv, "icmp") == 0)
				*flags |= XFRM_STATE_ICMP;
			else if (strcmp(*argv, "af-unspec") == 0)
				*flags |= XFRM_STATE_AF_UNSPEC;
			else if (strcmp(*argv, "align4") == 0)
				*flags |= XFRM_STATE_ALIGN4;
			else if (strcmp(*argv, "esn") == 0)
				*flags |= XFRM_STATE_ESN;
			else {
				PREV_ARG(); /* back track */
				break;
			}

			if (!NEXT_ARG_OK())
				break;
			NEXT_ARG();
		}
	}

	*argcp = argc;
	*argvp = argv;

	return 0;
}
Example #6
0
static int xfrm_state_flag_parse(__u8 *flags, int *argcp, char ***argvp)
{
	int argc = *argcp;
	char **argv = *argvp;
	int len = strlen(*argv);

	if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
		__u8 val = 0;

		if (get_u8(&val, *argv, 16))
			invarg("\"FLAG\" is invalid", *argv);
		*flags = val;
	} else {
		while (1) {
			if (strcmp(*argv, "noecn") == 0)
				*flags |= XFRM_STATE_NOECN;
			else if (strcmp(*argv, "decap-dscp") == 0)
				*flags |= XFRM_STATE_DECAP_DSCP;
			else if (strcmp(*argv, "wildrecv") == 0)
				*flags |= XFRM_STATE_WILDRECV;
			else {
				PREV_ARG(); /* back track */
				break;
			}

			if (!NEXT_ARG_OK())
				break;
			NEXT_ARG();
		}
	}

	filter.state_flags_mask = XFRM_FILTER_MASK_FULL;

	*argcp = argc;
	*argvp = argv;

	return 0;
}
int xfrm_id_parse(xfrm_address_t *saddr, struct xfrm_id *id, __u16 *family,
		  int loose, int *argcp, char ***argvp)
{
	int argc = *argcp;
	char **argv = *argvp;
	inet_prefix dst;
	inet_prefix src;

	memset(&dst, 0, sizeof(dst));
	memset(&src, 0, sizeof(src));

	while (1) {
		if (strcmp(*argv, "src") == 0) {
			NEXT_ARG();

			get_prefix(&src, *argv, preferred_family);
			if (src.family == AF_UNSPEC)
				invarg("\"src\" address family is AF_UNSPEC", *argv);
			if (family)
				*family = src.family;

			memcpy(saddr, &src.data, sizeof(*saddr));

			filter.id_src_mask = src.bitlen;

		} else if (strcmp(*argv, "dst") == 0) {
			NEXT_ARG();

			get_prefix(&dst, *argv, preferred_family);
			if (dst.family == AF_UNSPEC)
				invarg("\"dst\" address family is AF_UNSPEC", *argv);
			if (family)
				*family = dst.family;

			memcpy(&id->daddr, &dst.data, sizeof(id->daddr));

			filter.id_dst_mask = dst.bitlen;

		} else if (strcmp(*argv, "proto") == 0) {
			int ret;

			NEXT_ARG();

			ret = xfrm_xfrmproto_getbyname(*argv);
			if (ret < 0)
				invarg("\"XFRM_PROTO\" is invalid", *argv);

			id->proto = (__u8)ret;

			filter.id_proto_mask = XFRM_FILTER_MASK_FULL;

		} else if (strcmp(*argv, "spi") == 0) {
			__u32 spi;

			NEXT_ARG();
			if (get_u32(&spi, *argv, 0))
				invarg("\"SPI\" is invalid", *argv);

			spi = htonl(spi);
			id->spi = spi;

			filter.id_spi_mask = XFRM_FILTER_MASK_FULL;

		} else {
			PREV_ARG(); /* back track */
			break;
		}

		if (!NEXT_ARG_OK())
			break;
		NEXT_ARG();
	}

	if (src.family && dst.family && (src.family != dst.family))
		invarg("the same address family is required between \"src\" and \"dst\"", *argv);

	if (loose == 0 && id->proto == 0)
		missarg("XFRM_PROTO");
	if (argc == *argcp)
		missarg("ID");

	*argcp = argc;
	*argvp = argv;

	return 0;
}
int xfrm_selector_parse(struct xfrm_selector *sel, int *argcp, char ***argvp)
{
	int argc = *argcp;
	char **argv = *argvp;
	inet_prefix dst;
	inet_prefix src;
	char *upspecp = NULL;

	memset(&dst, 0, sizeof(dst));
	memset(&src, 0, sizeof(src));

	while (1) {
		if (strcmp(*argv, "src") == 0) {
			NEXT_ARG();

			get_prefix(&src, *argv, preferred_family);
			if (src.family == AF_UNSPEC)
				invarg("\"src\" address family is AF_UNSPEC", *argv);
			sel->family = src.family;

			memcpy(&sel->saddr, &src.data, sizeof(sel->saddr));
			sel->prefixlen_s = src.bitlen;

			filter.sel_src_mask = src.bitlen;

		} else if (strcmp(*argv, "dst") == 0) {
			NEXT_ARG();

			get_prefix(&dst, *argv, preferred_family);
			if (dst.family == AF_UNSPEC)
				invarg("\"dst\" address family is AF_UNSPEC", *argv);
			sel->family = dst.family;

			memcpy(&sel->daddr, &dst.data, sizeof(sel->daddr));
			sel->prefixlen_d = dst.bitlen;

			filter.sel_dst_mask = dst.bitlen;

		} else if (strcmp(*argv, "dev") == 0) {
			int ifindex;

			NEXT_ARG();

			if (strcmp(*argv, "none") == 0)
				ifindex = 0;
			else {
				ifindex = ll_name_to_index(*argv);
				if (ifindex <= 0)
					invarg("\"DEV\" is invalid", *argv);
			}
			sel->ifindex = ifindex;

			filter.sel_dev_mask = XFRM_FILTER_MASK_FULL;

		} else {
			if (upspecp) {
				PREV_ARG(); /* back track */
				break;
			} else {
				upspecp = *argv;
				xfrm_selector_upspec_parse(sel, &argc, &argv);
			}
		}

		if (!NEXT_ARG_OK())
			break;

		NEXT_ARG();
	}

	if (src.family && dst.family && (src.family != dst.family))
		invarg("the same address family is required between \"src\" and \"dst\"", *argv);

	if (argc == *argcp)
		missarg("SELECTOR");

	*argcp = argc;
	*argvp = argv;

	return 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;

	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\" 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("\"PORT\" 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("\"PORT\" 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("\"type\" value 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("\"code\" value is invalid", *argv);
			sel->dport = htons(sel->dport);
			sel->dport_mask = ~((__u16)0);

			filter.upspec_dport_mask = XFRM_FILTER_MASK_FULL;

		} else {
			PREV_ARG(); /* back track */
			break;
		}

		if (!NEXT_ARG_OK())
			break;
		NEXT_ARG();
	}
	if (argc == *argcp)
		missarg("UPSPEC");
	if (sportp || dportp) {
		switch (sel->proto) {
		case IPPROTO_TCP:
		case IPPROTO_UDP:
		case IPPROTO_SCTP:
		case IPPROTO_DCCP:
			break;
		default:
			fprintf(stderr, "\"sport\" and \"dport\" are invalid with proto=%s\n", strxf_proto(sel->proto));
			exit(1);
		}
	}
	if (typep || codep) {
		switch (sel->proto) {
		case IPPROTO_ICMP:
		case IPPROTO_ICMPV6:
		case IPPROTO_MH:
			break;
		default:
			fprintf(stderr, "\"type\" and \"code\" are invalid with proto=%s\n", strxf_proto(sel->proto));
			exit(1);
		}
	}

	*argcp = argc;
	*argvp = argv;

	return 0;
}
Example #10
0
int xfrm_id_parse(xfrm_address_t *saddr, struct xfrm_id *id, __u16 *family,
		  int loose, int *argcp, char ***argvp)
{
	int argc = *argcp;
	char **argv = *argvp;
	inet_prefix dst;
	inet_prefix src;

	memset(&dst, 0, sizeof(dst));
	memset(&src, 0, sizeof(src));

	while (1) {
		if (strcmp(*argv, "src") == 0) {
			NEXT_ARG();

			get_prefix(&src, *argv, preferred_family);
			if (src.family == AF_UNSPEC)
				invarg("value after \"src\" has an unrecognized address family", *argv);
			if (family)
				*family = src.family;

			memcpy(saddr, &src.data, sizeof(*saddr));

			filter.id_src_mask = src.bitlen;

		} else if (strcmp(*argv, "dst") == 0) {
			NEXT_ARG();

			get_prefix(&dst, *argv, preferred_family);
			if (dst.family == AF_UNSPEC)
				invarg("value after \"dst\" has an unrecognized address family", *argv);
			if (family)
				*family = dst.family;

			memcpy(&id->daddr, &dst.data, sizeof(id->daddr));

			filter.id_dst_mask = dst.bitlen;

		} else if (strcmp(*argv, "proto") == 0) {
			int ret;

			NEXT_ARG();

			ret = xfrm_xfrmproto_getbyname(*argv);
			if (ret < 0)
				invarg("XFRM-PROTO value is invalid", *argv);

			id->proto = (__u8)ret;

			filter.id_proto_mask = XFRM_FILTER_MASK_FULL;

		} else if (strcmp(*argv, "spi") == 0) {
			__u32 spi;

			NEXT_ARG();
			if (get_u32(&spi, *argv, 0))
				invarg("SPI value is invalid", *argv);

			spi = htonl(spi);
			id->spi = spi;

			filter.id_spi_mask = XFRM_FILTER_MASK_FULL;

		} else {
			PREV_ARG(); /* back track */
			break;
		}

		if (!NEXT_ARG_OK())
			break;
		NEXT_ARG();
	}

	if (src.family && dst.family && (src.family != dst.family))
		invarg("the same address family is required between values after \"src\" and \"dst\"", *argv);

	if (id->spi && id->proto) {
		if (xfrm_xfrmproto_is_ro(id->proto)) {
			fprintf(stderr, "\"spi\" is invalid with XFRM-PROTO value \"%s\"\n",
			        strxf_xfrmproto(id->proto));
			exit(1);
		} else if (id->proto == IPPROTO_COMP && ntohl(id->spi) >= 0x10000) {
			fprintf(stderr, "SPI value is too large with XFRM-PROTO value \"%s\"\n",
			        strxf_xfrmproto(id->proto));
			exit(1);
		}
	}

	if (loose == 0 && id->proto == 0)
		missarg("XFRM-PROTO");
	if (argc == *argcp)
		missarg("ID");

	*argcp = argc;
	*argvp = argv;

	return 0;
}
Example #11
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;
}
Example #12
0
static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
			   struct iplink_req *req)
{
	int len, argc = *argcp;
	char **argv = *argvp;
	struct rtattr *vfinfo;

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

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

		} else {
			/* rewind arg */
			PREV_ARG();
			break;
		}
	}

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

	addattr_nest_end(&req->n, vfinfo);

	*argcp = argc;
	*argvp = argv;
	return 0;
}
Example #13
0
void
mpls_parse_instr(struct mpls_instr_req *instr, int *pargc, char ***pargv,
	int direction) {
	int argc = *pargc;
	char **argv = *pargv;
	int c = 0;

	while (argc > 0) {
		if (strcmp(*argv, "nexthop") == 0) {
			NEXT_ARG();
			inet_prefix addr;
			instr->mir_instr[c].mir_opcode = MPLS_OP_SET;
			instr->mir_instr[c].mir_set.mni_if =
				ll_name_to_index(*argv);
			NEXT_ARG();
			if (strcmp(*argv, "ipv4") == 0) {
				struct sockaddr_in *sin = (struct sockaddr_in*)
					&instr->mir_instr[c].mir_set.mni_addr;
				NEXT_ARG();
				get_addr(&addr, *argv, AF_INET);
				sin->sin_family = AF_INET;
				memcpy(&sin->sin_addr, &addr.data,
					addr.bytelen);
			} else if (strcmp(*argv, "ipv6") == 0) {
				struct sockaddr_in6 *sin6=(struct sockaddr_in6*)
					&instr->mir_instr[c].mir_set.mni_addr;
				NEXT_ARG();
				get_addr(&addr, *argv, AF_INET6);
				sin6->sin6_family = AF_INET6;
				memcpy(&sin6->sin6_addr, &addr.data,
					addr.bytelen);
			} else if (strcmp(*argv, "packet") == 0) {
				struct sockaddr *s =
					&instr->mir_instr[c].mir_set.mni_addr;
				s->sa_family = AF_PACKET;
			} else if (strcmp(*argv, "none") == 0) {
				struct sockaddr *s =
					&instr->mir_instr[c].mir_set.mni_addr;
				memset(s, 0, sizeof(struct sockaddr));
				continue;
			} else {
				invarg(*argv, "invalid nexthop type");
			}
		} else if (strcmp(*argv, "push") == 0) {
			NEXT_ARG();
			instr->mir_instr[c].mir_opcode = MPLS_OP_PUSH;
			*pargc = argc; *pargv = argv;
			mpls_parse_label(&instr->mir_instr[c].mir_push,
				pargc, pargv);
			argc = *pargc; argv = *pargv;
		} else if (strcmp(*argv, "forward") == 0) {
			__u32 key;
			NEXT_ARG();
			if (get_unsigned(&key, *argv, 0))
				invarg(*argv, "invalid key");
			instr->mir_instr[c].mir_fwd.ml_type = MPLS_LABEL_KEY;
			instr->mir_instr[c].mir_fwd.u.ml_key = key;
			instr->mir_instr[c].mir_opcode = MPLS_OP_FWD;
		} else if (strcmp(*argv, "pop") == 0) {
			if (direction == MPLS_OUT)
				invarg(*argv, "invalid NHLFE instruction");
			instr->mir_instr[c].mir_opcode = MPLS_OP_POP;
		} else if (strcmp(*argv, "peek") == 0) {
			if (direction == MPLS_OUT)
				invarg(*argv, "invalid NHLFE instruction");
			instr->mir_instr[c].mir_opcode = MPLS_OP_PEEK;
		} else if (strcmp(*argv, "deliver") == 0) {
			if (direction == MPLS_OUT)
				invarg(*argv, "invalid NHLFE instruction");
			instr->mir_instr[c].mir_opcode = MPLS_OP_DLV;
		} else if (strcmp(*argv, "set-dscp") == 0) {
			__u32 dscp;
			if (direction == MPLS_OUT)
				invarg(*argv, "invalid NHLFE instruction");
			NEXT_ARG();
			if (get_unsigned(&dscp, *argv, 0))
				invarg(*argv, "invalid DSCP");
			instr->mir_instr[c].mir_opcode = MPLS_OP_SET_DS;
			instr->mir_instr[c].mir_set_ds = dscp;
		} else if (strcmp(*argv, "set-tcindex") == 0) {
			__u32 tcindex;
			NEXT_ARG();
			if (get_unsigned(&tcindex, *argv, 0))
				invarg(*argv, "invalid TCINDEX");
			instr->mir_instr[c].mir_opcode = MPLS_OP_SET_TC;
			instr->mir_instr[c].mir_set_tc = tcindex;
		} else if (strcmp(*argv, "set-exp") == 0) {
			__u32 exp;
			NEXT_ARG();
			if (get_unsigned(&exp, *argv, 0))
				invarg(*argv, "invalid EXP");
			instr->mir_instr[c].mir_opcode = MPLS_OP_SET_EXP;
			instr->mir_instr[c].mir_set_exp = exp;
		} else if (strcmp(*argv, "set-rx-if") == 0) {
			if (direction == MPLS_OUT)
				invarg(*argv, "invalid NHLFE instruction");
			NEXT_ARG();
			instr->mir_instr[c].mir_opcode = MPLS_OP_SET_RX;
			instr->mir_instr[c].mir_set_rx =ll_name_to_index(*argv);
		} else if (strcmp(*argv, "expfwd") == 0) {
			int done = 0;
			unsigned int exp;
			unsigned int key;
			do {
				NEXT_ARG();
				if (get_unsigned(&exp, *argv, 0)) {
					done = 1;
					break;
				}
				NEXT_ARG();
				if (get_unsigned(&key, *argv, 0)) {
					done = 1;
					break;
				}
				instr->mir_instr[c].mir_exp_fwd.ef_key[exp] = key;
			} while (!done);
			PREV_ARG();
			instr->mir_instr[c].mir_opcode = MPLS_OP_EXP_FWD;
		} else if (strcmp(*argv, "exp2tc") == 0) {
			int done = 0;
			unsigned int exp;
			unsigned int tcindex;
			do {
				NEXT_ARG();
				if (get_unsigned(&exp, *argv, 0)) {
					done = 1;
					break;
				}
				NEXT_ARG();
				if (get_unsigned(&tcindex, *argv, 0)) {
					done = 1;
					break;
				}
				instr->mir_instr[c].mir_exp2tc.e2t[exp] =
									tcindex;
			} while (!done);
			PREV_ARG();
			instr->mir_instr[c].mir_opcode = MPLS_OP_EXP2TC;
		} else if (strcmp(*argv, "exp2ds") == 0) {
			int done = 0;
			unsigned int exp;
			unsigned int dscp;
			if (direction == MPLS_OUT)
				invarg(*argv, "invalid NHLFE instruction");
			do {
				NEXT_ARG();
				if (get_unsigned(&exp, *argv, 0)) {
					done = 1;
					break;
				}
				NEXT_ARG();
				if (get_unsigned(&dscp, *argv, 0)) {
					done = 1;
					break;
				}
				instr->mir_instr[c].mir_exp2ds.e2d[exp] = dscp;
			} while (!done);
			PREV_ARG();
			instr->mir_instr[c].mir_opcode = MPLS_OP_EXP2DS;
		} else if (strcmp(*argv, "nffwd") == 0) {
			int done = 0;
			unsigned int nfmark;
			unsigned int key;
			unsigned int mask;
			NEXT_ARG();
			if (!get_unsigned(&mask, *argv, 0)) {
				instr->mir_instr[c].mir_nf_fwd.nf_mask = mask;
				do {
					NEXT_ARG();
					if (get_unsigned(&nfmark, *argv, 0)) {
						done = 1;
						break;
					}
					NEXT_ARG();
					if (get_unsigned(&key, *argv, 0)) {
						done = 1;
						break;
					}
					instr->mir_instr[c].mir_nf_fwd.nf_key[nfmark] = key;
				} while (!done);
			}
			PREV_ARG();
			instr->mir_instr[c].mir_opcode = MPLS_OP_NF_FWD;
		} else if (strcmp(*argv, "nf2exp") == 0) {
			int done = 0;
			unsigned int nfmark;
			unsigned int exp;
			unsigned int mask;
			NEXT_ARG();
			if (!get_unsigned(&mask, *argv, 0)) {
				instr->mir_instr[c].mir_nf2exp.n2e_mask = mask;
				do {
					NEXT_ARG();
					if (get_unsigned(&nfmark, *argv, 0)) {
						done = 1;
						break;
					}
					NEXT_ARG();
					if (get_unsigned(&exp, *argv, 0)) {
						done = 1;
						break;
					}
					instr->mir_instr[c].mir_nf2exp.n2e[nfmark] = exp;
				} while (!done);
			}
			PREV_ARG();
			instr->mir_instr[c].mir_opcode = MPLS_OP_NF2EXP;
		} else if (strcmp(*argv, "tc2exp") == 0) {
			int done = 0;
			unsigned int tcindex;
			unsigned int exp;
			unsigned int mask;
			NEXT_ARG();
			if (!get_unsigned(&mask, *argv, 0)) {
				instr->mir_instr[c].mir_tc2exp.t2e_mask = mask;
				do {
					NEXT_ARG();
					if (get_unsigned(&tcindex, *argv, 0)) {
						done = 1;
						break;
					}
					NEXT_ARG();
					if (get_unsigned(&exp, *argv, 0)) {
						done = 1;
						break;
					}
					instr->mir_instr[c].mir_tc2exp.t2e[tcindex] = exp;
				} while (!done);
			}
			PREV_ARG();
			instr->mir_instr[c].mir_opcode = MPLS_OP_TC2EXP;
		} else if (strcmp(*argv, "ds2exp") == 0) {
			int done = 0;
			unsigned int dscp;
			unsigned int exp;
			unsigned int mask;
			if (direction == MPLS_IN)
				invarg(*argv, "invalid ILM instruction");
			NEXT_ARG();
			if (!get_unsigned(&mask, *argv, 0)) {
				instr->mir_instr[c].mir_ds2exp.d2e_mask = mask;
				do {
					NEXT_ARG();
					if (get_unsigned(&dscp, *argv, 0)) {
						done = 1;
						break;
					}
					NEXT_ARG();
					if (get_unsigned(&exp, *argv, 0)) {
						done = 1;
						break;
					}
					instr->mir_instr[c].mir_ds2exp.d2e[dscp] = exp;
				} while (!done);
			}
			PREV_ARG();
			instr->mir_instr[c].mir_opcode = MPLS_OP_DS2EXP;
		} else if (strcmp(*argv, "dsfwd") == 0) {
			int done = 0;
			unsigned int dscp;
			unsigned int key;
			unsigned int mask;
			NEXT_ARG();
			if (!get_unsigned(&mask, *argv, 0)) {
				instr->mir_instr[c].mir_ds_fwd.df_mask = mask;
				do {
					NEXT_ARG();
					if (get_unsigned(&dscp, *argv, 0)) {
						done = 1;
						break;
					}
					NEXT_ARG();
					if (get_unsigned(&key, *argv, 0)) {
						done = 1;
						break;
					}
					instr->mir_instr[c].mir_ds_fwd.df_key[dscp] = key;
				} while (!done);
			}
			PREV_ARG();
			instr->mir_instr[c].mir_opcode = MPLS_OP_DS_FWD;
		} else {
			invarg(*argv, "invalid mpls instruction");
		}
		argc--; argv++; c++;
	}
	instr->mir_instr_length = c;
	instr->mir_direction = direction;

	*pargc = argc;
	*pargv = argv;
}
Example #14
0
static int parse_bpf(struct action_util *a, int *argc_p, char ***argv_p,
		     int tca_id, struct nlmsghdr *n)
{
	char **argv = *argv_p, bpf_name[256];
	struct rtattr *tail;
	struct tc_act_bpf parm = { 0 };
	struct sock_filter bpf_ops[BPF_MAXINSNS];
	bool ebpf = false, seen_run = false;
	const char *bpf_uds_name = NULL;
	const char *bpf_sec_name = NULL;
	char *bpf_obj = NULL;
	int argc = *argc_p, ret = 0;
	__u16 bpf_len = 0;
	__u32 bpf_fd = 0;

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

	NEXT_ARG();

	while (argc > 0) {
		if (matches(*argv, "run") == 0) {
			bool from_file;
			int ret;

			NEXT_ARG();
opt_bpf:
			bpf_sec_name = bpf_default_section(bpf_type);
			seen_run = true;

			if (strcmp(*argv, "bytecode-file") == 0 ||
			    strcmp(*argv, "bcf") == 0) {
				from_file = true;
			} else if (strcmp(*argv, "bytecode") == 0 ||
				   strcmp(*argv, "bc") == 0) {
				from_file = false;
			} else if (strcmp(*argv, "object-file") == 0 ||
				   strcmp(*argv, "obj") == 0) {
				ebpf = true;
			} else {
				fprintf(stderr, "unexpected \"%s\"\n", *argv);
				explain();
				return -1;
			}

			NEXT_ARG();
			if (ebpf) {
				bpf_obj = *argv;
				NEXT_ARG();

				if (strcmp(*argv, "section") == 0 ||
				    strcmp(*argv, "sec") == 0) {
					NEXT_ARG();
					bpf_sec_name = *argv;
					NEXT_ARG();
				}
				if (strcmp(*argv, "export") == 0 ||
				    strcmp(*argv, "exp") == 0) {
					NEXT_ARG();
					bpf_uds_name = *argv;
					NEXT_ARG();
				}

				PREV_ARG();
			}

			ret = ebpf ? bpf_open_object(bpf_obj, bpf_type, bpf_sec_name) :
				     bpf_parse_ops(argc, argv, bpf_ops, from_file);
			if (ret < 0) {
				fprintf(stderr, "%s\n", ebpf ?
					"Could not load object" :
					"Illegal \"bytecode\"");
				return -1;
			}

			if (ebpf) {
				bpf_obj = basename(bpf_obj);

				snprintf(bpf_name, sizeof(bpf_name), "%s:[%s]",
					 bpf_obj, bpf_sec_name);

				bpf_fd = ret;
			} else {
				bpf_len = ret;
			}
		} else if (matches(*argv, "help") == 0) {
			usage();
		} else {
			if (!seen_run)
				goto opt_bpf;
			break;
		}
		argc--;
		argv++;
	}

	parm.action = TC_ACT_PIPE;
	if (argc) {
		if (matches(*argv, "reclassify") == 0) {
			parm.action = TC_ACT_RECLASSIFY;
			argc--;
			argv++;
		} else if (matches(*argv, "pipe") == 0) {
			parm.action = TC_ACT_PIPE;
			argc--;
			argv++;
		} else if (matches(*argv, "drop") == 0 ||
			   matches(*argv, "shot") == 0) {
			parm.action = TC_ACT_SHOT;
			argc--;
			argv++;
		} else if (matches(*argv, "continue") == 0) {
			parm.action = TC_ACT_UNSPEC;
			argc--;
			argv++;
		} else if (matches(*argv, "pass") == 0) {
			parm.action = TC_ACT_OK;
			argc--;
			argv++;
		}
	}

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

	if ((!bpf_len && !ebpf) || (!bpf_fd && ebpf)) {
		fprintf(stderr, "bpf: Bytecode needs to be passed\n");
		explain();
		return -1;
	}

	tail = NLMSG_TAIL(n);

	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
	addattr_l(n, MAX_MSG, TCA_ACT_BPF_PARMS, &parm, sizeof(parm));

	if (ebpf) {
		addattr32(n, MAX_MSG, TCA_ACT_BPF_FD, bpf_fd);
		addattrstrz(n, MAX_MSG, TCA_ACT_BPF_NAME, bpf_name);
	} else {
		addattr16(n, MAX_MSG, TCA_ACT_BPF_OPS_LEN, bpf_len);
		addattr_l(n, MAX_MSG, TCA_ACT_BPF_OPS, &bpf_ops,
			  bpf_len * sizeof(struct sock_filter));
	}

	tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;

	*argc_p = argc;
	*argv_p = argv;

	if (bpf_uds_name)
		ret = bpf_send_map_fds(bpf_uds_name, bpf_obj);

	return ret;
}