Exemple #1
0
static bool
do_ipset_cmd(struct ipset_session* session, enum ipset_cmd cmd, const char *setname,
		const ip_address_t *addr, uint32_t timeout, const char* iface)
{
	const struct ipset_type *type;
	uint8_t family;
	int r;

	ipset_session_data_set(session, IPSET_SETNAME, setname);

	type = ipset_type_get(session, cmd);
	if (type == NULL) {
		/* possible reasons for failure: set name does not exist */
		return false;
	}

	family = (addr->ifa.ifa_family == AF_INET) ? NFPROTO_IPV4 : NFPROTO_IPV6;
	ipset_session_data_set(session, IPSET_OPT_FAMILY, &family);
	ipset_session_data_set(session, IPSET_OPT_IP, &addr->u);
	if (timeout)
		ipset_session_data_set(session, IPSET_OPT_TIMEOUT, &timeout);
	if (iface)
		ipset_session_data_set(session, IPSET_OPT_IFACE, iface);

	r = ipset_cmd1(session, cmd, 0);

	return r == 0;
}
Exemple #2
0
/**
 * This function was designed for three values of cmd:
 * CMD_TEST: true if exists, false if not exists (or set name not found)
 * CMD_ADD: true if added, false if error occurred (set name not found?)
 * CMD_DEL: true if deleted, false if error occurred (set name not found?)
 */
static bool
try_ipset_cmd(enum ipset_cmd cmd, const char *setname,
		const struct in_addr *addr, uint32_t timeout) {
	const struct ipset_type *type;
	uint8_t family;
	int r;
	r = ipset_session_data_set(session, IPSET_SETNAME, setname);
	/* since the IPSET_SETNAME option is valid, this should never fail */
	assert(r == 0);

	type = ipset_type_get(session, cmd);
	if (type == NULL) {
		/* possible reasons for failure: set name does not exist */
		return false;
	}

	family = NFPROTO_IPV4;
	ipset_session_data_set(session, IPSET_OPT_FAMILY, &family);
	ipset_session_data_set(session, IPSET_OPT_IP, addr);
	if (timeout)
		ipset_session_data_set(session, IPSET_OPT_TIMEOUT, &timeout);

	r = ipset_cmd(session, cmd, /*lineno*/ 0);
	/* assume that errors always occur if NOT in set. To do it otherwise,
	 * see lib/session.c for IPSET_CMD_TEST in ipset_cmd */
	return r == 0;
}
Exemple #3
0
/* Parse ICMP and ICMPv6 type/code */
static int
parse_icmp_typecode(struct ipset_session *session,
		    enum ipset_opt opt, const char *str,
		    const char *family)
{
	uint16_t typecode;
	uint8_t type, code;
	char *a, *saved, *tmp;
	int err;
		
	saved = tmp = strdup(str);
	if (tmp == NULL)
		return ipset_err(session,
				 "Cannot allocate memory to duplicate %s.",
				 str);
	a = cidr_separator(tmp);
	if (a == NULL) {
		free(saved);
		return ipset_err(session,
				 "Cannot parse %s as an %s type/code.", str, family);
	}
	*a++ = '\0';
	if ((err = string_to_u8(session, a, &type)) != 0
	    || (err = string_to_u8(session, tmp, &code)) != 0)
	    	goto error;
		
	typecode = (type << 8) | code;
	err = ipset_session_data_set(session, opt, &typecode);

error:
	free(saved);
	return err;
}
Exemple #4
0
/**
 * ipset_parse_ether - parse ethernet address
 * @session: session structure
 * @opt: option kind of the data
 * @str: string to parse
 *
 * Parse string as an ethernet address. The parsed ethernet
 * address is stored in the data blob of the session.
 *
 * Returns 0 on success or a negative error code.
 */
int
ipset_parse_ether(struct ipset_session *session,
		  enum ipset_opt opt, const char *str)
{
	unsigned int i = 0;
	unsigned char ether[ETH_ALEN];
	
	assert(session);
	assert(opt == IPSET_OPT_ETHER);
	assert(str);

	if (strlen(str) != ETH_ALEN * 3 - 1)
		goto error;

	for (i = 0; i < ETH_ALEN; i++) {
		long number;
		char *end;

		number = strtol(str + i * 3, &end, 16);

		if (end == str + i * 3 + 2
		    && (*end == ':' || *end == '\0')
		    && number >= 0 && number <= 255)
			ether[i] = number;
		else
			goto error;
	}
	return ipset_session_data_set(session, opt, ether);

error:
	return syntax_err("cannot parse '%s' as ethernet address", str);
}
Exemple #5
0
static int
get_addrinfo(struct ipset_session *session,
	     enum ipset_opt opt,
	     const char *str,
	     struct addrinfo **info,
	     uint8_t family)
{
        struct addrinfo *i;
	size_t addrlen = family == AF_INET ? sizeof(struct sockaddr_in)
					   : sizeof(struct sockaddr_in6);
        int found, err = 0;

	if ((*info = call_getaddrinfo(session, str, family)) == NULL) {
		syntax_err("cannot parse %s: resolving to %s address failed",
			   str, family == AF_INET ? "IPv4" : "IPv6");
		return EINVAL;
	}

	for (i = *info, found = 0; i != NULL; i = i->ai_next) {
		if (i->ai_family != family || i->ai_addrlen != addrlen)
			continue;
		if (found == 0) {
			if (family == AF_INET) {
				/* Workaround: direct cast increases required alignment on Sparc */
				const struct sockaddr_in *saddr = (void *)i->ai_addr;
				err = ipset_session_data_set(session, opt, &saddr->sin_addr);
			} else {
				/* Workaround: direct cast increases required alignment on Sparc */
				const struct sockaddr_in6 *saddr = (void *)i->ai_addr;
				err = ipset_session_data_set(session, opt, &saddr->sin6_addr);
			}
		} else if (found == 1) {
			ipset_warn(session,
				   "%s resolves to multiple addresses: "
				   "using only the first one returned "
				   "by the resolver",
				   str);
		}
		found++;
	}
	if (found == 0)
		return syntax_err("cannot parse %s: "
				  "%s address could not be resolved",
				  str, family == AF_INET ? "IPv4" : "IPv6");
	return err;
}
Exemple #6
0
/**
 * ipset_parse_setname - parse string as a setname
 * @session: session structure
 * @opt: option kind of the data
 * @str: string to parse
 *
 * Parse string as a setname.
 * The value is stored in the data blob of the session.
 *
 * Returns 0 on success or a negative error code.
 */
int
ipset_parse_setname(struct ipset_session *session,
		    enum ipset_opt opt, const char *str)
{
	assert(session);
	assert(opt == IPSET_SETNAME
	       || opt == IPSET_OPT_NAME
	       || opt == IPSET_OPT_SETNAME2);
	assert(str);

	check_setname(str, NULL);

	return ipset_session_data_set(session, opt, str);
}
Exemple #7
0
/**
 * ipset_parse_icmpv6 - parse an ICMPv6 name or type/code
 * @session: session structure
 * @opt: option kind of the data
 * @str: string to parse
 *
 * Parse string as an ICMPv6 name or type/code numbers.
 * The parsed ICMPv6 type/code is stored in the data blob of the session.
 *
 * Returns 0 on success or a negative error code.
 */
int
ipset_parse_icmpv6(struct ipset_session *session,
		   enum ipset_opt opt, const char *str)
{
	uint16_t typecode;

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

	if (name_to_icmpv6(str, &typecode) < 0)
		return parse_icmp_typecode(session, opt, str, "ICMPv6");

	return ipset_session_data_set(session, opt, &typecode);
}
Exemple #8
0
/**
 * ipset_parse_uint8 - parse string as an unsigned short integer
 * @session: session structure
 * @opt: option kind of the data
 * @str: string to parse
 *
 * Parse string as an unsigned short integer number.
 * The value is stored in the data blob of the session.
 *
 * Returns 0 on success or a negative error code.
 */
int
ipset_parse_uint8(struct ipset_session *session,
		  enum ipset_opt opt, const char *str)
{
	uint8_t value;
	int err;
	
	assert(session);
	assert(str);

	if ((err = string_to_u8(session, str, &value)) == 0)
		return ipset_session_data_set(session, opt, &value);

	return err;
}
Exemple #9
0
static int
parse_ipaddr(struct ipset_session *session,
	     enum ipset_opt opt, const char *str,
	     uint8_t family)
{
        uint8_t m = family == AF_INET ? 32 : 128;
        int aerr = EINVAL, err = 0, range = 0;
        char *saved = strdup(str);
        char *a, *tmp = saved;
        struct addrinfo *info;
        enum ipset_opt copt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR
        			: IPSET_OPT_CIDR2;

	if (tmp == NULL)
		return ipset_err(session,
				 "Cannot allocate memory to duplicate %s.",
				 str);
	if ((a = cidr_separator(tmp)) != NULL) {
		/* IP/mask */
		*a++ = '\0';

		if ((err = string_to_cidr(session, a, 0, m, &m)) != 0
		    || (err = ipset_session_data_set(session, copt, &m)) != 0)
			goto out;
	} else if ((a = range_separator(tmp)) != NULL) {
		/* IP-IP */
		*a++ = '\0';
		D("range %s", a);
		range++;
	}
	if ((aerr = get_addrinfo(session, opt, tmp, &info, family)) != 0
	    || !range)
		goto out;
	freeaddrinfo(info);
	aerr = get_addrinfo(session, IPSET_OPT_IP_TO, a, &info, family);

out:
	if (aerr != EINVAL)
		/* getaddrinfo not failed */
		freeaddrinfo(info);
	else if (aerr)
		err = -1;
	free(saved);
	return err;
} 
Exemple #10
0
/**
 * ipset_parse_proto - parse protocol name
 * @session: session structure
 * @opt: option kind of the data
 * @str: string to parse
 *
 * Parse string as a protocol name.
 * The parsed protocol is stored in the data blob of the session.
 *
 * Returns 0 on success or a negative error code.
 */
int
ipset_parse_proto(struct ipset_session *session,
		  enum ipset_opt opt, const char *str)
{
	const struct protoent *protoent;
	uint8_t proto = 0;

	assert(session);
	assert(opt == IPSET_OPT_PROTO);
	assert(str);
	
	protoent = getprotobyname(strcasecmp(str, "icmpv6") == 0
				  ? "ipv6-icmp" : str);
	if (protoent == NULL)
		return syntax_err("cannot parse '%s' "
				  "as a protocol name", str);
	proto = protoent->p_proto;
	if (!proto)
		return syntax_err("Unsupported protocol '%s'", str);
	
	return ipset_session_data_set(session, opt, &proto);
}
Exemple #11
0
/**
 * ipset_parse_single_port - parse a single port number or name
 * @session: session structure
 * @opt: option kind of the data
 * @str: string to parse
 * @proto: protocol
 *
 * Parse string as a single port number or name. The parsed port
 * number is stored in the data blob of the session.
 *
 * Returns 0 on success or a negative error code.
 */
int
ipset_parse_port(struct ipset_session *session,
		 enum ipset_opt opt, const char *str,
		 const char *proto)
{
	uint16_t port;
	int err;

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

	if ((err = string_to_u16(session, str, &port)) == 0
	    || (err = parse_portname(session, str, &port, proto)) == 0)
		err = ipset_session_data_set(session, opt, &port);

	if (!err)
		/* No error, so reset false error messages! */
		ipset_session_report_reset(session);

	return err;
}
Exemple #12
0
		ipset_session_data_set(session, IPSET_OPT_TIMEOUT, &timeout);
	if (iface)
		ipset_session_data_set(session, IPSET_OPT_IFACE, iface);

	r = ipset_cmd1(session, cmd, 0);

	return r == 0;
}

static bool
ipset_create(struct ipset_session* session, const char *setname, const char *typename, uint8_t family)
{
	const struct ipset_type *type;
	int r;

	r = ipset_session_data_set(session, IPSET_SETNAME, setname);

	ipset_session_data_set(session, IPSET_OPT_TYPENAME, typename);

	type = ipset_type_get(session, IPSET_CMD_CREATE);
	if (type == NULL)
		return false;

	ipset_session_data_set(session, IPSET_OPT_TYPE, type);
	ipset_session_data_set(session, IPSET_OPT_FAMILY, &family);

	r = ipset_cmd1(session, IPSET_CMD_CREATE, 0);
	return r == 0;
}

static bool