From 1b53724a61cf22bc7ba754211334e6a06d197fad Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 22 Jan 2011 15:55:08 +0100 Subject: [PATCH] ipset: update to 5.4.1 --- doc/changelog.txt | 4 + extensions/ipset-5/Kbuild | 2 +- extensions/ipset-5/ip_set.h | 152 +++----- extensions/ipset-5/ip_set_ahash.h | 44 +-- extensions/ipset-5/ip_set_bitmap_ip.c | 72 ++-- extensions/ipset-5/ip_set_bitmap_ipmac.c | 59 +-- extensions/ipset-5/ip_set_bitmap_port.c | 74 ++-- extensions/ipset-5/ip_set_core.c | 395 ++++++++++++--------- extensions/ipset-5/ip_set_getport.c | 136 +++++++ extensions/ipset-5/ip_set_getport.h | 127 +------ extensions/ipset-5/ip_set_hash_ip.c | 97 +++-- extensions/ipset-5/ip_set_hash_ipport.c | 113 +++--- extensions/ipset-5/ip_set_hash_ipportip.c | 127 ++++--- extensions/ipset-5/ip_set_hash_ipportnet.c | 159 ++++----- extensions/ipset-5/ip_set_hash_net.c | 72 ++-- extensions/ipset-5/ip_set_hash_netport.c | 123 +++---- extensions/ipset-5/ip_set_kernel.h | 15 - extensions/ipset-5/ip_set_list_set.c | 79 +++-- extensions/ipset-5/ip_set_timeout.h | 20 +- extensions/ipset-5/pfxlen.c | 14 +- extensions/ipset-5/pfxlen.h | 31 +- extensions/ipset-5/xt_set.c | 28 +- 22 files changed, 982 insertions(+), 961 deletions(-) create mode 100644 extensions/ipset-5/ip_set_getport.c delete mode 100644 extensions/ipset-5/ip_set_kernel.h diff --git a/doc/changelog.txt b/doc/changelog.txt index 9d9ca97..049c11d 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -9,6 +9,10 @@ Enhancements: - Update to ipset 5.3 * make IPv4 and IPv6 address handling similar * show correct line numbers in restore output for parser errors +- Update to ipset 5.4 + * fixed ICMP and ICMPv6 handling + * fixed trailing whitespaces and pr_* messages + * fixed module loading at create/header commands v1.32 (2011-01-04) diff --git a/extensions/ipset-5/Kbuild b/extensions/ipset-5/Kbuild index b84b499..1ec5c40 100644 --- a/extensions/ipset-5/Kbuild +++ b/extensions/ipset-5/Kbuild @@ -6,6 +6,6 @@ obj-m += ip_set_bitmap_port.o ip_set_hash_ip.o ip_set_hash_ipport.o obj-m += ip_set_hash_ipportip.o ip_set_hash_ipportnet.o ip_set_hash_net.o obj-m += ip_set_hash_netport.o ip_set_list_set.o -ip_set-y := ip_set_core.o pfxlen.o +ip_set-y := ip_set_core.o ip_set_getport.o pfxlen.o EXTRA_CFLAGS += -DLCONFIG_IP_SET_MAX=256 diff --git a/extensions/ipset-5/ip_set.h b/extensions/ipset-5/ip_set.h index 7003c78..9d4b961 100644 --- a/extensions/ipset-5/ip_set.h +++ b/extensions/ipset-5/ip_set.h @@ -11,6 +11,8 @@ * published by the Free Software Foundation. */ +#include + /* The protocol version */ #define IPSET_PROTOCOL 5 @@ -292,7 +294,7 @@ struct ip_set { /* References to the set */ atomic_t ref; /* The core set type */ - const struct ip_set_type *type; + struct ip_set_type *type; /* The type variant doing the real job */ const struct ip_set_type_variant *variant; /* The actual INET family of the set */ @@ -317,37 +319,22 @@ extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb, extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb, u8 family, u8 dim, u8 flags); -/* Allocate members */ -static inline void * -ip_set_alloc(size_t size, gfp_t gfp_mask) +/* Utility functions */ +extern void * ip_set_alloc(size_t size, gfp_t gfp_mask); +extern void ip_set_free(void *members); +extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr); +extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr); + +static inline int +ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr) { - void *members = NULL; - - if (size < KMALLOC_MAX_SIZE) - members = kzalloc(size, gfp_mask | __GFP_NOWARN); - - if (members) { - pr_debug("%p: allocated with kmalloc", members); - return members; - } - - members = __vmalloc(size, gfp_mask | __GFP_ZERO, PAGE_KERNEL); - if (!members) - return NULL; - pr_debug("%p: allocated with vmalloc", members); - - return members; -} - -static inline void -ip_set_free(void *members) -{ - pr_debug("%p: free with %s", members, - is_vmalloc_addr(members) ? "vfree" : "kfree"); - if (is_vmalloc_addr(members)) - vfree(members); - else - kfree(members); + __be32 ip; + int ret = ip_set_get_ipaddr4(nla, &ip); + + if (ret) + return ret; + *ipaddr = ntohl(ip); + return 0; } /* Ignore IPSET_ERR_EXIST errors if asked to do so? */ @@ -357,92 +344,47 @@ ip_set_eexist(int ret, u32 flags) return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST); } +/* Check the NLA_F_NET_BYTEORDER flag */ +static inline bool +ip_set_attr_netorder(struct nlattr *tb[], int type) +{ + return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER); +} + +static inline bool +ip_set_optattr_netorder(struct nlattr *tb[], int type) +{ + return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER); +} + /* Useful converters */ static inline u32 ip_set_get_h32(const struct nlattr *attr) { - u32 value = nla_get_u32(attr); - - return attr->nla_type & NLA_F_NET_BYTEORDER ? ntohl(value) : value; + return ntohl(nla_get_be32(attr)); } static inline u16 ip_set_get_h16(const struct nlattr *attr) { - u16 value = nla_get_u16(attr); - - return attr->nla_type & NLA_F_NET_BYTEORDER ? ntohs(value) : value; -} - -static inline u32 -ip_set_get_n32(const struct nlattr *attr) -{ - u32 value = nla_get_u32(attr); - - return attr->nla_type & NLA_F_NET_BYTEORDER ? value : htonl(value); -} - -static inline u16 -ip_set_get_n16(const struct nlattr *attr) -{ - u16 value = nla_get_u16(attr); - - return attr->nla_type & NLA_F_NET_BYTEORDER ? value : htons(value); -} - -static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = { - [IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 }, - [IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY, - .len = sizeof(struct in6_addr) }, -}; - -static inline int -ip_set_get_ipaddr4(struct nlattr *attr[], int type, u32 *ipaddr) -{ - struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1] = {}; - - if (!attr[type]) - return -IPSET_ERR_PROTOCOL; - - if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, - nla_data(attr[type]), nla_len(attr[type]), - ipaddr_policy)) - return -IPSET_ERR_PROTOCOL; - if (!tb[IPSET_ATTR_IPADDR_IPV4]) - return -IPSET_ERR_IPADDR_IPV4; - - *ipaddr = ip_set_get_n32(tb[IPSET_ATTR_IPADDR_IPV4]); - return 0; -} - -static inline int -ip_set_get_ipaddr6(struct nlattr *attr[], int type, union nf_inet_addr *ipaddr) -{ - struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1] = {}; - - if (!attr[type]) - return -IPSET_ERR_PROTOCOL; - - if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, - nla_data(attr[type]), nla_len(attr[type]), - ipaddr_policy)) - return -IPSET_ERR_PROTOCOL; - if (!tb[IPSET_ATTR_IPADDR_IPV6]) - return -IPSET_ERR_IPADDR_IPV6; - - memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]), - sizeof(struct in6_addr)); - return 0; + return ntohs(nla_get_be16(attr)); } #define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED) #define ipset_nest_end(skb, start) nla_nest_end(skb, start) -#define NLA_PUT_NET32(skb, type, value) \ - NLA_PUT_BE32(skb, type | NLA_F_NET_BYTEORDER, value) - -#define NLA_PUT_NET16(skb, type, value) \ - NLA_PUT_BE16(skb, type | NLA_F_NET_BYTEORDER, value) +#ifndef NLA_PUT_NET16 +#define NLA_PUT_NET16(skb, attrtype, value) \ + NLA_PUT_BE16(skb, attrtype | NLA_F_NET_BYTEORDER, value) +#endif +#ifndef NLA_PUT_NET32 +#define NLA_PUT_NET32(skb, attrtype, value) \ + NLA_PUT_BE32(skb, attrtype | NLA_F_NET_BYTEORDER, value) +#endif +#ifndef NLA_PUT_NET64 +#define NLA_PUT_NET64(skb, attrtype, value) \ + NLA_PUT_BE64(skb, attrtype | NLA_F_NET_BYTEORDER, value) +#endif #define NLA_PUT_IPADDR4(skb, type, ipaddr) \ do { \ @@ -466,14 +408,14 @@ do { \ } while (0) /* Get address from skbuff */ -static inline u32 +static inline __be32 ip4addr(const struct sk_buff *skb, bool src) { return src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr; } static inline void -ip4addrptr(const struct sk_buff *skb, bool src, u32 *addr) +ip4addrptr(const struct sk_buff *skb, bool src, __be32 *addr) { *addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr; } diff --git a/extensions/ipset-5/ip_set_ahash.h b/extensions/ipset-5/ip_set_ahash.h index 7c36f63..2f4bb3a 100644 --- a/extensions/ipset-5/ip_set_ahash.h +++ b/extensions/ipset-5/ip_set_ahash.h @@ -63,7 +63,7 @@ struct ip_set_hash { }; /* Compute htable_bits from the user input parameter hashsize */ -static inline u8 +static u8 htable_bits(u32 hashsize) { /* Assume that hashsize == 2^htable_bits */ @@ -81,14 +81,14 @@ htable_bits(u32 hashsize) /* Network cidr size book keeping when the hash stores different * sized networks */ -static inline void +static void add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask) { u8 i; ++h->nets[cidr-1].nets; - pr_debug("add_cidr added %u: %u", cidr, h->nets[cidr-1].nets); + pr_debug("add_cidr added %u: %u\n", cidr, h->nets[cidr-1].nets); if (h->nets[cidr-1].nets > 1) return; @@ -103,14 +103,14 @@ add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask) h->nets[i].cidr = cidr; } -static inline void +static void del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask) { u8 i; --h->nets[cidr-1].nets; - pr_debug("del_cidr deleted %u: %u", cidr, h->nets[cidr-1].nets); + pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets); if (h->nets[cidr-1].nets != 0) return; @@ -142,7 +142,7 @@ ahash_destroy(struct htable *t) } /* Calculate the actual memory size of the set data */ -static inline size_t +static size_t ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask) { u32 i; @@ -340,7 +340,7 @@ retry: /* Give time to other readers of the set */ synchronize_rcu_bh(); - pr_debug("set %s resized from %u (%p) to %u (%p)", set->name, + pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name, orig->htable_bits, orig, t->htable_bits, t); ahash_destroy(orig); @@ -436,7 +436,7 @@ type_pf_del(struct ip_set *set, void *value, u32 timeout) /* Special test function which takes into account the different network * sizes added to the set */ -static inline int +static int type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) { struct ip_set_hash *h = set->data; @@ -447,7 +447,7 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) u32 key; u8 host_mask = SET_HOST_MASK(set->family); - pr_debug("test by nets"); + pr_debug("test by nets\n"); for (; j < host_mask && h->nets[j].cidr; j++) { type_pf_data_netmask(d, h->nets[j].cidr); key = HKEY(d, h->initval, t->htable_bits); @@ -546,14 +546,14 @@ type_pf_list(const struct ip_set *set, atd = ipset_nest_start(skb, IPSET_ATTR_ADT); if (!atd) return -EFAULT; - pr_debug("list hash set %s", set->name); + pr_debug("list hash set %s\n", set->name); for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) { incomplete = skb_tail_pointer(skb); n = hbucket(t, cb->args[2]); - pr_debug("cb->args[2]: %lu, t %p n %p", cb->args[2], t, n); + pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n); for (i = 0; i < n->pos; i++) { data = ahash_data(n, i); - pr_debug("list hash %lu hbucket %p i %u, data %p", + pr_debug("list hash %lu hbucket %p i %u, data %p\n", cb->args[2], n, i, data); nested = ipset_nest_start(skb, IPSET_ATTR_DATA); if (!nested) { @@ -686,7 +686,7 @@ type_pf_expire(struct ip_set_hash *h) for (j = 0; j < n->pos; j++) { data = ahash_tdata(n, j); if (type_pf_data_expired(data)) { - pr_debug("expired %u/%u", i, j); + pr_debug("expired %u/%u\n", i, j); #ifdef IP_SET_HASH_WITH_NETS del_cidr(h, data->cidr, HOST_MASK); #endif @@ -701,7 +701,7 @@ type_pf_expire(struct ip_set_hash *h) if (n->pos + AHASH_INIT_SIZE < n->size) { void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) * sizeof(struct type_pf_telem), - GFP_KERNEL); + GFP_ATOMIC); if (!tmp) /* Still try to delete expired elements */ continue; @@ -807,8 +807,8 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout) ret = -IPSET_ERR_EXIST; goto out; } - } else if (j == AHASH_MAX_SIZE + 1 - && type_pf_data_expired(data)) + } else if (j == AHASH_MAX_SIZE + 1 && + type_pf_data_expired(data)) j = i; } if (j != AHASH_MAX_SIZE + 1) { @@ -881,7 +881,7 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout) } #ifdef IP_SET_HASH_WITH_NETS -static inline int +static int type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) { struct ip_set_hash *h = set->data; @@ -952,10 +952,10 @@ type_pf_tlist(const struct ip_set *set, n = hbucket(t, cb->args[2]); for (i = 0; i < n->pos; i++) { data = ahash_tdata(n, i); - pr_debug("list %p %u", n, i); + pr_debug("list %p %u\n", n, i); if (type_pf_data_expired(data)) continue; - pr_debug("do list %p %u", n, i); + pr_debug("do list %p %u\n", n, i); nested = ipset_nest_start(skb, IPSET_ATTR_DATA); if (!nested) { if (cb->args[2] == first) { @@ -1008,7 +1008,7 @@ type_pf_gc(unsigned long ul_set) struct ip_set *set = (struct ip_set *) ul_set; struct ip_set_hash *h = set->data; - pr_debug("called"); + pr_debug("called\n"); write_lock_bh(&set->lock); type_pf_expire(h); write_unlock_bh(&set->lock); @@ -1017,7 +1017,7 @@ type_pf_gc(unsigned long ul_set) add_timer(&h->gc); } -static inline void +static void type_pf_gc_init(struct ip_set *set) { struct ip_set_hash *h = set->data; @@ -1027,7 +1027,7 @@ type_pf_gc_init(struct ip_set *set) h->gc.function = type_pf_gc; h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ; add_timer(&h->gc); - pr_debug("gc initialized, run in every %u", + pr_debug("gc initialized, run in every %u\n", IPSET_GC_PERIOD(h->timeout)); } diff --git a/extensions/ipset-5/ip_set_bitmap_ip.c b/extensions/ipset-5/ip_set_bitmap_ip.c index b44bdc7..e011864 100644 --- a/extensions/ipset-5/ip_set_bitmap_ip.c +++ b/extensions/ipset-5/ip_set_bitmap_ip.c @@ -9,7 +9,6 @@ /* Kernel module implementing an IP set type: the bitmap:ip type */ -#include "ip_set_kernel.h" #include #include #include @@ -47,9 +46,9 @@ struct bitmap_ip { }; static inline u32 -ip_to_id(const struct bitmap_ip *map, u32 ip) +ip_to_id(const struct bitmap_ip *m, u32 ip) { - return ((ip & HOSTMASK(map->netmask)) - map->first_ip)/map->hosts; + return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts; } static inline int @@ -122,13 +121,15 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len, bitmap_ip_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP])) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &ip); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); if (ret) return ret; - ip = ntohl(ip); if (ip < map->first_ip || ip > map->last_ip) return -IPSET_ERR_BITMAP_RANGE; @@ -142,10 +143,9 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len, return bitmap_ip_test(map, ip_to_id(map, ip)); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; - ip_to = ntohl(ip_to); if (ip > ip_to) { swap(ip, ip_to); if (ip < map->first_ip) @@ -156,8 +156,8 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len, if (cidr > 32) return -IPSET_ERR_INVALID_CIDR; - ip &= HOSTMASK(cidr); - ip_to = ip | ~HOSTMASK(cidr); + ip &= ip_set_hostmask(cidr); + ip_to = ip | ~ip_set_hostmask(cidr); } else ip_to = ip; @@ -264,9 +264,9 @@ bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b) const struct bitmap_ip *x = a->data; const struct bitmap_ip *y = b->data; - return x->first_ip == y->first_ip - && x->last_ip == y->last_ip - && x->netmask == y->netmask; + return x->first_ip == y->first_ip && + x->last_ip == y->last_ip && + x->netmask == y->netmask; } static const struct ip_set_type_variant bitmap_ip = { @@ -362,13 +362,16 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len, bitmap_ip_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &ip); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); if (ret) return ret; - ip = ntohl(ip); if (ip < map->first_ip || ip > map->last_ip) return -IPSET_ERR_BITMAP_RANGE; @@ -378,10 +381,9 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len, ip_to_id((const struct bitmap_ip *)map, ip)); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; - ip_to = ntohl(ip_to); if (ip > ip_to) { swap(ip, ip_to); if (ip < map->first_ip) @@ -392,8 +394,8 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len, if (cidr > 32) return -IPSET_ERR_INVALID_CIDR; - ip &= HOSTMASK(cidr); - ip_to = ip | ~HOSTMASK(cidr); + ip &= ip_set_hostmask(cidr); + ip_to = ip | ~ip_set_hostmask(cidr); } else ip_to = ip; @@ -511,10 +513,10 @@ bitmap_ip_timeout_same_set(const struct ip_set *a, const struct ip_set *b) const struct bitmap_ip_timeout *x = a->data; const struct bitmap_ip_timeout *y = b->data; - return x->first_ip == y->first_ip - && x->last_ip == y->last_ip - && x->netmask == y->netmask - && x->timeout == y->timeout; + return x->first_ip == y->first_ip && + x->last_ip == y->last_ip && + x->netmask == y->netmask && + x->timeout == y->timeout; } static const struct ip_set_type_variant bitmap_ip_timeout = { @@ -547,7 +549,7 @@ bitmap_ip_gc(unsigned long ul_set) add_timer(&map->gc); } -static inline void +static void bitmap_ip_gc_init(struct ip_set *set) { struct bitmap_ip_timeout *map = set->data; @@ -603,16 +605,18 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len, bitmap_ip_create_policy)) return -IPSET_ERR_PROTOCOL; - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &first_ip); + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip); if (ret) return ret; - first_ip = ntohl(first_ip); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &last_ip); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip); if (ret) return ret; - last_ip = htonl(last_ip); if (first_ip > last_ip) { u32 tmp = first_ip; @@ -624,7 +628,7 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len, if (cidr >= 32) return -IPSET_ERR_INVALID_CIDR; - last_ip = first_ip | ~HOSTMASK(cidr); + last_ip = first_ip | ~ip_set_hostmask(cidr); } else return -IPSET_ERR_PROTOCOL; @@ -634,8 +638,8 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len, if (netmask > 32) return -IPSET_ERR_INVALID_NETMASK; - first_ip &= HOSTMASK(netmask); - last_ip |= ~HOSTMASK(netmask); + first_ip &= ip_set_hostmask(netmask); + last_ip |= ~ip_set_hostmask(netmask); } if (netmask == 32) { @@ -647,18 +651,18 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len, mask = range_to_mask(first_ip, last_ip, &mask_bits); - if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) - || netmask <= mask_bits) + if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) || + netmask <= mask_bits) return -IPSET_ERR_BITMAP_RANGE; - pr_debug("mask_bits %u, netmask %u", mask_bits, netmask); + pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask); hosts = 2 << (32 - netmask - 1); elements = 2 << (netmask - mask_bits - 1); } if (elements > IPSET_BITMAP_MAX_RANGE + 1) return -IPSET_ERR_BITMAP_RANGE_SIZE; - pr_debug("hosts %u, elements %u", hosts, elements); + pr_debug("hosts %u, elements %u\n", hosts, elements); if (tb[IPSET_ATTR_TIMEOUT]) { struct bitmap_ip_timeout *map; diff --git a/extensions/ipset-5/ip_set_bitmap_ipmac.c b/extensions/ipset-5/ip_set_bitmap_ipmac.c index 4c36d1d..7363527 100644 --- a/extensions/ipset-5/ip_set_bitmap_ipmac.c +++ b/extensions/ipset-5/ip_set_bitmap_ipmac.c @@ -10,7 +10,6 @@ /* Kernel module implementing an IP set type: the bitmap:ip,mac type */ -#include "ip_set_kernel.h" #include #include #include @@ -95,9 +94,9 @@ bitmap_expired(const struct bitmap_ipmac *map, u32 id) static inline int bitmap_ipmac_exist(const struct ipmac_telem *elem) { - return elem->match == MAC_UNSET - || (elem->match == MAC_FILLED - && !ip_set_timeout_expired(elem->timeout)); + return elem->match == MAC_UNSET || + (elem->match == MAC_FILLED && + !ip_set_timeout_expired(elem->timeout)); } /* Base variant */ @@ -114,8 +113,8 @@ bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout) /* Trigger kernel to fill out the ethernet address */ return -EAGAIN; case MAC_FILLED: - return data->ether == NULL - || compare_ether_addr(data->ether, elem->ether) == 0; + return data->ether == NULL || + compare_ether_addr(data->ether, elem->ether) == 0; } return 0; } @@ -223,9 +222,9 @@ bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout) /* Trigger kernel to fill out the ethernet address */ return -EAGAIN; case MAC_FILLED: - return (data->ether == NULL - || compare_ether_addr(data->ether, elem->ether) == 0) - && !bitmap_expired(map, data->id); + return (data->ether == NULL || + compare_ether_addr(data->ether, elem->ether) == 0) && + !bitmap_expired(map, data->id); } return 0; } @@ -348,8 +347,8 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, return -IPSET_ERR_BITMAP_RANGE; /* Backward compatibility: we don't check the second flag */ - if (skb_mac_header(skb) < skb->head - || (skb_mac_header(skb) + ETH_HLEN) > skb->data) + if (skb_mac_header(skb) < skb->head || + (skb_mac_header(skb) + ETH_HLEN) > skb->data) return -EINVAL; data.id -= map->first_ip; @@ -381,13 +380,16 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len, bitmap_ipmac_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.id); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &data.id); if (ret) return ret; - data.id = ntohl(data.id); if (data.id < map->first_ip || data.id > map->last_ip) return -IPSET_ERR_BITMAP_RANGE; @@ -464,12 +466,12 @@ bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b) const struct bitmap_ipmac *x = a->data; const struct bitmap_ipmac *y = b->data; - return x->first_ip == y->first_ip - && x->last_ip == y->last_ip - && x->timeout == y->timeout; + return x->first_ip == y->first_ip && + x->last_ip == y->last_ip && + x->timeout == y->timeout; } -const struct ip_set_type_variant bitmap_ipmac = { +static const struct ip_set_type_variant bitmap_ipmac = { .kadt = bitmap_ipmac_kadt, .uadt = bitmap_ipmac_uadt, .adt = { @@ -484,7 +486,7 @@ const struct ip_set_type_variant bitmap_ipmac = { .same_set = bitmap_ipmac_same_set, }; -const struct ip_set_type_variant bitmap_tipmac = { +static const struct ip_set_type_variant bitmap_tipmac = { .kadt = bitmap_ipmac_kadt, .uadt = bitmap_ipmac_uadt, .adt = { @@ -512,8 +514,8 @@ bitmap_ipmac_gc(unsigned long ul_set) read_lock_bh(&set->lock); for (id = 0; id <= last; id++) { elem = bitmap_ipmac_elem(map, id); - if (elem->match == MAC_FILLED - && ip_set_timeout_expired(elem->timeout)) + if (elem->match == MAC_FILLED && + ip_set_timeout_expired(elem->timeout)) elem->match = MAC_EMPTY; } read_unlock_bh(&set->lock); @@ -522,7 +524,7 @@ bitmap_ipmac_gc(unsigned long ul_set) add_timer(&map->gc); } -static inline void +static void bitmap_ipmac_gc_init(struct ip_set *set) { struct bitmap_ipmac *map = set->data; @@ -540,6 +542,7 @@ static const struct nla_policy bitmap_ipmac_create_policy[IPSET_ATTR_CREATE_MAX+1] = { [IPSET_ATTR_IP] = { .type = NLA_NESTED }, [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, }; @@ -574,16 +577,18 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len, bitmap_ipmac_create_policy)) return -IPSET_ERR_PROTOCOL; - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &first_ip); + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip); if (ret) return ret; - first_ip = ntohl(first_ip); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &last_ip); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip); if (ret) return ret; - last_ip = ntohl(last_ip); if (first_ip > last_ip) { u32 tmp = first_ip; @@ -595,7 +600,7 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len, if (cidr >= 32) return -IPSET_ERR_INVALID_CIDR; - last_ip = first_ip | ~HOSTMASK(cidr); + last_ip = first_ip | ~ip_set_hostmask(cidr); } else return -IPSET_ERR_PROTOCOL; @@ -634,7 +639,7 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len, return 0; } -struct ip_set_type bitmap_ipmac_type = { +static struct ip_set_type bitmap_ipmac_type = { .name = "bitmap:ip,mac", .protocol = IPSET_PROTOCOL, .features = IPSET_TYPE_IP | IPSET_TYPE_MAC, diff --git a/extensions/ipset-5/ip_set_bitmap_port.c b/extensions/ipset-5/ip_set_bitmap_port.c index 9cf7154..5c5c6f3 100644 --- a/extensions/ipset-5/ip_set_bitmap_port.c +++ b/extensions/ipset-5/ip_set_bitmap_port.c @@ -7,7 +7,6 @@ /* Kernel module implementing an IP set type: the bitmap:port type */ -#include "ip_set_kernel.h" #include #include #include @@ -71,12 +70,13 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb, enum ipset_adt adt, u8 pf, u8 dim, u8 flags) { struct bitmap_port *map = set->data; + __be16 __port; u16 port = 0; - if (!get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &port)) + if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port)) return -EINVAL; - port = ntohs(port); + port = ntohs(__port); if (port < map->first_port || port > map->last_port) return -IPSET_ERR_BITMAP_RANGE; @@ -116,14 +116,14 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len, bitmap_port_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - if (tb[IPSET_ATTR_PORT]) - port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); - else - return -IPSET_ERR_PROTOCOL; - + port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); if (port < map->first_port || port > map->last_port) return -IPSET_ERR_BITMAP_RANGE; @@ -246,11 +246,11 @@ bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b) const struct bitmap_port *x = a->data; const struct bitmap_port *y = b->data; - return x->first_port == y->first_port - && x->last_port == y->last_port; + return x->first_port == y->first_port && + x->last_port == y->last_port; } -const struct ip_set_type_variant bitmap_port = { +static const struct ip_set_type_variant bitmap_port = { .kadt = bitmap_port_kadt, .uadt = bitmap_port_uadt, .destroy = bitmap_port_destroy, @@ -308,12 +308,13 @@ bitmap_port_timeout_kadt(struct ip_set *set, const struct sk_buff *skb, enum ipset_adt adt, u8 pf, u8 dim, u8 flags) { struct bitmap_port_timeout *map = set->data; + __be16 __port; u16 port = 0; - if (!get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &port)) + if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port)) return -EINVAL; - port = ntohs(port); + port = ntohs(__port); if (port < map->first_port || port > map->last_port) return -IPSET_ERR_BITMAP_RANGE; @@ -346,14 +347,15 @@ bitmap_port_timeout_uadt(struct ip_set *set, struct nlattr *head, int len, bitmap_port_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - if (tb[IPSET_ATTR_PORT]) - port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); - else - return -IPSET_ERR_PROTOCOL; - + port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); if (port < map->first_port || port > map->last_port) return -IPSET_ERR_BITMAP_RANGE; @@ -483,12 +485,12 @@ bitmap_port_timeout_same_set(const struct ip_set *a, const struct ip_set *b) const struct bitmap_port_timeout *x = a->data; const struct bitmap_port_timeout *y = b->data; - return x->first_port == y->first_port - && x->last_port == y->last_port - && x->timeout == y->timeout; + return x->first_port == y->first_port && + x->last_port == y->last_port && + x->timeout == y->timeout; } -const struct ip_set_type_variant bitmap_port_timeout = { +static const struct ip_set_type_variant bitmap_port_timeout = { .kadt = bitmap_port_timeout_kadt, .uadt = bitmap_port_timeout_uadt, .destroy = bitmap_port_timeout_destroy, @@ -519,7 +521,7 @@ bitmap_port_gc(unsigned long ul_set) add_timer(&map->gc); } -static inline void +static void bitmap_port_gc_init(struct ip_set *set) { struct bitmap_port_timeout *map = set->data; @@ -567,21 +569,19 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len, bitmap_port_create_policy)) return -IPSET_ERR_PROTOCOL; - if (tb[IPSET_ATTR_PORT]) - first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); - else + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) return -IPSET_ERR_PROTOCOL; - if (tb[IPSET_ATTR_PORT_TO]) { - last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); - if (first_port > last_port) { - u16 tmp = first_port; + first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); + last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); + if (first_port > last_port) { + u16 tmp = first_port; - first_port = last_port; - last_port = tmp; - } - } else - return -IPSET_ERR_PROTOCOL; + first_port = last_port; + last_port = tmp; + } if (tb[IPSET_ATTR_TIMEOUT]) { struct bitmap_port_timeout *map; @@ -611,7 +611,7 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len, return -ENOMEM; map->memsize = bitmap_bytes(0, last_port - first_port); - pr_debug("memsize: %zu", map->memsize); + pr_debug("memsize: %zu\n", map->memsize); if (!init_map_port(set, map, first_port, last_port)) { kfree(map); return -ENOMEM; @@ -622,7 +622,7 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len, return 0; } -struct ip_set_type bitmap_port_type = { +static struct ip_set_type bitmap_port_type = { .name = "bitmap:port", .protocol = IPSET_PROTOCOL, .features = IPSET_TYPE_PORT, diff --git a/extensions/ipset-5/ip_set_core.c b/extensions/ipset-5/ip_set_core.c index 3af992f..d17cffe 100644 --- a/extensions/ipset-5/ip_set_core.c +++ b/extensions/ipset-5/ip_set_core.c @@ -9,7 +9,6 @@ /* Kernel module for IP set management */ -#include "ip_set_kernel.h" #include #include #include @@ -26,7 +25,7 @@ #include #define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN) -static struct list_head ip_set_type_list; /* all registered set types */ +static LIST_HEAD(ip_set_type_list); /* all registered set types */ static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */ static struct ip_set **ip_set_list; /* all individual sets */ @@ -34,7 +33,7 @@ static ip_set_id_t ip_set_max = LCONFIG_IP_SET_MAX; /* max number of sets */ #define STREQ(a, b) (strncmp(a, b, IPSET_MAXNAMELEN) == 0) -static int max_sets; +static unsigned int max_sets; module_param(max_sets, int, 0600); MODULE_PARM_DESC(max_sets, "maximal number of sets"); @@ -64,60 +63,77 @@ ip_set_type_unlock(void) /* Register and deregister settype */ -static inline struct ip_set_type * +static struct ip_set_type * find_set_type(const char *name, u8 family, u8 revision) { struct ip_set_type *type; list_for_each_entry_rcu(type, &ip_set_type_list, list) - if (STREQ(type->name, name) - && (type->family == family || type->family == AF_UNSPEC) - && type->revision == revision) + if (STREQ(type->name, name) && + (type->family == family || type->family == AF_UNSPEC) && + type->revision == revision) return type; return NULL; } -/* Find a set type so that rcu_read_lock() is called by the function. - * If we succeeded, the RCU lock is NOT released and the caller - * must release it later. - */ -static struct ip_set_type * -find_set_type_rcu(const char *name, u8 family, u8 revision) +/* Unlock, try to load a set type module and lock again */ +static int +try_to_load_type(const char *name) { - struct ip_set_type *type; + nfnl_unlock(); + pr_debug("try to load ip_set_%s\n", name); + if (request_module("ip_set_%s", name) < 0) { + pr_warning("Can't find ip_set type %s\n", name); + nfnl_lock(); + return -IPSET_ERR_FIND_TYPE; + } + nfnl_lock(); + return -EAGAIN; +} +/* Find a set type and reference it */ +static int +find_set_type_get(const char *name, u8 family, u8 revision, + struct ip_set_type **found) +{ rcu_read_lock(); - type = find_set_type(name, family, revision); - if (type == NULL) + *found = find_set_type(name, family, revision); + if (*found) { + int err = !try_module_get((*found)->me); rcu_read_unlock(); + return err ? -EFAULT : 0; + } + rcu_read_unlock(); - return type; + return try_to_load_type(name); } /* Find a given set type by name and family. * If we succeeded, the supported minimal and maximum revisions are * filled out. */ -static bool +static int find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max) { struct ip_set_type *type; - bool ret = false; + bool found = false; *min = *max = 0; rcu_read_lock(); list_for_each_entry_rcu(type, &ip_set_type_list, list) - if (STREQ(type->name, name) - && (type->family == family || type->family == AF_UNSPEC)) { - ret = true; + if (STREQ(type->name, name) && + (type->family == family || type->family == AF_UNSPEC)) { + found = true; if (type->revision < *min) *min = type->revision; else if (type->revision > *max) *max = type->revision; } rcu_read_unlock(); + if (found) + return 0; - return ret; + return try_to_load_type(name); } #define family_name(f) ((f) == AF_INET ? "inet" : \ @@ -149,7 +165,7 @@ ip_set_type_register(struct ip_set_type *type) goto unlock; } list_add_rcu(&type->list, &ip_set_type_list); - pr_debug("type %s, family %s, revision %u registered.", + pr_debug("type %s, family %s, revision %u registered.\n", type->name, family_name(type->family), type->revision); unlock: ip_set_type_unlock(); @@ -169,7 +185,7 @@ ip_set_type_unregister(struct ip_set_type *type) goto unlock; } list_del_rcu(&type->list); - pr_debug("type %s, family %s, revision %u unregistered.", + pr_debug("type %s, family %s, revision %u unregistered.\n", type->name, family_name(type->family), type->revision); unlock: ip_set_type_unlock(); @@ -178,6 +194,92 @@ unlock: } EXPORT_SYMBOL_GPL(ip_set_type_unregister); +/* Utility functions */ +void * +ip_set_alloc(size_t size, gfp_t gfp_mask) +{ + void *members = NULL; + + if (size < KMALLOC_MAX_SIZE) + members = kzalloc(size, gfp_mask | __GFP_NOWARN); + + if (members) { + pr_debug("%p: allocated with kmalloc\n", members); + return members; + } + + members = __vmalloc(size, gfp_mask | __GFP_ZERO | __GFP_HIGHMEM, + PAGE_KERNEL); + if (!members) + return NULL; + pr_debug("%p: allocated with vmalloc\n", members); + + return members; +} +EXPORT_SYMBOL_GPL(ip_set_alloc); + +void +ip_set_free(void *members) +{ + pr_debug("%p: free with %s\n", members, + is_vmalloc_addr(members) ? "vfree" : "kfree"); + if (is_vmalloc_addr(members)) + vfree(members); + else + kfree(members); +} +EXPORT_SYMBOL_GPL(ip_set_free); + +static inline bool +flag_nested(const struct nlattr *nla) +{ + return nla->nla_type & NLA_F_NESTED; +} + +static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = { + [IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 }, + [IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY, + .len = sizeof(struct in6_addr) }, +}; + +int +ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr) +{ + struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1]; + + if (unlikely(!flag_nested(nla))) + return -IPSET_ERR_PROTOCOL; + if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, nla_data(nla), nla_len(nla), + ipaddr_policy)) + return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4))) + return -IPSET_ERR_PROTOCOL; + + *ipaddr = nla_get_be32(tb[IPSET_ATTR_IPADDR_IPV4]); + return 0; +} +EXPORT_SYMBOL_GPL(ip_set_get_ipaddr4); + +int +ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr) +{ + struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1]; + + if (unlikely(!flag_nested(nla))) + return -IPSET_ERR_PROTOCOL; + + if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, nla_data(nla), nla_len(nla), + ipaddr_policy)) + return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6))) + return -IPSET_ERR_PROTOCOL; + + memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]), + sizeof(struct in6_addr)); + return 0; +} +EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6); + /* * Creating/destroying/renaming/swapping affect the existence and * the properties of a set. All of these can be executed from userspace @@ -216,10 +318,10 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb, int ret = 0; BUG_ON(set == NULL || atomic_read(&set->ref) == 0); - pr_debug("set %s, index %u", set->name, index); + pr_debug("set %s, index %u\n", set->name, index); - if (dim < set->type->dimension - || !(family == set->family || set->family == AF_UNSPEC)) + if (dim < set->type->dimension || + !(family == set->family || set->family == AF_UNSPEC)) return 0; read_lock_bh(&set->lock); @@ -228,7 +330,7 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb, if (ret == -EAGAIN) { /* Type requests element to be completed */ - pr_debug("element must be competed, ADD is triggered"); + pr_debug("element must be competed, ADD is triggered\n"); write_lock_bh(&set->lock); set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags); write_unlock_bh(&set->lock); @@ -248,10 +350,10 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb, int ret; BUG_ON(set == NULL || atomic_read(&set->ref) == 0); - pr_debug("set %s, index %u", set->name, index); + pr_debug("set %s, index %u\n", set->name, index); - if (dim < set->type->dimension - || !(family == set->family || set->family == AF_UNSPEC)) + if (dim < set->type->dimension || + !(family == set->family || set->family == AF_UNSPEC)) return 0; write_lock_bh(&set->lock); @@ -270,10 +372,10 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb, int ret = 0; BUG_ON(set == NULL || atomic_read(&set->ref) == 0); - pr_debug("set %s, index %u", set->name, index); + pr_debug("set %s, index %u\n", set->name, index); - if (dim < set->type->dimension - || !(family == set->family || set->family == AF_UNSPEC)) + if (dim < set->type->dimension || + !(family == set->family || set->family == AF_UNSPEC)) return 0; write_lock_bh(&set->lock); @@ -423,8 +525,8 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_put); static inline bool protocol_failed(struct nlattr *const *tb) { - return !tb[IPSET_ATTR_PROTOCOL] - || nla_get_u8(tb[IPSET_ATTR_PROTOCOL]) != IPSET_PROTOCOL; + return !tb[IPSET_ATTR_PROTOCOL] || + nla_get_u8(tb[IPSET_ATTR_PROTOCOL]) != IPSET_PROTOCOL; } static inline u32 @@ -433,13 +535,7 @@ flag_exist(const struct genlmsghdr *ghdr) return ghdr->reserved & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST; } -static inline bool -flag_nested(const struct nlattr *nla) -{ - return nla->nla_type & NLA_F_NESTED; -} - -static void * +static struct nlmsghdr * start_msg(struct sk_buff *skb, u32 pid, u32 seq, unsigned int flags, enum ipset_cmd cmd) { @@ -508,13 +604,6 @@ find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set) return 0; } -static inline void -load_type_module(const char *typename) -{ - pr_debug("try to load ip_set_%s", typename); - request_module("ip_set_%s", typename); -} - static int ip_set_create(struct sk_buff *skb, struct genl_info *info) { @@ -527,20 +616,20 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info) u32 flags = flag_exist(info->genlhdr); int ret = 0, len; - if (unlikely(protocol_failed(attr) - || attr[IPSET_ATTR_SETNAME] == NULL - || attr[IPSET_ATTR_TYPENAME] == NULL - || attr[IPSET_ATTR_REVISION] == NULL - || attr[IPSET_ATTR_FAMILY] == NULL - || (attr[IPSET_ATTR_DATA] != NULL - && !flag_nested(attr[IPSET_ATTR_DATA])))) + if (unlikely(protocol_failed(attr) || + attr[IPSET_ATTR_SETNAME] == NULL || + attr[IPSET_ATTR_TYPENAME] == NULL || + attr[IPSET_ATTR_REVISION] == NULL || + attr[IPSET_ATTR_FAMILY] == NULL || + (attr[IPSET_ATTR_DATA] != NULL && + !flag_nested(attr[IPSET_ATTR_DATA])))) return -IPSET_ERR_PROTOCOL; name = nla_data(attr[IPSET_ATTR_SETNAME]); typename = nla_data(attr[IPSET_ATTR_TYPENAME]); family = nla_get_u8(attr[IPSET_ATTR_FAMILY]); revision = nla_get_u8(attr[IPSET_ATTR_REVISION]); - pr_debug("setname: %s, typename: %s, family: %s, revision: %u", + pr_debug("setname: %s, typename: %s, family: %s, revision: %u\n", name, typename, family_name(family), revision); /* @@ -563,32 +652,15 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info) * After referencing the type, we try to create the type * specific part of the set without holding any locks. */ - set->type = find_set_type_rcu(typename, family, revision); - if (set->type == NULL) { - /* Try loading the module */ - load_type_module(typename); - set->type = find_set_type_rcu(typename, family, revision); - if (set->type == NULL) { - pr_warning("Can't find ip_set type %s, family %s, " - "revision %u: set '%s' not created", - typename, family_name(family), revision, - name); - ret = -IPSET_ERR_FIND_TYPE; - goto out; - } - } - if (!try_module_get(set->type->me)) { - rcu_read_unlock(); - ret = -EFAULT; + ret = find_set_type_get(typename, family, revision, &(set->type)); + if (ret) goto out; - } - rcu_read_unlock(); /* * Without holding any locks, create private part. */ len = attr[IPSET_ATTR_DATA] ? nla_len(attr[IPSET_ATTR_DATA]) : 0; - pr_debug("data len: %u", len); + pr_debug("data len: %u\n", len); ret = set->type->create(set, attr[IPSET_ATTR_DATA] ? nla_data(attr[IPSET_ATTR_DATA]) : NULL, len, flags); @@ -604,12 +676,12 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info) */ if ((ret = find_free_id(set->name, &index, &clash)) != 0) { /* If this is the same set and requested, ignore error */ - if (ret == -EEXIST - && (flags & IPSET_FLAG_EXIST) - && STREQ(set->type->name, clash->type->name) - && set->type->family == clash->type->family - && set->type->revision == clash->type->revision - && set->variant->same_set(set, clash)) + if (ret == -EEXIST && + (flags & IPSET_FLAG_EXIST) && + STREQ(set->type->name, clash->type->name) && + set->type->family == clash->type->family && + set->type->revision == clash->type->revision && + set->variant->same_set(set, clash)) ret = 0; goto cleanup; } @@ -617,7 +689,7 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info) /* * Finally! Add our shiny new set to the list, and be done. */ - pr_debug("create: '%s' created with index %u!", set->name, index); + pr_debug("create: '%s' created with index %u!\n", set->name, index); ip_set_list[index] = set; return ret; @@ -640,12 +712,12 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = { .len = IPSET_MAXNAMELEN - 1 }, }; -static inline void +static void ip_set_destroy_set(ip_set_id_t index) { struct ip_set *set = ip_set_list[index]; - pr_debug("set: %s", set->name); + pr_debug("set: %s\n", set->name); ip_set_list[index] = NULL; /* Must call it without holding any lock */ @@ -666,8 +738,8 @@ ip_set_destroy(struct sk_buff *skb, struct genl_info *info) /* References are protected by the nfnl mutex */ if (!attr[IPSET_ATTR_SETNAME]) { for (i = 0; i < ip_set_max; i++) { - if (ip_set_list[i] != NULL - && (atomic_read(&ip_set_list[i]->ref))) + if (ip_set_list[i] != NULL && + (atomic_read(&ip_set_list[i]->ref))) return -IPSET_ERR_BUSY; } for (i = 0; i < ip_set_max; i++) { @@ -688,10 +760,10 @@ ip_set_destroy(struct sk_buff *skb, struct genl_info *info) /* Flush sets */ -static inline void +static void ip_set_flush_set(struct ip_set *set) { - pr_debug("set: %s", set->name); + pr_debug("set: %s\n", set->name); write_lock_bh(&set->lock); set->variant->flush(set); @@ -741,9 +813,9 @@ ip_set_rename(struct sk_buff *skb, struct genl_info *info) const char *name2; ip_set_id_t i; - if (unlikely(protocol_failed(attr) - || attr[IPSET_ATTR_SETNAME] == NULL - || attr[IPSET_ATTR_SETNAME2] == NULL)) + if (unlikely(protocol_failed(attr) || + attr[IPSET_ATTR_SETNAME] == NULL || + attr[IPSET_ATTR_SETNAME2] == NULL)) return -IPSET_ERR_PROTOCOL; set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); @@ -754,8 +826,8 @@ ip_set_rename(struct sk_buff *skb, struct genl_info *info) name2 = nla_data(attr[IPSET_ATTR_SETNAME2]); for (i = 0; i < ip_set_max; i++) { - if (ip_set_list[i] != NULL - && STREQ(ip_set_list[i]->name, name2)) + if (ip_set_list[i] != NULL && + STREQ(ip_set_list[i]->name, name2)) return -IPSET_ERR_EXIST_SETNAME2; } strncpy(set->name, name2, IPSET_MAXNAMELEN); @@ -781,9 +853,9 @@ ip_set_swap(struct sk_buff *skb, struct genl_info *info) char from_name[IPSET_MAXNAMELEN]; u32 from_ref; - if (unlikely(protocol_failed(attr) - || attr[IPSET_ATTR_SETNAME] == NULL - || attr[IPSET_ATTR_SETNAME2] == NULL)) + if (unlikely(protocol_failed(attr) || + attr[IPSET_ATTR_SETNAME] == NULL || + attr[IPSET_ATTR_SETNAME2] == NULL)) return -IPSET_ERR_PROTOCOL; from_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); @@ -800,8 +872,8 @@ ip_set_swap(struct sk_buff *skb, struct genl_info *info) /* Features must not change. * Not an artifical restriction anymore, as we must prevent * possible loops created by swapping in setlist type of sets. */ - if (!(from->type->features == to->type->features - && from->type->family == to->type->family)) + if (!(from->type->features == to->type->features && + from->type->family == to->type->family)) return -IPSET_ERR_TYPE_MISMATCH; /* No magic here: ref munging protected by the nfnl_lock */ @@ -830,7 +902,7 @@ static int ip_set_dump_done(struct netlink_callback *cb) { if (cb->args[2]) { - pr_debug("release set %s", ip_set_list[cb->args[1]]->name); + pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name); __ip_set_put((ip_set_id_t) cb->args[1]); } return 0; @@ -843,14 +915,13 @@ dump_attrs(void *phdr) const struct nlmsghdr *nlh = phdr - GENL_HDRLEN - NLMSG_HDRLEN; int rem; - pr_debug("nlmsg_len: %u", nlh->nlmsg_len); - pr_debug("dump nlmsg"); + pr_debug("dump nlmsg\n"); nlmsg_for_each_attr(attr, nlh, sizeof(struct genlmsghdr), rem) { - pr_debug("type: %u, len %u", nla_type(attr), attr->nla_len); + pr_debug("type: %u, len %u\n", nla_type(attr), attr->nla_len); } } -static inline int +static int dump_init(struct netlink_callback *cb) { struct nlmsghdr *nlh = nlmsg_hdr(cb->skb); @@ -919,14 +990,14 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) /* When dumping all sets, we must dump "sorted" * so that lists (unions of sets) are dumped last. */ - if (cb->args[0] != DUMP_ONE - && !((cb->args[0] == DUMP_ALL) - ^ (set->type->features & IPSET_DUMP_LAST))) + if (cb->args[0] != DUMP_ONE && + !((cb->args[0] == DUMP_ALL) ^ + (set->type->features & IPSET_DUMP_LAST))) continue; - pr_debug("List set: %s", set->name); + pr_debug("List set: %s\n", set->name); if (!cb->args[2]) { /* Start listing: make sure set won't be destroyed */ - pr_debug("reference set"); + pr_debug("reference set\n"); __ip_set_get(index); } nlh = start_msg(skb, NETLINK_CB(cb->skb).pid, @@ -972,7 +1043,7 @@ nla_put_failure: release_refcount: /* If there was an error or set is done, release set */ if (ret || !cb->args[2]) { - pr_debug("release set %s", ip_set_list[index]->name); + pr_debug("release set %s\n", ip_set_list[index]->name); __ip_set_put(index); } @@ -983,6 +1054,7 @@ release_refcount: out: if (nlh) { genlmsg_end(skb, nlh); + pr_debug("nlmsg_len: %u\n", skb->len); dump_attrs(nlh); } @@ -1034,9 +1106,9 @@ call_ad(struct sk_buff *skb, struct nlattr *const attr[], ret = set->variant->uadt(set, head, len, adt, &lineno, flags); write_unlock_bh(&set->lock); - } while (ret == -EAGAIN - && set->variant->resize - && (ret = set->variant->resize(set, retried++)) == 0); + } while (ret == -EAGAIN && + set->variant->resize && + (ret = set->variant->resize(set, retried++)) == 0); if (!ret || (ret == -IPSET_ERR_EXIST && eexist)) return 0; @@ -1060,15 +1132,15 @@ ip_set_uadd(struct sk_buff *skb, struct genl_info *info) u32 flags = flag_exist(info->genlhdr); int ret = 0; - if (unlikely(protocol_failed(attr) - || attr[IPSET_ATTR_SETNAME] == NULL - || !((attr[IPSET_ATTR_DATA] != NULL) - ^ (attr[IPSET_ATTR_ADT] != NULL)) - || (attr[IPSET_ATTR_DATA] != NULL - && !flag_nested(attr[IPSET_ATTR_DATA])) - || (attr[IPSET_ATTR_ADT] != NULL - && (!flag_nested(attr[IPSET_ATTR_ADT]) - || attr[IPSET_ATTR_LINENO] == NULL)))) + if (unlikely(protocol_failed(attr) || + attr[IPSET_ATTR_SETNAME] == NULL || + !((attr[IPSET_ATTR_DATA] != NULL) ^ + (attr[IPSET_ATTR_ADT] != NULL)) || + (attr[IPSET_ATTR_DATA] != NULL && + !flag_nested(attr[IPSET_ATTR_DATA])) || + (attr[IPSET_ATTR_ADT] != NULL && + (!flag_nested(attr[IPSET_ATTR_ADT]) || + attr[IPSET_ATTR_LINENO] == NULL)))) return -IPSET_ERR_PROTOCOL; set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); @@ -1082,8 +1154,8 @@ ip_set_uadd(struct sk_buff *skb, struct genl_info *info) int nla_rem; nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) { - if (nla_type(nla) != IPSET_ATTR_DATA - || !flag_nested(nla)) + if (nla_type(nla) != IPSET_ATTR_DATA || + !flag_nested(nla)) return -IPSET_ERR_PROTOCOL; ret = call_ad(skb, attr, set, nla, IPSET_ADD, flags); @@ -1104,15 +1176,15 @@ ip_set_udel(struct sk_buff *skb, struct genl_info *info) u32 flags = flag_exist(info->genlhdr); int ret = 0; - if (unlikely(protocol_failed(attr) - || attr[IPSET_ATTR_SETNAME] == NULL - || !((attr[IPSET_ATTR_DATA] != NULL) - ^ (attr[IPSET_ATTR_ADT] != NULL)) - || (attr[IPSET_ATTR_DATA] != NULL - && !flag_nested(attr[IPSET_ATTR_DATA])) - || (attr[IPSET_ATTR_ADT] != NULL - && (!flag_nested(attr[IPSET_ATTR_ADT]) - || attr[IPSET_ATTR_LINENO] == NULL)))) + if (unlikely(protocol_failed(attr) || + attr[IPSET_ATTR_SETNAME] == NULL || + !((attr[IPSET_ATTR_DATA] != NULL) ^ + (attr[IPSET_ATTR_ADT] != NULL)) || + (attr[IPSET_ATTR_DATA] != NULL && + !flag_nested(attr[IPSET_ATTR_DATA])) || + (attr[IPSET_ATTR_ADT] != NULL && + (!flag_nested(attr[IPSET_ATTR_ADT]) || + attr[IPSET_ATTR_LINENO] == NULL)))) return -IPSET_ERR_PROTOCOL; set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); @@ -1126,8 +1198,8 @@ ip_set_udel(struct sk_buff *skb, struct genl_info *info) int nla_rem; nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) { - if (nla_type(nla) != IPSET_ATTR_DATA - || !flag_nested(nla)) + if (nla_type(nla) != IPSET_ATTR_DATA || + !flag_nested(nla)) return -IPSET_ERR_PROTOCOL; ret = call_ad(skb, attr, set, nla, IPSET_DEL, flags); @@ -1146,10 +1218,10 @@ ip_set_utest(struct sk_buff *skb, struct genl_info *info) struct ip_set *set; int ret = 0; - if (unlikely(protocol_failed(attr) - || attr[IPSET_ATTR_SETNAME] == NULL - || attr[IPSET_ATTR_DATA] == NULL - || !flag_nested(attr[IPSET_ATTR_DATA]))) + if (unlikely(protocol_failed(attr) || + attr[IPSET_ATTR_SETNAME] == NULL || + attr[IPSET_ATTR_DATA] == NULL || + !flag_nested(attr[IPSET_ATTR_DATA]))) return -IPSET_ERR_PROTOCOL; set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); @@ -1182,8 +1254,8 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info) ip_set_id_t index; int ret = 0; - if (unlikely(protocol_failed(attr) - || attr[IPSET_ATTR_SETNAME] == NULL)) + if (unlikely(protocol_failed(attr) || + attr[IPSET_ATTR_SETNAME] == NULL)) return -IPSET_ERR_PROTOCOL; index = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); @@ -1240,22 +1312,16 @@ ip_set_type(struct sk_buff *skb, struct genl_info *info) const char *typename; int ret = 0; - if (unlikely(protocol_failed(attr) - || attr[IPSET_ATTR_TYPENAME] == NULL - || attr[IPSET_ATTR_FAMILY] == NULL)) + if (unlikely(protocol_failed(attr) || + attr[IPSET_ATTR_TYPENAME] == NULL || + attr[IPSET_ATTR_FAMILY] == NULL)) return -IPSET_ERR_PROTOCOL; family = nla_get_u8(attr[IPSET_ATTR_FAMILY]); typename = nla_data(attr[IPSET_ATTR_TYPENAME]); - if (!find_set_type_minmax(typename, family, &min, &max)) { - /* Try to load in the type module */ - load_type_module(typename); - if (!find_set_type_minmax(typename, family, &min, &max)) { - pr_debug("can't find: %s, family: %u", - typename, family); - return -EEXIST; - } - } + ret = find_set_type_minmax(typename, family, &min, &max); + if (ret) + return ret; skb2 = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); if (skb2 == NULL) @@ -1272,6 +1338,7 @@ ip_set_type(struct sk_buff *skb, struct genl_info *info) NLA_PUT_U8(skb2, IPSET_ATTR_REVISION_MIN, min); genlmsg_end(skb2, nlh2); + pr_debug("Send TYPE, nlmsg_len: %u\n", skb2->len); ret = genlmsg_unicast(genl_info_net(info), skb2, NETLINK_CB(skb).pid); if (ret < 0) return -EFAULT; @@ -1421,7 +1488,7 @@ static struct genl_family ip_set_netlink_subsys __read_mostly = { /* Interface to iptables/ip6tables */ static int -ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len) +ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) { unsigned *op; void *data; @@ -1482,8 +1549,8 @@ ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len) case IP_SET_OP_GET_BYINDEX: { struct ip_set_req_get_set *req_get = data; - if (*len != sizeof(struct ip_set_req_get_set) - || req_get->set.index >= ip_set_max) { + if (*len != sizeof(struct ip_set_req_get_set) || + req_get->set.index >= ip_set_max) { ret = -EINVAL; goto done; } @@ -1531,12 +1598,10 @@ ip_set_init(void) ip_set_list = kzalloc(sizeof(struct ip_set *) * ip_set_max, GFP_KERNEL); if (!ip_set_list) { - pr_err("ip_set: Unable to create ip_set_list"); + pr_err("ip_set: Unable to create ip_set_list\n"); return -ENOMEM; } - INIT_LIST_HEAD(&ip_set_type_list); - ret = genl_register_family_with_ops(&ip_set_netlink_subsys, ip_set_netlink_subsys_cb, ARRAY_SIZE(ip_set_netlink_subsys_cb)); if (ret != 0) { @@ -1546,13 +1611,13 @@ ip_set_init(void) } ret = nf_register_sockopt(&so_set); if (ret != 0) { - pr_err("SO_SET registry failed: %d", ret); + pr_err("SO_SET registry failed: %d\n", ret); genl_unregister_family(&ip_set_netlink_subsys); kfree(ip_set_list); return ret; } - pr_notice("ip_set: protocol %u", IPSET_PROTOCOL); + pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL); return 0; } @@ -1563,7 +1628,7 @@ ip_set_fini(void) nf_unregister_sockopt(&so_set); genl_unregister_family(&ip_set_netlink_subsys); kfree(ip_set_list); - pr_debug("these are the famous last words"); + pr_debug("these are the famous last words\n"); } module_init(ip_set_init); diff --git a/extensions/ipset-5/ip_set_getport.c b/extensions/ipset-5/ip_set_getport.c new file mode 100644 index 0000000..d6cf5d2 --- /dev/null +++ b/extensions/ipset-5/ip_set_getport.c @@ -0,0 +1,136 @@ +/* Copyright (C) 2003-2011 Jozsef Kadlecsik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* Get Layer-4 data from the packets */ + +#include +#include +#include +#include +#include +#include + +#include "ip_set_getport.h" + +/* We must handle non-linear skbs */ +static bool +get_port(const struct sk_buff *skb, int protocol, unsigned int protooff, + bool src, __be16 *port, u8 *proto) +{ + switch (protocol) { + case IPPROTO_TCP: { + struct tcphdr _tcph; + const struct tcphdr *th; + + th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph); + if (th == NULL) + /* No choice either */ + return false; + + *port = src ? th->source : th->dest; + break; + } + case IPPROTO_UDP: { + struct udphdr _udph; + const struct udphdr *uh; + + uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph); + if (uh == NULL) + /* No choice either */ + return false; + + *port = src ? uh->source : uh->dest; + break; + } + case IPPROTO_ICMP: { + struct icmphdr _ich; + const struct icmphdr *ic; + + ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich); + if (ic == NULL) + return false; + + *port = (__force __be16)htons((ic->type << 8) | ic->code); + break; + } + case IPPROTO_ICMPV6: { + struct icmp6hdr _ich; + const struct icmp6hdr *ic; + + ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich); + if (ic == NULL) + return false; + + *port = (__force __be16) + htons((ic->icmp6_type << 8) | ic->icmp6_code); + break; + } + default: + break; + } + *proto = protocol; + + return true; +} + +bool +ip_set_get_ip4_port(const struct sk_buff *skb, bool src, + __be16 *port, u8 *proto) +{ + const struct iphdr *iph = ip_hdr(skb); + unsigned int protooff = ip_hdrlen(skb); + int protocol = iph->protocol; + + /* See comments at tcp_match in ip_tables.c */ + if (protocol <= 0 || (ntohs(iph->frag_off) & IP_OFFSET)) + return false; + + return get_port(skb, protocol, protooff, src, port, proto); +} +EXPORT_SYMBOL_GPL(ip_set_get_ip4_port); + +bool +ip_set_get_ip6_port(const struct sk_buff *skb, bool src, + __be16 *port, u8 *proto) +{ + unsigned int protooff = 0; + int protocol; + unsigned short fragoff; + + protocol = ipv6_find_hdr(skb, &protooff, -1, &fragoff); + if (protocol <= 0 || fragoff) + return false; + + return get_port(skb, protocol, protooff, src, port, proto); +} +EXPORT_SYMBOL_GPL(ip_set_get_ip6_port); + +bool +ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port) +{ + bool ret; + u8 proto; + + switch (pf) { + case AF_INET: + ret = ip_set_get_ip4_port(skb, src, port, &proto); + case AF_INET6: + ret = ip_set_get_ip6_port(skb, src, port, &proto); + default: + return false; + } + if (!ret) + return ret; + switch (proto) { + case IPPROTO_TCP: + case IPPROTO_UDP: + return true; + default: + return false; + } +} +EXPORT_SYMBOL_GPL(ip_set_get_ip_port); diff --git a/extensions/ipset-5/ip_set_getport.h b/extensions/ipset-5/ip_set_getport.h index 8be8ecf..694c433 100644 --- a/extensions/ipset-5/ip_set_getport.h +++ b/extensions/ipset-5/ip_set_getport.h @@ -1,126 +1,11 @@ #ifndef _IP_SET_GETPORT_H #define _IP_SET_GETPORT_H -#ifdef __KERNEL__ -#include -#include -#include -#include - -#define IPSET_INVALID_PORT 65536 - -/* We must handle non-linear skbs */ -static inline bool -get_port(const struct sk_buff *skb, int protocol, unsigned int protooff, - bool src, u16 *port, u8 *proto) -{ - switch (protocol) { - case IPPROTO_TCP: { - struct tcphdr _tcph; - const struct tcphdr *th; - - th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph); - if (th == NULL) - /* No choice either */ - return false; - - *port = src ? th->source : th->dest; - break; - } - case IPPROTO_UDP: { - struct udphdr _udph; - const struct udphdr *uh; - - uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph); - if (uh == NULL) - /* No choice either */ - return false; - - *port = src ? uh->source : uh->dest; - break; - } - case IPPROTO_ICMP: { - struct icmphdr _icmph; - const struct icmphdr *ic; - - ic = skb_header_pointer(skb, protooff, sizeof(_icmph), &_icmph); - if (ic == NULL) - return false; - - *port = (ic->type << 8) & ic->code; - break; - } - case IPPROTO_ICMPV6: { - struct icmp6hdr _icmph; - const struct icmp6hdr *ic; - - ic = skb_header_pointer(skb, protooff, sizeof(_icmph), &_icmph); - if (ic == NULL) - return false; - - *port = (ic->icmp6_type << 8) & ic->icmp6_code; - break; - } - default: - break; - } - *proto = protocol; - - return true; -} - -static inline bool -get_ip4_port(const struct sk_buff *skb, bool src, u16 *port, u8 *proto) -{ - const struct iphdr *iph = ip_hdr(skb); - unsigned int protooff = ip_hdrlen(skb); - int protocol = iph->protocol; - - /* See comments at tcp_match in ip_tables.c */ - if (protocol <= 0 || (ntohs(iph->frag_off) & IP_OFFSET)) - return false; - - return get_port(skb, protocol, protooff, src, port, proto); -} - -static inline bool -get_ip6_port(const struct sk_buff *skb, bool src, u16 *port, u8 *proto) -{ - unsigned int protooff = 0; - int protocol; - unsigned short fragoff; - - protocol = ipv6_find_hdr(skb, &protooff, -1, &fragoff); - if (protocol <= 0 || fragoff) - return false; - - return get_port(skb, protocol, protooff, src, port, proto); -} - -static inline bool -get_ip_port(const struct sk_buff *skb, u8 pf, bool src, u16 *port) -{ - bool ret; - u8 proto; - - switch (pf) { - case AF_INET: - ret = get_ip4_port(skb, src, port, &proto); - case AF_INET6: - ret = get_ip6_port(skb, src, port, &proto); - default: - return false; - } - if (!ret) - return ret; - switch (proto) { - case IPPROTO_TCP: - case IPPROTO_UDP: - return true; - default: - return false; - } -} -#endif /* __KERNEL__ */ +extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src, + __be16 *port, u8 *proto); +extern bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src, + __be16 *port, u8 *proto); +extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, + __be16 *port); #endif /*_IP_SET_GETPORT_H*/ diff --git a/extensions/ipset-5/ip_set_hash_ip.c b/extensions/ipset-5/ip_set_hash_ip.c index 5e12105..3eaa910 100644 --- a/extensions/ipset-5/ip_set_hash_ip.c +++ b/extensions/ipset-5/ip_set_hash_ip.c @@ -7,7 +7,6 @@ /* Kernel module implementing an IP set type: the hash:ip type */ -#include "ip_set_kernel.h" #include "jhash.h" #include #include @@ -46,12 +45,12 @@ hash_ip_same_set(const struct ip_set *a, const struct ip_set *b); /* Member elements without timeout */ struct hash_ip4_elem { - u32 ip; + __be32 ip; }; /* Member elements with timeout support */ struct hash_ip4_telem { - u32 ip; + __be32 ip; unsigned long timeout; }; @@ -74,12 +73,6 @@ hash_ip4_data_copy(struct hash_ip4_elem *dst, const struct hash_ip4_elem *src) dst->ip = src->ip; } -static inline void -hash_ip4_data_swap(struct hash_ip4_elem *dst, struct hash_ip4_elem *src) -{ - swap(dst->ip, src->ip); -} - /* Zero valued IP addresses cannot be stored */ static inline void hash_ip4_data_zero_out(struct hash_ip4_elem *elem) @@ -97,7 +90,7 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data) { const struct hash_ip4_telem *tdata = @@ -124,10 +117,10 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb, { const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - u32 ip; + __be32 ip; ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip); - ip &= NETMASK(h->netmask); + ip &= ip_set_netmask(h->netmask); if (ip == 0) return -EINVAL; @@ -149,23 +142,26 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len, const struct ip_set_hash *h = set->data; struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; - u32 ip, nip, ip_to, hosts, timeout = h->timeout; + u32 ip, ip_to, hosts, timeout = h->timeout; + __be32 nip; int ret = 0; if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, hash_ip4_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &ip); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); if (ret) return ret; - ip &= NETMASK(h->netmask); - if (ip == 0) - return -IPSET_ERR_HASH_ELEM; + ip &= ip_set_hostmask(h->netmask); if (tb[IPSET_ATTR_TIMEOUT]) { if (!with_timeout(h->timeout)) @@ -173,15 +169,17 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST) - return adtfn(set, &ip, timeout); + if (adt == IPSET_TEST) { + nip = htonl(ip); + if (nip == 0) + return -IPSET_ERR_HASH_ELEM; + return adtfn(set, &nip, timeout); + } - ip = ntohl(ip); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; - ip_to = ntohl(ip_to); if (ip > ip_to) swap(ip, ip_to); } else if (tb[IPSET_ATTR_CIDR]) { @@ -189,8 +187,8 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len, if (cidr > 32) return -IPSET_ERR_INVALID_CIDR; - ip &= HOSTMASK(cidr); - ip_to = ip | ~HOSTMASK(cidr); + ip &= ip_set_hostmask(cidr); + ip_to = ip | ~ip_set_hostmask(cidr); } else ip_to = ip; @@ -198,6 +196,8 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len, for (; !before(ip_to, ip); ip += hosts) { nip = htonl(ip); + if (nip == 0) + return -IPSET_ERR_HASH_ELEM; ret = adtfn(set, &nip, timeout); if (ret && !ip_set_eexist(ret, flags)) @@ -215,9 +215,9 @@ hash_ip_same_set(const struct ip_set *a, const struct ip_set *b) const struct ip_set_hash *y = b->data; /* Resizing changes htable_bits, so we ignore it */ - return x->maxelem == y->maxelem - && x->timeout == y->timeout - && x->netmask == y->netmask; + return x->maxelem == y->maxelem && + x->timeout == y->timeout && + x->netmask == y->netmask; } /* The type variant functions: IPv6 */ @@ -250,16 +250,6 @@ hash_ip6_data_copy(struct hash_ip6_elem *dst, const struct hash_ip6_elem *src) ipv6_addr_copy(&dst->ip.in6, &src->ip.in6); } -static inline void -hash_ip6_data_swap(struct hash_ip6_elem *dst, struct hash_ip6_elem *src) -{ - struct in6_addr tmp; - - ipv6_addr_copy(&tmp, &dst->ip.in6); - ipv6_addr_copy(&dst->ip.in6, &src->ip.in6); - ipv6_addr_copy(&src->ip.in6, &tmp); -} - static inline void hash_ip6_data_zero_out(struct hash_ip6_elem *elem) { @@ -269,13 +259,13 @@ hash_ip6_data_zero_out(struct hash_ip6_elem *elem) static inline void ip6_netmask(union nf_inet_addr *ip, u8 prefix) { - ip->ip6[0] &= NETMASK6(prefix)[0]; - ip->ip6[1] &= NETMASK6(prefix)[1]; - ip->ip6[2] &= NETMASK6(prefix)[2]; - ip->ip6[3] &= NETMASK6(prefix)[3]; + ip->ip6[0] &= ip_set_netmask6(prefix)[0]; + ip->ip6[1] &= ip_set_netmask6(prefix)[1]; + ip->ip6[2] &= ip_set_netmask6(prefix)[2]; + ip->ip6[3] &= ip_set_netmask6(prefix)[3]; } -static inline bool +static bool hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *data) { NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); @@ -285,7 +275,7 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data) { const struct hash_ip6_telem *e = @@ -344,10 +334,14 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ip6_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &ip); if (ret) return ret; @@ -389,13 +383,18 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) if (!(set->family == AF_INET || set->family == AF_INET6)) return -IPSET_ERR_INVALID_FAMILY; netmask = set->family == AF_INET ? 32 : 128; - pr_debug("Create set %s with family %s", + pr_debug("Create set %s with family %s\n", set->name, set->family == AF_INET ? "inet" : "inet6"); if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len, hash_ip_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) @@ -408,9 +407,9 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) if (tb[IPSET_ATTR_NETMASK]) { netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]); - if ((set->family == AF_INET && netmask > 32) - || (set->family == AF_INET6 && netmask > 128) - || netmask == 0) + if ((set->family == AF_INET && netmask > 32) || + (set->family == AF_INET6 && netmask > 128) || + netmask == 0) return -IPSET_ERR_INVALID_NETMASK; } @@ -451,7 +450,7 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) ? &hash_ip4_variant : &hash_ip6_variant; } - pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)", + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", set->name, jhash_size(h->table->htable_bits), h->table->htable_bits, h->maxelem, set->data, h->table); diff --git a/extensions/ipset-5/ip_set_hash_ipport.c b/extensions/ipset-5/ip_set_hash_ipport.c index e92f6c5..0ffc9fb 100644 --- a/extensions/ipset-5/ip_set_hash_ipport.c +++ b/extensions/ipset-5/ip_set_hash_ipport.c @@ -7,7 +7,6 @@ /* Kernel module implementing an IP set type: the hash:ip,port type */ -#include "ip_set_kernel.h" #include "jhash.h" #include #include @@ -47,16 +46,16 @@ hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b); /* Member elements without timeout */ struct hash_ipport4_elem { - u32 ip; - u16 port; + __be32 ip; + __be16 port; u8 proto; u8 padding; }; /* Member elements with timeout support */ struct hash_ipport4_telem { - u32 ip; - u16 port; + __be32 ip; + __be16 port; u8 proto; u8 padding; unsigned long timeout; @@ -66,9 +65,9 @@ static inline bool hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1, const struct hash_ipport4_elem *ip2) { - return ip1->ip == ip2->ip - && ip1->port == ip2->port - && ip1->proto == ip2->proto; + return ip1->ip == ip2->ip && + ip1->port == ip2->port && + ip1->proto == ip2->proto; } static inline bool @@ -86,22 +85,13 @@ hash_ipport4_data_copy(struct hash_ipport4_elem *dst, dst->proto = src->proto; } -static inline void -hash_ipport4_data_swap(struct hash_ipport4_elem *dst, - struct hash_ipport4_elem *src) -{ - swap(dst->ip, src->ip); - swap(dst->port, src->port); - swap(dst->proto, src->proto); -} - static inline void hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem) { elem->proto = 0; } -static inline bool +static bool hash_ipport4_data_list(struct sk_buff *skb, const struct hash_ipport4_elem *data) { @@ -114,7 +104,7 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_ipport4_data_tlist(struct sk_buff *skb, const struct hash_ipport4_elem *data) { @@ -145,8 +135,8 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb, ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport4_elem data = { }; - if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, - &data.port, &data.proto)) + if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, + &data.port, &data.proto)) return -EINVAL; ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); @@ -182,15 +172,21 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipport_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; if (tb[IPSET_ATTR_PORT]) - data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]); + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); else return -IPSET_ERR_PROTOCOL; @@ -218,20 +214,19 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST - || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) - || !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] - || tb[IPSET_ATTR_PORT_TO])) { + if (adt == IPSET_TEST || + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || + !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || + tb[IPSET_ATTR_PORT_TO])) { ret = adtfn(set, &data, timeout); return ip_set_eexist(ret, flags) ? 0 : ret; } ip = ntohl(data.ip); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; - ip_to = ntohl(ip_to); if (ip > ip_to) swap(ip, ip_to); } else if (tb[IPSET_ATTR_CIDR]) { @@ -239,8 +234,8 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len, if (cidr > 32) return -IPSET_ERR_INVALID_CIDR; - ip &= HOSTMASK(cidr); - ip_to = ip | ~HOSTMASK(cidr); + ip &= ip_set_hostmask(cidr); + ip_to = ip | ~ip_set_hostmask(cidr); } else ip_to = ip; @@ -273,22 +268,22 @@ hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b) const struct ip_set_hash *y = b->data; /* Resizing changes htable_bits, so we ignore it */ - return x->maxelem == y->maxelem - && x->timeout == y->timeout; + return x->maxelem == y->maxelem && + x->timeout == y->timeout; } /* The type variant functions: IPv6 */ struct hash_ipport6_elem { union nf_inet_addr ip; - u16 port; + __be16 port; u8 proto; u8 padding; }; struct hash_ipport6_telem { union nf_inet_addr ip; - u16 port; + __be16 port; u8 proto; u8 padding; unsigned long timeout; @@ -298,9 +293,9 @@ static inline bool hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1, const struct hash_ipport6_elem *ip2) { - return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 - && ip1->port == ip2->port - && ip1->proto == ip2->proto; + return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && + ip1->port == ip2->port && + ip1->proto == ip2->proto; } static inline bool @@ -316,24 +311,13 @@ hash_ipport6_data_copy(struct hash_ipport6_elem *dst, memcpy(dst, src, sizeof(*dst)); } -static inline void -hash_ipport6_data_swap(struct hash_ipport6_elem *dst, - struct hash_ipport6_elem *src) -{ - struct hash_ipport6_elem tmp; - - memcpy(&tmp, dst, sizeof(tmp)); - memcpy(dst, src, sizeof(tmp)); - memcpy(src, &tmp, sizeof(tmp)); -} - static inline void hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem) { elem->proto = 0; } -static inline bool +static bool hash_ipport6_data_list(struct sk_buff *skb, const struct hash_ipport6_elem *data) { @@ -346,7 +330,7 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_ipport6_data_tlist(struct sk_buff *skb, const struct hash_ipport6_elem *data) { @@ -379,8 +363,8 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb, ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport6_elem data = { }; - if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, - &data.port, &data.proto)) + if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, + &data.port, &data.proto)) return -EINVAL; ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); @@ -404,15 +388,21 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipport_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; if (tb[IPSET_ATTR_PORT]) - data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]); + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); else return -IPSET_ERR_PROTOCOL; @@ -440,9 +430,9 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST - || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) - || !tb[IPSET_ATTR_PORT_TO]) { + if (adt == IPSET_TEST || + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || + !tb[IPSET_ATTR_PORT_TO]) { ret = adtfn(set, &data, timeout); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -491,6 +481,11 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) hash_ipport_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) @@ -536,7 +531,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) ? &hash_ipport4_variant : &hash_ipport6_variant; } - pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)", + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", set->name, jhash_size(h->table->htable_bits), h->table->htable_bits, h->maxelem, set->data, h->table); diff --git a/extensions/ipset-5/ip_set_hash_ipportip.c b/extensions/ipset-5/ip_set_hash_ipportip.c index e074f3b..5063775 100644 --- a/extensions/ipset-5/ip_set_hash_ipportip.c +++ b/extensions/ipset-5/ip_set_hash_ipportip.c @@ -7,7 +7,6 @@ /* Kernel module implementing an IP set type: the hash:ip,port,ip type */ -#include "ip_set_kernel.h" #include "jhash.h" #include #include @@ -47,18 +46,18 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b); /* Member elements without timeout */ struct hash_ipportip4_elem { - u32 ip; - u32 ip2; - u16 port; + __be32 ip; + __be32 ip2; + __be16 port; u8 proto; u8 padding; }; /* Member elements with timeout support */ struct hash_ipportip4_telem { - u32 ip; - u32 ip2; - u16 port; + __be32 ip; + __be32 ip2; + __be16 port; u8 proto; u8 padding; unsigned long timeout; @@ -68,10 +67,10 @@ static inline bool hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1, const struct hash_ipportip4_elem *ip2) { - return ip1->ip == ip2->ip - && ip1->ip2 == ip2->ip2 - && ip1->port == ip2->port - && ip1->proto == ip2->proto; + return ip1->ip == ip2->ip && + ip1->ip2 == ip2->ip2 && + ip1->port == ip2->port && + ip1->proto == ip2->proto; } static inline bool @@ -87,24 +86,13 @@ hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst, memcpy(dst, src, sizeof(*dst)); } -static inline void -hash_ipportip4_data_swap(struct hash_ipportip4_elem *dst, - struct hash_ipportip4_elem *src) -{ - struct hash_ipportip4_elem tmp; - - memcpy(&tmp, dst, sizeof(tmp)); - memcpy(dst, src, sizeof(tmp)); - memcpy(src, &tmp, sizeof(tmp)); -} - static inline void hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem) { elem->proto = 0; } -static inline bool +static bool hash_ipportip4_data_list(struct sk_buff *skb, const struct hash_ipportip4_elem *data) { @@ -118,7 +106,7 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_ipportip4_data_tlist(struct sk_buff *skb, const struct hash_ipportip4_elem *data) { @@ -150,8 +138,8 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb, ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportip4_elem data = { }; - if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, - &data.port, &data.proto)) + if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, + &data.port, &data.proto)) return -EINVAL; ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); @@ -189,19 +177,25 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipportip_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP2, &data.ip2); + 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]); + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); else return -IPSET_ERR_PROTOCOL; @@ -229,20 +223,19 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST - || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) - || !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] - || tb[IPSET_ATTR_PORT_TO])) { + if (adt == IPSET_TEST || + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || + !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || + tb[IPSET_ATTR_PORT_TO])) { ret = adtfn(set, &data, timeout); return ip_set_eexist(ret, flags) ? 0 : ret; } ip = ntohl(data.ip); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; - ip_to = ntohl(ip_to); if (ip > ip_to) swap(ip, ip_to); } else if (tb[IPSET_ATTR_CIDR]) { @@ -250,8 +243,8 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len, if (cidr > 32) return -IPSET_ERR_INVALID_CIDR; - ip &= HOSTMASK(cidr); - ip_to = ip | ~HOSTMASK(cidr); + ip &= ip_set_hostmask(cidr); + ip_to = ip | ~ip_set_hostmask(cidr); } else ip_to = ip; @@ -284,8 +277,8 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b) const struct ip_set_hash *y = b->data; /* Resizing changes htable_bits, so we ignore it */ - return x->maxelem == y->maxelem - && x->timeout == y->timeout; + return x->maxelem == y->maxelem && + x->timeout == y->timeout; } /* The type variant functions: IPv6 */ @@ -293,7 +286,7 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b) struct hash_ipportip6_elem { union nf_inet_addr ip; union nf_inet_addr ip2; - u16 port; + __be16 port; u8 proto; u8 padding; }; @@ -301,7 +294,7 @@ struct hash_ipportip6_elem { struct hash_ipportip6_telem { union nf_inet_addr ip; union nf_inet_addr ip2; - u16 port; + __be16 port; u8 proto; u8 padding; unsigned long timeout; @@ -311,10 +304,10 @@ static inline bool hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1, const struct hash_ipportip6_elem *ip2) { - return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 - && ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 - && ip1->port == ip2->port - && ip1->proto == ip2->proto; + return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && + ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 && + ip1->port == ip2->port && + ip1->proto == ip2->proto; } static inline bool @@ -330,24 +323,13 @@ hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst, memcpy(dst, src, sizeof(*dst)); } -static inline void -hash_ipportip6_data_swap(struct hash_ipportip6_elem *dst, - struct hash_ipportip6_elem *src) -{ - struct hash_ipportip6_elem tmp; - - memcpy(&tmp, dst, sizeof(tmp)); - memcpy(dst, src, sizeof(tmp)); - memcpy(src, &tmp, sizeof(tmp)); -} - static inline void hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem) { elem->proto = 0; } -static inline bool +static bool hash_ipportip6_data_list(struct sk_buff *skb, const struct hash_ipportip6_elem *data) { @@ -361,7 +343,7 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_ipportip6_data_tlist(struct sk_buff *skb, const struct hash_ipportip6_elem *data) { @@ -395,8 +377,8 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb, ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportip6_elem data = { }; - if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, - &data.port, &data.proto)) + if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, + &data.port, &data.proto)) return -EINVAL; ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); @@ -421,19 +403,25 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipportip_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP2, &data.ip2); + 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]); + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); else return -IPSET_ERR_PROTOCOL; @@ -461,9 +449,9 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST - || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) - || !tb[IPSET_ATTR_PORT_TO]) { + if (adt == IPSET_TEST || + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || + !tb[IPSET_ATTR_PORT_TO]) { ret = adtfn(set, &data, timeout); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -512,6 +500,11 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head, hash_ipportip_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) @@ -557,7 +550,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head, ? &hash_ipportip4_variant : &hash_ipportip6_variant; } - pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)", + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", set->name, jhash_size(h->table->htable_bits), h->table->htable_bits, h->maxelem, set->data, h->table); diff --git a/extensions/ipset-5/ip_set_hash_ipportnet.c b/extensions/ipset-5/ip_set_hash_ipportnet.c index 1a257b9..85fa6c7 100644 --- a/extensions/ipset-5/ip_set_hash_ipportnet.c +++ b/extensions/ipset-5/ip_set_hash_ipportnet.c @@ -7,7 +7,6 @@ /* Kernel module implementing an IP set type: the hash:ip,port,net type */ -#include "ip_set_kernel.h" #include "jhash.h" #include #include @@ -47,18 +46,18 @@ hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b); /* Member elements without timeout */ struct hash_ipportnet4_elem { - u32 ip; - u32 ip2; - u16 port; + __be32 ip; + __be32 ip2; + __be16 port; u8 cidr; u8 proto; }; /* Member elements with timeout support */ struct hash_ipportnet4_telem { - u32 ip; - u32 ip2; - u16 port; + __be32 ip; + __be32 ip2; + __be16 port; u8 cidr; u8 proto; unsigned long timeout; @@ -68,11 +67,11 @@ static inline bool hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1, const struct hash_ipportnet4_elem *ip2) { - return ip1->ip == ip2->ip - && ip1->ip2 == ip2->ip2 - && ip1->cidr == ip2->cidr - && ip1->port == ip2->port - && ip1->proto == ip2->proto; + return ip1->ip == ip2->ip && + ip1->ip2 == ip2->ip2 && + ip1->cidr == ip2->cidr && + ip1->port == ip2->port && + ip1->proto == ip2->proto; } static inline bool @@ -88,21 +87,10 @@ hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst, memcpy(dst, src, sizeof(*dst)); } -static inline void -hash_ipportnet4_data_swap(struct hash_ipportnet4_elem *dst, - struct hash_ipportnet4_elem *src) -{ - struct hash_ipportnet4_elem tmp; - - memcpy(&tmp, dst, sizeof(tmp)); - memcpy(dst, src, sizeof(tmp)); - memcpy(src, &tmp, sizeof(tmp)); -} - static inline void hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr) { - elem->ip2 &= NETMASK(cidr); + elem->ip2 &= ip_set_netmask(cidr); elem->cidr = cidr; } @@ -112,7 +100,7 @@ hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem) elem->proto = 0; } -static inline bool +static bool hash_ipportnet4_data_list(struct sk_buff *skb, const struct hash_ipportnet4_elem *data) { @@ -127,7 +115,7 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_ipportnet4_data_tlist(struct sk_buff *skb, const struct hash_ipportnet4_elem *data) { @@ -169,13 +157,13 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, if (adt == IPSET_TEST) data.cidr = HOST_MASK; - if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, - &data.port, &data.proto)) + if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, + &data.port, &data.proto)) return -EINVAL; ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2); - data.ip2 &= NETMASK(data.cidr); + data.ip2 &= ip_set_netmask(data.cidr); return adtfn(set, &data, h->timeout); } @@ -210,14 +198,20 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipportnet_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP2, &data.ip2); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2); if (ret) return ret; @@ -227,16 +221,16 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len, if (!data.cidr) return -IPSET_ERR_INVALID_CIDR; - data.ip2 &= NETMASK(data.cidr); + data.ip2 &= ip_set_netmask(data.cidr); if (tb[IPSET_ATTR_PORT]) - data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]); + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); else return -IPSET_ERR_PROTOCOL; if (tb[IPSET_ATTR_PROTO]) { data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); - + if (data.proto == 0) return -IPSET_ERR_INVALID_PROTO; } else @@ -258,20 +252,19 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST - || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) - || !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] - || tb[IPSET_ATTR_PORT_TO])) { + if (adt == IPSET_TEST || + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || + !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || + tb[IPSET_ATTR_PORT_TO])) { ret = adtfn(set, &data, timeout); return ip_set_eexist(ret, flags) ? 0 : ret; } ip = ntohl(data.ip); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; - ip_to = ntohl(ip_to); if (ip > ip_to) swap(ip, ip_to); } else if (tb[IPSET_ATTR_CIDR]) { @@ -279,8 +272,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len, if (cidr > 32) return -IPSET_ERR_INVALID_CIDR; - ip &= HOSTMASK(cidr); - ip_to = ip | ~HOSTMASK(cidr); + ip &= ip_set_hostmask(cidr); + ip_to = ip | ~ip_set_hostmask(cidr); } else ip_to = ip; @@ -311,10 +304,10 @@ hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b) { const struct ip_set_hash *x = a->data; const struct ip_set_hash *y = b->data; - + /* Resizing changes htable_bits, so we ignore it */ - return x->maxelem == y->maxelem - && x->timeout == y->timeout; + return x->maxelem == y->maxelem && + x->timeout == y->timeout; } /* The type variant functions: IPv6 */ @@ -322,7 +315,7 @@ hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b) struct hash_ipportnet6_elem { union nf_inet_addr ip; union nf_inet_addr ip2; - u16 port; + __be16 port; u8 cidr; u8 proto; }; @@ -330,7 +323,7 @@ struct hash_ipportnet6_elem { struct hash_ipportnet6_telem { union nf_inet_addr ip; union nf_inet_addr ip2; - u16 port; + __be16 port; u8 cidr; u8 proto; unsigned long timeout; @@ -340,11 +333,11 @@ static inline bool hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1, const struct hash_ipportnet6_elem *ip2) { - return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 - && ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 - && ip1->cidr == ip2->cidr - && ip1->port == ip2->port - && ip1->proto == ip2->proto; + return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && + ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 && + ip1->cidr == ip2->cidr && + ip1->port == ip2->port && + ip1->proto == ip2->proto; } static inline bool @@ -360,17 +353,6 @@ hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst, memcpy(dst, src, sizeof(*dst)); } -static inline void -hash_ipportnet6_data_swap(struct hash_ipportnet6_elem *dst, - struct hash_ipportnet6_elem *src) -{ - struct hash_ipportnet6_elem tmp; - - memcpy(&tmp, dst, sizeof(tmp)); - memcpy(dst, src, sizeof(tmp)); - memcpy(src, &tmp, sizeof(tmp)); -} - static inline void hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem) { @@ -380,10 +362,10 @@ hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem) static inline void ip6_netmask(union nf_inet_addr *ip, u8 prefix) { - ip->ip6[0] &= NETMASK6(prefix)[0]; - ip->ip6[1] &= NETMASK6(prefix)[1]; - ip->ip6[2] &= NETMASK6(prefix)[2]; - ip->ip6[3] &= NETMASK6(prefix)[3]; + ip->ip6[0] &= ip_set_netmask6(prefix)[0]; + ip->ip6[1] &= ip_set_netmask6(prefix)[1]; + ip->ip6[2] &= ip_set_netmask6(prefix)[2]; + ip->ip6[3] &= ip_set_netmask6(prefix)[3]; } static inline void @@ -393,7 +375,7 @@ hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr) elem->cidr = cidr; } -static inline bool +static bool hash_ipportnet6_data_list(struct sk_buff *skb, const struct hash_ipportnet6_elem *data) { @@ -408,13 +390,13 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_ipportnet6_data_tlist(struct sk_buff *skb, const struct hash_ipportnet6_elem *data) { - const struct hash_ipportnet6_telem *e = + const struct hash_ipportnet6_telem *e = (const struct hash_ipportnet6_telem *)data; - + 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); @@ -449,8 +431,8 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, if (adt == IPSET_TEST) data.cidr = HOST_MASK; - if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, - &data.port, &data.proto)) + if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, + &data.port, &data.proto)) return -EINVAL; ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); @@ -476,14 +458,20 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipportnet_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP2, &data.ip2); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2); if (ret) return ret; @@ -496,7 +484,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len, ip6_netmask(&data.ip2, data.cidr); if (tb[IPSET_ATTR_PORT]) - data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]); + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); else return -IPSET_ERR_PROTOCOL; @@ -524,9 +512,9 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST - || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) - || !tb[IPSET_ATTR_PORT_TO]) { + if (adt == IPSET_TEST || + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || + !tb[IPSET_ATTR_PORT_TO]) { ret = adtfn(set, &data, timeout); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -575,6 +563,11 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head, hash_ipportnet_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) @@ -609,7 +602,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head, if (tb[IPSET_ATTR_TIMEOUT]) { h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); - + set->variant = set->family == AF_INET ? &hash_ipportnet4_tvariant : &hash_ipportnet6_tvariant; @@ -622,11 +615,11 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head, set->variant = set->family == AF_INET ? &hash_ipportnet4_variant : &hash_ipportnet6_variant; } - - pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)", + + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", set->name, jhash_size(h->table->htable_bits), h->table->htable_bits, h->maxelem, set->data, h->table); - + return 0; } diff --git a/extensions/ipset-5/ip_set_hash_net.c b/extensions/ipset-5/ip_set_hash_net.c index bc8a8db..7f01112 100644 --- a/extensions/ipset-5/ip_set_hash_net.c +++ b/extensions/ipset-5/ip_set_hash_net.c @@ -7,7 +7,6 @@ /* Kernel module implementing an IP set type: the hash:net type */ -#include "ip_set_kernel.h" #include "jhash.h" #include #include @@ -45,7 +44,7 @@ hash_net_same_set(const struct ip_set *a, const struct ip_set *b); /* Member elements without timeout */ struct hash_net4_elem { - u32 ip; + __be32 ip; u16 padding0; u8 padding1; u8 cidr; @@ -53,7 +52,7 @@ struct hash_net4_elem { /* Member elements with timeout support */ struct hash_net4_telem { - u32 ip; + __be32 ip; u16 padding0; u8 padding1; u8 cidr; @@ -81,18 +80,10 @@ hash_net4_data_copy(struct hash_net4_elem *dst, dst->cidr = src->cidr; } -static inline void -hash_net4_data_swap(struct hash_net4_elem *dst, - struct hash_net4_elem *src) -{ - swap(dst->ip, src->ip); - swap(dst->cidr, src->cidr); -} - static inline void hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr) { - elem->ip &= NETMASK(cidr); + elem->ip &= ip_set_netmask(cidr); elem->cidr = cidr; } @@ -103,7 +94,7 @@ hash_net4_data_zero_out(struct hash_net4_elem *elem) elem->cidr = 0; } -static inline bool +static bool hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data) { NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); @@ -114,7 +105,7 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_net4_data_tlist(struct sk_buff *skb, const struct hash_net4_elem *data) { const struct hash_net4_telem *tdata = @@ -151,7 +142,7 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb, data.cidr = HOST_MASK; ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); - data.ip &= NETMASK(data.cidr); + data.ip &= ip_set_netmask(data.cidr); return adtfn(set, &data, h->timeout); } @@ -177,10 +168,14 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len, hash_net_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; @@ -190,7 +185,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len, if (!data.cidr) return -IPSET_ERR_INVALID_CIDR; - data.ip &= NETMASK(data.cidr); + data.ip &= ip_set_netmask(data.cidr); if (tb[IPSET_ATTR_TIMEOUT]) { if (!with_timeout(h->timeout)) @@ -210,8 +205,8 @@ hash_net_same_set(const struct ip_set *a, const struct ip_set *b) const struct ip_set_hash *y = b->data; /* Resizing changes htable_bits, so we ignore it */ - return x->maxelem == y->maxelem - && x->timeout == y->timeout; + return x->maxelem == y->maxelem && + x->timeout == y->timeout; } /* The type variant functions: IPv6 */ @@ -235,8 +230,8 @@ static inline bool hash_net6_data_equal(const struct hash_net6_elem *ip1, const struct hash_net6_elem *ip2) { - return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 - && ip1->cidr == ip2->cidr; + return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && + ip1->cidr == ip2->cidr; } static inline bool @@ -253,16 +248,6 @@ hash_net6_data_copy(struct hash_net6_elem *dst, dst->cidr = src->cidr; } -static inline void -hash_net6_data_swap(struct hash_net6_elem *dst, struct hash_net6_elem *src) -{ - struct hash_net6_elem tmp; - - memcpy(&tmp, dst, sizeof(tmp)); - memcpy(dst, src, sizeof(tmp)); - memcpy(src, &tmp, sizeof(tmp)); -} - static inline void hash_net6_data_zero_out(struct hash_net6_elem *elem) { @@ -272,10 +257,10 @@ hash_net6_data_zero_out(struct hash_net6_elem *elem) static inline void ip6_netmask(union nf_inet_addr *ip, u8 prefix) { - ip->ip6[0] &= NETMASK6(prefix)[0]; - ip->ip6[1] &= NETMASK6(prefix)[1]; - ip->ip6[2] &= NETMASK6(prefix)[2]; - ip->ip6[3] &= NETMASK6(prefix)[3]; + ip->ip6[0] &= ip_set_netmask6(prefix)[0]; + ip->ip6[1] &= ip_set_netmask6(prefix)[1]; + ip->ip6[2] &= ip_set_netmask6(prefix)[2]; + ip->ip6[3] &= ip_set_netmask6(prefix)[3]; } static inline void @@ -285,7 +270,7 @@ hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr) elem->cidr = cidr; } -static inline bool +static bool hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data) { NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); @@ -296,7 +281,7 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_net6_data_tlist(struct sk_buff *skb, const struct hash_net6_elem *data) { const struct hash_net6_telem *e = @@ -353,10 +338,14 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_net_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; @@ -405,6 +394,11 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) hash_net_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) @@ -452,7 +446,7 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) ? &hash_net4_variant : &hash_net6_variant; } - pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)", + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", set->name, jhash_size(h->table->htable_bits), h->table->htable_bits, h->maxelem, set->data, h->table); diff --git a/extensions/ipset-5/ip_set_hash_netport.c b/extensions/ipset-5/ip_set_hash_netport.c index 168cdc3..6e86b62 100644 --- a/extensions/ipset-5/ip_set_hash_netport.c +++ b/extensions/ipset-5/ip_set_hash_netport.c @@ -7,7 +7,6 @@ /* Kernel module implementing an IP set type: the hash:net,port type */ -#include "ip_set_kernel.h" #include "jhash.h" #include #include @@ -46,16 +45,16 @@ hash_netport_same_set(const struct ip_set *a, const struct ip_set *b); /* Member elements without timeout */ struct hash_netport4_elem { - u32 ip; - u16 port; + __be32 ip; + __be16 port; u8 proto; u8 cidr; }; /* Member elements with timeout support */ struct hash_netport4_telem { - u32 ip; - u16 port; + __be32 ip; + __be16 port; u8 proto; u8 cidr; unsigned long timeout; @@ -65,10 +64,10 @@ static inline bool hash_netport4_data_equal(const struct hash_netport4_elem *ip1, const struct hash_netport4_elem *ip2) { - return ip1->ip == ip2->ip - && ip1->port == ip2->port - && ip1->proto == ip2->proto - && ip1->cidr == ip2->cidr; + return ip1->ip == ip2->ip && + ip1->port == ip2->port && + ip1->proto == ip2->proto && + ip1->cidr == ip2->cidr; } static inline bool @@ -87,20 +86,10 @@ hash_netport4_data_copy(struct hash_netport4_elem *dst, dst->cidr = src->cidr; } -static inline void -hash_netport4_data_swap(struct hash_netport4_elem *dst, - struct hash_netport4_elem *src) -{ - swap(dst->ip, src->ip); - swap(dst->port, src->port); - swap(dst->proto, src->proto); - swap(dst->cidr, src->cidr); -} - static inline void hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr) { - elem->ip &= NETMASK(cidr); + elem->ip &= ip_set_netmask(cidr); elem->cidr = cidr; } @@ -110,7 +99,7 @@ hash_netport4_data_zero_out(struct hash_netport4_elem *elem) elem->proto = 0; } -static inline bool +static bool hash_netport4_data_list(struct sk_buff *skb, const struct hash_netport4_elem *data) { @@ -124,7 +113,7 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_netport4_data_tlist(struct sk_buff *skb, const struct hash_netport4_elem *data) { @@ -165,12 +154,12 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb, if (adt == IPSET_TEST) data.cidr = HOST_MASK; - if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, - &data.port, &data.proto)) + if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, + &data.port, &data.proto)) return -EINVAL; ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); - data.ip &= NETMASK(data.cidr); + data.ip &= ip_set_netmask(data.cidr); return adtfn(set, &data, h->timeout); } @@ -202,10 +191,16 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len, hash_netport_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; @@ -213,10 +208,10 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len, data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); if (!data.cidr) return -IPSET_ERR_INVALID_CIDR; - data.ip &= NETMASK(data.cidr); + data.ip &= ip_set_netmask(data.cidr); if (tb[IPSET_ATTR_PORT]) - data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]); + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); else return -IPSET_ERR_PROTOCOL; @@ -244,9 +239,9 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST - || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) - || !tb[IPSET_ATTR_PORT_TO]) { + if (adt == IPSET_TEST || + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || + !tb[IPSET_ATTR_PORT_TO]) { ret = adtfn(set, &data, timeout); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -275,22 +270,22 @@ hash_netport_same_set(const struct ip_set *a, const struct ip_set *b) const struct ip_set_hash *y = b->data; /* Resizing changes htable_bits, so we ignore it */ - return x->maxelem == y->maxelem - && x->timeout == y->timeout; + return x->maxelem == y->maxelem && + x->timeout == y->timeout; } /* The type variant functions: IPv6 */ struct hash_netport6_elem { union nf_inet_addr ip; - u16 port; + __be16 port; u8 proto; u8 cidr; }; struct hash_netport6_telem { union nf_inet_addr ip; - u16 port; + __be16 port; u8 proto; u8 cidr; unsigned long timeout; @@ -300,10 +295,10 @@ static inline bool hash_netport6_data_equal(const struct hash_netport6_elem *ip1, const struct hash_netport6_elem *ip2) { - return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 - && ip1->port == ip2->port - && ip1->proto == ip2->proto - && ip1->cidr == ip2->cidr; + return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && + ip1->port == ip2->port && + ip1->proto == ip2->proto && + ip1->cidr == ip2->cidr; } static inline bool @@ -319,17 +314,6 @@ hash_netport6_data_copy(struct hash_netport6_elem *dst, memcpy(dst, src, sizeof(*dst)); } -static inline void -hash_netport6_data_swap(struct hash_netport6_elem *dst, - struct hash_netport6_elem *src) -{ - struct hash_netport6_elem tmp; - - memcpy(&tmp, dst, sizeof(tmp)); - memcpy(dst, src, sizeof(tmp)); - memcpy(src, &tmp, sizeof(tmp)); -} - static inline void hash_netport6_data_zero_out(struct hash_netport6_elem *elem) { @@ -339,10 +323,10 @@ hash_netport6_data_zero_out(struct hash_netport6_elem *elem) static inline void ip6_netmask(union nf_inet_addr *ip, u8 prefix) { - ip->ip6[0] &= NETMASK6(prefix)[0]; - ip->ip6[1] &= NETMASK6(prefix)[1]; - ip->ip6[2] &= NETMASK6(prefix)[2]; - ip->ip6[3] &= NETMASK6(prefix)[3]; + ip->ip6[0] &= ip_set_netmask6(prefix)[0]; + ip->ip6[1] &= ip_set_netmask6(prefix)[1]; + ip->ip6[2] &= ip_set_netmask6(prefix)[2]; + ip->ip6[3] &= ip_set_netmask6(prefix)[3]; } static inline void @@ -352,7 +336,7 @@ hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr) elem->cidr = cidr; } -static inline bool +static bool hash_netport6_data_list(struct sk_buff *skb, const struct hash_netport6_elem *data) { @@ -366,7 +350,7 @@ nla_put_failure: return 1; } -static inline bool +static bool hash_netport6_data_tlist(struct sk_buff *skb, const struct hash_netport6_elem *data) { @@ -406,8 +390,8 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb, if (adt == IPSET_TEST) data.cidr = HOST_MASK; - if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, - &data.port, &data.proto)) + if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, + &data.port, &data.proto)) return -EINVAL; ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); @@ -432,10 +416,16 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_netport_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; @@ -446,7 +436,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len, ip6_netmask(&data.ip, data.cidr); if (tb[IPSET_ATTR_PORT]) - data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]); + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); else return -IPSET_ERR_PROTOCOL; @@ -474,9 +464,9 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len, timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST - || !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) - || !tb[IPSET_ATTR_PORT_TO]) { + if (adt == IPSET_TEST || + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || + !tb[IPSET_ATTR_PORT_TO]) { ret = adtfn(set, &data, timeout); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -525,6 +515,11 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) hash_netport_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) @@ -572,7 +567,7 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) ? &hash_netport4_variant : &hash_netport6_variant; } - pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)", + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", set->name, jhash_size(h->table->htable_bits), h->table->htable_bits, h->maxelem, set->data, h->table); diff --git a/extensions/ipset-5/ip_set_kernel.h b/extensions/ipset-5/ip_set_kernel.h deleted file mode 100644 index d770589..0000000 --- a/extensions/ipset-5/ip_set_kernel.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _IP_SET_KERNEL_H -#define _IP_SET_KERNEL_H - -#ifdef __KERNEL__ - -#ifdef CONFIG_DEBUG_KERNEL -/* Complete debug messages */ -#define pr_fmt(fmt) "%s %s[%i]: " fmt "\n", __FILE__, __func__, __LINE__ -#endif - -#include - -#endif /* __KERNEL__ */ - -#endif /*_IP_SET_H */ diff --git a/extensions/ipset-5/ip_set_list_set.c b/extensions/ipset-5/ip_set_list_set.c index c1434a1..398adc4 100644 --- a/extensions/ipset-5/ip_set_list_set.c +++ b/extensions/ipset-5/ip_set_list_set.c @@ -7,7 +7,6 @@ /* Kernel module implementing an IP set type: the list:set type */ -#include "ip_set_kernel.h" #include #include #include @@ -68,8 +67,8 @@ list_set_expired(const struct list_set *map, u32 id) static inline int list_set_exist(const struct set_telem *elem) { - return elem->id != IPSET_INVALID_ID - && !ip_set_timeout_expired(elem->timeout); + return elem->id != IPSET_INVALID_ID && + !ip_set_timeout_expired(elem->timeout); } /* Set list without and with timeout */ @@ -122,22 +121,22 @@ static const struct nla_policy list_set_adt_policy[IPSET_ATTR_ADT_MAX+1] = { [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, }; -static inline bool +static bool next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id) { const struct set_elem *elem; if (i + 1 < map->size) { elem = list_set_elem(map, i + 1); - return !!(elem->id == id - && !(with_timeout(map->timeout) - && list_set_expired(map, i + 1))); + return !!(elem->id == id && + !(with_timeout(map->timeout) && + list_set_expired(map, i + 1))); } return 0; } -static inline void +static void list_elem_add(struct list_set *map, u32 i, ip_set_id_t id) { struct set_elem *e; @@ -150,7 +149,7 @@ list_elem_add(struct list_set *map, u32 i, ip_set_id_t id) } } -static inline void +static void list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id, unsigned long timeout) { @@ -223,20 +222,22 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len, list_set_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_NAME] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - if (tb[IPSET_ATTR_NAME]) { - id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s); - if (id == IPSET_INVALID_ID) - return -IPSET_ERR_NAME; - /* "Loop detection" */ - if (s->type->features & IPSET_TYPE_NAME) { - ret = -IPSET_ERR_LOOP; - goto finish; - } - } else - return -IPSET_ERR_PROTOCOL; + id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s); + if (id == IPSET_INVALID_ID) + return -IPSET_ERR_NAME; + /* "Loop detection" */ + if (s->type->features & IPSET_TYPE_NAME) { + ret = -IPSET_ERR_LOOP; + goto finish; + } if (tb[IPSET_ATTR_CADT_FLAGS]) { u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); @@ -270,8 +271,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len, case IPSET_TEST: for (i = 0; i < map->size && !ret; i++) { elem = list_set_elem(map, i); - if (elem->id == IPSET_INVALID_ID - || (before != 0 && i + 1 >= map->size)) + if (elem->id == IPSET_INVALID_ID || + (before != 0 && i + 1 >= map->size)) break; else if (with_timeout && list_set_expired(map, i)) continue; @@ -286,8 +287,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len, case IPSET_ADD: for (i = 0; i < map->size && !ret; i++) { elem = list_set_elem(map, i); - if (elem->id == id - && !(with_timeout && list_set_expired(map, i))) + if (elem->id == id && + !(with_timeout && list_set_expired(map, i))) ret = -IPSET_ERR_EXIST; } if (ret == -IPSET_ERR_EXIST) @@ -318,14 +319,14 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len, break; } else if (with_timeout && list_set_expired(map, i)) continue; - else if (elem->id == id - && (before == 0 - || (before > 0 - && next_id_eq(map, i, refid)))) + else if (elem->id == id && + (before == 0 || + (before > 0 && + next_id_eq(map, i, refid)))) ret = list_set_del(map, id, i); - else if (before < 0 - && elem->id == refid - && next_id_eq(map, i, id)) + else if (before < 0 && + elem->id == refid && + next_id_eq(map, i, id)) ret = list_set_del(map, id, i + 1); } break; @@ -449,8 +450,8 @@ list_set_same_set(const struct ip_set *a, const struct ip_set *b) const struct list_set *x = a->data; const struct list_set *y = b->data; - return x->size == y->size - && x->timeout == y->timeout; + return x->size == y->size && + x->timeout == y->timeout; } static const struct ip_set_type_variant list_set = { @@ -476,8 +477,8 @@ list_set_gc(unsigned long ul_set) read_lock_bh(&set->lock); for (i = map->size - 1; i >= 0; i--) { e = (struct set_telem *) list_set_elem(map, i); - if (e->id != IPSET_INVALID_ID - && list_set_expired(map, i)) + if (e->id != IPSET_INVALID_ID && + list_set_expired(map, i)) list_set_del(map, e->id, i); } read_unlock_bh(&set->lock); @@ -486,7 +487,7 @@ list_set_gc(unsigned long ul_set) add_timer(&map->gc); } -static inline void +static void list_set_gc_init(struct ip_set *set) { struct list_set *map = set->data; @@ -506,7 +507,7 @@ list_set_create_policy[IPSET_ATTR_CREATE_MAX+1] = { [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, }; -static inline bool +static bool init_list_set(struct ip_set *set, u32 size, size_t dsize, unsigned long timeout) { @@ -542,6 +543,10 @@ list_set_create(struct ip_set *set, struct nlattr *head, int len, list_set_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_SIZE]) size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]); if (size < IP_SET_LIST_MIN_SIZE) diff --git a/extensions/ipset-5/ip_set_timeout.h b/extensions/ipset-5/ip_set_timeout.h index 7383716..9f30c5f 100644 --- a/extensions/ipset-5/ip_set_timeout.h +++ b/extensions/ipset-5/ip_set_timeout.h @@ -43,17 +43,17 @@ ip_set_timeout_uget(struct nlattr *tb) static inline bool ip_set_timeout_test(unsigned long timeout) { - return timeout != IPSET_ELEM_UNSET - && (timeout == IPSET_ELEM_PERMANENT - || time_after(timeout, jiffies)); + return timeout != IPSET_ELEM_UNSET && + (timeout == IPSET_ELEM_PERMANENT || + time_after(timeout, jiffies)); } static inline bool ip_set_timeout_expired(unsigned long timeout) { - return timeout != IPSET_ELEM_UNSET - && timeout != IPSET_ELEM_PERMANENT - && time_before(timeout, jiffies); + return timeout != IPSET_ELEM_UNSET && + timeout != IPSET_ELEM_PERMANENT && + time_before(timeout, jiffies); } static inline unsigned long @@ -88,15 +88,15 @@ ip_set_timeout_get(unsigned long timeout) static inline bool ip_set_timeout_test(unsigned long timeout) { - return timeout == IPSET_ELEM_PERMANENT - || time_after(timeout, jiffies); + return timeout == IPSET_ELEM_PERMANENT || + time_after(timeout, jiffies); } static inline bool ip_set_timeout_expired(unsigned long timeout) { - return timeout != IPSET_ELEM_PERMANENT - && time_before(timeout, jiffies); + return timeout != IPSET_ELEM_PERMANENT && + time_before(timeout, jiffies); } static inline unsigned long diff --git a/extensions/ipset-5/pfxlen.c b/extensions/ipset-5/pfxlen.c index e3473ba..e9c0764 100644 --- a/extensions/ipset-5/pfxlen.c +++ b/extensions/ipset-5/pfxlen.c @@ -14,7 +14,7 @@ * This table works for both IPv4 and IPv6; * just use prefixlen_netmask_map[prefixlength].ip. */ -const union nf_inet_addr prefixlen_netmask_map[] = { +const union nf_inet_addr ip_set_netmask_map[] = { E(0x00000000, 0x00000000, 0x00000000, 0x00000000), E(0x80000000, 0x00000000, 0x00000000, 0x00000000), E(0xC0000000, 0x00000000, 0x00000000, 0x00000000), @@ -145,17 +145,19 @@ const union nf_inet_addr prefixlen_netmask_map[] = { E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE), E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF), }; -EXPORT_SYMBOL_GPL(prefixlen_netmask_map); +EXPORT_SYMBOL_GPL(ip_set_netmask_map); #undef E -#define E(a, b, c, d) \ - {.ip6 = { a, b, c, d } } +#define E(a, b, c, d) \ + {.ip6 = { (__force __be32) a, (__force __be32) b, \ + (__force __be32) c, (__force __be32) d, \ + } } /* * This table works for both IPv4 and IPv6; * just use prefixlen_hostmask_map[prefixlength].ip. */ -const union nf_inet_addr prefixlen_hostmask_map[] = { +const union nf_inet_addr ip_set_hostmask_map[] = { E(0x00000000, 0x00000000, 0x00000000, 0x00000000), E(0x80000000, 0x00000000, 0x00000000, 0x00000000), E(0xC0000000, 0x00000000, 0x00000000, 0x00000000), @@ -286,4 +288,4 @@ const union nf_inet_addr prefixlen_hostmask_map[] = { E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE), E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF), }; -EXPORT_SYMBOL_GPL(prefixlen_hostmask_map); +EXPORT_SYMBOL_GPL(ip_set_hostmask_map); diff --git a/extensions/ipset-5/pfxlen.h b/extensions/ipset-5/pfxlen.h index fe7153c..0e1fb50 100644 --- a/extensions/ipset-5/pfxlen.h +++ b/extensions/ipset-5/pfxlen.h @@ -5,12 +5,31 @@ #include /* Prefixlen maps, by Jan Engelhardt */ -extern const union nf_inet_addr prefixlen_netmask_map[]; -extern const union nf_inet_addr prefixlen_hostmask_map[]; +extern const union nf_inet_addr ip_set_netmask_map[]; +extern const union nf_inet_addr ip_set_hostmask_map[]; -#define NETMASK(n) prefixlen_netmask_map[n].ip -#define NETMASK6(n) prefixlen_netmask_map[n].ip6 -#define HOSTMASK(n) prefixlen_hostmask_map[n].ip -#define HOSTMASK6(n) prefixlen_hostmask_map[n].ip6 +static inline __be32 +ip_set_netmask(u8 pfxlen) +{ + return ip_set_netmask_map[pfxlen].ip; +} + +static inline const __be32 * +ip_set_netmask6(u8 pfxlen) +{ + return &ip_set_netmask_map[pfxlen].ip6[0]; +} + +static inline u32 +ip_set_hostmask(u8 pfxlen) +{ + return (__force u32) ip_set_hostmask_map[pfxlen].ip; +} + +static inline const __be32 * +ip_set_hostmask6(u8 pfxlen) +{ + return &ip_set_hostmask_map[pfxlen].ip6[0]; +} #endif /*_PFXLEN_H */ diff --git a/extensions/ipset-5/xt_set.c b/extensions/ipset-5/xt_set.c index beb3dab..56e6937 100644 --- a/extensions/ipset-5/xt_set.c +++ b/extensions/ipset-5/xt_set.c @@ -108,12 +108,12 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par) index = ip_set_nfnl_get_byindex(info->match_set.index); if (index == IPSET_INVALID_ID) { - pr_warning("Cannot find set indentified by id %u to match", + pr_warning("Cannot find set indentified by id %u to match\n", info->match_set.index); return CHECK_FAIL; /* error */ } if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) { - pr_warning("That's nasty!"); + pr_warning("That's nasty!\n"); return CHECK_FAIL; /* error */ } @@ -167,7 +167,7 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) if (info->add_set.index != IPSET_INVALID_ID) { index = ip_set_nfnl_get_byindex(info->add_set.index); if (index == IPSET_INVALID_ID) { - pr_warning("cannot find add_set index %u as target", + pr_warning("cannot find add_set index %u as target\n", info->add_set.index); return CHECK_FAIL; /* error */ } @@ -176,14 +176,14 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) if (info->del_set.index != IPSET_INVALID_ID) { index = ip_set_nfnl_get_byindex(info->del_set.index); if (index == IPSET_INVALID_ID) { - pr_warning("cannot find del_set index %u as target", + pr_warning("cannot find del_set index %u as target\n", info->del_set.index); return CHECK_FAIL; /* error */ } } - if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0 - || info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) { - pr_warning("That's nasty!"); + if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0 || + info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) { + pr_warning("That's nasty!\n"); return CHECK_FAIL; /* error */ } @@ -237,12 +237,12 @@ set_match_checkentry(const struct xt_mtchk_param *par) index = ip_set_nfnl_get_byindex(info->match_set.index); if (index == IPSET_INVALID_ID) { - pr_warning("Cannot find set indentified by id %u to match", + pr_warning("Cannot find set indentified by id %u to match\n", info->match_set.index); return CHECK_FAIL; /* error */ } if (info->match_set.dim > IPSET_DIM_MAX) { - pr_warning("That's nasty!"); + pr_warning("That's nasty!\n"); return CHECK_FAIL; /* error */ } @@ -295,7 +295,7 @@ set_target_checkentry(const struct xt_tgchk_param *par) if (info->add_set.index != IPSET_INVALID_ID) { index = ip_set_nfnl_get_byindex(info->add_set.index); if (index == IPSET_INVALID_ID) { - pr_warning("cannot find add_set index %u as target", + pr_warning("cannot find add_set index %u as target\n", info->add_set.index); return CHECK_FAIL; /* error */ } @@ -304,14 +304,14 @@ set_target_checkentry(const struct xt_tgchk_param *par) if (info->del_set.index != IPSET_INVALID_ID) { index = ip_set_nfnl_get_byindex(info->del_set.index); if (index == IPSET_INVALID_ID) { - pr_warning("cannot find del_set index %u as target", + pr_warning("cannot find del_set index %u as target\n", info->del_set.index); return CHECK_FAIL; /* error */ } } - if (info->add_set.dim > IPSET_DIM_MAX - || info->del_set.flags > IPSET_DIM_MAX) { - pr_warning("That's nasty!"); + if (info->add_set.dim > IPSET_DIM_MAX || + info->del_set.flags > IPSET_DIM_MAX) { + pr_warning("That's nasty!\n"); return CHECK_FAIL; /* error */ }