Пример #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, &prefix_out->addr);
	if (error)
		return error;

	token = strtok(NULL, "/");
	if (!token) {
		prefix_out->len = IPV4_MAX_PREFIX;
		return 0;
	}
	return str_to_u8(token, &prefix_out->len, 0, 32); /* Error msg already printed. */
}

#undef STR_MAX_LEN
#define STR_MAX_LEN (INET6_ADDRSTRLEN + 1 + 3) /* [addr + null chara] + / + pref len */
int str_to_prefix6(const char *str, struct ipv6_prefix *prefix_out)
{
	const char *FORMAT = "<IPv6 address>[/<length>] (eg. 64:ff9b::/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, &prefix_out->addr);
	if (error)
		return error;

	token = strtok(NULL, "/");
	if (!token) {
		prefix_out->len = IPV6_MAX_PREFIX;
		return 0;
	}
	return str_to_u8(token, &prefix_out->len, 0, 128); /* Error msg already printed. */
}
Пример #2
0
/* Convert 'str_' (as described in the documentation for the "monitor" command
 * in the ovs-ofctl man page) into 'fmr'. */
void
parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr,
                           const char *str_)
{
    static uint32_t id;

    char *string = xstrdup(str_);
    char *save_ptr = NULL;
    char *name;

    fmr->id = id++;
    fmr->flags = (NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE | NXFMF_MODIFY
                  | NXFMF_OWN | NXFMF_ACTIONS);
    fmr->out_port = OFPP_NONE;
    fmr->table_id = 0xff;
    match_init_catchall(&fmr->match);

    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 (!strcmp(name, "!initial")) {
            fmr->flags &= ~NXFMF_INITIAL;
        } else if (!strcmp(name, "!add")) {
            fmr->flags &= ~NXFMF_ADD;
        } else if (!strcmp(name, "!delete")) {
            fmr->flags &= ~NXFMF_DELETE;
        } else if (!strcmp(name, "!modify")) {
            fmr->flags &= ~NXFMF_MODIFY;
        } else if (!strcmp(name, "!actions")) {
            fmr->flags &= ~NXFMF_ACTIONS;
        } else if (!strcmp(name, "!own")) {
            fmr->flags &= ~NXFMF_OWN;
        } else if (parse_protocol(name, &p)) {
            match_set_dl_type(&fmr->match, htons(p->dl_type));
            if (p->nw_proto) {
                match_set_nw_proto(&fmr->match, p->nw_proto);
            }
        } else {
            char *value;

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

            if (!strcmp(name, "table")) {
                fmr->table_id = str_to_u8(value, name);
            } else if (!strcmp(name, "out_port")) {
                fmr->out_port = u16_to_ofp(atoi(value));
            } else if (mf_from_name(name)) {
                parse_field(mf_from_name(name), value, &fmr->match);
            } else {
                ovs_fatal(0, "%s: unknown keyword %s", str_, name);
            }
        }
    }
    free(string);
}
Пример #3
0
static int set_general_u8(struct arguments *args, enum general_module module, __u8 type,
		char *value, __u8 min, __u8 max)
{
	__u8 tmp;
	int error;

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

	return set_general_arg(args, module, type, sizeof(tmp), &tmp);
}
Пример #4
0
/**
 * Load subnet array.
 * @param[in] cfg Config section.
 * @param[in] option Option name.
 * @param[in,out] array Resulting array.
 * @return <0 - error. 0 - success. >0 - not found.
 */
static int zcfg_load_subnet_list(const config_setting_t *option, zsubnet_group_t *array)
{
    utarray_init(array, &ut_ip_range_icd);

    if (!option) {
        return 1;
    }

    if (CONFIG_TYPE_LIST != option->type) {
        return -1;
    }

    int count = config_setting_length(option);

    for (int i = 0; i < count; i++) {
        ip_range_t range;
        char ip_str[INET_ADDRSTRLEN];
        const char *item = config_setting_get_string_elem(option, i);
        const char *cidr_pos = strchr(item, '/');

        // search CIDR, and make sure, that ip part is not bigger than buffer size
        if (cidr_pos && (((size_t) (cidr_pos - item) < sizeof(ip_str)))) {
            strncpy(ip_str, item, cidr_pos - item);
            ip_str[cidr_pos - item] = '\0';

            struct in_addr ip_addr;
            if (0 < inet_pton(AF_INET, ip_str, &ip_addr)) {
                uint8_t cidr = 0;
                if ((0 == str_to_u8(cidr_pos + 1, &cidr)) && (cidr <= CIDR_MAX)) {
                    range.ip_start = ntohl(ip_addr.s_addr);
                    range.ip_end = IP_RANGE_END(range.ip_start, cidr);
                    utarray_push_back(array, &range);
                    continue;
                }
            }
        }

        // error handler
        ZLOG(LOG_ERR, "config:%s:%s: invalid subnet: %s", option->parent->name, option->name, item);
        utarray_done(array);
        return -1;
    }

    if (count) {
        utarray_sort(array, ip_range_cmp);
    }

    return 0;
}
Пример #5
0
static void
parse_named_instruction(enum ovs_instruction_type type,
                        char *arg, struct ofpbuf *ofpacts)
{
    enum ofperr error;

    switch (type) {
    case OVSINST_OFPIT11_APPLY_ACTIONS:
        NOT_REACHED();  /* This case is handled by str_to_inst_ofpacts() */
        break;

    case OVSINST_OFPIT11_WRITE_ACTIONS:
        /* XXX */
        ovs_fatal(0, "instruction write-actions is not supported yet");
        break;

    case OVSINST_OFPIT11_CLEAR_ACTIONS:
        ofpact_put_CLEAR_ACTIONS(ofpacts);
        break;

    case OVSINST_OFPIT13_METER:
        ofpact_put_METER(ofpacts)->meter_id = str_to_u32(arg);
        break;

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

    case OVSINST_OFPIT11_GOTO_TABLE: {
        struct ofpact_goto_table *ogt = ofpact_put_GOTO_TABLE(ofpacts);
        char *table_s = strsep(&arg, ",");
        if (!table_s || !table_s[0]) {
            ovs_fatal(0, "instruction goto-table needs table id");
        }
        ogt->table_id = str_to_u8(table_s, "table");
        break;
    }
    }

    /* If write_metadata is specified as an action AND an instruction, ofpacts
       could be invalid. */
    error = ofpacts_verify(ofpacts->data, ofpacts->size);
    if (error) {
        ovs_fatal(0, "Incorrect instruction ordering");
    }
}
Пример #6
0
int str_to_prefix(const char *str, struct ipv6_prefix *prefix_out)
{
	const char *FORMAT = "<IPv6 address>/<length> (eg. 64:ff9b::/96)";
	/* [addr + null chara] + / + pref len */
	const unsigned int STR_MAX_LEN = INET6_ADDRSTRLEN + 1 + 3;
	/* strtok corrupts the string, so we'll be using this copy instead. */
	char str_copy[STR_MAX_LEN];
	char *token;
	__u8 valid_lengths[] = POOL6_PREFIX_LENGTHS;
	int valid_lengths_size = sizeof(valid_lengths) / sizeof(valid_lengths[0]);
	int i;
	int error;

	if (strlen(str) + 1 > STR_MAX_LEN) {
		log_err(ERR_PARSE_PREFIX, "'%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_PREFIX, "Cannot parse '%s' as a %s.", str, FORMAT);
		return -EINVAL;
	}

	error = str_to_addr6(token, &prefix_out->address);
	if (error)
		return error;

	token = strtok(NULL, "/");
	if (!token) {
		log_err(ERR_PARSE_PREFIX, "'%s' does not seem to contain a mask (format: %s).", str, FORMAT);
		return -EINVAL;
	}
	error = str_to_u8(token, &prefix_out->len, 0, 0xFF);
	if (error)
		return error; /* Error msg already printed. */

	for (i = 0; i < valid_lengths_size; i++)
		if (prefix_out->len == valid_lengths[i])
			return 0;

	log_err(ERR_PREF_LEN_RANGE, "%u is not a valid prefix length.", prefix_out->len);
	return -EINVAL;
}
Пример #7
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;
}
Пример #8
0
bool str_to_prefix(const char *str, struct ipv6_prefix *prefix_out)
{
	const char *FORMAT = "<IPv6 address>/<length> (eg. 64:ff9b::/96)";
	const int STR_MAX_LEN = INET6_ADDRSTRLEN + 1 + 3; // [addr + null chara] + / + prefix len
	char str_copy[STR_MAX_LEN]; // strtok corrupts the string, so we'll be using this copy instead.
	char *token;
	__u8 valid_lengths[] = POOL6_PREFIX_LENGTHS;
	int valid_lengths_size = sizeof(valid_lengths) / sizeof((valid_lengths)[0]);
	int i;

	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, &prefix_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 mask (format: %s).\n", str, FORMAT);
		return false;
	}
	if (!str_to_u8(token, &prefix_out->len, 0, 0xFF))
		return false; // Error msg already printed.

	for (i = 0; i < valid_lengths_size; i++)
		if (prefix_out->len == valid_lengths[i])
			return true;

	printf("Error: %u is not a valid prefix length.\n", prefix_out->len);
	return false;
}
Пример #9
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);
}
Пример #10
0
/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man
 * page) into 'mm' for sending the specified meter_mod 'command' to a switch.
 */
void
parse_ofp_meter_mod_str(struct ofputil_meter_mod *mm, const char *str_,
                        int command, bool verbose)
{
    enum {
        F_METER = 1 << 0,
        F_FLAGS = 1 << 1,
        F_BANDS = 1 << 2,
    } fields;
    char *string = xstrdup(str_);
    char *save_ptr = NULL;
    char *band_str = NULL;
    char *name;

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

    case OFPMC13_ADD:
        fields = F_METER | F_FLAGS | F_BANDS;
        break;

    case OFPMC13_DELETE:
        fields = F_METER;
        break;

    case OFPMC13_MODIFY:
        fields = F_METER | F_FLAGS | F_BANDS;
        break;

    default:
        NOT_REACHED();
    }

    mm->command = command;
    mm->meter.meter_id = 0;
    mm->meter.flags = 0;
    if (fields & F_BANDS) {
        band_str = strstr(string, "band");
        if (!band_str) {
            ofp_fatal(str_, verbose, "must specify bands");
        }
        *band_str = '\0';

        band_str = strchr(band_str + 1, '=');
        if (!band_str) {
            ofp_fatal(str_, verbose, "must specify bands");
        }

        band_str++;
    }
    for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
         name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {

        if (fields & F_FLAGS && !strcmp(name, "kbps")) {
            mm->meter.flags |= OFPMF13_KBPS;
        } else if (fields & F_FLAGS && !strcmp(name, "pktps")) {
            mm->meter.flags |= OFPMF13_PKTPS;
        } else if (fields & F_FLAGS && !strcmp(name, "burst")) {
            mm->meter.flags |= OFPMF13_BURST;
        } else if (fields & F_FLAGS && !strcmp(name, "stats")) {
            mm->meter.flags |= OFPMF13_STATS;
        } 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, "meter")) {
                if (!strcmp(value, "all")) {
                    mm->meter.meter_id = OFPM13_ALL;
                } else if (!strcmp(value, "controller")) {
                    mm->meter.meter_id = OFPM13_CONTROLLER;
                } else if (!strcmp(value, "slowpath")) {
                    mm->meter.meter_id = OFPM13_SLOWPATH;
                } else {
                    mm->meter.meter_id = str_to_u32(value);
                    if (mm->meter.meter_id > OFPM13_MAX) {
                        ofp_fatal(str_, verbose, "invalid value for %s", name);
                    }
                }
            } else {
                ofp_fatal(str_, verbose, "unknown keyword %s", name);
            }
        }
    }
    if (fields & F_METER && !mm->meter.meter_id) {
        ofp_fatal(str_, verbose, "must specify 'meter'");
    }
    if (fields & F_FLAGS && !mm->meter.flags) {
        ofp_fatal(str_, verbose,
                  "meter must specify either 'kbps' or 'pktps'");
    }

    if (fields & F_BANDS) {
        struct ofpbuf bands;
        uint16_t n_bands = 0;
        struct ofputil_meter_band *band = NULL;
        int i;

        ofpbuf_init(&bands, 64);

        for (name = strtok_r(band_str, "=, \t\r\n", &save_ptr); name;
             name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {

            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, "type")) {
                /* Start a new band */
                band = ofpbuf_put_zeros(&bands, sizeof *band);
                n_bands++;

                if (!strcmp(value, "drop")) {
                    band->type = OFPMBT13_DROP;
                } else if (!strcmp(value, "dscp_remark")) {
                    band->type = OFPMBT13_DSCP_REMARK;
                } else {
                    ofp_fatal(str_, verbose, "field %s unknown value %s", name,
                              value);
                }
            } else if (!band || !band->type) {
                ofp_fatal(str_, verbose,
                          "band must start with the 'type' keyword");
            } else if (!strcmp(name, "rate")) {
                band->rate = str_to_u32(value);
            } else if (!strcmp(name, "burst_size")) {
                band->burst_size = str_to_u32(value);
            } else if (!strcmp(name, "prec_level")) {
                band->prec_level = str_to_u8(value, name);
            } else {
                ofp_fatal(str_, verbose, "unknown keyword %s", name);
            }
        }
        /* validate bands */
        if (!n_bands) {
            ofp_fatal(str_, verbose, "meter must have bands");
        }

        mm->meter.n_bands = n_bands;
        mm->meter.bands = ofpbuf_steal_data(&bands);

        for (i = 0; i < n_bands; ++i) {
            band = &mm->meter.bands[i];

            if (!band->type) {
                ofp_fatal(str_, verbose, "band must have 'type'");
            }
            if (band->type == OFPMBT13_DSCP_REMARK) {
                if (!band->prec_level) {
                    ofp_fatal(str_, verbose, "'dscp_remark' band must have"
                              " 'prec_level'");
                }
            } else {
                if (band->prec_level) {
                    ofp_fatal(str_, verbose, "Only 'dscp_remark' band may have"
                              " 'prec_level'");
                }
            }
            if (!band->rate) {
                ofp_fatal(str_, verbose, "band must have 'rate'");
            }
            if (mm->meter.flags & OFPMF13_BURST) {
                if (!band->burst_size) {
                    ofp_fatal(str_, verbose, "band must have 'burst_size' "
                              "when 'burst' flag is set");
                }
            } else {
                if (band->burst_size) {
                    ofp_fatal(str_, verbose, "band may have 'burst_size' only "
                              "when 'burst' flag is set");
                }
            }
        }
    } else {
        mm->meter.n_bands = 0;
        mm->meter.bands = NULL;
    }

    free(string);
}
Пример #11
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;
}