From 0d32c5c070f817229110f92d7b31df9a3e4eeec5 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Sun, 24 Oct 2010 21:42:48 +0200 Subject: Fixes, cleanups, comments - More comments added to the code - ICMP and ICMPv6 support added to the hash:ip,port, hash:ip,port,ip and hash:ip,port,net types - hash:net and hash:ip,port,net types are reworked - hash:net,port type added - Wrong direction parameters fixed in hash:ip,port - Helps and manpage are updated - More tests added - Ugly macros are rewritten to functions in parse.c (Holger Eitzenberger) - resize related bug in hash types fixed (Holger Eitzenberger) - autoreconf patches by Jan Engelhardt applied - netlink patch minimalized: dumping can be initialized by a second parsing of the message (thanks to David and Patrick for the suggestion) - IPv4/IPv6 address attributes are introduced in order to fix the context (suggested by David) --- kernel/ip_set_hash_ipportip.c | 121 +++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 77 deletions(-) (limited to 'kernel/ip_set_hash_ipportip.c') diff --git a/kernel/ip_set_hash_ipportip.c b/kernel/ip_set_hash_ipportip.c index d2db3a9..a20f1ef 100644 --- a/kernel/ip_set_hash_ipportip.c +++ b/kernel/ip_set_hash_ipportip.c @@ -107,11 +107,10 @@ static inline bool hash_ipportip4_data_list(struct sk_buff *skb, const struct hash_ipportip4_elem *data) { - NLA_PUT_NET32(skb, IPSET_ATTR_IP, data->ip); - NLA_PUT_NET32(skb, IPSET_ATTR_IP2, data->ip2); + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2); NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - if (data->proto != IPSET_IPPROTO_TCPUDP) - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); return 0; nla_put_failure: @@ -125,11 +124,10 @@ hash_ipportip4_data_tlist(struct sk_buff *skb, const struct hash_ipportip4_telem *tdata = (const struct hash_ipportip4_telem *)data; - NLA_PUT_NET32(skb, IPSET_ATTR_IP, tdata->ip); - NLA_PUT_NET32(skb, IPSET_ATTR_IP2, tdata->ip2); + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2); NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port); - if (data->proto != IPSET_IPPROTO_TCPUDP) - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(ip_set_timeout_get(tdata->timeout))); @@ -139,8 +137,6 @@ nla_put_failure: return 1; } -#define IP_SET_HASH_WITH_PROTO - #define PF 4 #define HOST_MASK 32 #include @@ -151,7 +147,7 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb, { struct chash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_ipportip4_elem data = { .proto = h->proto }; + struct hash_ipportip4_elem data = { }; if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, &data.port, &data.proto)) @@ -164,9 +160,9 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb, } static const struct nla_policy -hash_ipportip4_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = { - [IPSET_ATTR_IP] = { .type = NLA_U32 }, - [IPSET_ATTR_IP2] = { .type = NLA_U32 }, +hash_ipportip_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = { + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, [IPSET_ATTR_PORT] = { .type = NLA_U16 }, [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, @@ -180,26 +176,24 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len, struct chash *h = set->data; struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_ipportip4_elem data = { .proto = h->proto }; + struct hash_ipportip4_elem data = { }; u32 timeout = h->timeout; int ret; if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_ipportip4_adt_policy)) + hash_ipportip_adt_policy)) return -IPSET_ERR_PROTOCOL; if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - if (tb[IPSET_ATTR_IP]) - data.ip = ip_set_get_n32(tb[IPSET_ATTR_IP]); - else - return -IPSET_ERR_PROTOCOL; + ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip); + if (ret) + return ret; - if (tb[IPSET_ATTR_IP2]) - data.ip2 = ip_set_get_n32(tb[IPSET_ATTR_IP2]); - else - return -IPSET_ERR_PROTOCOL; + ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP2, &data.ip2); + if (ret) + return ret; if (tb[IPSET_ATTR_PORT]) data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]); @@ -209,15 +203,15 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len, if (tb[IPSET_ATTR_PROTO]) { data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); - if (data.proto == 0 || data.proto >= IPSET_IPPROTO_TCPUDP) + if (data.proto == 0) return -IPSET_ERR_INVALID_PROTO; - } else if (data.proto == IPSET_IPPROTO_ANY) + } else return -IPSET_ERR_MISSING_PROTO; switch (data.proto) { case IPPROTO_UDP: case IPPROTO_TCP: - case IPSET_IPPROTO_TCPUDP: + case IPPROTO_ICMP: break; default: data.port = 0; @@ -230,7 +224,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, GFP_KERNEL, timeout); + ret = adtfn(set, &data, GFP_ATOMIC, timeout); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -244,7 +238,6 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b) /* Resizing changes htable_bits, so we ignore it */ return x->maxelem == y->maxelem && x->timeout == y->timeout - && x->proto == y->proto && x->array_size == y->array_size && x->chain_limit == y->chain_limit; } @@ -312,11 +305,10 @@ static inline bool hash_ipportip6_data_list(struct sk_buff *skb, const struct hash_ipportip6_elem *data) { - NLA_PUT(skb, IPSET_ATTR_IP, sizeof(struct in6_addr), &data->ip); - NLA_PUT(skb, IPSET_ATTR_IP2, sizeof(struct in6_addr), &data->ip2); + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - if (data->proto != IPSET_IPPROTO_TCPUDP) - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); return 0; nla_put_failure: @@ -330,11 +322,10 @@ hash_ipportip6_data_tlist(struct sk_buff *skb, const struct hash_ipportip6_telem *e = (const struct hash_ipportip6_telem *)data; - NLA_PUT(skb, IPSET_ATTR_IP, sizeof(struct in6_addr), &e->ip); - NLA_PUT(skb, IPSET_ATTR_IP2, sizeof(struct in6_addr), &data->ip2); + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); - if (data->proto != IPSET_IPPROTO_TCPUDP) - NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(ip_set_timeout_get(e->timeout))); return 0; @@ -356,7 +347,7 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb, { struct chash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_ipportip6_elem data = { .proto = h->proto }; + struct hash_ipportip6_elem data = { }; if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, &data.port, &data.proto)) @@ -368,18 +359,6 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb, return adtfn(set, &data, GFP_ATOMIC, h->timeout); } -static const struct nla_policy -hash_ipportip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = { - [IPSET_ATTR_IP] = { .type = NLA_BINARY, - .len = sizeof(struct in6_addr) }, - [IPSET_ATTR_IP2] = { .type = NLA_BINARY, - .len = sizeof(struct in6_addr) }, - [IPSET_ATTR_PORT] = { .type = NLA_U16 }, - [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, - [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, -}; - static int hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len, enum ipset_adt adt, u32 *lineno, u32 flags) @@ -387,28 +366,24 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len, struct chash *h = set->data; struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_ipportip6_elem data = { .proto = h->proto }; + struct hash_ipportip6_elem data = { }; u32 timeout = h->timeout; int ret; if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_ipportip6_adt_policy)) + hash_ipportip_adt_policy)) return -IPSET_ERR_PROTOCOL; if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - if (tb[IPSET_ATTR_IP]) - memcpy(&data.ip, nla_data(tb[IPSET_ATTR_IP]), - sizeof(struct in6_addr)); - else - return -IPSET_ERR_PROTOCOL; + ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip); + if (ret) + return ret; - if (tb[IPSET_ATTR_IP2]) - memcpy(&data.ip2, nla_data(tb[IPSET_ATTR_IP2]), - sizeof(struct in6_addr)); - else - return -IPSET_ERR_PROTOCOL; + ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP2, &data.ip2); + if (ret) + return ret; if (tb[IPSET_ATTR_PORT]) data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]); @@ -418,15 +393,15 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len, if (tb[IPSET_ATTR_PROTO]) { data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); - if (data.proto == 0 || data.proto >= IPSET_IPPROTO_TCPUDP) + if (data.proto == 0) return -IPSET_ERR_INVALID_PROTO; - } else if (data.proto == IPSET_IPPROTO_ANY) + } else return -IPSET_ERR_MISSING_PROTO; switch (data.proto) { case IPPROTO_UDP: case IPPROTO_TCP: - case IPSET_IPPROTO_TCPUDP: + case IPPROTO_ICMPV6: break; default: data.port = 0; @@ -439,7 +414,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, GFP_KERNEL, timeout); + ret = adtfn(set, &data, GFP_ATOMIC, timeout); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -452,7 +427,6 @@ hash_ipportip_create_policy[IPSET_ATTR_CREATE_MAX+1] __read_mostly = { [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, - [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, }; @@ -463,7 +437,6 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head, struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1]; struct chash *h; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; - u8 proto = IPSET_IPPROTO_TCPUDP; /* Backward compatibility */ if (!(set->family == AF_INET || set->family == AF_INET6)) return -IPSET_ERR_INVALID_FAMILY; @@ -481,12 +454,6 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head, if (tb[IPSET_ATTR_MAXELEM]) maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]); - if (tb[IPSET_ATTR_PROTO]) { - proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); - if (!proto) - return -IPSET_ERR_INVALID_PROTO; - } - h = kzalloc(sizeof(*h), GFP_KERNEL); if (!h) return -ENOMEM; @@ -496,11 +463,11 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head, h->array_size = CHASH_DEFAULT_ARRAY_SIZE; h->chain_limit = CHASH_DEFAULT_CHAIN_LIMIT; get_random_bytes(&h->initval, sizeof(h->initval)); - h->proto = proto; h->timeout = IPSET_NO_TIMEOUT; - h->htable = ip_set_alloc(jhash_size(h->htable_bits) * sizeof(struct slist), - GFP_KERNEL); + h->htable = ip_set_alloc( + jhash_size(h->htable_bits) * sizeof(struct slist), + GFP_KERNEL); if (!h->htable) { kfree(h); return -ENOMEM; -- cgit v1.2.3