Example #1
0
	/* strtok corrupts the string, so we'll be using this copy instead. */
	char str_copy[STR_MAX_LEN];
	char *token;
	int error;

	if (strlen(str) + 1 > STR_MAX_LEN) {
		log_err("'%s' is too long for this poor, limited parser...", str);
		return -EINVAL;
	}
	strcpy(str_copy, str);

	token = strtok(str_copy, "#");
	if (!token) {
		log_err("Cannot parse '%s' as a %s.", str, FORMAT);
		return -EINVAL;
	}

	error = str_to_addr4(token, &addr_out->l3);
	if (error)
		return error;

	token = strtok(NULL, "#");
	if (!token) {
		log_err("'%s' does not seem to contain a port (format: %s).", str, FORMAT);
		return -EINVAL;
	}
	return str_to_u16(token, &addr_out->l4, 0, MAX_PORT); /* Error msg already printed. */
}

#undef STR_MAX_LEN
#define STR_MAX_LEN (INET6_ADDRSTRLEN + 1 + 5) /* [addr + null chara] + # + port */
int str_to_addr6_port(const char *str, struct ipv6_transport_addr *addr_out)
{
	const char *FORMAT = "<IPv6 address>#<port> (eg. 2001:db8::1#96)";
	/* strtok corrupts the string, so we'll be using this copy instead. */
	char str_copy[STR_MAX_LEN];
	char *token;
	int error;

	if (strlen(str) + 1 > STR_MAX_LEN) {
		log_err("'%s' is too long for this poor, limited parser...", str);
		return -EINVAL;
	}
	strcpy(str_copy, str);

	token = strtok(str_copy, "#");
	if (!token) {
		log_err("Cannot parse '%s' as a %s.", str, FORMAT);
		return -EINVAL;
	}

	error = str_to_addr6(token, &addr_out->l3);
	if (error)
		return error;

	token = strtok(NULL, "#");
	if (!token) {
		log_err("'%s' does not seem to contain a port (format: %s).", str, FORMAT);
		return -EINVAL;
	}
	return str_to_u16(token, &addr_out->l4, 0, MAX_PORT); /* Error msg already printed. */
}
Example #2
0
static void
parse_sample(struct ofpbuf *b, char *arg)
{
    struct ofpact_sample *os = ofpact_put_SAMPLE(b);
    char *key, *value;

    while (ofputil_parse_key_value(&arg, &key, &value)) {
        if (!strcmp(key, "probability")) {
            os->probability = str_to_u16(value, "probability");
            if (os->probability == 0) {
                ovs_fatal(0, "invalid probability value \"%s\"", value);
            }
        } else if (!strcmp(key, "collector_set_id")) {
            os->collector_set_id = str_to_u32(value);
        } else if (!strcmp(key, "obs_domain_id")) {
            os->obs_domain_id = str_to_u32(value);
        } else if (!strcmp(key, "obs_point_id")) {
            os->obs_point_id = str_to_u32(value);
        } else {
            ovs_fatal(0, "invalid key \"%s\" in \"sample\" argument",
                      key);
        }
    }
    if (os->probability == 0) {
        ovs_fatal(0, "non-zero \"probability\" must be specified on sample");
    }
}
Example #3
0
static void
parse_fin_timeout(struct ofpbuf *b, char *arg)
{
    struct ofpact_fin_timeout *oft = ofpact_put_FIN_TIMEOUT(b);
    char *key, *value;

    while (ofputil_parse_key_value(&arg, &key, &value)) {
        if (!strcmp(key, "idle_timeout")) {
            oft->fin_idle_timeout = str_to_u16(value, key);
        } else if (!strcmp(key, "hard_timeout")) {
            oft->fin_hard_timeout = str_to_u16(value, key);
        } else {
            ovs_fatal(0, "invalid key '%s' in 'fin_timeout' argument", key);
        }
    }
}
Example #4
0
bool str_to_addr6_port(const char *str, struct ipv6_tuple_address *addr_out)
{
	const char *FORMAT = "<IPv6 address>#<port> (eg. 64:ff9b::#96)";
	const int STR_MAX_LEN = INET6_ADDRSTRLEN + 1 + 5; // [addr + null chara] + # + port
	char str_copy[STR_MAX_LEN]; // strtok corrupts the string, so we'll be using this copy instead.
	char *token;

	if (strlen(str) + 1 > STR_MAX_LEN) {
		printf("Error: '%s' is too long for this poor, limited parser...\n", str);
		return false;
	}
	strcpy(str_copy, str);

	token = strtok(str_copy, "#");
	if (!token || !str_to_addr6(token, &addr_out->address)) {
		printf("Error: Cannot parse '%s' as a %s.\n", str, FORMAT);
		return false;
	}

	token = strtok(NULL, "#");
	if (!token) {
		printf("Error: '%s' does not seem to contain a port (format: %s).\n", str, FORMAT);
		return false;
	}
	if (!str_to_u16(token, &addr_out->l4_id, 0, MAX_PORT))
		return false; // Error msg already printed.

	return true;
}
Example #5
0
bool str_to_u8(const char *str, __u8 *u8_out, __u8 min, __u8 max)
{
	__u16 result;
	if (!str_to_u16(str, &result, min, max))
		return false; // Error msg already printed.
	*u8_out = result;
	return true;
}
Example #6
0
int str_to_u16_array(const char *str, __u16 **array_out, __u16 *array_len_out)
{
	const unsigned int str_max_len = 2048;
	/* strtok corrupts the string, so we'll be using this copy instead. */
	char str_copy[str_max_len];
	char *token;
	__u16 *array;
	__u16 array_len;

	/* Validate str and copy it to the temp buffer. */
	if (strlen(str) + 1 > str_max_len) {
		log_err(ERR_PARSE_INTARRAY, "'%s' is too long for this poor, limited parser...", str);
		return -EINVAL;
	}
	strcpy(str_copy, str);

	/* Count the number of ints in the string. */
	array_len = 0;
	token = strtok(str_copy, ",");
	while (token) {
		array_len++;
		token = strtok(NULL, ",");
	}

	if (array_len == 0) {
		log_err(ERR_PARSE_INTARRAY, "'%s' seems to be an empty list, which is not supported.", str);
		return -EINVAL;
	}

	/* Build the result. */
	array = malloc(array_len * sizeof(__u16));
	if (!array) {
		log_err(ERR_ALLOC_FAILED, "Memory allocation failed. Cannot parse the input...");
		return -ENOMEM;
	}

	strcpy(str_copy, str);

	array_len = 0;
	token = strtok(str_copy, ",");
	while (token) {
		int error;

		error = str_to_u16(token, &array[array_len], 0, 0xFFFF);
		if (error) {
			free(array);
			return error; /* Error msg already printed. */
		}

		array_len++;
		token = strtok(NULL, ",");
	}

	/* Finish. */
	*array_out = array;
	*array_len_out = array_len;
	return 0;
}
Example #7
0
static void
parse_controller(struct ofpbuf *b, char *arg)
{
    enum ofp_packet_in_reason reason = OFPR_ACTION;
    uint16_t controller_id = 0;
    uint16_t max_len = UINT16_MAX;

    if (!arg[0]) {
        /* Use defaults. */
    } else if (strspn(arg, "0123456789") == strlen(arg)) {
        max_len = str_to_u16(arg, "max_len");
    } else {
        char *name, *value;

        while (ofputil_parse_key_value(&arg, &name, &value)) {
            if (!strcmp(name, "reason")) {
                if (!ofputil_packet_in_reason_from_string(value, &reason)) {
                    ovs_fatal(0, "unknown reason \"%s\"", value);
                }
            } else if (!strcmp(name, "max_len")) {
                max_len = str_to_u16(value, "max_len");
            } else if (!strcmp(name, "id")) {
                controller_id = str_to_u16(value, "id");
            } else {
                ovs_fatal(0, "unknown key \"%s\" parsing controller action",
                          name);
            }
        }
    }

    if (reason == OFPR_ACTION && controller_id == 0) {
        struct ofpact_output *output;

        output = ofpact_put_OUTPUT(b);
        output->port = OFPP_CONTROLLER;
        output->max_len = max_len;
    } else {
        struct ofpact_controller *controller;

        controller = ofpact_put_CONTROLLER(b);
        controller->max_len = max_len;
        controller->reason = reason;
        controller->controller_id = controller_id;
    }
}
Example #8
0
int str_to_plateaus_array(const char *str, __u16 *plateaus, __u16 *count)
{
	/* strtok corrupts the string, so we'll be using this copy instead. */
	char *str_copy;
	char *token;
	unsigned int len;
	int error = 0;

	/* Validate str and copy it to the temp buffer. */
	str_copy = malloc(strlen(str) + 1);
	if (!str_copy) {
		log_err("I ran out of memory.");
		return -ENOMEM;
	}

	strcpy(str_copy, str);

	/* Count the number of elements in the string. */
	len = 0;
	token = strtok(str_copy, ",");
	while (token) {
		len++;
		token = strtok(NULL, ",");
	}

	if (len == 0) {
		log_err("The plateaus string seems to be an empty list, which is not supported.");
		error = -EINVAL;
		goto end;
	}
	if (len > PLATEAUS_MAX) {
		log_err("Too many plateaus. The current max is %u.", PLATEAUS_MAX);
		error = -EINVAL;
		goto end;
	}

	/* Build the result. */
	*count = len;
	len = 0;
	strcpy(str_copy, str);
	token = strtok(str_copy, ",");
	while (token) {
		error = str_to_u16(token, &plateaus[len], 0, 0xFFFF);
		if (error)
			goto end; /* Error msg already printed. */

		len++;
		token = strtok(NULL, ",");
	}

	/* Fall through */

end:
	free(str_copy);
	return error;
}
Example #9
0
bool str_to_u16_array(const char *str, __u16 **array_out, __u16 *array_len_out)
{
	const int str_max_len = 2048;
	char str_copy[str_max_len]; // strtok corrupts the string, so we'll be using this copy instead.
	char *token;
	__u16 *array;
	__u16 array_len;

	// Validate str and copy it to the temp buffer.
	if (strlen(str) + 1 > str_max_len) {
		printf("Error: '%s' is too long for this poor, limited parser...\n", str);
		return false;
	}
	strcpy(str_copy, str);

	// Count the number of ints in the string.
	array_len = 0;
	token = strtok(str_copy, ",");
	while (token) {
		array_len++;
		token = strtok(NULL, ",");
	}

	if (array_len == 0) {
		printf("Error: '%s' seems to be an empty list, which is not supported.\n", str);
		return false;
	}

	// Build the result.
	array = malloc(array_len * sizeof(__u16));
	if (!array) {
		printf("Error: Memory allocation failed. Cannot parse...\n");
		return false;
	}

	strcpy(str_copy, str);

	array_len = 0;
	token = strtok(str_copy, ",");
	while (token) {
		if (!str_to_u16(token, &array[array_len], 0, 0xFFFF)) {
			free(array);
			return false; // Error msg already printed.
		}
		array_len++;
		token = strtok(NULL, ",");
	}

	// Finish.
	*array_out = array;
	*array_len_out = array_len;
	return true;
}
Example #10
0
File: jool.c Project: npowern/NAT64
static int set_general_u16(struct arguments *args, enum general_module module, __u8 type,
		char *value, __u16 min, __u16 max)
{
	__u16 tmp;
	int error;

	error = str_to_u16(value, &tmp, min, max);
	if (error)
		return error;

	return set_general_arg(args, module, type, sizeof(tmp), &tmp);
}
Example #11
0
int str_to_u8(const char *str, __u8 *u8_out, __u8 min, __u8 max)
{
	__u16 result;
	int error;

	error = str_to_u16(str, &result, min, max);
	if (error)
		return error; /* Error msg already printed. */

	*u8_out = result;
	return 0;
}
Example #12
0
int str_to_addr4_port(const char *str, struct ipv4_tuple_address *addr_out)
{
	const char *FORMAT = "<IPv4 address>#<port> (eg. 10.20.30.40#50)";
	/* [addr + null chara] + # + port */
	const unsigned int STR_MAX_LEN = INET_ADDRSTRLEN + 1 + 5;
	/* strtok corrupts the string, so we'll be using this copy instead. */
	char str_copy[STR_MAX_LEN];
	char *token;
	int error;

	if (strlen(str) + 1 > STR_MAX_LEN) {
		log_err(ERR_PARSE_ADDR4_PORT, "'%s' is too long for this poor, limited parser...", str);
		return -EINVAL;
	}
	strcpy(str_copy, str);

	token = strtok(str_copy, "#");
	if (!token) {
		log_err(ERR_PARSE_ADDR4_PORT, "Cannot parse '%s' as a %s.", str, FORMAT);
		return -EINVAL;
	}

	error = str_to_addr4(token, &addr_out->address);
	if (error)
		return error;

	token = strtok(NULL, "#");
	if (!token) {
		log_err(ERR_PARSE_ADDR4_PORT, "'%s' does not seem to contain a port (format: %s).", str,
				FORMAT);
		return -EINVAL;
	}
	error = str_to_u16(token, &addr_out->l4_id, 0, MAX_PORT);
	if (error)
		return error; /* Error msg already printed. */

	return 0;
}
Example #13
0
/*!
 * \brief Parse NSEC3 parameters and fill structure with NSEC3 parameters.
 */
static bool parse_nsec3_params(dnssec_nsec3_params_t *params, const char *salt_str,
			       const char *algorithm_str, const char *iterations_str)
{
	uint8_t algorithm = 0;
	int r = str_to_u8(algorithm_str, &algorithm);
	if (r != DNSSEC_EOK) {
		error("Invalid algorithm number.");
		return false;
	}

	uint16_t iterations = 0;
	r = str_to_u16(iterations_str, &iterations);
	if (r != DNSSEC_EOK) {
		error("Invalid iteration count, %s.", dnssec_strerror(r));
		return false;
	}

	dnssec_binary_t salt = { 0 };
	r = str_to_salt(salt_str, &salt);
	if (r != DNSSEC_EOK) {
		error("Invalid salt, %s.", dnssec_strerror(r));
		return false;
	}

	if (salt.size > UINT8_MAX) {
		error("Invalid salt, maximum length is %d bytes.", UINT8_MAX);
		dnssec_binary_free(&salt);
		return false;
	}

	params->algorithm = algorithm;
	params->iterations = iterations;
	params->salt = salt;
	params->flags = 0;

	return true;
}
Example #14
0
/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man
 * page) into 'fm' for sending the specified flow_mod 'command' to a switch.
 * If 'actions' is specified, an action must be in 'string' and may be expanded
 * or reallocated.
 *
 * To parse syntax for an OFPT_FLOW_MOD (or NXT_FLOW_MOD), use an OFPFC_*
 * constant for 'command'.  To parse syntax for an OFPST_FLOW or
 * OFPST_AGGREGATE (or NXST_FLOW or NXST_AGGREGATE), use -1 for 'command'. */
void
parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
              bool verbose)
{
    enum {
        F_OUT_PORT = 1 << 0,
        F_ACTIONS = 1 << 1,
        F_TIMEOUT = 1 << 3,
        F_PRIORITY = 1 << 4,
        F_FLAGS = 1 << 5,
    } fields;
    char *string = xstrdup(str_);
    char *save_ptr = NULL;
    char *act_str = NULL;
    char *name;

    switch (command) {
    case -1:
        fields = F_OUT_PORT;
        break;

    case OFPFC_ADD:
        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
        break;

    case OFPFC_DELETE:
        fields = F_OUT_PORT;
        break;

    case OFPFC_DELETE_STRICT:
        fields = F_OUT_PORT | F_PRIORITY;
        break;

    case OFPFC_MODIFY:
        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
        break;

    case OFPFC_MODIFY_STRICT:
        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
        break;

    default:
        NOT_REACHED();
    }

    match_init_catchall(&fm->match);
    fm->priority = OFP_DEFAULT_PRIORITY;
    fm->cookie = htonll(0);
    fm->cookie_mask = htonll(0);
    if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) {
        /* For modify, by default, don't update the cookie. */
        fm->new_cookie = htonll(UINT64_MAX);
    } else{
        fm->new_cookie = htonll(0);
    }
    fm->table_id = 0xff;
    fm->command = command;
    fm->idle_timeout = OFP_FLOW_PERMANENT;
    fm->hard_timeout = OFP_FLOW_PERMANENT;
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_ANY;
    fm->flags = 0;
    if (fields & F_ACTIONS) {
        act_str = strstr(string, "action");
        if (!act_str) {
            ofp_fatal(str_, verbose, "must specify an action");
        }
        *act_str = '\0';

        act_str = strchr(act_str + 1, '=');
        if (!act_str) {
            ofp_fatal(str_, verbose, "must specify an action");
        }

        act_str++;
    }
    for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
         name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
        const struct protocol *p;

        if (parse_protocol(name, &p)) {
            match_set_dl_type(&fm->match, htons(p->dl_type));
            if (p->nw_proto) {
                match_set_nw_proto(&fm->match, p->nw_proto);
            }
        } else if (fields & F_FLAGS && !strcmp(name, "send_flow_rem")) {
            fm->flags |= OFPFF_SEND_FLOW_REM;
        } else if (fields & F_FLAGS && !strcmp(name, "check_overlap")) {
            fm->flags |= OFPFF_CHECK_OVERLAP;
        } else if (fields & F_FLAGS && !strcmp(name, "reset_counts")) {
            fm->flags |= OFPFF12_RESET_COUNTS;
        } else if (fields & F_FLAGS && !strcmp(name, "no_packet_counts")) {
            fm->flags |= OFPFF13_NO_PKT_COUNTS;
        } else if (fields & F_FLAGS && !strcmp(name, "no_byte_counts")) {
            fm->flags |= OFPFF13_NO_BYT_COUNTS;
        } else {
            char *value;

            value = strtok_r(NULL, ", \t\r\n", &save_ptr);
            if (!value) {
                ofp_fatal(str_, verbose, "field %s missing value", name);
            }

            if (!strcmp(name, "table")) {
                fm->table_id = str_to_u8(value, name);
            } else if (!strcmp(name, "out_port")) {
                if (!ofputil_port_from_string(value, &fm->out_port)) {
                    ofp_fatal(str_, verbose, "%s is not a valid OpenFlow port",
                              name);
                }
            } else if (fields & F_PRIORITY && !strcmp(name, "priority")) {
                fm->priority = str_to_u16(value, name);
            } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) {
                fm->idle_timeout = str_to_u16(value, name);
            } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) {
                fm->hard_timeout = str_to_u16(value, name);
            } else if (!strcmp(name, "cookie")) {
                char *mask = strchr(value, '/');

                if (mask) {
                    /* A mask means we're searching for a cookie. */
                    if (command == OFPFC_ADD) {
                        ofp_fatal(str_, verbose, "flow additions cannot use "
                                  "a cookie mask");
                    }
                    *mask = '\0';
                    fm->cookie = htonll(str_to_u64(value));
                    fm->cookie_mask = htonll(str_to_u64(mask+1));
                } else {
                    /* No mask means that the cookie is being set. */
                    if (command != OFPFC_ADD && command != OFPFC_MODIFY
                            && command != OFPFC_MODIFY_STRICT) {
                        ofp_fatal(str_, verbose, "cannot set cookie");
                    }
                    fm->new_cookie = htonll(str_to_u64(value));
                }
            } else if (mf_from_name(name)) {
                parse_field(mf_from_name(name), value, &fm->match);
            } else if (!strcmp(name, "duration")
                       || !strcmp(name, "n_packets")
                       || !strcmp(name, "n_bytes")
                       || !strcmp(name, "idle_age")
                       || !strcmp(name, "hard_age")) {
                /* Ignore these, so that users can feed the output of
                 * "ovs-ofctl dump-flows" back into commands that parse
                 * flows. */
            } else {
                ofp_fatal(str_, verbose, "unknown keyword %s", name);
            }
        }
    }
    if (!fm->cookie_mask && fm->new_cookie == htonll(UINT64_MAX)
            && (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT)) {
        /* On modifies without a mask, we are supposed to add a flow if
         * one does not exist.  If a cookie wasn't been specified, use a
         * default of zero. */
        fm->new_cookie = htonll(0);
    }
    if (fields & F_ACTIONS) {
        struct ofpbuf ofpacts;
        enum ofperr err;

        ofpbuf_init(&ofpacts, 32);
        str_to_inst_ofpacts(act_str, &ofpacts);
        fm->ofpacts_len = ofpacts.size;
        fm->ofpacts = ofpbuf_steal_data(&ofpacts);

        err = ofpacts_check(fm->ofpacts, fm->ofpacts_len, &fm->match.flow,
                            OFPP_MAX, 0);
        if (err) {
            exit(EXIT_FAILURE);
        }

    } else {
        fm->ofpacts_len = 0;
        fm->ofpacts = NULL;
    }

    free(string);
}
Example #15
0
static void
parse_named_action(enum ofputil_action_code code,
                   char *arg, struct ofpbuf *ofpacts)
{
    struct ofpact_tunnel *tunnel;
    uint16_t vid;
    uint16_t ethertype;
    ovs_be32 ip;
    uint8_t pcp;
    uint8_t tos;

    switch (code) {
    case OFPUTIL_ACTION_INVALID:
        NOT_REACHED();

    case OFPUTIL_OFPAT10_OUTPUT:
    case OFPUTIL_OFPAT11_OUTPUT:
        parse_output(arg, ofpacts);
        break;

    case OFPUTIL_OFPAT10_SET_VLAN_VID:
    case OFPUTIL_OFPAT11_SET_VLAN_VID:
        vid = str_to_u32(arg);
        if (vid & ~VLAN_VID_MASK) {
            ovs_fatal(0, "%s: not a valid VLAN VID", arg);
        }
        ofpact_put_SET_VLAN_VID(ofpacts)->vlan_vid = vid;
        break;

    case OFPUTIL_OFPAT10_SET_VLAN_PCP:
    case OFPUTIL_OFPAT11_SET_VLAN_PCP:
        pcp = str_to_u32(arg);
        if (pcp & ~7) {
            ovs_fatal(0, "%s: not a valid VLAN PCP", arg);
        }
        ofpact_put_SET_VLAN_PCP(ofpacts)->vlan_pcp = pcp;
        break;

    case OFPUTIL_OFPAT12_SET_FIELD:
        set_field_parse(arg, ofpacts);
        break;

    case OFPUTIL_OFPAT10_STRIP_VLAN:
    case OFPUTIL_OFPAT11_POP_VLAN:
        ofpact_put_STRIP_VLAN(ofpacts);
        break;

    case OFPUTIL_OFPAT11_PUSH_VLAN:
        ethertype = str_to_u16(arg, "ethertype");
        if (ethertype != ETH_TYPE_VLAN_8021Q) {
            /* XXX ETH_TYPE_VLAN_8021AD case isn't supported */
            ovs_fatal(0, "%s: not a valid VLAN ethertype", arg);
        }
        ofpact_put_PUSH_VLAN(ofpacts);
        break;

    case OFPUTIL_OFPAT11_SET_QUEUE:
        ofpact_put_SET_QUEUE(ofpacts)->queue_id = str_to_u32(arg);
        break;


    case OFPUTIL_OFPAT10_SET_DL_SRC:
    case OFPUTIL_OFPAT11_SET_DL_SRC:
        str_to_mac(arg, ofpact_put_SET_ETH_SRC(ofpacts)->mac);
        break;

    case OFPUTIL_OFPAT10_SET_DL_DST:
    case OFPUTIL_OFPAT11_SET_DL_DST:
        str_to_mac(arg, ofpact_put_SET_ETH_DST(ofpacts)->mac);
        break;

    case OFPUTIL_OFPAT10_SET_NW_SRC:
    case OFPUTIL_OFPAT11_SET_NW_SRC:
        str_to_ip(arg, &ip);
        ofpact_put_SET_IPV4_SRC(ofpacts)->ipv4 = ip;
        break;

    case OFPUTIL_OFPAT10_SET_NW_DST:
    case OFPUTIL_OFPAT11_SET_NW_DST:
        str_to_ip(arg, &ip);
        ofpact_put_SET_IPV4_DST(ofpacts)->ipv4 = ip;
        break;

    case OFPUTIL_OFPAT10_SET_NW_TOS:
    case OFPUTIL_OFPAT11_SET_NW_TOS:
        tos = str_to_u32(arg);
        if (tos & ~IP_DSCP_MASK) {
            ovs_fatal(0, "%s: not a valid TOS", arg);
        }
        ofpact_put_SET_IPV4_DSCP(ofpacts)->dscp = tos;
        break;

    case OFPUTIL_OFPAT11_DEC_NW_TTL:
        NOT_REACHED();

    case OFPUTIL_OFPAT10_SET_TP_SRC:
    case OFPUTIL_OFPAT11_SET_TP_SRC:
        ofpact_put_SET_L4_SRC_PORT(ofpacts)->port = str_to_u32(arg);
        break;

    case OFPUTIL_OFPAT10_SET_TP_DST:
    case OFPUTIL_OFPAT11_SET_TP_DST:
        ofpact_put_SET_L4_DST_PORT(ofpacts)->port = str_to_u32(arg);
        break;

    case OFPUTIL_OFPAT10_ENQUEUE:
        parse_enqueue(arg, ofpacts);
        break;

    case OFPUTIL_NXAST_RESUBMIT:
        parse_resubmit(arg, ofpacts);
        break;

    case OFPUTIL_NXAST_SET_TUNNEL:
    case OFPUTIL_NXAST_SET_TUNNEL64:
        tunnel = ofpact_put_SET_TUNNEL(ofpacts);
        tunnel->ofpact.compat = code;
        tunnel->tun_id = str_to_u64(arg);
        break;

    case OFPUTIL_NXAST_WRITE_METADATA:
        parse_metadata(ofpacts, arg);
        break;

    case OFPUTIL_NXAST_SET_QUEUE:
        ofpact_put_SET_QUEUE(ofpacts)->queue_id = str_to_u32(arg);
        break;

    case OFPUTIL_NXAST_POP_QUEUE:
        ofpact_put_POP_QUEUE(ofpacts);
        break;

    case OFPUTIL_NXAST_REG_MOVE:
        nxm_parse_reg_move(ofpact_put_REG_MOVE(ofpacts), arg);
        break;

    case OFPUTIL_NXAST_REG_LOAD:
        nxm_parse_reg_load(ofpact_put_REG_LOAD(ofpacts), arg);
        break;

    case OFPUTIL_NXAST_NOTE:
        parse_note(arg, ofpacts);
        break;

    case OFPUTIL_NXAST_MULTIPATH:
        multipath_parse(ofpact_put_MULTIPATH(ofpacts), arg);
        break;

    case OFPUTIL_NXAST_BUNDLE:
        bundle_parse(arg, ofpacts);
        break;

    case OFPUTIL_NXAST_BUNDLE_LOAD:
        bundle_parse_load(arg, ofpacts);
        break;

    case OFPUTIL_NXAST_RESUBMIT_TABLE:
    case OFPUTIL_NXAST_OUTPUT_REG:
    case OFPUTIL_NXAST_DEC_TTL_CNT_IDS:
        NOT_REACHED();

    case OFPUTIL_NXAST_LEARN:
        learn_parse(arg, ofpacts);
        break;

    case OFPUTIL_NXAST_EXIT:
        ofpact_put_EXIT(ofpacts);
        break;

    case OFPUTIL_NXAST_DEC_TTL:
        parse_dec_ttl(ofpacts, arg);
        break;

    case OFPUTIL_NXAST_SET_MPLS_TTL:
    case OFPUTIL_OFPAT11_SET_MPLS_TTL:
        parse_set_mpls_ttl(ofpacts, arg);
        break;

    case OFPUTIL_OFPAT11_DEC_MPLS_TTL:
    case OFPUTIL_NXAST_DEC_MPLS_TTL:
        ofpact_put_DEC_MPLS_TTL(ofpacts);
        break;

    case OFPUTIL_NXAST_FIN_TIMEOUT:
        parse_fin_timeout(ofpacts, arg);
        break;

    case OFPUTIL_NXAST_CONTROLLER:
        parse_controller(ofpacts, arg);
        break;

    case OFPUTIL_OFPAT11_PUSH_MPLS:
    case OFPUTIL_NXAST_PUSH_MPLS:
        ofpact_put_PUSH_MPLS(ofpacts)->ethertype =
            htons(str_to_u16(arg, "push_mpls"));
        break;

    case OFPUTIL_OFPAT11_POP_MPLS:
    case OFPUTIL_NXAST_POP_MPLS:
        ofpact_put_POP_MPLS(ofpacts)->ethertype =
            htons(str_to_u16(arg, "pop_mpls"));
        break;

    case OFPUTIL_NXAST_STACK_PUSH:
        nxm_parse_stack_action(ofpact_put_STACK_PUSH(ofpacts), arg);
        break;
    case OFPUTIL_NXAST_STACK_POP:
        nxm_parse_stack_action(ofpact_put_STACK_POP(ofpacts), arg);
        break;

    case OFPUTIL_NXAST_SAMPLE:
        parse_sample(ofpacts, arg);
        break;
    }
}
Example #16
0
int main(int argc, char **argv)
{
    int ch, longindex, ret, port = SD_LISTEN_PORT, io_port = SD_LISTEN_PORT;
    int rc = 1;
    const char *dirp = DEFAULT_OBJECT_DIR, *short_options;
    char *dir, *pid_file = NULL, *bindaddr = NULL, log_path[PATH_MAX],
                *argp = NULL;
    bool explicit_addr = false;
    bool daemonize = true;
    int32_t nr_vnodes = -1;
    int64_t zone = -1;
    struct cluster_driver *cdrv;
    struct option *long_options;
#ifdef HAVE_HTTP
    const char *http_options = NULL;
#endif
    static struct logger_user_info sheep_info;
    struct stat logdir_st;
    enum log_dst_type log_dst_type;

    sys->cinfo.flags |= SD_CLUSTER_FLAG_AUTO_VNODES;
    sys->node_status = SD_NODE_STATUS_INITIALIZATION;

    sys->rthrottling.max_exec_count = 0;
    sys->rthrottling.queue_work_interval = 0;
    sys->rthrottling.throttling = false;

    install_crash_handler(crash_handler);
    signal(SIGPIPE, SIG_IGN);

    install_sighandler(SIGHUP, sighup_handler, false);

    long_options = build_long_options(sheep_options);
    short_options = build_short_options(sheep_options);
    while ((ch = getopt_long(argc, argv, short_options, long_options,
                             &longindex)) >= 0) {
        switch (ch) {
        case 'p':
            port = str_to_u16(optarg);
            if (errno != 0 || port < 1) {
                sd_err("Invalid port number '%s'", optarg);
                exit(1);
            }
            break;
        case 'P':
            pid_file = optarg;
            break;
#ifdef HAVE_HTTP
        case 'r':
            http_options = optarg;
            break;
#endif
        case 'l':
            if (option_parse(optarg, ",", log_parsers) < 0)
                exit(1);
            break;
        case 'n':
            sys->nosync = true;
            break;
        case 'y':
            if (!str_to_addr(optarg, sys->this_node.nid.addr)) {
                sd_err("Invalid address: '%s'", optarg);
                exit(1);
            }
            explicit_addr = true;
            break;
        case 'D':
            sys->backend_dio = true;
            break;
        case 'f':
            daemonize = false;
            break;
        case 'g':
            if (nr_vnodes > 0) {
                sd_err("Options '-g' and '-V' can not be both specified");
                exit(1);
            }
            nr_vnodes = 0;
            break;
        case 'z':
            zone = str_to_u32(optarg);
            if (errno != 0) {
                sd_err("Invalid zone id '%s': must be "
                       "an integer between 0 and %u", optarg,
                       UINT32_MAX);
                exit(1);
            }
            sys->this_node.zone = zone;
            break;
        case 'u':
            sys->upgrade = true;
            break;
        case 'c':
            sys->cdrv = find_cdrv(optarg);
            if (!sys->cdrv) {
                sd_err("Invalid cluster driver '%s'", optarg);
                fprintf(stderr, "Supported drivers:");
                FOR_EACH_CLUSTER_DRIVER(cdrv) {
                    fprintf(stderr, " %s", cdrv->name);
                }
                fprintf(stderr, "\n");
                exit(1);
            }

            sys->cdrv_option = get_cdrv_option(sys->cdrv, optarg);
            break;
        case 'i':
            if (option_parse(optarg, ",", ionic_parsers) < 0)
                exit(1);

            if (!str_to_addr(io_addr, sys->this_node.nid.io_addr)) {
                sd_err("Bad addr: '%s'", io_addr);
                exit(1);
            }

            if (io_pt)
                if (sscanf(io_pt, "%u", &io_port) != 1) {
                    sd_err("Bad port '%s'", io_pt);
                    exit(1);
                }
            sys->this_node.nid.io_port = io_port;
#ifdef HAVE_ACCELIO
            if (!strcmp(io_transport, "tcp"))
                sys->this_node.nid.io_transport_type =
                    IO_TRANSPORT_TYPE_TCP;
            else if (!strcmp(io_transport, "rdma"))
                sys->this_node.nid.io_transport_type =
                    IO_TRANSPORT_TYPE_RDMA;
            else {
                sd_err("unknown transport type: %s",
                       io_transport);
                exit(1);
            }
#endif
            break;
        case 'j':
            uatomic_set_true(&sys->use_journal);
            if (option_parse(optarg, ",", journal_parsers) < 0)
                exit(1);
            if (!jsize) {
                sd_err("you must specify size for journal");
                exit(1);
            }
            break;
        case 'b':
            if (!inetaddr_is_valid(optarg))
                exit(1);
            bindaddr = optarg;
            break;
        case 'h':
            usage(0);
            break;
        case 'R':
            if (option_parse(optarg, ",", recovery_parsers) < 0)
                exit(1);
            sys->rthrottling.max_exec_count = max_exec_count;
            sys->rthrottling.queue_work_interval
                = queue_work_interval;
            if (max_exec_count > 0 && queue_work_interval > 0)
                sys->rthrottling.throttling = true;
            break;
        case 'v':
            fprintf(stdout, "Sheepdog daemon version %s\n",
                    PACKAGE_VERSION);
            exit(0);
            break;
        case 'V':
            sys->cinfo.flags &= ~SD_CLUSTER_FLAG_AUTO_VNODES;
            if (nr_vnodes == 0) {
                sd_err("Options '-g' and '-V' can not be both specified");
                exit(1);
            }
            nr_vnodes = str_to_u16(optarg);
            if (errno != 0 || nr_vnodes < 1) {
                sd_err("Invalid number of vnodes '%s': must be "
                       "an integer between 1 and %u",
                       optarg, UINT16_MAX);
                exit(1);
            }
            break;
        case 'W':
            wildcard_recovery = true;
            break;
        case 'w':
            if (option_parse(optarg, ",", wq_parsers) < 0)
                exit(1);
            break;
        default:
            usage(1);
            break;
        }
    }
Example #17
0
/*
 * PARSER. Field 2 in ARGP.
 */
static int parse_opt(int key, char *arg, struct argp_state *state)
{
	struct arguments *arguments = state->input;
	int error = 0;
	__u16 temp;

	switch (key) {
	case ARGP_POOL6:
		arguments->mode = MODE_POOL6;
		break;
	case ARGP_POOL4:
		arguments->mode = MODE_POOL4;
		break;
	case ARGP_BIB:
		arguments->mode = MODE_BIB;
		break;
	case ARGP_SESSION:
		arguments->mode = MODE_SESSION;
		break;
	case ARGP_FILTERING:
		arguments->mode = MODE_FILTERING;
		break;
	case ARGP_TRANSLATE:
		arguments->mode = MODE_TRANSLATE;
		break;

	case ARGP_DISPLAY:
		arguments->operation = OP_DISPLAY;
		break;
	case ARGP_ADD:
		arguments->operation = OP_ADD;
		break;
	case ARGP_REMOVE:
		arguments->operation = OP_REMOVE;
		break;

	case ARGP_UDP:
		arguments->udp = true;
		break;
	case ARGP_TCP:
		arguments->tcp = true;
		break;
	case ARGP_ICMP:
		arguments->icmp = true;
		break;

	case ARGP_ADDRESS:
		error = str_to_addr4(arg, &arguments->pool4_addr);
		arguments->pool4_addr_set = true;
		break;
	case ARGP_PREFIX:
		error = str_to_prefix(arg, &arguments->pool6_prefix);
		arguments->pool6_prefix_set = true;
		break;
//	case ARGP_STATIC:
//		arguments->static_entries = true;
//		break;
//	case ARGP_DYNAMIC:
//		arguments->dynamic_entries = true;
//		break;
//
//	case ARGP_IPV6:
//		error = str_to_addr6_port(arg, &arguments->bib_addr6);
//		arguments->bib_addr6_set = true;
//		break;
//	case ARGP_IPV4:
//		error = str_to_addr4_port(arg, &arguments->bib_addr4);
//		arguments->bib_addr4_set = true;
//		break;
	case ARGP_REMOTE6:
		error = str_to_addr6_port(arg, &arguments->session_pair6.remote);
		arguments->session_pair6_remote_set = true;
		break;
	case ARGP_LOCAL6:
		error = str_to_addr6_port(arg, &arguments->session_pair6.local);
		arguments->session_pair6_local_set = true;
		break;
	case ARGP_LOCAL4:
		error = str_to_addr4_port(arg, &arguments->session_pair4.local);
		arguments->session_pair4_local_set = true;
		break;
	case ARGP_REMOTE4:
		error = str_to_addr4_port(arg, &arguments->session_pair4.remote);
		arguments->session_pair4_remote_set = true;
		break;

	case ARGP_DROP_ADDR:
		arguments->mode = MODE_FILTERING;
		arguments->operation |= DROP_BY_ADDR_MASK;
		error = str_to_bool(arg, &arguments->filtering.drop_by_addr);
		break;
	case ARGP_DROP_INFO:
		arguments->mode = MODE_FILTERING;
		arguments->operation |= DROP_ICMP6_INFO_MASK;
		error = str_to_bool(arg, &arguments->filtering.drop_icmp6_info);
		break;
//	case ARGP_DROP_TCP:
//		arguments->mode = MODE_FILTERING;
//		arguments->operation |= DROP_EXTERNAL_TCP_MASK;
//		error = str_to_bool(arg, &arguments->filtering.drop_external_tcp);
//		break;
	case ARGP_UDP_TO:
		arguments->mode = MODE_FILTERING;
		arguments->operation |= UDP_TIMEOUT_MASK;
		error = str_to_u16(arg, &temp, UDP_MIN, 0xFFFF);
		arguments->filtering.to.udp = temp;
		break;
	case ARGP_ICMP_TO:
		arguments->mode = MODE_FILTERING;
		arguments->operation |= ICMP_TIMEOUT_MASK;
		error = str_to_u16(arg, &temp, 0, 0xFFFF);
		arguments->filtering.to.icmp = temp;
		break;
	case ARGP_TCP_TO:
		arguments->mode = MODE_FILTERING;
		arguments->operation |= TCP_EST_TIMEOUT_MASK;
		error = str_to_u16(arg, &temp, TCP_EST, 0xFFFF);
		arguments->filtering.to.tcp_est = temp;
		break;
	case ARGP_TCP_TRANS_TO:
		arguments->mode = MODE_FILTERING;
		arguments->operation |= TCP_TRANS_TIMEOUT_MASK;
		error = str_to_u16(arg, &temp, TCP_TRANS, 0xFFFF);
		arguments->filtering.to.tcp_trans = temp;
		break;

	case ARGP_HEAD:
		arguments->mode = MODE_TRANSLATE;
		arguments->operation |= SKB_HEAD_ROOM_MASK;
		error = str_to_u16(arg, &arguments->translate.skb_head_room, 0, 0xFFFF);
		break;
	case ARGP_TAIL:
		arguments->mode = MODE_TRANSLATE;
		arguments->operation |= SKB_TAIL_ROOM_MASK;
		error = str_to_u16(arg, &arguments->translate.skb_tail_room, 0, 0xFFFF);
		break;
	case ARGP_RESET_TCLASS:
		arguments->mode = MODE_TRANSLATE;
		arguments->operation |= RESET_TCLASS_MASK;
		error = str_to_bool(arg, &arguments->translate.reset_traffic_class);
		break;
	case ARGP_RESET_TOS:
		arguments->mode = MODE_TRANSLATE;
		arguments->operation |= RESET_TOS_MASK;
		error = str_to_bool(arg, &arguments->translate.reset_tos);
		break;
	case ARGP_NEW_TOS:
		arguments->mode = MODE_TRANSLATE;
		arguments->operation |= NEW_TOS_MASK;
		error = str_to_u8(arg, &arguments->translate.new_tos, 0, 0xFF);
		break;
	case ARGP_DF:
		arguments->mode = MODE_TRANSLATE;
		arguments->operation |= DF_ALWAYS_ON_MASK;
		error = str_to_bool(arg, &arguments->translate.df_always_on);
		break;
	case ARGP_BUILD_ID:
		arguments->mode = MODE_TRANSLATE;
		arguments->operation |= BUILD_IPV4_ID_MASK;
		error = str_to_bool(arg, &arguments->translate.build_ipv4_id);
		break;
	case ARGP_LOWER_MTU_FAIL:
		arguments->mode = MODE_TRANSLATE;
		arguments->operation |= LOWER_MTU_FAIL_MASK;
		error = str_to_bool(arg, &arguments->translate.lower_mtu_fail);
		break;
	case ARGP_NEXT_MTU6:
		arguments->mode = MODE_TRANSLATE;
		arguments->operation |= IPV6_NEXTHOP_MTU_MASK;
		error = str_to_u16(arg, &arguments->translate.ipv6_nexthop_mtu, 0, 0xFFFF);
		break;
	case ARGP_NEXT_MTU4:
		arguments->mode = MODE_TRANSLATE;
		arguments->operation |= IPV4_NEXTHOP_MTU_MASK;
		error = str_to_u16(arg, &arguments->translate.ipv4_nexthop_mtu, 0, 0xFFFF);
		break;
	case ARGP_PLATEAUS:
		arguments->mode = MODE_TRANSLATE;
		arguments->operation |= MTU_PLATEAUS_MASK;
		error = str_to_u16_array(arg, &arguments->translate.mtu_plateaus,
				&arguments->translate.mtu_plateau_count);
		break;

	default:
		return ARGP_ERR_UNKNOWN;
	}

	return error;
}
Example #18
0
/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man
 * page) into 'fm' for sending the specified flow_mod 'command' to a switch.
 * If 'actions' is specified, an action must be in 'string' and may be expanded
 * or reallocated.
 *
 * To parse syntax for an OFPT_FLOW_MOD (or NXT_FLOW_MOD), use an OFPFC_*
 * constant for 'command'.  To parse syntax for an OFPST_FLOW or
 * OFPST_AGGREGATE (or NXST_FLOW or NXST_AGGREGATE), use -1 for 'command'. */
void
parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
              bool verbose)
{
    enum {
        F_OUT_PORT = 1 << 0,
        F_ACTIONS = 1 << 1,
        F_TIMEOUT = 1 << 3,
        F_PRIORITY = 1 << 4
    } fields;
    char *string = xstrdup(str_);
    char *save_ptr = NULL;
    char *act_str = NULL;
    char *name;

    switch (command) {
    case -1:
        fields = F_OUT_PORT;
        break;

    case OFPFC_ADD:
        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY;
        break;

    case OFPFC_DELETE:
        fields = F_OUT_PORT;
        break;

    case OFPFC_DELETE_STRICT:
        fields = F_OUT_PORT | F_PRIORITY;
        break;

    case OFPFC_MODIFY:
        fields = F_ACTIONS;
        break;

    case OFPFC_MODIFY_STRICT:
        fields = F_ACTIONS | F_PRIORITY;
        break;

    default:
        NOT_REACHED();
    }

    cls_rule_init_catchall(&fm->cr, OFP_DEFAULT_PRIORITY);
    fm->cookie = htonll(0);
    fm->cookie_mask = htonll(0);
    if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) {
        /* For modify, by default, don't update the cookie. */
        fm->new_cookie = htonll(UINT64_MAX);
    } else{
        fm->new_cookie = htonll(0);
    }
    fm->table_id = 0xff;
    fm->command = command;
    fm->idle_timeout = OFP_FLOW_PERMANENT;
    fm->hard_timeout = OFP_FLOW_PERMANENT;
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = 0;
    if (fields & F_ACTIONS) {
        act_str = strstr(string, "action");
        if (!act_str) {
            ofp_fatal(str_, verbose, "must specify an action");
        }
        *act_str = '\0';

        act_str = strchr(act_str + 1, '=');
        if (!act_str) {
            ofp_fatal(str_, verbose, "must specify an action");
        }

        act_str++;
    }
    for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
         name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
        const struct protocol *p;

        if (parse_protocol(name, &p)) {
            cls_rule_set_dl_type(&fm->cr, htons(p->dl_type));
            if (p->nw_proto) {
                cls_rule_set_nw_proto(&fm->cr, p->nw_proto);
            }
        } else {
            char *value;

            value = strtok_r(NULL, ", \t\r\n", &save_ptr);
            if (!value) {
                ofp_fatal(str_, verbose, "field %s missing value", name);
            }

            if (!strcmp(name, "table")) {
                fm->table_id = str_to_table_id(value);
            } else if (!strcmp(name, "out_port")) {
                fm->out_port = atoi(value);
            } else if (fields & F_PRIORITY && !strcmp(name, "priority")) {
                fm->cr.priority = str_to_u16(value, name);
            } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) {
                fm->idle_timeout = str_to_u16(value, name);
            } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) {
                fm->hard_timeout = str_to_u16(value, name);
            } else if (!strcmp(name, "cookie")) {
                char *mask = strchr(value, '/');

                if (mask) {
                    /* A mask means we're searching for a cookie. */
                    if (command == OFPFC_ADD) {
                        ofp_fatal(str_, verbose, "flow additions cannot use "
                                  "a cookie mask");
                    }
                    *mask = '\0';
                    fm->cookie = htonll(str_to_u64(value));
                    fm->cookie_mask = htonll(str_to_u64(mask+1));
                } else {
                    /* No mask means that the cookie is being set. */
                    if (command != OFPFC_ADD && command != OFPFC_MODIFY
                            && command != OFPFC_MODIFY_STRICT) {
                        ofp_fatal(str_, verbose, "cannot set cookie");
                    }
                    fm->new_cookie = htonll(str_to_u64(value));
                }
            } else if (mf_from_name(name)) {
                parse_field(mf_from_name(name), value, &fm->cr);
            } else if (!strcmp(name, "duration")
                       || !strcmp(name, "n_packets")
                       || !strcmp(name, "n_bytes")) {
                /* Ignore these, so that users can feed the output of
                 * "ovs-ofctl dump-flows" back into commands that parse
                 * flows. */
            } else {
                ofp_fatal(str_, verbose, "unknown keyword %s", name);
            }
        }
    }
    if (!fm->cookie_mask && fm->new_cookie == htonll(UINT64_MAX)
            && (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT)) {
        /* On modifies without a mask, we are supposed to add a flow if
         * one does not exist.  If a cookie wasn't been specified, use a
         * default of zero. */
        fm->new_cookie = htonll(0);
    }
    if (fields & F_ACTIONS) {
        struct ofpbuf actions;

        ofpbuf_init(&actions, sizeof(union ofp_action));
        str_to_action(&fm->cr.flow, act_str, &actions);
        fm->actions = ofpbuf_steal_data(&actions);
        fm->n_actions = actions.size / sizeof(union ofp_action);
    } else {
        fm->actions = NULL;
        fm->n_actions = 0;
    }

    free(string);
}