static struct expr_node *
parse_zero(struct locus *loc, char **str, int *ownp)
{
	eat_spaces(str);
	if (**str == '(') {
		++*str;
		int own;
		struct expr_node *arg = parse_argnum(loc, str, &own, 0);
		if (arg == NULL)
			return NULL;
		if (parse_char(loc, str, ')') < 0) {
		fail:
			expr_destroy(arg);
			free(arg);
			return NULL;
		}

		struct expr_node *ret = build_zero_w_arg(arg, own);
		if (ret == NULL)
			goto fail;
		*ownp = 1;
		return ret;

	} else {
		*ownp = 0;
		return expr_node_zero();
	}
}
Ejemplo n.º 2
0
/* Parses OVN actions, in the format described for the "actions" column in the
 * Logical_Flow table in ovn-sb(5), and appends the parsed versions of the
 * actions to 'ofpacts' as "struct ofpact"s.
 *
 * 'symtab' provides a table of "struct expr_symbol"s to support (as one would
 * provide to expr_parse()).
 *
 * 'ports' must be a map from strings (presumably names of ports) to integers
 * (as one would provide to expr_to_matches()).  Strings used in the actions
 * that are not in 'ports' are translated to zero.
 *
 * 'ct_zones' provides a map from a port name to its connection tracking zone.
 *
 * OVN maps each logical flow table (ltable), one-to-one, onto a physical
 * OpenFlow flow table (ptable).  A number of parameters describe this mapping
 * and data related to flow tables:
 *
 *     - 'first_ptable' and 'n_tables' define the range of OpenFlow tables to
 *       which the logical "next" action should be able to jump.  Logical table
 *       0 maps to OpenFlow table 'first_ptable', logical table 1 to
 *       'first_ptable + 1', and so on.  If 'n_tables' is 0 then "next" is
 *       disallowed entirely.
 *
 *     - 'cur_ltable' is an offset from 'first_ptable' (e.g. 0 <= cur_ltable <
 *       n_ptables) of the logical flow that contains the actions.  If
 *       cur_ltable + 1 < n_tables, then this defines the default table that
 *       "next" will jump to.
 *
 * 'next_table_id' should be the OpenFlow table to which the "next" action will
 * resubmit, or 0 to disable "next".
 *
 *     - 'output_ptable' should be the OpenFlow table to which the logical
 *       "output" action will resubmit
 *
 * Some actions add extra requirements (prerequisites) to the flow's match.  If
 * so, this function sets '*prereqsp' to the actions' prerequisites; otherwise,
 * it sets '*prereqsp' to NULL.  The caller owns '*prereqsp' and must
 * eventually free it.
 *
 * Returns NULL on success, otherwise a malloc()'d error message that the
 * caller must free.  On failure, 'ofpacts' has the same contents and
 * '*prereqsp' is set to NULL, but some tokens may have been consumed from
 * 'lexer'.
  */
char * OVS_WARN_UNUSED_RESULT
actions_parse(struct lexer *lexer, const struct shash *symtab,
              const struct simap *ports, const struct simap *ct_zones,
              uint8_t first_ptable, uint8_t n_tables, uint8_t cur_ltable,
              uint8_t output_ptable, struct ofpbuf *ofpacts,
              struct expr **prereqsp)
{
    size_t ofpacts_start = ofpacts->size;

    struct action_context ctx;
    ctx.lexer = lexer;
    ctx.symtab = symtab;
    ctx.ports = ports;
    ctx.ct_zones = ct_zones;
    ctx.first_ptable = first_ptable;
    ctx.n_tables = n_tables;
    ctx.cur_ltable = cur_ltable;
    ctx.output_ptable = output_ptable;
    ctx.error = NULL;
    ctx.ofpacts = ofpacts;
    ctx.prereqs = NULL;

    parse_actions(&ctx);

    if (!ctx.error) {
        *prereqsp = ctx.prereqs;
        return NULL;
    } else {
        ofpacts->size = ofpacts_start;
        expr_destroy(ctx.prereqs);
        *prereqsp = NULL;
        return ctx.error;
    }
}
Ejemplo n.º 3
0
/* Parses OVN actions, in the format described for the "actions" column in the
 * Logical_Flow table in ovn-sb(5), and appends the parsed versions of the
 * actions to 'ofpacts' as "struct ofpact"s.
 *
 * 'ap' provides most of the parameters for translation.
 *
 * Some actions add extra requirements (prerequisites) to the flow's match.  If
 * so, this function sets '*prereqsp' to the actions' prerequisites; otherwise,
 * it sets '*prereqsp' to NULL.  The caller owns '*prereqsp' and must
 * eventually free it.
 *
 * Returns NULL on success, otherwise a malloc()'d error message that the
 * caller must free.  On failure, 'ofpacts' has the same contents and
 * '*prereqsp' is set to NULL, but some tokens may have been consumed from
 * 'lexer'.
  */
char * OVS_WARN_UNUSED_RESULT
actions_parse(struct lexer *lexer, const struct action_params *ap,
              struct ofpbuf *ofpacts, struct expr **prereqsp)
{
    size_t ofpacts_start = ofpacts->size;

    struct action_context ctx = {
        .ap = ap,
        .lexer = lexer,
        .error = NULL,
        .ofpacts = ofpacts,
        .prereqs = NULL,
    };
    parse_actions(&ctx);

    if (!ctx.error) {
        *prereqsp = ctx.prereqs;
        return NULL;
    } else {
        ofpacts->size = ofpacts_start;
        expr_destroy(ctx.prereqs);
        *prereqsp = NULL;
        return ctx.error;
    }
}
Ejemplo n.º 4
0
Archivo: main.c Proyecto: thewhoo/ifj15
int main(int argc, char **argv)
{

    if (argc < 2)
        exit_error(E_INTERNAL);

    FILE *fp = fopen(argv[1], "r");
    if (fp == NULL)
        exit_error(E_INTERNAL);

    //gcInit();

    lex_init(fp);

    global_init();
    
    expr_init();

    parse();

    fclose(fp);
	
	expr_destroy();
	
    interpret();

    //gcDestroy();

    return 0;
}
Ejemplo n.º 5
0
void
mn_delete(cml_node *mn)
{
    strdelete(mn->name);
    strdelete(mn->banner);
    listclear(mn->rules_using);
    if (mn->visibility_expr != 0)
    	expr_destroy(mn->visibility_expr);
    if (mn->saveability_expr != 0)
    	expr_destroy(mn->saveability_expr);
    /* only remove the list structure, all nodes are deleted seperately */
    listclear(mn->children);
    if (mn->expr != 0)
    	expr_destroy(mn->expr);
    atom_dtor(&mn->value);
    listclear(mn->transactions_guarded);
    listclear(mn->bindings);
    range_delete(mn->range);
    listdelete(mn->enumdefs, cml_enumdef, cml_enumdef_delete);
    listclear(mn->dependants);
    listclear(mn->dependees);
    strdelete(mn->help_text);
    g_free(mn);
}
Ejemplo n.º 6
0
static void
cmd_destroy(cmd_t * cmd_p)
{
	if (!cmd_p)
		return;

	if (!queue_isempty(&cmd_p->qn))
		(void) queue_remove(&cmd_p->qn);

	if (!cmd_p->isnamed)
		expr_destroy(cmd_p->expr.expr_p);

	free(cmd_p);

}				/* end cmd_destroy */
Ejemplo n.º 7
0
static void
set_destroy(set_t * set_p)
{
	if (!set_p)
		return;

	/* remove ourselves from any list */
	if (!queue_isempty(&set_p->qn))
		(void) queue_remove(&set_p->qn);

	if (set_p->setname_p)
		free(set_p->setname_p);

	/* destroy the exprlist */
	expr_destroy(set_p->exprlist_p);

	free(set_p);

}				/* end set_destroy */
static int
parse_string(struct protolib *plib, struct locus *loc,
	     char **str, struct arg_type_info **retp, int *ownp)
{
	struct arg_type_info *info = NULL;
	struct expr_node *length;
	int own_length;

	if (isdigit(CTYPE_CONV(**str))) {
		/* string0 is string[retval], length is zero(retval)
		 * stringN is string[argN], length is zero(argN) */
		long l;
		if (parse_int(loc, str, &l) < 0
		    || check_int(loc, l) < 0)
			return -1;

		struct expr_node *length_arg = malloc(sizeof(*length_arg));
		if (length_arg == NULL)
			return -1;

		if (l == 0)
			expr_init_named(length_arg, "retval", 0);
		else
			expr_init_argno(length_arg, l - 1);

		length = build_zero_w_arg(length_arg, 1);
		if (length == NULL) {
			expr_destroy(length_arg);
			free(length_arg);
			return -1;
		}
		own_length = 1;

	} else {
		eat_spaces(str);
		if (**str == '[') {
			(*str)++;
			eat_spaces(str);

			length = parse_argnum(loc, str, &own_length, 1);
			if (length == NULL)
				return -1;

			eat_spaces(str);
			parse_char(loc, str, ']');

		} else if (**str == '(') {
			/* Usage of "string" as lens.  */
			++*str;

			eat_spaces(str);
			info = parse_type(plib, loc, str, NULL, 0, ownp, NULL);
			if (info == NULL)
				return -1;

			length = NULL;
			own_length = 0;

			eat_spaces(str);
			parse_char(loc, str, ')');

		} else {
			/* It was just a simple string after all.  */
			length = expr_node_zero();
			own_length = 0;
		}
	}

	/* String is a pointer to array of chars.  */
	if (info == NULL) {
		struct arg_type_info *info1 = malloc(sizeof(*info1));
		struct arg_type_info *info2 = malloc(sizeof(*info2));
		if (info1 == NULL || info2 == NULL) {
			free(info1);
			free(info2);
		fail:
			if (own_length) {
				assert(length != NULL);
				expr_destroy(length);
				free(length);
			}
			return -1;
		}
		type_init_array(info2, type_get_simple(ARGTYPE_CHAR), 0,
				length, own_length);
		type_init_pointer(info1, info2, 1);

		info = info1;
		*ownp = 1;
	}

	/* We'll need to set the lens, so unshare.  */
	if (unshare_type_info(loc, &info, ownp) < 0)
		/* If unshare_type_info failed, it must have been as a
		 * result of cloning attempt because *OWNP was 0.
		 * Thus we don't need to destroy INFO.  */
		goto fail;

	info->lens = &string_lens;
	info->own_lens = 0;

	*retp = info;
	return 0;
}
Ejemplo n.º 9
0
static void
test_parse_actions(const char *input)
{
    struct shash symtab;
    struct hmap dhcp_opts;
    struct hmap dhcpv6_opts;
    struct hmap nd_ra_opts;
    struct simap ports;

    create_symtab(&symtab);
    create_gen_opts(&dhcp_opts, &dhcpv6_opts, &nd_ra_opts);

    /* Initialize group ids. */
    struct ovn_extend_table group_table;
    ovn_extend_table_init(&group_table);

    /* Initialize meter ids for QoS. */
    struct ovn_extend_table meter_table;
    ovn_extend_table_init(&meter_table);

    simap_init(&ports);
    simap_put(&ports, "eth0", 5);
    simap_put(&ports, "eth1", 6);
    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));

    struct ofpbuf ovnacts;
    struct expr *prereqs;
    char *error;

    puts(input);

    ofpbuf_init(&ovnacts, 0);

    const struct ovnact_parse_params pp = {
        .symtab = &symtab,
        .dhcp_opts = &dhcp_opts,
        .dhcpv6_opts = &dhcpv6_opts,
        .nd_ra_opts = &nd_ra_opts,
        .n_tables = 24,
        .cur_ltable = 10,
    };
    error = ovnacts_parse_string(input, &pp, &ovnacts, &prereqs);
    if (!error) {
        /* Convert the parsed representation back to a string and print it,
         * if it's different from the input. */
        struct ds ovnacts_s = DS_EMPTY_INITIALIZER;
        ovnacts_format(ovnacts.data, ovnacts.size, &ovnacts_s);
        if (strcmp(input, ds_cstr(&ovnacts_s))) {
            printf("    formats as %s\n", ds_cstr(&ovnacts_s));
        }

        /* Encode the actions into OpenFlow and print. */
        const struct ovnact_encode_params ep = {
            .lookup_port = lookup_port_cb,
            .aux = &ports,
            .is_switch = true,
            .group_table = &group_table,
            .meter_table = &meter_table,

            .pipeline = OVNACT_P_INGRESS,
            .ingress_ptable = 8,
            .egress_ptable = 40,
            .output_ptable = 64,
            .mac_bind_ptable = 65,
        };
        struct ofpbuf ofpacts;
        ofpbuf_init(&ofpacts, 0);
        ovnacts_encode(ovnacts.data, ovnacts.size, &ep, &ofpacts);
        struct ds ofpacts_s = DS_EMPTY_INITIALIZER;
        struct ofpact_format_params fp = { .s = &ofpacts_s };
        ofpacts_format(ofpacts.data, ofpacts.size, &fp);
        printf("    encodes as %s\n", ds_cstr(&ofpacts_s));
        ds_destroy(&ofpacts_s);
        ofpbuf_uninit(&ofpacts);

        /* Print prerequisites if any. */
        if (prereqs) {
            struct ds prereqs_s = DS_EMPTY_INITIALIZER;
            expr_format(prereqs, &prereqs_s);
            printf("    has prereqs %s\n", ds_cstr(&prereqs_s));
            ds_destroy(&prereqs_s);
        }

        /* Now re-parse and re-format the string to verify that it's
         * round-trippable. */
        struct ofpbuf ovnacts2;
        struct expr *prereqs2;
        ofpbuf_init(&ovnacts2, 0);
        error = ovnacts_parse_string(ds_cstr(&ovnacts_s), &pp, &ovnacts2,
                                     &prereqs2);
        if (!error) {
            struct ds ovnacts2_s = DS_EMPTY_INITIALIZER;
            ovnacts_format(ovnacts2.data, ovnacts2.size, &ovnacts2_s);
            if (strcmp(ds_cstr(&ovnacts_s), ds_cstr(&ovnacts2_s))) {
                printf("    bad reformat: %s\n", ds_cstr(&ovnacts2_s));
            }
            ds_destroy(&ovnacts2_s);
        } else {
            printf("    reparse error: %s\n", error);
            free(error);
        }
        expr_destroy(prereqs2);

        ovnacts_free(ovnacts2.data, ovnacts2.size);
        ofpbuf_uninit(&ovnacts2);
        ds_destroy(&ovnacts_s);
    } else {
        printf("    %s\n", error);
        free(error);
    }

    expr_destroy(prereqs);
    ovnacts_free(ovnacts.data, ovnacts.size);
    ofpbuf_uninit(&ovnacts);

    simap_destroy(&ports);
    expr_symtab_destroy(&symtab);
    shash_destroy(&symtab);
    dhcp_opts_destroy(&dhcp_opts);
    dhcp_opts_destroy(&dhcpv6_opts);
    nd_ra_opts_destroy(&nd_ra_opts);
    ovn_extend_table_destroy(&group_table);
    ovn_extend_table_destroy(&meter_table);
}

static void
test_parse_expr(const char *input)
{
    struct shash symtab;
    struct shash addr_sets;
    struct shash port_groups;
    struct simap ports;
    struct expr *expr;
    char *error;

    create_symtab(&symtab);
    create_addr_sets(&addr_sets);
    create_port_groups(&port_groups);

    simap_init(&ports);
    simap_put(&ports, "eth0", 5);
    simap_put(&ports, "eth1", 6);
    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
    simap_put(&ports, "lsp1", 0x11);
    simap_put(&ports, "lsp2", 0x12);
    simap_put(&ports, "lsp3", 0x13);

    expr = expr_parse_string(input, &symtab, &addr_sets,
                             &port_groups, &error);
    if (!error) {
        expr = expr_annotate(expr, &symtab, &error);
    }
    if (!error) {
        expr = expr_simplify(expr, is_chassis_resident_cb, &ports);
        expr = expr_normalize(expr);
        ovs_assert(expr_is_normalized(expr));
    }
    if (!error) {
        struct hmap matches;

        expr_to_matches(expr, lookup_port_cb, &ports, &matches);
        expr_matches_print(&matches, stdout);
        expr_matches_destroy(&matches);
    } else {
        puts(error);
        free(error);
    }
    expr_destroy(expr);
    simap_destroy(&ports);
    expr_symtab_destroy(&symtab);
    shash_destroy(&symtab);
    expr_const_sets_destroy(&addr_sets);
    shash_destroy(&addr_sets);
    expr_const_sets_destroy(&port_groups);
    shash_destroy(&port_groups);
}

static bool
lookup_atoi_cb(const void *aux OVS_UNUSED, const char *port_name,
               unsigned int *portp)
{
    *portp = atoi(port_name);
    return true;
}

static void
test_expr_to_packets(const char *input)
{
    struct shash symtab;
    create_symtab(&symtab);

    struct flow uflow;
    char *error = expr_parse_microflow(input, &symtab, NULL, NULL,
                                       lookup_atoi_cb, NULL, &uflow);
    if (error) {
        puts(error);
        free(error);
        expr_symtab_destroy(&symtab);
        shash_destroy(&symtab);
        return;
    }

    uint64_t packet_stub[128 / 8];
    struct dp_packet packet;
    dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub);
    flow_compose(&packet, &uflow, NULL, 64);

    struct ds output = DS_EMPTY_INITIALIZER;
    const uint8_t *buf = dp_packet_data(&packet);
    for (int i = 0; i < dp_packet_size(&packet); i++) {
        uint8_t val = buf[i];
        ds_put_format(&output, "%02"PRIx8, val);
    }
    puts(ds_cstr(&output));
    ds_destroy(&output);
    dp_packet_uninit(&packet);
    expr_symtab_destroy(&symtab);
    shash_destroy(&symtab);
}

int
LLVMFuzzerTestOneInput(const uint8_t *input_, size_t size)
{
    /* Bail out if we cannot construct at least a 1 char string. */
    const char *input = (const char *) input_;
    if (size < 2 || input[size - 1] != '\0' || strchr(input, '\n') ||
        strlen(input) != size - 1) {
        return 0;
    }

    /* Disable logging to avoid write to disk. */
    static bool isInit = false;
    if (!isInit) {
        vlog_set_verbosity("off");
        isInit = true;
    }

    /* Parse, annotate, simplify, normalize expr and convert to flows. */
    test_parse_expr(input);

    /* Parse actions. */
    test_parse_actions(input);

    /* Test OVN lexer. */
    test_lex(input);

    /* Expr to packets. */
    test_expr_to_packets(input);

    return 0;
}