예제 #1
0
int parse_ip(uint32_t *addr, const char *saddr)
{
	if (parse_vars(&saddr, saddr)) {
		return -1;
	}

	char *ip_parts[5];

	char saddr_cpy[MAX_STR_LEN_PROC];
	if (strlen(saddr) > MAX_STR_LEN_PROC) {
		set_errf("String too long (max supported: %d)", MAX_STR_LEN_PROC);
		return -2;
	}
	strncpy(saddr_cpy, saddr, MAX_STR_LEN_PROC);

	if (4 != rte_strsplit(saddr_cpy, strlen(saddr_cpy), ip_parts, 5, '.')) {
		set_errf("Expecting 4 octets in ip.");
		return -1;
	}

	uint32_t val;
	for (uint8_t i = 0; i < 4; ++i) {
		val = atoi(ip_parts[i]);
		if (val > 255) {
			set_errf("Maximum value for octet is 255 but octet %u is %u", i, val);
			return -1;
		}
		*addr = *addr << 8 | val;
	}
	return 0;
}
예제 #2
0
int parse_int_mask(uint32_t *val, uint32_t *mask, const char *str)
{
	char str_cpy[MAX_STR_LEN_PROC];
	char *mask_str;

	if (parse_vars(&str, str)) {
		return -1;
	}

	if (strlen(str) > MAX_STR_LEN_PROC) {
		set_errf("String too long (max supported: %d)", MAX_STR_LEN_PROC);
		return -2;
	}
	strncpy(str_cpy, str, MAX_STR_LEN_PROC);


	mask_str = strchr(str_cpy, '&');

	if (mask_str == NULL) {
		set_errf("Missing '&' when parsing mask");
		return -2;
	}

	*mask_str = 0;

	if (parse_int(val, str))
		return -1;
	if (parse_int(mask, mask_str + 1))
		return -1;

	return 0;
}
예제 #3
0
int parse_ip4_cidr(struct ip4_subnet *val, const char *str2)
{
	char str[MAX_STR_LEN_PROC];
	char *slash;
	int prefix;

	if (parse_vars(str, sizeof(str), str2))
		return -1;

	slash = strstr(str, "/");

	if (slash == NULL) {
		set_errf("Missing '/' when parsing CIDR notation");
		return -2;
	}

	*slash = 0;
	prefix = atoi(slash + 1);
	val->prefix = prefix;

	if (prefix > 32) {
		set_errf("Prefix %d is too big", prefix);
		return -2;
	}
	if (prefix < 1) {
		set_errf("Prefix %d is too small", prefix);
	}
	if (parse_ip(&val->ip, str))
		return -2;

	/* Apply mask making all bits outside the prefix zero */
	val->ip &= ((int)(1 << 31)) >> (prefix - 1);

	return 0;
}
예제 #4
0
int parse_ip6_cidr(struct ip6_subnet *val, const char *saddr)
{
	char saddr_cpy[MAX_STR_LEN_PROC];
	char *slash;
	int prefix;
	if (parse_vars(&saddr, saddr)) {
		return -1;
	}

	if (strlen(saddr) > MAX_STR_LEN_PROC) {
		set_errf("String too long (max supported: %d)", MAX_STR_LEN_PROC);
		return -2;
	}

	strncpy(saddr_cpy, saddr, MAX_STR_LEN_PROC);
	slash = strstr(saddr_cpy, "/");

	if (slash == NULL) {
		set_errf("Missing '/' when parsing CIDR notation");
		return -2;
	}

	*slash = 0;
	prefix = atoi(slash + 1);
	val->prefix = prefix;

	parse_ip6((struct ipv6_addr *)&val->ip, saddr_cpy);

	/* Apply mask making all bits outside the prefix zero */

	int p = 120;
	int cnt = 0;

	while (p >= prefix) {
		val->ip[15-cnt] = 0;
		p -= 8;
		cnt++;
	}

	if (prefix % 8 != 0) {
		val->ip[15-cnt] &= ((int8_t)(1 << 7)) >> ((prefix %8) - 1);
	}
예제 #5
0
int parse_ip4_cidr(struct ip4_subnet *val, const char *saddr)
{
	char saddr_cpy[MAX_STR_LEN_PROC];
	char *slash;
	int prefix;

	if (parse_vars(&saddr, saddr)) {
		return -1;
	}

	if (strlen(saddr) > MAX_STR_LEN_PROC) {
		set_errf("String too long (max supported: %d)", MAX_STR_LEN_PROC);
		return -2;
	}

	strncpy(saddr_cpy, saddr, MAX_STR_LEN_PROC);
	slash = strstr(saddr_cpy, "/");

	if (slash == NULL) {
		set_errf("Missing '/' when parsing CIDR notation");
		return -2;
	}

	*slash = 0;
	prefix = atoi(slash + 1);
	val->prefix = prefix;

	if (prefix > 32) {
		set_errf("Prefix %d is too big", prefix);
		return -2;
	}
	if (prefix < 1) {
		set_errf("Prefix %d is too small", prefix);
	}
	if (parse_ip(&val->ip, saddr_cpy))
		return -2;

	/* Apply mask making all bits outside the prefix zero */
	val->ip &= ((int)(1 << 31)) >> (prefix - 1);

	return 0;
}
예제 #6
0
static int parse_single_var(const char **val, const char *name)
{
	for (uint8_t i = 0; i < nb_vars; ++i) {
		if (!strcmp(name, vars[i].name)) {
                        *val = vars[i].val;
			return 0;
		}
	}
	set_errf("Variable '%s' not defined!", name);
	return 1;
}
예제 #7
0
static int parse_single_var(char *val, size_t len, const char *name)
{
	struct var *match;

	match = var_lookup(name);
	if (match) {
		if (strlen(match->val) + 1 > len) {
			set_errf("Variables '%s' with value '%s' is too long\n",
				 match->name, match->val);
			return -1;
		}
		strncpy(val, match->val, len);
		return 0;
	}
	else {
		/* name + 1 to skip leading '$' */
		if (lua_to_string(prox_lua(), GLOBAL, name + 1, val, len) >= 0)
			return 0;
	}

	set_errf("Variable '%s' not defined!", name);
	return 1;
}
예제 #8
0
int parse_range(uint32_t* lo, uint32_t* hi, const char *str2)
{
	char str[MAX_STR_LEN_PROC];
	char *dash;

	if (parse_vars(str, sizeof(str), str2))
		return -1;

	dash = strstr(str, "-");

	if (dash == NULL) {
		set_errf("Missing '-' when parsing mask");
		return -2;
	}

	*dash = 0;

	if (parse_int(lo, str))
		return -1;
	if (parse_int(hi, dash + 1))
		return -1;

	int64_t tmp = strtol(str, 0, 0);
	if (tmp > UINT32_MAX) {
		set_errf("Integer is bigger than %u", UINT32_MAX);
		return -1;
	}
	if (tmp < 0) {
		set_errf("Integer is negative");
		return -2;
	}

	*lo = tmp;

	tmp = strtol(dash + 1, 0, 0);
	if (tmp > UINT32_MAX) {
		set_errf("Integer is bigger than %u", UINT32_MAX);
		return -1;
	}
	if (tmp < 0) {
		set_errf("Integer is negative");
		return -2;
	}

	*hi = tmp;

	if (*lo > *hi) {
		set_errf("Low boundary is above high boundary in range");
		return -2;
	}

	return 0;
}
예제 #9
0
int parse_ip6_cidr(struct ip6_subnet *val, const char *str2)
{
	char str[MAX_STR_LEN_PROC];
	char *slash;
	int prefix;

	if (parse_vars(str, sizeof(str), str2))
		return -1;

	slash = strstr(str, "/");

	if (slash == NULL) {
		set_errf("Missing '/' when parsing CIDR notation");
		return -2;
	}

	*slash = 0;
	prefix = atoi(slash + 1);
	val->prefix = prefix;

	parse_ip6((struct ipv6_addr *)&val->ip, str);

	/* Apply mask making all bits outside the prefix zero */

	int p = 120;
	int cnt = 0;

	while (p >= prefix) {
		val->ip[15-cnt] = 0;
		p -= 8;
		cnt++;
	}

	if (prefix % 8 != 0) {
		val->ip[15-cnt] &= ((int8_t)(1 << 7)) >> ((prefix %8) - 1);
	}
예제 #10
0
int parse_int_mask(uint32_t *val, uint32_t *mask, const char *str2)
{
	char str[MAX_STR_LEN_PROC];
	char *mask_str;

	if (parse_vars(str, sizeof(str), str2))
		return -1;

	mask_str = strchr(str, '&');

	if (mask_str == NULL) {
		set_errf("Missing '&' when parsing mask");
		return -2;
	}

	*mask_str = 0;

	if (parse_int(val, str))
		return -1;
	if (parse_int(mask, mask_str + 1))
		return -1;

	return 0;
}
예제 #11
0
int parse_range(uint32_t* lo, uint32_t* hi, const char *str)
{
	char str_cpy[MAX_STR_LEN_PROC];
	char *dash;

	if (parse_vars(&str, str)) {
		return -1;
	}

	if (strlen(str) > MAX_STR_LEN_PROC) {
		set_errf("String too long (max supported: %d)", MAX_STR_LEN_PROC);
		return -2;
	}

	strncpy(str_cpy, str, MAX_STR_LEN_PROC);

	dash = strstr(str_cpy, "-");

	if (dash == NULL) {
		set_errf("Missing '-' when parsing mask");
		return -2;
	}

	*dash = 0;

	if (parse_int(lo, str_cpy))
		return -1;
	if (parse_int(hi, dash + 1))
		return -1;


	int64_t tmp = strtol(str_cpy, 0, 0);
	if (tmp > UINT32_MAX) {
		set_errf("Integer is bigger than %u", UINT32_MAX);
		return -1;
	}
	if (tmp < 0) {
		set_errf("Integer is negative");
		return -2;
	}

	*lo = tmp;

	tmp = strtol(dash + 1, 0, 0);
	if (tmp > UINT32_MAX) {
		set_errf("Integer is bigger than %u", UINT32_MAX);
		return -1;
	}
	if (tmp < 0) {
		set_errf("Integer is negative");
		return -2;
	}

	*hi = tmp;

	if (*lo > *hi) {
		set_errf("Low boundary is above high boundary in range");
		return -2;
	}

	return 0;
}
예제 #12
0
/* Replace $... and each occurrence of ${...} with what has been added
   through add_var */
static int parse_vars(const char **val, const char *name)
{
	static char result[2048];
	static char cur_var[2048];
	size_t name_len = strlen(name);
	enum parse_vars_state {NO_VAR, WHOLE_VAR, INLINE_VAR} state = NO_VAR;
	size_t result_len = 0;
	size_t start_var = 0;

	if (name == result) {
		*val = name;
		return 0;
	}

	memset(result, 0, sizeof(result));
	PROX_PANIC(name_len > sizeof(result), "\tUnable to parse var %s: too long\n", name);
		
	for (size_t i = 0; i < name_len; ++i) {
		switch (state) {
		case NO_VAR:
			if (name[i] == '$') {
				if (i != name_len - 1 && name[i + 1] == '{') {
					start_var = i + 2;
					state = INLINE_VAR;
					i = i + 1;
				}
				else if (i == 0 && i != name_len - 1) {
					state = WHOLE_VAR;
				}
				else {
					set_errf("Invalid variable syntax");
					return -1;
				}
			}
			else {
				result[result_len++] = name[i];
			}
			break;
		case INLINE_VAR:
			if (name[i] == '}') {
				const char *parsed;

				cur_var[0] = '$';
				size_t var_len = i - start_var;
				if (var_len == 0) {
					set_errf("Empty variable are not allowed");
					return -1;
				}

				strncpy(&cur_var[1], &name[start_var], var_len);
				cur_var[1 + var_len] = 0;
				if (parse_single_var(&parsed, cur_var)) {
					return -1;
				}
				strcpy(&result[result_len], parsed);
				result_len += strlen(parsed);
				state = NO_VAR;
			}
			else if (i == name_len - 1) {
				set_errf("Invalid variable syntax, expected '}'.");
				return -1;
			}
			break;
		case WHOLE_VAR:
			if (i == name_len - 1) {
				return parse_single_var(val, name);
			}
			break;
		}
	}
	*val = result;
	return 0;
}