static int meta_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
			   struct bstr *args)
{
	int opnd;
	struct bstr *a;
	struct tcf_meta_hdr meta_hdr;
	unsigned long lvalue = 0, rvalue = 0;

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

	if (args == NULL)
		return PARSE_ERR(args, "meta: missing arguments");

	if (!bstrcmp(args, "list")) {
		list_meta_ids(stderr);
		return -1;
	}

	a = parse_object(args, args, &meta_hdr.left, &lvalue, NULL);
	if (a == PARSE_FAILURE)
		return -1;
	else if (a == NULL)
		return PARSE_ERR(args, "meta: missing operand");

	if (!bstrcmp(a, "eq"))
		opnd = TCF_EM_OPND_EQ;
	else if (!bstrcmp(a, "gt"))
		opnd = TCF_EM_OPND_GT;
	else if (!bstrcmp(a, "lt"))
		opnd = TCF_EM_OPND_LT;
	else
		return PARSE_ERR(a, "meta: invalid operand");

	meta_hdr.left.op = (__u8) opnd;

	if (a->next == NULL)
		return PARSE_ERR(args, "meta: missing rvalue");
	a = bstr_next(a);

	a = parse_object(args, a, &meta_hdr.right, &rvalue, &meta_hdr.left);
	if (a == PARSE_FAILURE)
		return -1;
	else if (a != NULL)
		return PARSE_ERR(a, "meta: unexpected trailer");


	addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));

	addattr_l(n, MAX_MSG, TCA_EM_META_HDR, &meta_hdr, sizeof(meta_hdr));

	dump_value(n, TCA_EM_META_LVALUE, lvalue, &meta_hdr.left);
	dump_value(n, TCA_EM_META_RVALUE, rvalue, &meta_hdr.right);

	return 0;
}
Exemplo n.º 2
0
ASTNode* parse_literal(std::vector<token> &tokens, tokIter &it) {
  START_PARSE(LiteralNode);
  //IF WE ADD A "LITERAL" TOKEN TYPE, FIX THIS!
  READ_OF_TYPE(IDENT);
  int value = 0;
  std::string text = it->text;
  try {
       if (text != "double") throw 1;
       if (!check_next(tokens,it,IDENT)) throw 1;
       it++; text = it->text;
       double dvalue = std::stod(text);
       node->value = (int) (dvalue * (1 << 16));
       SUCCEED_PARSE;
  } catch(...) {};
  try {
          value = std::stoi(text);
          //NOTE: above stoi has some quirks. "123abc" -> 123, even though there is text.
          //POSSIBLY DO SOME BOUNDS CHECKING?
          node->value = value<<16;
          SUCCEED_PARSE;
  } catch (...) {
    //stoi exception when it fails.
    PARSE_ERR(text + " was not any expression?");
  }
  return nullptr;
}
Exemplo n.º 3
0
ASTNode* parse_phi(std::vector<token> &tokens, tokIter &it) {
  START_PARSE(PhiNode);
  READ_TEXT("phi");
  while(check_next(tokens,it,OPENBRACE)) {
    it++;
    ASTNode* expr = parse_expression(tokens,it);
    if (!expr) PARSE_ERR("phi node had a bad value?");
    if (!check_next(tokens,it,VAR)) { delete expr; PARSE_ERR("phi node had bad predecessor?");}
    it++;
    std::string pred = it->text;
    if (!check_next(tokens,it,CLOSEBRACE)) { delete expr; PARSE_ERR("phi node format...");};
    it++;
    node->values.push_back(ASTsubtree(expr));
    node->source_blocks.push_back(current_function+pred);
  }
  SUCCEED_PARSE;
}
Exemplo n.º 4
0
ASTNode* parse_load(std::vector<token> &tokens, tokIter &it) {
  START_PARSE(LoadNode);
  READ_TEXT("load");
  READ_TEXT("at");
  ASTNode* addr = parse_expression(tokens,it);
  if (!addr) PARSE_ERR("load had no address?");
  node->address = ASTsubtree(addr);
  SUCCEED_PARSE;
}
Exemplo n.º 5
0
static int ipset_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
			    struct bstr *args)
{
	struct xt_set_info set_info = {};
	int ret;

#define PARSE_ERR(CARG, FMT, ARGS...) \
	em_parse_error(EINVAL, args, CARG, &ipset_ematch_util, FMT, ##ARGS)

	if (args == NULL)
		return PARSE_ERR(args, "ipset: missing set name");

	if (args->len >= IPSET_MAXNAMELEN)
		return PARSE_ERR(args, "ipset: set name too long (max %u)", IPSET_MAXNAMELEN - 1);
	ret = get_set_byname(args->data, &set_info);
	if (ret < 0)
		return PARSE_ERR(args, "ipset: unknown set name '%s'", args->data);

	if (args->next == NULL)
		return PARSE_ERR(args, "ipset: missing set flags");

	args = bstr_next(args);
	if (parse_dirs(args->data, &set_info))
		return PARSE_ERR(args, "ipset: error parsing set flags");

	if (args->next) {
		args = bstr_next(args);
		return PARSE_ERR(args, "ipset: unknown parameter");
	}

	addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
	addraw_l(n, MAX_MSG, &set_info, sizeof(set_info));

#undef PARSE_ERR
	return 0;
}
Exemplo n.º 6
0
static int nbyte_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
			    struct bstr *args)
{
	struct bstr *a;
	struct bstr *needle = args;
	unsigned long offset = 0, layer = TCF_LAYER_NETWORK;
	int offset_present = 0;
	struct tcf_em_nbyte nb;

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

#define PARSE_ERR(CARG, FMT, ARGS...) \
	em_parse_error(EINVAL, args, CARG, &nbyte_ematch_util, FMT ,##ARGS)

	if (args == NULL)
		return PARSE_ERR(args, "nbyte: missing arguments");

	if (needle->len <= 0)
		return PARSE_ERR(args, "nbyte: needle length is 0");

	for (a = bstr_next(args); a; a = bstr_next(a)) {
		if (!bstrcmp(a, "at")) {
			if (a->next == NULL)
				return PARSE_ERR(a, "nbyte: missing argument");
			a = bstr_next(a);

			offset = bstrtoul(a);
			if (offset == ULONG_MAX)
				return PARSE_ERR(a, "nbyte: invalid offset, " \
				    "must be numeric");

			offset_present = 1;
		} else if (!bstrcmp(a, "layer")) {
			if (a->next == NULL)
				return PARSE_ERR(a, "nbyte: missing argument");
			a = bstr_next(a);

			layer = parse_layer(a);
			if (layer == INT_MAX) {
				layer = bstrtoul(a);
				if (layer == ULONG_MAX)
					return PARSE_ERR(a, "nbyte: invalid " \
					    "layer");
			}

			if (layer > TCF_LAYER_MAX)
				return PARSE_ERR(a, "nbyte: illegal layer, " \
				    "must be in 0..%d", TCF_LAYER_MAX);
		} else
			return PARSE_ERR(a, "nbyte: unknown parameter");
	}

	if (offset_present == 0)
		return PARSE_ERR(a, "nbyte: offset required");

	nb.len = needle->len;
	nb.layer = (__u8) layer;
	nb.off = (__u16) offset;

	addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
	addraw_l(n, MAX_MSG, &nb, sizeof(nb));
	addraw_l(n, MAX_MSG, needle->data, needle->len);

#undef PARSE_ERR
	return 0;
}
static inline struct bstr *
parse_object(struct bstr *args, struct bstr *arg, struct tcf_meta_val *obj,
	     unsigned long *dst, struct tcf_meta_val *left)
{
	struct meta_entry *entry;
	unsigned long num;
	struct bstr *a;

	if (arg->quoted) {
		obj->kind = TCF_META_TYPE_VAR << 12;
		obj->kind |= TCF_META_ID_VALUE;
		*dst = (unsigned long) arg;
		return bstr_next(arg);
	}

	num = bstrtoul(arg);
	if (num != ULONG_MAX) {
		obj->kind = TCF_META_TYPE_INT << 12;
		obj->kind |= TCF_META_ID_VALUE;
		*dst = (unsigned long) num;
		return bstr_next(arg);
	}

	entry = lookup_meta_entry(arg);

	if (entry == NULL) {
		PARSE_ERR(arg, "meta: unknown meta id\n");
		return PARSE_FAILURE;
	}

	obj->kind = entry->id | (map_type(entry->mask[0]) << 12);

	if (left) {
		struct tcf_meta_val *right = obj;

		if (TCF_META_TYPE(right->kind) == TCF_META_TYPE(left->kind))
			goto compatible;

		if (can_adopt(left) && !can_adopt(right)) {
			if (is_compatible(left, right))
				left->kind = overwrite_type(left, right);
			else
				goto not_compatible;
		} else if (can_adopt(right) && !can_adopt(left)) {
			if (is_compatible(right, left))
				right->kind = overwrite_type(right, left);
			else
				goto not_compatible;
		} else if (can_adopt(left) && can_adopt(right)) {
			if (is_compatible(left, right))
				left->kind = overwrite_type(left, right);
			else if (is_compatible(right, left))
				right->kind = overwrite_type(right, left);
			else
				goto not_compatible;
		} else
			goto not_compatible;
	}

compatible:

	a = bstr_next(arg);

	while(a) {
		if (!bstrcmp(a, "shift")) {
			unsigned long shift;

			if (a->next == NULL) {
				PARSE_ERR(a, "meta: missing argument");
				return PARSE_FAILURE;
			}
			a = bstr_next(a);

			shift = bstrtoul(a);
			if (shift == ULONG_MAX) {
				PARSE_ERR(a, "meta: invalid shift, must " \
				    "be numeric");
				return PARSE_FAILURE;
			}

			obj->shift = (__u8) shift;
			a = bstr_next(a);
		} else if (!bstrcmp(a, "mask")) {
			unsigned long mask;

			if (a->next == NULL) {
				PARSE_ERR(a, "meta: missing argument");
				return PARSE_FAILURE;
			}
			a = bstr_next(a);

			mask = bstrtoul(a);
			if (mask == ULONG_MAX) {
				PARSE_ERR(a, "meta: invalid mask, must be " \
				    "numeric");
				return PARSE_FAILURE;
			}
			*dst = (unsigned long) mask;
			a = bstr_next(a);
		} else
			break;
	}

	return a;

not_compatible:
	PARSE_ERR(arg, "lvalue and rvalue are not compatible.");
	return PARSE_FAILURE;
}
Exemplo n.º 8
0
static int cmp_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
                          struct bstr *args)
{
    struct bstr *a;
    int align, opnd = 0;
    unsigned long offset = 0, layer = TCF_LAYER_NETWORK, mask = 0, value = 0;
    int offset_present = 0, value_present = 0;
    struct tcf_em_cmp cmp;

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

#define PARSE_ERR(CARG, FMT, ARGS...) \
	em_parse_error(EINVAL, args, CARG, &cmp_ematch_util, FMT ,##ARGS)

    if (args == NULL)
        return PARSE_ERR(args, "cmp: missing arguments");

    if (!bstrcmp(args, "u8"))
        align = TCF_EM_ALIGN_U8;
    else if (!bstrcmp(args, "u16"))
        align = TCF_EM_ALIGN_U16;
    else if (!bstrcmp(args, "u32"))
        align = TCF_EM_ALIGN_U32;
    else
        return PARSE_ERR(args, "cmp: invalid alignment");

    for (a = bstr_next(args); a; a = bstr_next(a)) {
        if (!bstrcmp(a, "at")) {
            if (a->next == NULL)
                return PARSE_ERR(a, "cmp: missing argument");
            a = bstr_next(a);

            offset = bstrtoul(a);
            if (offset == ULONG_MAX)
                return PARSE_ERR(a, "cmp: invalid offset, " \
                                 "must be numeric");

            offset_present = 1;
        } else if (!bstrcmp(a, "layer")) {
            if (a->next == NULL)
                return PARSE_ERR(a, "cmp: missing argument");
            a = bstr_next(a);

            layer = parse_layer(a);
            if (layer == INT_MAX) {
                layer = bstrtoul(a);
                if (layer == ULONG_MAX)
                    return PARSE_ERR(a, "cmp: invalid " \
                                     "layer");
            }

            if (layer > TCF_LAYER_MAX)
                return PARSE_ERR(a, "cmp: illegal layer, " \
                                 "must be in 0..%d", TCF_LAYER_MAX);
        } else if (!bstrcmp(a, "mask")) {
            if (a->next == NULL)
                return PARSE_ERR(a, "cmp: missing argument");
            a = bstr_next(a);

            mask = bstrtoul(a);
            if (mask == ULONG_MAX)
                return PARSE_ERR(a, "cmp: invalid mask");
        } else if (!bstrcmp(a, "trans")) {
            cmp.flags |= TCF_EM_CMP_TRANS;
        } else if (!bstrcmp(a, "eq") || !bstrcmp(a, "gt") ||
                   !bstrcmp(a, "lt")) {

            if (!bstrcmp(a, "eq"))
                opnd = TCF_EM_OPND_EQ;
            else if (!bstrcmp(a, "gt"))
                opnd = TCF_EM_OPND_GT;
            else if (!bstrcmp(a, "lt"))
                opnd = TCF_EM_OPND_LT;

            if (a->next == NULL)
                return PARSE_ERR(a, "cmp: missing argument");
            a = bstr_next(a);

            value = bstrtoul(a);
            if (value == ULONG_MAX)
                return PARSE_ERR(a, "cmp: invalid value");

            value_present = 1;
        } else
            return PARSE_ERR(a, "nbyte: unknown parameter");
    }

    if (offset_present == 0 || value_present == 0)
        return PARSE_ERR(a, "cmp: offset and value required");

    cmp.val = (__u32) value;
    cmp.mask = (__u32) mask;
    cmp.off = (__u16) offset;
    cmp.align = (__u8) align;
    cmp.layer = (__u8) layer;
    cmp.opnd = (__u8) opnd;

    addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
    addraw_l(n, MAX_MSG, &cmp, sizeof(cmp));

#undef PARSE_ERR
    return 0;
}
Exemplo n.º 9
0
static int u32_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
			  struct bstr *args)
{
	struct bstr *a;
	int align, nh_len;
	unsigned long key, mask, offmask = 0, offset;
	struct tc_u32_key u_key;

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

#define PARSE_ERR(CARG, FMT, ARGS...) \
	em_parse_error(EINVAL, args, CARG, &u32_ematch_util, FMT ,##ARGS)

	if (args == NULL)
		return PARSE_ERR(args, "u32: missing arguments");

	if (!bstrcmp(args, "u8"))
		align = 1;
	else if (!bstrcmp(args, "u16"))
		align = 2;
	else if (!bstrcmp(args, "u32"))
		align = 4;
	else
		return PARSE_ERR(args, "u32: invalid alignment");

	a = bstr_next(args);
	if (a == NULL)
		return PARSE_ERR(a, "u32: missing key");

	key = bstrtoul(a);
	if (key == ULONG_MAX)
		return PARSE_ERR(a, "u32: invalid key, must be numeric");

	a = bstr_next(a);
	if (a == NULL)
		return PARSE_ERR(a, "u32: missing mask");

	mask = bstrtoul(a);
	if (mask == ULONG_MAX)
		return PARSE_ERR(a, "u32: invalid mask, must be numeric");

	a = bstr_next(a);
	if (a == NULL || bstrcmp(a, "at") != 0)
		return PARSE_ERR(a, "u32: missing \"at\"");

	a = bstr_next(a);
	if (a == NULL)
		return PARSE_ERR(a, "u32: missing offset");

	nh_len = strlen("nexthdr+");
	if (a->len > nh_len && !memcmp(a->data, "nexthdr+", nh_len)) {
		char buf[a->len - nh_len + 1];
		offmask = -1;
		memcpy(buf, a->data + nh_len, a->len - nh_len);
		offset = strtoul(buf, NULL, 0);
	} else if (!bstrcmp(a, "nexthdr+")) {
		a = bstr_next(a);
		if (a == NULL)
			return PARSE_ERR(a, "u32: missing offset");
		offset = bstrtoul(a);
	} else
		offset = bstrtoul(a);

	if (offset == ULONG_MAX)
		return PARSE_ERR(a, "u32: invalid offset");

	if (a->next)
		return PARSE_ERR(a->next, "u32: unexpected trailer");

	switch (align) {
		case 1:
			if (key > 0xFF)
				return PARSE_ERR(a, "Illegal key (>0xFF)");
			if (mask > 0xFF)
				return PARSE_ERR(a, "Illegal mask (>0xFF)");

			key <<= 24 - ((offset & 3) * 8);
			mask <<= 24 - ((offset & 3) * 8);
			offset &= ~3;
			break;

		case 2:
			if (key > 0xFFFF)
				return PARSE_ERR(a, "Illegal key (>0xFFFF)");
			if (mask > 0xFFFF)
				return PARSE_ERR(a, "Illegal mask (>0xFFFF)");

			if ((offset & 3) == 0) {
				key <<= 16;
				mask <<= 16;
			}
			offset &= ~3;
			break;
	}

	key = htonl(key);
	mask = htonl(mask);

	if (offset % 4)
		return PARSE_ERR(a, "u32: invalid offset alignment, " \
		    "must be aligned to 4.");

	key &= mask;

	u_key.mask = mask;
	u_key.val = key;
	u_key.off = offset;
	u_key.offmask = offmask;

	addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
	addraw_l(n, MAX_MSG, &u_key, sizeof(u_key));

#undef PARSE_ERR
	return 0;
}
Exemplo n.º 10
0
static int canid_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
			  struct bstr *args)
{
	int iseff = 0;
	int ret = 0;
	struct rules rules = {
		.rules_capacity = 25, /* Denominator of EM_CANID_RULES_MAX
			Will be multiplied by 2 to calculate the size for realloc() */
		.rules_cnt = 0
	};

#define PARSE_ERR(CARG, FMT, ARGS...) \
	em_parse_error(EINVAL, args, CARG, &canid_ematch_util, FMT, ##ARGS)

	if (args == NULL)
		return PARSE_ERR(args, "canid: missing arguments");

	rules.rules_raw = malloc(sizeof(struct can_filter) * rules.rules_capacity);
	memset(rules.rules_raw, 0, sizeof(struct can_filter) * rules.rules_capacity);

	do {
		if (!bstrcmp(args, "sff")) {
			iseff = 0;
		} else if (!bstrcmp(args, "eff")) {
			iseff = 1;
		} else {
			ret = PARSE_ERR(args, "canid: invalid key");
			goto exit;
		}

		args = bstr_next(args);
		if (args == NULL) {
			ret = PARSE_ERR(args, "canid: missing argument");
			goto exit;
		}

		ret = canid_parse_rule(&rules, args, iseff);
		if (ret == -1) {
			ret = PARSE_ERR(args, "canid: Improperly formed CAN ID & mask\n");
			goto exit;
		} else if (ret == -2) {
			ret = PARSE_ERR(args, "canid: Too many arguments on input\n");
			goto exit;
		}
	} while ((args = bstr_next(args)) != NULL);

	addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
	addraw_l(n, MAX_MSG, rules.rules_raw,
		sizeof(struct can_filter) * rules.rules_cnt);

#undef PARSE_ERR
exit:
	free(rules.rules_raw);
	return ret;
}

static int canid_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
			  int data_len)
{
	struct can_filter *conf = data; /* Array with rules */
	int rules_count;
	int i;

	rules_count = data_len / sizeof(struct can_filter);

	for (i = 0; i < rules_count; i++) {
		struct can_filter *pcfltr = &conf[i];

		if (pcfltr->can_id & CAN_EFF_FLAG) {
			if (pcfltr->can_mask == (CAN_EFF_FLAG | CAN_EFF_MASK))
				fprintf(fd, "eff 0x%"PRIX32,
						pcfltr->can_id & CAN_EFF_MASK);
			else
				fprintf(fd, "eff 0x%"PRIX32":0x%"PRIX32,
						pcfltr->can_id & CAN_EFF_MASK,
						pcfltr->can_mask & CAN_EFF_MASK);
		} else {
			if (pcfltr->can_mask == (CAN_EFF_FLAG | CAN_SFF_MASK))
				fprintf(fd, "sff 0x%"PRIX32,
						pcfltr->can_id & CAN_SFF_MASK);
			else
				fprintf(fd, "sff 0x%"PRIX32":0x%"PRIX32,
						pcfltr->can_id & CAN_SFF_MASK,
						pcfltr->can_mask & CAN_SFF_MASK);
		}

		if ((i + 1) < rules_count)
			fprintf(fd, " ");
	}

	return 0;
}

struct ematch_util canid_ematch_util = {
	.kind = "canid",
	.kind_num = TCF_EM_CANID,
	.parse_eopt = canid_parse_eopt,
	.print_eopt = canid_print_eopt,
	.print_usage = canid_print_usage
};