- 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)
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
* published by the Free Software Foundation.
*/
+#include <linux/netlink.h>
+
/* The protocol version */
#define IPSET_PROTOCOL 5
/* 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 */
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)
-{
- 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);
+/* 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);
- return members;
-}
-
-static inline void
-ip_set_free(void *members)
+static inline int
+ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
{
- 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? */
return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
}
-/* Useful converters */
-static inline u32
-ip_set_get_h32(const struct nlattr *attr)
+/* Check the NLA_F_NET_BYTEORDER flag */
+static inline bool
+ip_set_attr_netorder(struct nlattr *tb[], int type)
{
- u32 value = nla_get_u32(attr);
-
- return attr->nla_type & NLA_F_NET_BYTEORDER ? ntohl(value) : value;
+ return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
}
-static inline u16
-ip_set_get_h16(const struct nlattr *attr)
+static inline bool
+ip_set_optattr_netorder(struct nlattr *tb[], int type)
{
- u16 value = nla_get_u16(attr);
-
- return attr->nla_type & NLA_F_NET_BYTEORDER ? ntohs(value) : value;
+ return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
}
+/* Useful converters */
static inline u32
-ip_set_get_n32(const struct nlattr *attr)
+ip_set_get_h32(const struct nlattr *attr)
{
- u32 value = nla_get_u32(attr);
-
- return attr->nla_type & NLA_F_NET_BYTEORDER ? value : htonl(value);
+ return ntohl(nla_get_be32(attr));
}
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)
+ip_set_get_h16(const struct nlattr *attr)
{
- 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 { \
} 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;
}
};
/* Compute htable_bits from the user input parameter hashsize */
-static inline u8
+static u8
htable_bits(u32 hashsize)
{
/* Assume that hashsize == 2^htable_bits */
/* 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;
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;
}
/* 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;
/* 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);
/* 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;
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);
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) {
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
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;
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) {
}
#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;
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) {
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);
add_timer(&h->gc);
}
-static inline void
+static void
type_pf_gc_init(struct ip_set *set)
{
struct ip_set_hash *h = set->data;
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));
}
/* Kernel module implementing an IP set type: the bitmap:ip type */
-#include "ip_set_kernel.h"
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/skbuff.h>
};
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
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;
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)
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;
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 = {
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;
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)
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;
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 = {
add_timer(&map->gc);
}
-static inline void
+static void
bitmap_ip_gc_init(struct ip_set *set)
{
struct bitmap_ip_timeout *map = set->data;
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;
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;
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) {
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;
/* Kernel module implementing an IP set type: the bitmap:ip,mac type */
-#include "ip_set_kernel.h"
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/etherdevice.h>
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 */
/* 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;
}
/* 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;
}
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;
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;
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 = {
.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 = {
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);
add_timer(&map->gc);
}
-static inline void
+static void
bitmap_ipmac_gc_init(struct ip_set *set)
{
struct bitmap_ipmac *map = set->data;
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 },
};
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;
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;
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,
/* Kernel module implementing an IP set type: the bitmap:port type */
-#include "ip_set_kernel.h"
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/tcp.h>
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;
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;
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,
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;
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;
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,
add_timer(&map->gc);
}
-static inline void
+static void
bitmap_port_gc_init(struct ip_set *set)
{
struct bitmap_port_timeout *map = set->data;
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;
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;
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,
/* Kernel module for IP set management */
-#include "ip_set_kernel.h"
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <net/genetlink.h>
#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 */
#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");
/* 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" : \
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();
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();
}
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
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);
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);
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);
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);
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
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)
{
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)
{
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);
/*
* 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);
*/
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;
}
/*
* 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;
.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 */
/* 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++) {
/* 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);
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]));
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);
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]));
/* 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 */
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;
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);
/* 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,
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);
}
out:
if (nlh) {
genlmsg_end(skb, nlh);
+ pr_debug("nlmsg_len: %u\n", skb->len);
dump_attrs(nlh);
}
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;
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]));
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);
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]));
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);
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]));
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]));
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)
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;
/* 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;
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;
}
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) {
}
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;
}
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);
--- /dev/null
+/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * 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 <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/icmp.h>
+#include <linux/icmpv6.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <net/ip.h>
+
+#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);
#ifndef _IP_SET_GETPORT_H
#define _IP_SET_GETPORT_H
-#ifdef __KERNEL__
-#include <linux/icmp.h>
-#include <linux/icmpv6.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <net/ip.h>
-
-#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*/
/* Kernel module implementing an IP set type: the hash:ip type */
-#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
/* 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;
};
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)
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 =
{
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;
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))
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]) {
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;
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))
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 */
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)
{
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);
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 =
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;
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)
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;
}
? &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);
/* Kernel module implementing an IP set type: the hash:ip,port type */
-#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
/* 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;
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
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)
{
return 1;
}
-static inline bool
+static bool
hash_ipport4_data_tlist(struct sk_buff *skb,
const struct hash_ipport4_elem *data)
{
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);
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;
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]) {
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;
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;
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
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)
{
return 1;
}
-static inline bool
+static bool
hash_ipport6_data_tlist(struct sk_buff *skb,
const struct hash_ipport6_elem *data)
{
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);
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;
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;
}
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)
? &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);
/* Kernel module implementing an IP set type: the hash:ip,port,ip type */
-#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
/* 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;
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
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)
{
return 1;
}
-static inline bool
+static bool
hash_ipportip4_data_tlist(struct sk_buff *skb,
const struct hash_ipportip4_elem *data)
{
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);
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;
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]) {
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;
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_ipportip6_elem {
union nf_inet_addr ip;
union nf_inet_addr ip2;
- u16 port;
+ __be16 port;
u8 proto;
u8 padding;
};
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;
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
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)
{
return 1;
}
-static inline bool
+static bool
hash_ipportip6_data_tlist(struct sk_buff *skb,
const struct hash_ipportip6_elem *data)
{
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);
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;
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;
}
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)
? &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);
/* Kernel module implementing an IP set type: the hash:ip,port,net type */
-#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
/* 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;
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
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;
}
elem->proto = 0;
}
-static inline bool
+static bool
hash_ipportnet4_data_list(struct sk_buff *skb,
const struct hash_ipportnet4_elem *data)
{
return 1;
}
-static inline bool
+static bool
hash_ipportnet4_data_tlist(struct sk_buff *skb,
const struct hash_ipportnet4_elem *data)
{
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);
}
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;
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
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]) {
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;
{
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 */
struct hash_ipportnet6_elem {
union nf_inet_addr ip;
union nf_inet_addr ip2;
- u16 port;
+ __be16 port;
u8 cidr;
u8 proto;
};
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;
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
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)
{
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
elem->cidr = cidr;
}
-static inline bool
+static bool
hash_ipportnet6_data_list(struct sk_buff *skb,
const struct hash_ipportnet6_elem *data)
{
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);
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);
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;
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;
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;
}
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)
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;
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;
}
/* Kernel module implementing an IP set type: the hash:net type */
-#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
/* Member elements without timeout */
struct hash_net4_elem {
- u32 ip;
+ __be32 ip;
u16 padding0;
u8 padding1;
u8 cidr;
/* Member elements with timeout support */
struct hash_net4_telem {
- u32 ip;
+ __be32 ip;
u16 padding0;
u8 padding1;
u8 cidr;
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;
}
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);
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 =
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);
}
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;
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))
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 */
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
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)
{
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
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);
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 =
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;
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)
? &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);
/* Kernel module implementing an IP set type: the hash:net,port type */
-#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
/* 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;
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
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;
}
elem->proto = 0;
}
-static inline bool
+static bool
hash_netport4_data_list(struct sk_buff *skb,
const struct hash_netport4_elem *data)
{
return 1;
}
-static inline bool
+static bool
hash_netport4_data_tlist(struct sk_buff *skb,
const struct hash_netport4_elem *data)
{
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);
}
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;
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;
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;
}
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;
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
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)
{
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
elem->cidr = cidr;
}
-static inline bool
+static bool
hash_netport6_data_list(struct sk_buff *skb,
const struct hash_netport6_elem *data)
{
return 1;
}
-static inline bool
+static bool
hash_netport6_data_tlist(struct sk_buff *skb,
const struct hash_netport6_elem *data)
{
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);
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;
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;
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;
}
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)
? &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);
+++ /dev/null
-#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 <linux/kernel.h>
-
-#endif /* __KERNEL__ */
-
-#endif /*_IP_SET_H */
/* Kernel module implementing an IP set type: the list:set type */
-#include "ip_set_kernel.h"
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/skbuff.h>
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 */
[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;
}
}
-static inline void
+static void
list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id,
unsigned long timeout)
{
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]);
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;
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)
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;
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 = {
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);
add_timer(&map->gc);
}
-static inline void
+static void
list_set_gc_init(struct ip_set *set)
{
struct list_set *map = set->data;
[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)
{
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)
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
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
* 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),
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),
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
};
-EXPORT_SYMBOL_GPL(prefixlen_hostmask_map);
+EXPORT_SYMBOL_GPL(ip_set_hostmask_map);
#include <linux/netfilter.h>
/* 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 */
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 */
}
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 */
}
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 */
}
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 */
}
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 */
}
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 */
}