From bb4f6b818fe371b754abd61cffb97cb5145e8e1d Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Sun, 15 May 2011 12:04:19 +0200 Subject: Support range for IPv4 at adding/deleting elements for hash:*net* types The range internally is converted to the network(s) equal to the range. Example: # ipset new test hash:net # ipset add test 10.2.0.0-10.2.1.12 # ipset list test Name: test Type: hash:net Header: family inet hashsize 1024 maxelem 65536 Size in memory: 16888 References: 0 Members: 10.2.1.12 10.2.1.0/29 10.2.0.0/24 10.2.1.8/30 --- lib/data.c | 9 +++++++++ lib/parse.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- lib/session.c | 4 ++++ 3 files changed, 63 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/data.c b/lib/data.c index 022e4b4..1541728 100644 --- a/lib/data.c +++ b/lib/data.c @@ -66,6 +66,7 @@ struct ipset_data { /* ADT/LIST/SAVE */ struct { union nf_inet_addr ip2; + union nf_inet_addr ip2_to; uint8_t cidr2; uint8_t proto; char ether[ETH_ALEN]; @@ -289,6 +290,11 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value) return -1; copy_addr(data->family, &data->adt.ip2, value); break; + case IPSET_OPT_IP2_TO: + if (!(data->family == AF_INET || data->family == AF_INET6)) + return -1; + copy_addr(data->family, &data->adt.ip2_to, value); + break; case IPSET_OPT_CIDR2: data->adt.cidr2 = *(const uint8_t *) value; break; @@ -401,6 +407,8 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt) return data->adt.nameref; case IPSET_OPT_IP2: return &data->adt.ip2; + case IPSET_OPT_IP2_TO: + return &data->adt.ip2_to; case IPSET_OPT_CIDR2: return &data->adt.cidr2; case IPSET_OPT_PROTO: @@ -436,6 +444,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family) case IPSET_OPT_IP: case IPSET_OPT_IP_TO: case IPSET_OPT_IP2: + case IPSET_OPT_IP2_TO: return family == AF_INET ? sizeof(uint32_t) : sizeof(struct in6_addr); case IPSET_OPT_PORT: diff --git a/lib/parse.c b/lib/parse.c index 0c15231..091fc6d 100644 --- a/lib/parse.c +++ b/lib/parse.c @@ -667,8 +667,15 @@ parse_ipaddr(struct ipset_session *session, 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; + enum ipset_opt copt, opt2; + + if (opt == IPSET_OPT_IP) { + copt = IPSET_OPT_CIDR; + opt2 = IPSET_OPT_IP_TO; + } else { + copt = IPSET_OPT_CIDR2; + opt2 = IPSET_OPT_IP2_TO; + } if (tmp == NULL) return ipset_err(session, @@ -691,7 +698,7 @@ parse_ipaddr(struct ipset_session *session, || !range) goto out; freeaddrinfo(info); - aerr = get_addrinfo(session, IPSET_OPT_IP_TO, a, &info, family); + aerr = get_addrinfo(session, opt2, a, &info, family); out: if (aerr != EINVAL) @@ -973,6 +980,46 @@ ipset_parse_ip4_single6(struct ipset_session *session, } +/** + * ipset_parse_ip4_net6 - parse IPv4|IPv6 address or address/cidr pattern + * @session: session structure + * @opt: option kind of the data + * @str: string to parse + * + * Parse string as an IPv4|IPv6 address or address/cidr pattern. For IPv4, + * address range is valid too. + * If family is not set yet in the data blob, INET is assumed. + * The values are stored in the data blob of the session. + * + * FIXME: if the hostname resolves to multiple addresses, + * the first one is used only. + * + * Returns 0 on success or a negative error code. + */ +int +ipset_parse_ip4_net6(struct ipset_session *session, + enum ipset_opt opt, const char *str) +{ + struct ipset_data *data; + uint8_t family; + + assert(session); + assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2); + assert(str); + + data = ipset_session_data(session); + family = ipset_data_family(data); + + if (family == AF_UNSPEC) { + family = AF_INET; + ipset_data_set(data, IPSET_OPT_FAMILY, &family); + } + + return family == AF_INET ? parse_ip(session, opt, str, IPADDR_ANY) + : ipset_parse_ipnet(session, opt, str); + +} + /** * ipset_parse_iptimeout - parse IPv4|IPv6 address and timeout * @session: session structure diff --git a/lib/session.c b/lib/session.c index 59405d4..a9c7c33 100644 --- a/lib/session.c +++ b/lib/session.c @@ -469,6 +469,10 @@ static const struct ipset_attr_policy adt_attrs[] = { .type = MNL_TYPE_U8, .opt = IPSET_OPT_CIDR2, }, + [IPSET_ATTR_IP2_TO] = { + .type = MNL_TYPE_NESTED, + .opt = IPSET_OPT_IP2_TO, + }, }; static const struct ipset_attr_policy ipaddr_attrs[] = { -- cgit v1.2.3