Beispiel #1
0
/*
 * debug attribute TCA_EM_META_HDR
 */
struct tcf_meta_hdr *debug_tca_em_meta_hdr(int lev, struct rtattr *meta, const char *name)
{
    struct tcf_meta_hdr *hdr;
    struct tcf_meta_val *left, *right;

    if(debug_rta_len_chk(lev, meta, name, sizeof(*hdr)))
        return(NULL);

    hdr = (struct tcf_meta_hdr *)RTA_DATA(meta);
    left = &(hdr->left);
    right = &(hdr->right);

    rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(meta->rta_len));
    rec_dbg(lev, "    [ tcf_meta_hdr(%d) ]", sizeof(*hdr));
    rec_dbg(lev, "        [ tcf_meta_val left(%d) ]", sizeof(*left));
    rec_dbg(lev, "            kind(%d): 0x%04x(%s,%s)",
        sizeof(left->kind), left->kind,
        conv_tcf_meta_type(TCF_META_TYPE(left->kind), 1),
        conv_tcf_meta_id(TCF_META_ID(left->kind), 1));
    rec_dbg(lev, "            shift(%d): %d", sizeof(left->shift), left->shift);
    rec_dbg(lev, "            op(%d): %d(%s)",
        sizeof(left->op), left->op, conv_tcf_em_opnd(left->op, 1));
    rec_dbg(lev, "        [ tcf_meta_val right(%d) ]", sizeof(*right));
    rec_dbg(lev, "            kind(%d): 0x%04x(%s,%s)",
        sizeof(right->kind), right->kind,
        conv_tcf_meta_type(TCF_META_TYPE(right->kind), 1),
        conv_tcf_meta_id(TCF_META_ID(right->kind), 1));
    rec_dbg(lev, "            shift(%d): %d", sizeof(right->shift), right->shift);
    rec_dbg(lev, "            op(%d): %d(%s)",
        sizeof(right->op), right->op, conv_tcf_em_opnd(right->op, 1));

    return(hdr);
}
Beispiel #2
0
static int meta_parse(struct rtnl_ematch *e, void *data, size_t len)
{
	struct meta_data *m = rtnl_ematch_data(e);
	struct nlattr *tb[TCA_EM_META_MAX+1];
	struct rtnl_meta_value *v;
	struct tcf_meta_hdr *hdr;
	void *vdata = NULL;
	size_t vlen = 0;
	int err;

	if ((err = nla_parse(tb, TCA_EM_META_MAX, data, len, meta_policy)) < 0)
		return err;

	if (!tb[TCA_EM_META_HDR])
		return -NLE_MISSING_ATTR;

	hdr = nla_data(tb[TCA_EM_META_HDR]);

	if (tb[TCA_EM_META_LVALUE]) {
		vdata = nla_data(tb[TCA_EM_META_LVALUE]);
		vlen = nla_len(tb[TCA_EM_META_LVALUE]);
	}

	v = meta_alloc(TCF_META_TYPE(hdr->left.kind),
		       TCF_META_ID(hdr->left.kind),
		       hdr->left.shift, vdata, vlen);
	if (!v)
		return -NLE_NOMEM;

	m->left = v;

	vlen = 0;
	if (tb[TCA_EM_META_RVALUE]) {
		vdata = nla_data(tb[TCA_EM_META_RVALUE]);
		vlen = nla_len(tb[TCA_EM_META_RVALUE]);
	}

	v = meta_alloc(TCF_META_TYPE(hdr->right.kind),
		       TCF_META_ID(hdr->right.kind),
		       hdr->right.shift, vdata, vlen);
	if (!v) {
		rtnl_meta_value_put(m->left);
		return -NLE_NOMEM;
	}

	m->right = v;
	m->opnd = hdr->left.op;

	return 0;
}
static inline int is_compatible(struct tcf_meta_val *what,
				struct tcf_meta_val *needed)
{
	char *p;
	struct meta_entry *entry;

	entry = lookup_meta_entry_byid(TCF_META_ID(what->kind));

	if (entry == NULL)
		return 0;

	for (p = entry->mask; p; p++)
		if (map_type(*p) == TCF_META_TYPE(needed->kind))
			return 1;

	return 0;
}
static inline void dump_value(struct nlmsghdr *n, int tlv, unsigned long val,
			      struct tcf_meta_val *hdr)
{
	__u32 t;

	switch (TCF_META_TYPE(hdr->kind)) {
		case TCF_META_TYPE_INT:
			t = val;
			addattr_l(n, MAX_MSG, tlv, &t, sizeof(t));
			break;

		case TCF_META_TYPE_VAR:
			if (TCF_META_ID(hdr->kind) == TCF_META_ID_VALUE) {
				struct bstr *a = (struct bstr *) val;
				addattr_l(n, MAX_MSG, tlv, a->data, a->len);
			}
			break;
	}
}
Beispiel #5
0
/*
 * debug attribute TCA_EM_META_LVALUE
 */
void debug_tca_em_meta_value(int lev, struct rtattr *meta, const char *name, struct tcf_meta_val *p)
{
    int i, type, len = RTA_PAYLOAD(meta) + 1;
    char *data = (char *)RTA_DATA(meta), *val;

    type = TCF_META_TYPE(p->kind);

    switch(type) {
        case TCF_META_TYPE_VAR:
            val = malloc(len);
            if(!val) {
                rec_dbg(lev, "%s(%hu): -- %s --",
                    name, RTA_ALIGN(meta->rta_len), strerror(errno));
                return;
            }
            memset(val, 0, len);

            for(i = 0; i < RTA_PAYLOAD(meta); i++)
                val[i] = isprint(data[i]) ? data[i] : '.';
            data[i] = '\0';

            rec_dbg(lev, "%s(%hu): %s",
                name, RTA_ALIGN(meta->rta_len), data);

            free(val);
            break;
        case TCF_META_TYPE_INT:
            if(RTA_PAYLOAD(meta) < sizeof(__u32)) {
                rec_dbg(lev, "%s(%hu): -- payload too short --",
                    name, RTA_ALIGN(meta->rta_len));
                return;
            }
            rec_dbg(lev, "%s(%hu): %d",
                name, RTA_ALIGN(meta->rta_len), *(int *)RTA_DATA(meta));
            break;
        default:
            rec_dbg(lev, "%s(%hu): -- unknown type(%d) --",
                name, RTA_ALIGN(meta->rta_len), type);
            return;
    }

}
Beispiel #6
0
/*
 * parse ematch meta value
 */
int parse_tca_em_meta_value(char *msg, char **mp, struct tcf_meta_val *val, struct rtattr *meta)
{
    int id = TCF_META_ID(val->kind);
    int type = TCF_META_TYPE(val->kind);
    char *data = (char *)RTA_DATA(meta);
    int i;

    if(id != TCF_META_ID_VALUE) {
        *mp = add_log(msg, *mp, "%s ", conv_tcf_meta_id(id, 0));
        if(val->shift)
            *mp = add_log(msg, *mp, "shift %d ", val->shift);
        if(type == TCF_META_TYPE_INT && *(unsigned *)RTA_DATA(meta)) {
            if(RTA_PAYLOAD(meta) < sizeof(__u32)) {
                rec_log("error: %s: payload too short", __func__);
                return(1);
            }
            *mp = add_log(msg, *mp, "mask 0x%08x ", *(unsigned *)RTA_DATA(meta));
        }

        return(0);
    }

    switch(type) {
        case TCF_META_TYPE_VAR:
            for(i = 0; i < RTA_PAYLOAD(meta); i++)
                *mp = add_log(msg, *mp, "%c", isprint(data[i]) ? data[i] : '.');
            break;
        case TCF_META_TYPE_INT:
            if(RTA_PAYLOAD(meta) < sizeof(__u32)) {
                rec_log("error: %s: payload too short", __func__);
                return(1);
            }
            *mp = add_log(msg, *mp, "%d", *(int *)RTA_DATA(meta));
            break;
        default:
            rec_log("error: %s: unknown type(%d)", __func__, type);
            return(1);
    }

    return(0);
}
static int print_object(FILE *fd, struct tcf_meta_val *obj, struct rtattr *rta)
{
	int id = TCF_META_ID(obj->kind);
	int type = TCF_META_TYPE(obj->kind);
	struct meta_entry *entry;

	if (id == TCF_META_ID_VALUE)
		return print_value(fd, type, rta);

	entry = lookup_meta_entry_byid(id);

	if (entry == NULL)
		fprintf(fd, "[unknown meta id %d]", id);
	else
		fprintf(fd, "%s", entry->kind);

	if (obj->shift)
		fprintf(fd, " shift %d", obj->shift);

	switch (type) {
		case TCF_META_TYPE_INT:
			if (rta) {
				if (RTA_PAYLOAD(rta) < sizeof(__u32))
					goto size_mismatch;

				fprintf(fd, " mask 0x%08x",
				    rta_getattr_u32(rta));
			}
			break;
	}

	return 0;

size_mismatch:
	fprintf(stderr, "meta int type mask TLV size mismatch\n");
	return -1;
}
Beispiel #8
0
static inline int meta_type(struct meta_value *v)
{
	return TCF_META_TYPE(v->hdr.kind);
}
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;
}
static inline int overwrite_type(struct tcf_meta_val *src,
				 struct tcf_meta_val *dst)
{
	return (TCF_META_TYPE(dst->kind) << 12) | TCF_META_ID(src->kind);
}