예제 #1
0
/**
 * ipset_print_ipaddr - print IPv4|IPv6 address to string
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print IPv4|IPv6 address or address/cidr to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_ipaddr(char *buf, unsigned int len,
		   const struct ipset_data *data, enum ipset_opt opt,
		   uint8_t env)
{
	const union nf_inet_addr *ip;
	uint8_t family, cidr;
	enum ipset_opt cidropt;
	int flags;

	assert(buf);
	assert(len > 0);
	assert(data);
	assert(opt == IPSET_OPT_IP
	       || opt == IPSET_OPT_IP_TO
	       || opt == IPSET_OPT_IP2);

	family = ipset_data_family(data);
	cidropt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR : IPSET_OPT_CIDR2;
	if (ipset_data_test(data, cidropt))
		cidr = *(const uint8_t *) ipset_data_get(data, cidropt);
	else
		cidr = family == AF_INET6 ? 128 : 32;
	flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;

	ip = ipset_data_get(data, opt);
	assert(ip);
	if (family == AF_INET)
		return snprintf_ipv4(buf, len, flags, ip, cidr);
	else if (family == AF_INET6)
		return snprintf_ipv6(buf, len, flags, ip, cidr);

	return -1;
}
예제 #2
0
/**
 * ipset_print_port - print port or port range
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print port or port range to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_port(char *buf, unsigned int len,
		 const struct ipset_data *data,
		 enum ipset_opt opt ASSERT_UNUSED,
		 uint8_t env UNUSED)
{
	const uint16_t *port;
	int size, offset = 0;

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

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

	port = ipset_data_get(data, IPSET_OPT_PORT);
	assert(port);
	size = snprintf(buf, len, "%u", *port);
	SNPRINTF_FAILURE(size, len, offset);	
	
	if (ipset_data_test(data, IPSET_OPT_PORT_TO)) {
		port = ipset_data_get(data, IPSET_OPT_PORT_TO);
		size = snprintf(buf + offset, len,
			        "%s%u",
			        IPSET_RANGE_SEPARATOR, *port);
		SNPRINTF_FAILURE(size, len, offset);
	}

	return offset;
}
예제 #3
0
/**
 * ipset_print_ip - print IPv4|IPv6 address to string
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print IPv4|IPv6 address, address/cidr or address range to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_ip(char *buf, unsigned int len,
	       const struct ipset_data *data, enum ipset_opt opt,
	       uint8_t env)
{
	const union nf_inet_addr *ip;
	uint8_t family, cidr;
	int flags, size, offset = 0;
	enum ipset_opt cidropt;

	assert(buf);
	assert(len > 0);
	assert(data);
	assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);

	D("len: %u", len);
	family = ipset_data_family(data);
	cidropt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR : IPSET_OPT_CIDR2;
	if (ipset_data_test(data, cidropt)) {
		cidr = *(const uint8_t *) ipset_data_get(data, cidropt);
		D("CIDR: %u", cidr);
	} else
		cidr = family == AF_INET6 ? 128 : 32;
	flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
	
	ip = ipset_data_get(data, opt);
	assert(ip);
	if (family == AF_INET)
		size = snprintf_ipv4(buf, len, flags, ip, cidr);
	else if (family == AF_INET6)
		size = snprintf_ipv6(buf, len, flags, ip, cidr);
	else
		return -1;
	D("size %i, len %u", size, len);
	SNPRINTF_FAILURE(size, len, offset);

	D("len: %u, offset %u", len, offset);
	if (!ipset_data_test(data, IPSET_OPT_IP_TO))
		return offset;

	size = snprintf(buf + offset, len, "%s", IPSET_RANGE_SEPARATOR);
	SNPRINTF_FAILURE(size, len, offset);

	ip = ipset_data_get(data, IPSET_OPT_IP_TO);
	if (family == AF_INET)
		size = snprintf_ipv4(buf + offset, len, flags, ip, cidr);
	else if (family == AF_INET6)
		size = snprintf_ipv6(buf + offset, len, flags, ip, cidr);
	else
		return -1;
	
	SNPRINTF_FAILURE(size, len, offset);	
	return offset;
}
예제 #4
0
/**
 * ipset_print_number - print number to string
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print number to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_number(char *buf, unsigned int len,
		   const struct ipset_data *data, enum ipset_opt opt,
		   uint8_t env UNUSED)
{
	size_t maxsize;
	const void *number;

	assert(buf);
	assert(len > 0);
	assert(data);
	
	number = ipset_data_get(data, opt);
	maxsize = ipset_data_sizeof(opt, AF_INET);
	D("opt: %u, maxsize %zu", opt, maxsize);
	if (maxsize == sizeof(uint8_t))
		return snprintf(buf, len, "%u", *(const uint8_t *) number);
	else if (maxsize == sizeof(uint16_t))
		return snprintf(buf, len, "%u", *(const uint16_t *) number);
	else if (maxsize == sizeof(uint32_t))
		return snprintf(buf, len, "%lu",
				(long unsigned) *(const uint32_t *) number);
	else
		assert(0);
	return 0;
}
예제 #5
0
파일: print.c 프로젝트: cyclops8456/ipset
/**
 * ipset_print_iface - print interface element string
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print interface element string to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_iface(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_IFACE);

	if (len < IFNAMSIZ + strlen("physdev:"))
		return -1;

	if (ipset_data_test(data, IPSET_OPT_PHYSDEV)) {
		size = snprintf(buf, len, "physdev:");
		SNPRINTF_FAILURE(size, len, offset);
	}
	name = ipset_data_get(data, opt);
	assert(name);
	size = snprintf(buf, len, "%s", name);
	SNPRINTF_FAILURE(size, len, offset);
	return offset;
}
예제 #6
0
파일: print.c 프로젝트: Olipro/ipset
int
ipset_print_skbmark(char *buf, unsigned int len,
		    const struct ipset_data *data, enum ipset_opt opt,
		    uint8_t env UNUSED)
{
	int size, offset = 0;
	const uint64_t *skbmark;
	uint32_t mark, mask;

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

	skbmark = ipset_data_get(data, IPSET_OPT_SKBMARK);
	assert(skbmark);
	mark = *skbmark >> 32;
	mask = *skbmark & 0xffffffff;
	if (mask == 0xffffffff)
		size = snprintf(buf + offset, len, "0x%"PRIx32, mark);
	else
		size = snprintf(buf + offset, len,
				"0x%"PRIx32"/0x%"PRIx32, mark, mask);
	SNPRINTF_FAILURE(size, len, offset);
	return offset;
}
예제 #7
0
/**
 * ipset_print_ether - print ethernet address to string
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print Ethernet address to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_ether(char *buf, unsigned int len,
		  const struct ipset_data *data, enum ipset_opt opt,
		  uint8_t env UNUSED)
{
	const unsigned char *ether;
	int i, size, offset = 0;
	
	assert(buf);
	assert(len > 0);
	assert(data);
	assert(opt == IPSET_OPT_ETHER);
	
	if (len < ETH_ALEN*3)
		return -1;
	
	ether = ipset_data_get(data, opt);
	assert(ether);

	size = snprintf(buf, len, "%02X", ether[0]);
	SNPRINTF_FAILURE(size, len, offset);
	for (i = 1; i < ETH_ALEN; i++) {
		size = snprintf(buf + offset, len, ":%02X", ether[i]);
		SNPRINTF_FAILURE(size, len, offset);
	}
	
	return offset;
}
예제 #8
0
파일: print.c 프로젝트: Olipro/ipset
/**
 * ipset_print_elem - print ADT elem according to settype
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print (multipart) element according to settype
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_elem(char *buf, unsigned int len,
		 const struct ipset_data *data, enum ipset_opt opt UNUSED,
		 uint8_t env)
{
	const struct ipset_type *type;
	int size, offset = 0;

	assert(buf);
	assert(len > 0);
	assert(data);

	type = ipset_data_get(data, IPSET_OPT_TYPE);
	if (!type)
		return -1;

	size = type->elem[IPSET_DIM_ONE - 1].print(buf, len, data,
			type->elem[IPSET_DIM_ONE - 1].opt, env);
	SNPRINTF_FAILURE(size, len, offset);
	IF_D(ipset_data_test(data, type->elem[IPSET_DIM_TWO - 1].opt),
	     "print second elem");
	if (type->dimension == IPSET_DIM_ONE ||
	    (type->last_elem_optional &&
	     !ipset_data_test(data, type->elem[IPSET_DIM_TWO - 1].opt)))
		return offset;

	size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
	SNPRINTF_FAILURE(size, len, offset);
	size = type->elem[IPSET_DIM_TWO - 1].print(buf + offset, len, data,
			type->elem[IPSET_DIM_TWO - 1].opt, env);
	SNPRINTF_FAILURE(size, len, offset);
	if (type->dimension == IPSET_DIM_TWO ||
	    (type->last_elem_optional &&
	     !ipset_data_test(data, type->elem[IPSET_DIM_THREE - 1].opt)))
		return offset;

	size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
	SNPRINTF_FAILURE(size, len, offset);
	size = type->elem[IPSET_DIM_THREE - 1].print(buf + offset, len, data,
			type->elem[IPSET_DIM_THREE - 1].opt, env);
	SNPRINTF_FAILURE(size, len, offset);
	if (type->dimension == IPSET_DIM_THREE ||
	    (type->last_elem_optional &&
	     !ipset_data_test(data, type->elem[IPSET_DIM_FOUR - 1].opt)))
		return offset;

	size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
	SNPRINTF_FAILURE(size, len, offset);
	size = type->elem[IPSET_DIM_FOUR - 1].print(buf + offset, len, data,
			type->elem[IPSET_DIM_FOUR - 1].opt, env);
	SNPRINTF_FAILURE(size, len, offset);
	
	return offset;
}
예제 #9
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;
}
예제 #10
0
파일: print.c 프로젝트: Olipro/ipset
/**
 * 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;
}
예제 #11
0
파일: print.c 프로젝트: Olipro/ipset
/**
 * ipset_print_comment - print arbitrary parameter string
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print arbitrary string to output buffer.
 *
 * Return length of printed string or error size.
 */
int ipset_print_comment(char *buf, unsigned int len,
		       const struct ipset_data *data, enum ipset_opt opt,
		       uint8_t env UNUSED)
{
	const char *comment;
	int size, offset = 0;

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

	comment = ipset_data_get(data, opt);
	assert(comment);
	size = snprintf(buf + offset, len, "\"%s\"", comment);
	SNPRINTF_FAILURE(size, len, offset);
	return offset;
}
예제 #12
0
/**
 * ipset_print_type - print ipset type string
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print ipset module string identifier to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_type(char *buf, unsigned int len,
		 const struct ipset_data *data, enum ipset_opt opt,
		 uint8_t env UNUSED)
{
	const struct ipset_type *type;

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

	type = ipset_data_get(data, opt);
	assert(type);
	if (len < strlen(type->name) + 1)
		return -1;
		
	return snprintf(buf, len, "%s", type->name);
}
예제 #13
0
파일: print.c 프로젝트: Olipro/ipset
int
ipset_print_skbprio(char *buf, unsigned int len,
		    const struct ipset_data *data, enum ipset_opt opt,
		    uint8_t env UNUSED)
{
	int size, offset = 0;
	const uint32_t *skbprio;

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

	skbprio = ipset_data_get(data, opt);
	assert(skbprio);
	size = snprintf(buf + offset, len, "%x:%x",
			*skbprio >> 16, *skbprio & 0xffff);
	SNPRINTF_FAILURE(size, len, offset);
	return offset;
}
예제 #14
0
/**
 * ipset_print_icmpv6 - print ICMPv6 code name or type/code
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print ICMPv6 code name or type/code name to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_icmpv6(char *buf, unsigned int len,
		   const struct ipset_data *data,
		   enum ipset_opt opt ASSERT_UNUSED,
		   uint8_t env UNUSED)
{
	const char *name;
	uint16_t typecode;

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

	typecode = *(const uint16_t *) ipset_data_get(data, IPSET_OPT_PORT);
	name = icmpv6_to_name(typecode >> 8, typecode & 0xFF);
	if (name != NULL)
		return snprintf(buf, len, "%s", name);
	else
		return snprintf(buf, len, "%u/%u", typecode >> 8, typecode & 0xFF);
}
예제 #15
0
파일: print.c 프로젝트: Olipro/ipset
/**
 * ipset_print_mark - print mark to string
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print mark to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_mark(char *buf, unsigned int len,
		   const struct ipset_data *data,
		   enum ipset_opt opt ASSERT_UNUSED,
		   uint8_t env UNUSED)
{
	const uint32_t *mark;
	int size, offset = 0;

	assert(buf);
	assert(len > 0);
	assert(data);
	assert(opt == IPSET_OPT_MARK || opt == IPSET_OPT_MARKMASK);

	mark = ipset_data_get(data, opt);
	assert(mark);

	size = snprintf(buf, len, "0x%08"PRIx32, *mark);
	SNPRINTF_FAILURE(size, len, offset);

	return offset;
}
예제 #16
0
/**
 * ipset_print_proto - print protocol name
 * @buf: printing buffer
 * @len: length of available buffer space
 * @data: data blob
 * @opt: the option kind
 * @env: environment flags
 *
 * Print protocol name to output buffer.
 *
 * Return lenght of printed string or error size.
 */
int
ipset_print_proto(char *buf, unsigned int len,
		  const struct ipset_data *data,
		  enum ipset_opt opt ASSERT_UNUSED,
		  uint8_t env UNUSED)
{
	const struct protoent *protoent;
	uint8_t proto;

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

	proto = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO);
	assert(proto);
	
	protoent = getprotobynumber(proto);
	if (protoent)
		return snprintf(buf, len, "%s", protoent->p_name);

	/* Should not happen */	
	return snprintf(buf, len, "%u", proto);
}
예제 #17
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;
}