Exemple #1
0
/**
 * ipset_parse_iptimeout - parse IPv4|IPv6 address and timeout
 * @session: session structure
 * @opt: option kind of the data
 * @str: string to parse
 *
 * Parse string as an IPv4|IPv6 address and timeout parameter.
 * If family is not set yet in the data blob, INET is assumed.
 * The value is stored in the data blob of the session.
 *
 * Compatibility parser.
 *
 * Returns 0 on success or a negative error code.
 */
int
ipset_parse_iptimeout(struct ipset_session *session,
		      enum ipset_opt opt, const char *str)
{
	char *tmp, *saved, *a;
	int err;

	assert(session);
	assert(opt == IPSET_OPT_IP);
	assert(str);

	/* IP,timeout */
	if (ipset_data_flags_test(ipset_session_data(session),
				  IPSET_FLAG(IPSET_OPT_TIMEOUT)))
		return syntax_err("mixed syntax, timeout already specified");
		 
	tmp = saved = strdup(str);	
	if (saved == NULL)
		return ipset_err(session,
				 "Cannot allocate memory to duplicate %s.",
				 str);

	a = elem_separator(tmp);
	if (a == NULL) {
		free(saved);
		return syntax_err("Missing separator from %s", str);
	}
	*a++ = '\0';
	err = parse_ip(session, opt, tmp, IPADDR_ANY);
	if (!err)
		err = ipset_parse_uint32(session, IPSET_OPT_TIMEOUT, a);

	free(saved);
	return err;
}
Exemple #2
0
/**
 * ipset_parse_family - parse INET|INET6 family names
 * @session: session structure
 * @opt: option kind of the data
 * @str: string to parse
 *
 * Parse string as an INET|INET6 family name.
 * The value is stored in the data blob of the session.
 *
 * Returns 0 on success or a negative error code.
 */
int
ipset_parse_family(struct ipset_session *session,
		   enum ipset_opt opt, const char *str)
{
	struct ipset_data *data;
	uint8_t family;
	
	assert(session);
	assert(opt == IPSET_OPT_FAMILY);
	assert(str);

	data = ipset_session_data(session);
	if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_FAMILY)))
		syntax_err("protocol family may not be specified "
			   "multiple times");

	if (STREQ(str, "inet") || STREQ(str, "ipv4") || STREQ(str, "-4"))
		family = AF_INET;
	else if (STREQ(str, "inet6") || STREQ(str, "ipv6") || STREQ(str, "-6"))
		family = AF_INET6;
	else if (STREQ(str, "any") || STREQ(str, "unspec"))
		family = AF_UNSPEC;
	else
		return syntax_err("unknown INET family %s", str);
				
	return ipset_data_set(data, opt, &family);
}
Exemple #3
0
/**
 * ipset_parse_name_compat - parse setname as element
 * @session: session structure
 * @opt: option kind of the data
 * @str: string to parse
 *
 * Parse string as a setname or a setname element to add to a set.
 * The pattern "setname,before|after,setname" is recognized and
 * parsed.
 * The value is stored in the data blob of the session.
 *
 * Returns 0 on success or a negative error code.
 */
int
ipset_parse_name_compat(struct ipset_session *session,
			enum ipset_opt opt, const char *str)
{
	char *saved;
	char *a = NULL, *b = NULL, *tmp;
	int err, before = 0;
	const char *sep = IPSET_ELEM_SEPARATOR;
	struct ipset_data *data;

	assert(session);
	assert(opt == IPSET_OPT_NAME);
	assert(str);

	data = ipset_session_data(session);
	if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_NAMEREF)))
		syntax_err("mixed syntax, before|after option already used");

	tmp = saved = strdup(str);	
	if (saved == NULL)
		return ipset_err(session,
				 "Cannot allocate memory to duplicate %s.",
				 str);
	if ((a = elem_separator(tmp)) != NULL) {
		/* setname,[before|after,setname */
		*a++ = '\0';
		if ((b = elem_separator(a)) != NULL)
			*b++ = '\0';
		if (b == NULL
		    || !(STREQ(a, "before") || STREQ(a, "after"))) {
			err = ipset_err(session, "you must specify elements "
					"as setname%s[before|after]%ssetname",
					sep, sep);
			goto out;
		}
		before = STREQ(a, "before");
	}
	check_setname(tmp, saved);
	if ((err = ipset_data_set(data, opt, tmp)) != 0 || b == NULL)
		goto out;

	check_setname(b, saved);
	if ((err = ipset_data_set(data,
				  IPSET_OPT_NAMEREF, b)) != 0)
		goto out;

	if (before)
		err = ipset_data_set(data, IPSET_OPT_BEFORE, &before);

out:
	free(saved);
	return err;
}
Exemple #4
0
/**
 * ipset_print_proto_port - print proto:port
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print protocol and port to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_proto_port(char *buf, unsigned int len,
		       const struct ipset_data *data,
		       enum ipset_opt opt ASSERT_UNUSED,
		       uint8_t env UNUSED)
{
	int size, offset = 0;

	assert(buf);
	assert(len > 0);
	assert(data);
	assert(opt == IPSET_OPT_PORT || opt == IPSET_OPT_PORT2);

	if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_PROTO))) {
		uint8_t proto = *(const uint8_t *) ipset_data_get(data,
							IPSET_OPT_PROTO);
		size = ipset_print_proto(buf, len, data, IPSET_OPT_PROTO, env);
		SNPRINTF_FAILURE(size, len, offset);
		if (len < 2)
			return -ENOSPC;
		size = snprintf(buf + offset, len, IPSET_PROTO_SEPARATOR);
		SNPRINTF_FAILURE(size, len, offset);

		switch (proto) {
		case IPPROTO_TCP:
		case IPPROTO_SCTP:
		case IPPROTO_UDP:
		case IPPROTO_UDPLITE:
			break;
		case IPPROTO_ICMP:
			size = ipset_print_icmp(buf + offset, len, data,
						opt, env);
			goto out;
		case IPPROTO_ICMPV6:
			size = ipset_print_icmpv6(buf + offset, len, data,
						  opt, env);
			goto out;
		default:
			break;
		}
	}
	size = ipset_print_port(buf + offset, len, data, opt, env);
out:
	SNPRINTF_FAILURE(size, len, offset);
	return offset;
}
Exemple #5
0
/**
 * ipset_parse_after - parse string as "after" reference setname
 * @session: session structure
 * @opt: option kind of the data
 * @str: string to parse
 *
 * Parse string as a "after" reference setname for list:set
 * type of sets. The value is stored in the data blob of the session.
 *
 * Returns 0 on success or a negative error code.
 */
int
ipset_parse_after(struct ipset_session *session,
		   enum ipset_opt opt, const char *str)
{
	struct ipset_data *data;

	assert(session);
	assert(opt == IPSET_OPT_NAMEREF);
	assert(str);

	data = ipset_session_data(session);
	if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_NAMEREF)))
		syntax_err("mixed syntax, before|after option already used");

	check_setname(str, NULL);

	return ipset_data_set(data, opt, str);
}
Exemple #6
0
/**
 * ipset_print_name - print setname element string
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print setname element string to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_name(char *buf, unsigned int len,
		 const struct ipset_data *data, enum ipset_opt opt,
		 uint8_t env UNUSED)
{
	const char *name;
	int size, offset = 0;

	assert(buf);
	assert(len > 0);
	assert(data);
	assert(opt == IPSET_OPT_NAME);

	if (len < 2*IPSET_MAXNAMELEN + 2 + strlen("before"))
		return -1;

	name = ipset_data_get(data, opt);
	assert(name);
	size = snprintf(buf, len, "%s", name);
	SNPRINTF_FAILURE(size, len, offset);	

	if (ipset_data_test(data, IPSET_OPT_NAMEREF)) {
		bool before = false;
		if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_FLAGS))) {
			const uint32_t *flags =
				ipset_data_get(data, IPSET_OPT_FLAGS);
			before = (*flags) & IPSET_FLAG_BEFORE;
		}
		size = snprintf(buf + offset, len,
			        " %s %s", before ? "before" : "after",
			        (const char *) ipset_data_get(data,
			        	IPSET_OPT_NAMEREF));
		SNPRINTF_FAILURE(size, len, offset);	
	}

	return offset;
}
Exemple #7
0
				IPSET_ARG_NONE,
			},
			.need = 0,
			.full = 0,
			.help = "",
		},
		[IPSET_ADD] = {
			.args = {
				IPSET_ARG_TIMEOUT,
				IPSET_ARG_NOMATCH,
				IPSET_ARG_PACKETS,
				IPSET_ARG_BYTES,
				IPSET_ARG_ADT_COMMENT,
				IPSET_ARG_NONE,
			},
			.need = IPSET_FLAG(IPSET_OPT_IP)
				| IPSET_FLAG(IPSET_OPT_IP2),
			.full = IPSET_FLAG(IPSET_OPT_IP)
				| IPSET_FLAG(IPSET_OPT_CIDR)
				| IPSET_FLAG(IPSET_OPT_IP_TO)
				| IPSET_FLAG(IPSET_OPT_IP2)
				| IPSET_FLAG(IPSET_OPT_CIDR2)
				| IPSET_FLAG(IPSET_OPT_IP2_TO),
			.help = "IP[/CIDR]|FROM-TO,IP[/CIDR]|FROM-TO",
		},
		[IPSET_DEL] = {
			.args = {
				IPSET_ARG_NONE,
			},
			.need = IPSET_FLAG(IPSET_OPT_IP)
				| IPSET_FLAG(IPSET_OPT_IP2),
Exemple #8
0
/**
 * ipset_parse_proto_port - parse (optional) protocol and a single port
 * @session: session structure
 * @opt: option kind of the data
 * @str: string to parse
 *
 * Parse string as a protocol and port, separated by a colon.
 * The protocol part is optional.
 * The parsed protocol and port numbers are stored in the data
 * blob of the session.
 *
 * Returns 0 on success or a negative error code.
 */
int
ipset_parse_proto_port(struct ipset_session *session,
		       enum ipset_opt opt, const char *str)
{
	struct ipset_data *data;
	char *a, *saved, *tmp;
	const char *proto;
	uint8_t p = IPPROTO_TCP;
	int err = 0;

	assert(session);
	assert(opt == IPSET_OPT_PORT);
	assert(str);

	data = ipset_session_data(session);
	saved = tmp = strdup(str);
	if (tmp == NULL)
		return ipset_err(session,
				 "Cannot allocate memory to duplicate %s.",
				 str);

	a = proto_separator(tmp);
	if (a != NULL) {
		uint8_t family = ipset_data_family(data);

		/* proto:port */
		*a++ = '\0';
		err = ipset_parse_proto(session, IPSET_OPT_PROTO, tmp);
		if (err)
			goto error;
		
		p = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO);
		switch (p) {
		case IPPROTO_TCP:
			proto = tmp;
			tmp = a;
			goto parse_port;
		case IPPROTO_UDP:
			proto = tmp;
			tmp = a;
			goto parse_port;
		case IPPROTO_ICMP:
			if (family != AF_INET) {
				syntax_err("Protocol ICMP can be used with family INET only");
				goto error;
			}
			err = ipset_parse_icmp(session, opt, a);
			break;
		case IPPROTO_ICMPV6:
			if (family != AF_INET6) {
				syntax_err("Protocol ICMPv6 can be used with family INET6 only");
				goto error;
			}
			err = ipset_parse_icmpv6(session, opt, a);
			break;
		default:
			if (!STREQ(a, "0")) {
				syntax_err("Protocol %s can be used with pseudo port value 0 only.");
				goto error;
			}
			ipset_data_flags_set(data, IPSET_FLAG(opt));
		}
		goto error;
	} else {
		proto = "TCP";	
		err = ipset_data_set(data, IPSET_OPT_PROTO, &p);
		if (err)
			goto error;
	}
parse_port:
	err = ipset_parse_tcpudp_port(session, opt, tmp, proto);

error:
	free(saved);
	return err;
}
Exemple #9
0
			.opt = IPSET_OPT_IP
		},
	},
	.cmd = {
		[IPSET_CREATE] = {
			.args = {
				IPSET_ARG_IPRANGE,
				IPSET_ARG_NETMASK,
				IPSET_ARG_TIMEOUT,
				/* Backward compatibility */
				IPSET_ARG_FROM_IP,
				IPSET_ARG_TO_IP,
				IPSET_ARG_NETWORK,
				IPSET_ARG_NONE,
			},
			.need = IPSET_FLAG(IPSET_OPT_IP)
				| IPSET_FLAG(IPSET_OPT_IP_TO),
			.full = IPSET_FLAG(IPSET_OPT_IP)
				| IPSET_FLAG(IPSET_OPT_IP_TO),
			.help = "range IP/CIDR|FROM-TO",
		},
		[IPSET_ADD] = {
			.args = {
				IPSET_ARG_TIMEOUT,
				IPSET_ARG_NONE,
			},
			.need = IPSET_FLAG(IPSET_OPT_IP),
			.full = IPSET_FLAG(IPSET_OPT_IP)
				| IPSET_FLAG(IPSET_OPT_IP_TO),
			.help = "IP|IP/CIDR|FROM-TO",
		},
Exemple #10
0
			.parse = ipset_parse_tcp_udp_port,
			.print = ipset_print_port,
			.opt = IPSET_OPT_PORT
		},
	},
	.cmd = {
		[IPSET_CREATE] = {
			.args = {
				IPSET_ARG_PORTRANGE,
				IPSET_ARG_TIMEOUT,
				/* Backward compatibility */
				IPSET_ARG_FROM_PORT,
				IPSET_ARG_TO_PORT,
				IPSET_ARG_NONE,
			},
			.need = IPSET_FLAG(IPSET_OPT_PORT)
				| IPSET_FLAG(IPSET_OPT_PORT_TO),
			.full = IPSET_FLAG(IPSET_OPT_PORT)
				| IPSET_FLAG(IPSET_OPT_PORT_TO),
			.help = "range [PROTO:]FROM-TO",
		},
		[IPSET_ADD] = {
			.args = {
				IPSET_ARG_TIMEOUT,
				IPSET_ARG_NONE,
			},
			.need = IPSET_FLAG(IPSET_OPT_PORT),
			.full = IPSET_FLAG(IPSET_OPT_PORT)
				| IPSET_FLAG(IPSET_OPT_PORT_TO),
			.help = "[PROTO:]PORT|FROM-TO",
		},
Exemple #11
0
				IPSET_ARG_SIZE,
				IPSET_ARG_TIMEOUT,
				IPSET_ARG_NONE,
			},
			.need = 0,
			.full = 0,
			.help = "",
		},
		[IPSET_ADD] = {
			.args = {
				IPSET_ARG_TIMEOUT,
				IPSET_ARG_BEFORE,
				IPSET_ARG_AFTER,
				IPSET_ARG_NONE,
			},
			.need = IPSET_FLAG(IPSET_OPT_NAME),
			.full = IPSET_FLAG(IPSET_OPT_NAME)
				| IPSET_FLAG(IPSET_OPT_BEFORE),
			.help = "NAME [before|after NAME]",
		},
		[IPSET_DEL] = {
			.args = {
				IPSET_ARG_BEFORE,
				IPSET_ARG_AFTER,
				IPSET_ARG_NONE,
			},
			.need = IPSET_FLAG(IPSET_OPT_NAME),
			.full = IPSET_FLAG(IPSET_OPT_NAME)
				| IPSET_FLAG(IPSET_OPT_BEFORE),
			.help = "NAME [before|after NAME]",
		},