ipset: update to 5.4.1

This commit is contained in:
Jan Engelhardt
2011-01-22 15:55:08 +01:00
parent 3141b2ff86
commit 1b53724a61
22 changed files with 982 additions and 961 deletions

View File

@@ -9,6 +9,10 @@ Enhancements:
- Update to ipset 5.3
* make IPv4 and IPv6 address handling similar
* show correct line numbers in restore output for parser errors
- Update to ipset 5.4
* fixed ICMP and ICMPv6 handling
* fixed trailing whitespaces and pr_* messages
* fixed module loading at create/header commands
v1.32 (2011-01-04)

View File

@@ -6,6 +6,6 @@ obj-m += ip_set_bitmap_port.o ip_set_hash_ip.o ip_set_hash_ipport.o
obj-m += ip_set_hash_ipportip.o ip_set_hash_ipportnet.o ip_set_hash_net.o
obj-m += ip_set_hash_netport.o ip_set_list_set.o
ip_set-y := ip_set_core.o pfxlen.o
ip_set-y := ip_set_core.o ip_set_getport.o pfxlen.o
EXTRA_CFLAGS += -DLCONFIG_IP_SET_MAX=256

View File

@@ -11,6 +11,8 @@
* published by the Free Software Foundation.
*/
#include <linux/netlink.h>
/* The protocol version */
#define IPSET_PROTOCOL 5
@@ -292,7 +294,7 @@ struct ip_set {
/* References to the set */
atomic_t ref;
/* The core set type */
const struct ip_set_type *type;
struct ip_set_type *type;
/* The type variant doing the real job */
const struct ip_set_type_variant *variant;
/* The actual INET family of the set */
@@ -317,37 +319,22 @@ extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
u8 family, u8 dim, u8 flags);
/* Allocate members */
static inline void *
ip_set_alloc(size_t size, gfp_t gfp_mask)
/* Utility functions */
extern void * ip_set_alloc(size_t size, gfp_t gfp_mask);
extern void ip_set_free(void *members);
extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr);
extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
static inline int
ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
{
void *members = NULL;
if (size < KMALLOC_MAX_SIZE)
members = kzalloc(size, gfp_mask | __GFP_NOWARN);
if (members) {
pr_debug("%p: allocated with kmalloc", members);
return members;
}
members = __vmalloc(size, gfp_mask | __GFP_ZERO, PAGE_KERNEL);
if (!members)
return NULL;
pr_debug("%p: allocated with vmalloc", members);
return members;
}
static inline void
ip_set_free(void *members)
{
pr_debug("%p: free with %s", members,
is_vmalloc_addr(members) ? "vfree" : "kfree");
if (is_vmalloc_addr(members))
vfree(members);
else
kfree(members);
__be32 ip;
int ret = ip_set_get_ipaddr4(nla, &ip);
if (ret)
return ret;
*ipaddr = ntohl(ip);
return 0;
}
/* Ignore IPSET_ERR_EXIST errors if asked to do so? */
@@ -357,92 +344,47 @@ ip_set_eexist(int ret, u32 flags)
return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
}
/* Check the NLA_F_NET_BYTEORDER flag */
static inline bool
ip_set_attr_netorder(struct nlattr *tb[], int type)
{
return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
}
static inline bool
ip_set_optattr_netorder(struct nlattr *tb[], int type)
{
return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
}
/* Useful converters */
static inline u32
ip_set_get_h32(const struct nlattr *attr)
{
u32 value = nla_get_u32(attr);
return attr->nla_type & NLA_F_NET_BYTEORDER ? ntohl(value) : value;
return ntohl(nla_get_be32(attr));
}
static inline u16
ip_set_get_h16(const struct nlattr *attr)
{
u16 value = nla_get_u16(attr);
return attr->nla_type & NLA_F_NET_BYTEORDER ? ntohs(value) : value;
}
static inline u32
ip_set_get_n32(const struct nlattr *attr)
{
u32 value = nla_get_u32(attr);
return attr->nla_type & NLA_F_NET_BYTEORDER ? value : htonl(value);
}
static inline u16
ip_set_get_n16(const struct nlattr *attr)
{
u16 value = nla_get_u16(attr);
return attr->nla_type & NLA_F_NET_BYTEORDER ? value : htons(value);
}
static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
[IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 },
[IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY,
.len = sizeof(struct in6_addr) },
};
static inline int
ip_set_get_ipaddr4(struct nlattr *attr[], int type, u32 *ipaddr)
{
struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1] = {};
if (!attr[type])
return -IPSET_ERR_PROTOCOL;
if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX,
nla_data(attr[type]), nla_len(attr[type]),
ipaddr_policy))
return -IPSET_ERR_PROTOCOL;
if (!tb[IPSET_ATTR_IPADDR_IPV4])
return -IPSET_ERR_IPADDR_IPV4;
*ipaddr = ip_set_get_n32(tb[IPSET_ATTR_IPADDR_IPV4]);
return 0;
}
static inline int
ip_set_get_ipaddr6(struct nlattr *attr[], int type, union nf_inet_addr *ipaddr)
{
struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1] = {};
if (!attr[type])
return -IPSET_ERR_PROTOCOL;
if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX,
nla_data(attr[type]), nla_len(attr[type]),
ipaddr_policy))
return -IPSET_ERR_PROTOCOL;
if (!tb[IPSET_ATTR_IPADDR_IPV6])
return -IPSET_ERR_IPADDR_IPV6;
memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]),
sizeof(struct in6_addr));
return 0;
return ntohs(nla_get_be16(attr));
}
#define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED)
#define ipset_nest_end(skb, start) nla_nest_end(skb, start)
#define NLA_PUT_NET32(skb, type, value) \
NLA_PUT_BE32(skb, type | NLA_F_NET_BYTEORDER, value)
#define NLA_PUT_NET16(skb, type, value) \
NLA_PUT_BE16(skb, type | NLA_F_NET_BYTEORDER, value)
#ifndef NLA_PUT_NET16
#define NLA_PUT_NET16(skb, attrtype, value) \
NLA_PUT_BE16(skb, attrtype | NLA_F_NET_BYTEORDER, value)
#endif
#ifndef NLA_PUT_NET32
#define NLA_PUT_NET32(skb, attrtype, value) \
NLA_PUT_BE32(skb, attrtype | NLA_F_NET_BYTEORDER, value)
#endif
#ifndef NLA_PUT_NET64
#define NLA_PUT_NET64(skb, attrtype, value) \
NLA_PUT_BE64(skb, attrtype | NLA_F_NET_BYTEORDER, value)
#endif
#define NLA_PUT_IPADDR4(skb, type, ipaddr) \
do { \
@@ -466,14 +408,14 @@ do { \
} while (0)
/* Get address from skbuff */
static inline u32
static inline __be32
ip4addr(const struct sk_buff *skb, bool src)
{
return src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
}
static inline void
ip4addrptr(const struct sk_buff *skb, bool src, u32 *addr)
ip4addrptr(const struct sk_buff *skb, bool src, __be32 *addr)
{
*addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
}

View File

@@ -63,7 +63,7 @@ struct ip_set_hash {
};
/* Compute htable_bits from the user input parameter hashsize */
static inline u8
static u8
htable_bits(u32 hashsize)
{
/* Assume that hashsize == 2^htable_bits */
@@ -81,14 +81,14 @@ htable_bits(u32 hashsize)
/* Network cidr size book keeping when the hash stores different
* sized networks */
static inline void
static void
add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
{
u8 i;
++h->nets[cidr-1].nets;
pr_debug("add_cidr added %u: %u", cidr, h->nets[cidr-1].nets);
pr_debug("add_cidr added %u: %u\n", cidr, h->nets[cidr-1].nets);
if (h->nets[cidr-1].nets > 1)
return;
@@ -103,14 +103,14 @@ add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
h->nets[i].cidr = cidr;
}
static inline void
static void
del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
{
u8 i;
--h->nets[cidr-1].nets;
pr_debug("del_cidr deleted %u: %u", cidr, h->nets[cidr-1].nets);
pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets);
if (h->nets[cidr-1].nets != 0)
return;
@@ -142,7 +142,7 @@ ahash_destroy(struct htable *t)
}
/* Calculate the actual memory size of the set data */
static inline size_t
static size_t
ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask)
{
u32 i;
@@ -340,7 +340,7 @@ retry:
/* Give time to other readers of the set */
synchronize_rcu_bh();
pr_debug("set %s resized from %u (%p) to %u (%p)", set->name,
pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name,
orig->htable_bits, orig, t->htable_bits, t);
ahash_destroy(orig);
@@ -436,7 +436,7 @@ type_pf_del(struct ip_set *set, void *value, u32 timeout)
/* Special test function which takes into account the different network
* sizes added to the set */
static inline int
static int
type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
{
struct ip_set_hash *h = set->data;
@@ -447,7 +447,7 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
u32 key;
u8 host_mask = SET_HOST_MASK(set->family);
pr_debug("test by nets");
pr_debug("test by nets\n");
for (; j < host_mask && h->nets[j].cidr; j++) {
type_pf_data_netmask(d, h->nets[j].cidr);
key = HKEY(d, h->initval, t->htable_bits);
@@ -546,14 +546,14 @@ type_pf_list(const struct ip_set *set,
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
if (!atd)
return -EFAULT;
pr_debug("list hash set %s", set->name);
pr_debug("list hash set %s\n", set->name);
for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) {
incomplete = skb_tail_pointer(skb);
n = hbucket(t, cb->args[2]);
pr_debug("cb->args[2]: %lu, t %p n %p", cb->args[2], t, n);
pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n);
for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i);
pr_debug("list hash %lu hbucket %p i %u, data %p",
pr_debug("list hash %lu hbucket %p i %u, data %p\n",
cb->args[2], n, i, data);
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested) {
@@ -686,7 +686,7 @@ type_pf_expire(struct ip_set_hash *h)
for (j = 0; j < n->pos; j++) {
data = ahash_tdata(n, j);
if (type_pf_data_expired(data)) {
pr_debug("expired %u/%u", i, j);
pr_debug("expired %u/%u\n", i, j);
#ifdef IP_SET_HASH_WITH_NETS
del_cidr(h, data->cidr, HOST_MASK);
#endif
@@ -701,7 +701,7 @@ type_pf_expire(struct ip_set_hash *h)
if (n->pos + AHASH_INIT_SIZE < n->size) {
void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
* sizeof(struct type_pf_telem),
GFP_KERNEL);
GFP_ATOMIC);
if (!tmp)
/* Still try to delete expired elements */
continue;
@@ -807,8 +807,8 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
ret = -IPSET_ERR_EXIST;
goto out;
}
} else if (j == AHASH_MAX_SIZE + 1
&& type_pf_data_expired(data))
} else if (j == AHASH_MAX_SIZE + 1 &&
type_pf_data_expired(data))
j = i;
}
if (j != AHASH_MAX_SIZE + 1) {
@@ -881,7 +881,7 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout)
}
#ifdef IP_SET_HASH_WITH_NETS
static inline int
static int
type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
{
struct ip_set_hash *h = set->data;
@@ -952,10 +952,10 @@ type_pf_tlist(const struct ip_set *set,
n = hbucket(t, cb->args[2]);
for (i = 0; i < n->pos; i++) {
data = ahash_tdata(n, i);
pr_debug("list %p %u", n, i);
pr_debug("list %p %u\n", n, i);
if (type_pf_data_expired(data))
continue;
pr_debug("do list %p %u", n, i);
pr_debug("do list %p %u\n", n, i);
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested) {
if (cb->args[2] == first) {
@@ -1008,7 +1008,7 @@ type_pf_gc(unsigned long ul_set)
struct ip_set *set = (struct ip_set *) ul_set;
struct ip_set_hash *h = set->data;
pr_debug("called");
pr_debug("called\n");
write_lock_bh(&set->lock);
type_pf_expire(h);
write_unlock_bh(&set->lock);
@@ -1017,7 +1017,7 @@ type_pf_gc(unsigned long ul_set)
add_timer(&h->gc);
}
static inline void
static void
type_pf_gc_init(struct ip_set *set)
{
struct ip_set_hash *h = set->data;
@@ -1027,7 +1027,7 @@ type_pf_gc_init(struct ip_set *set)
h->gc.function = type_pf_gc;
h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;
add_timer(&h->gc);
pr_debug("gc initialized, run in every %u",
pr_debug("gc initialized, run in every %u\n",
IPSET_GC_PERIOD(h->timeout));
}

View File

@@ -9,7 +9,6 @@
/* 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>
@@ -47,9 +46,9 @@ struct bitmap_ip {
};
static inline u32
ip_to_id(const struct bitmap_ip *map, u32 ip)
ip_to_id(const struct bitmap_ip *m, u32 ip)
{
return ((ip & HOSTMASK(map->netmask)) - map->first_ip)/map->hosts;
return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
}
static inline int
@@ -122,13 +121,15 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
bitmap_ip_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP]))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &ip);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
ip = ntohl(ip);
if (ip < map->first_ip || ip > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;
@@ -142,10 +143,9 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
return bitmap_ip_test(map, ip_to_id(map, ip));
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to) {
swap(ip, ip_to);
if (ip < map->first_ip)
@@ -156,8 +156,8 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -264,9 +264,9 @@ bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
const struct bitmap_ip *x = a->data;
const struct bitmap_ip *y = b->data;
return x->first_ip == y->first_ip
&& x->last_ip == y->last_ip
&& x->netmask == y->netmask;
return x->first_ip == y->first_ip &&
x->last_ip == y->last_ip &&
x->netmask == y->netmask;
}
static const struct ip_set_type_variant bitmap_ip = {
@@ -362,13 +362,16 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
bitmap_ip_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &ip);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
ip = ntohl(ip);
if (ip < map->first_ip || ip > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;
@@ -378,10 +381,9 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
ip_to_id((const struct bitmap_ip *)map, ip));
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to) {
swap(ip, ip_to);
if (ip < map->first_ip)
@@ -392,8 +394,8 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -511,10 +513,10 @@ bitmap_ip_timeout_same_set(const struct ip_set *a, const struct ip_set *b)
const struct bitmap_ip_timeout *x = a->data;
const struct bitmap_ip_timeout *y = b->data;
return x->first_ip == y->first_ip
&& x->last_ip == y->last_ip
&& x->netmask == y->netmask
&& x->timeout == y->timeout;
return x->first_ip == y->first_ip &&
x->last_ip == y->last_ip &&
x->netmask == y->netmask &&
x->timeout == y->timeout;
}
static const struct ip_set_type_variant bitmap_ip_timeout = {
@@ -547,7 +549,7 @@ bitmap_ip_gc(unsigned long ul_set)
add_timer(&map->gc);
}
static inline void
static void
bitmap_ip_gc_init(struct ip_set *set)
{
struct bitmap_ip_timeout *map = set->data;
@@ -603,16 +605,18 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
bitmap_ip_create_policy))
return -IPSET_ERR_PROTOCOL;
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &first_ip);
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
if (ret)
return ret;
first_ip = ntohl(first_ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &last_ip);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
if (ret)
return ret;
last_ip = htonl(last_ip);
if (first_ip > last_ip) {
u32 tmp = first_ip;
@@ -624,7 +628,7 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
if (cidr >= 32)
return -IPSET_ERR_INVALID_CIDR;
last_ip = first_ip | ~HOSTMASK(cidr);
last_ip = first_ip | ~ip_set_hostmask(cidr);
} else
return -IPSET_ERR_PROTOCOL;
@@ -634,8 +638,8 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
if (netmask > 32)
return -IPSET_ERR_INVALID_NETMASK;
first_ip &= HOSTMASK(netmask);
last_ip |= ~HOSTMASK(netmask);
first_ip &= ip_set_hostmask(netmask);
last_ip |= ~ip_set_hostmask(netmask);
}
if (netmask == 32) {
@@ -647,18 +651,18 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
mask = range_to_mask(first_ip, last_ip, &mask_bits);
if ((!mask && (first_ip || last_ip != 0xFFFFFFFF))
|| netmask <= mask_bits)
if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) ||
netmask <= mask_bits)
return -IPSET_ERR_BITMAP_RANGE;
pr_debug("mask_bits %u, netmask %u", mask_bits, netmask);
pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
hosts = 2 << (32 - netmask - 1);
elements = 2 << (netmask - mask_bits - 1);
}
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
return -IPSET_ERR_BITMAP_RANGE_SIZE;
pr_debug("hosts %u, elements %u", hosts, elements);
pr_debug("hosts %u, elements %u\n", hosts, elements);
if (tb[IPSET_ATTR_TIMEOUT]) {
struct bitmap_ip_timeout *map;

View File

@@ -10,7 +10,6 @@
/* 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>
@@ -95,9 +94,9 @@ bitmap_expired(const struct bitmap_ipmac *map, u32 id)
static inline int
bitmap_ipmac_exist(const struct ipmac_telem *elem)
{
return elem->match == MAC_UNSET
|| (elem->match == MAC_FILLED
&& !ip_set_timeout_expired(elem->timeout));
return elem->match == MAC_UNSET ||
(elem->match == MAC_FILLED &&
!ip_set_timeout_expired(elem->timeout));
}
/* Base variant */
@@ -114,8 +113,8 @@ bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
/* Trigger kernel to fill out the ethernet address */
return -EAGAIN;
case MAC_FILLED:
return data->ether == NULL
|| compare_ether_addr(data->ether, elem->ether) == 0;
return data->ether == NULL ||
compare_ether_addr(data->ether, elem->ether) == 0;
}
return 0;
}
@@ -223,9 +222,9 @@ bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
/* Trigger kernel to fill out the ethernet address */
return -EAGAIN;
case MAC_FILLED:
return (data->ether == NULL
|| compare_ether_addr(data->ether, elem->ether) == 0)
&& !bitmap_expired(map, data->id);
return (data->ether == NULL ||
compare_ether_addr(data->ether, elem->ether) == 0) &&
!bitmap_expired(map, data->id);
}
return 0;
}
@@ -348,8 +347,8 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
return -IPSET_ERR_BITMAP_RANGE;
/* Backward compatibility: we don't check the second flag */
if (skb_mac_header(skb) < skb->head
|| (skb_mac_header(skb) + ETH_HLEN) > skb->data)
if (skb_mac_header(skb) < skb->head ||
(skb_mac_header(skb) + ETH_HLEN) > skb->data)
return -EINVAL;
data.id -= map->first_ip;
@@ -381,13 +380,16 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len,
bitmap_ipmac_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.id);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &data.id);
if (ret)
return ret;
data.id = ntohl(data.id);
if (data.id < map->first_ip || data.id > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;
@@ -464,12 +466,12 @@ bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
const struct bitmap_ipmac *x = a->data;
const struct bitmap_ipmac *y = b->data;
return x->first_ip == y->first_ip
&& x->last_ip == y->last_ip
&& x->timeout == y->timeout;
return x->first_ip == y->first_ip &&
x->last_ip == y->last_ip &&
x->timeout == y->timeout;
}
const struct ip_set_type_variant bitmap_ipmac = {
static const struct ip_set_type_variant bitmap_ipmac = {
.kadt = bitmap_ipmac_kadt,
.uadt = bitmap_ipmac_uadt,
.adt = {
@@ -484,7 +486,7 @@ const struct ip_set_type_variant bitmap_ipmac = {
.same_set = bitmap_ipmac_same_set,
};
const struct ip_set_type_variant bitmap_tipmac = {
static const struct ip_set_type_variant bitmap_tipmac = {
.kadt = bitmap_ipmac_kadt,
.uadt = bitmap_ipmac_uadt,
.adt = {
@@ -512,8 +514,8 @@ bitmap_ipmac_gc(unsigned long ul_set)
read_lock_bh(&set->lock);
for (id = 0; id <= last; id++) {
elem = bitmap_ipmac_elem(map, id);
if (elem->match == MAC_FILLED
&& ip_set_timeout_expired(elem->timeout))
if (elem->match == MAC_FILLED &&
ip_set_timeout_expired(elem->timeout))
elem->match = MAC_EMPTY;
}
read_unlock_bh(&set->lock);
@@ -522,7 +524,7 @@ bitmap_ipmac_gc(unsigned long ul_set)
add_timer(&map->gc);
}
static inline void
static void
bitmap_ipmac_gc_init(struct ip_set *set)
{
struct bitmap_ipmac *map = set->data;
@@ -540,6 +542,7 @@ static const struct nla_policy
bitmap_ipmac_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
};
@@ -574,16 +577,18 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
bitmap_ipmac_create_policy))
return -IPSET_ERR_PROTOCOL;
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &first_ip);
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
if (ret)
return ret;
first_ip = ntohl(first_ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &last_ip);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
if (ret)
return ret;
last_ip = ntohl(last_ip);
if (first_ip > last_ip) {
u32 tmp = first_ip;
@@ -595,7 +600,7 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
if (cidr >= 32)
return -IPSET_ERR_INVALID_CIDR;
last_ip = first_ip | ~HOSTMASK(cidr);
last_ip = first_ip | ~ip_set_hostmask(cidr);
} else
return -IPSET_ERR_PROTOCOL;
@@ -634,7 +639,7 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
return 0;
}
struct ip_set_type bitmap_ipmac_type = {
static struct ip_set_type bitmap_ipmac_type = {
.name = "bitmap:ip,mac",
.protocol = IPSET_PROTOCOL,
.features = IPSET_TYPE_IP | IPSET_TYPE_MAC,

View File

@@ -7,7 +7,6 @@
/* 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>
@@ -71,12 +70,13 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
{
struct bitmap_port *map = set->data;
__be16 __port;
u16 port = 0;
if (!get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &port))
if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
return -EINVAL;
port = ntohs(port);
port = ntohs(__port);
if (port < map->first_port || port > map->last_port)
return -IPSET_ERR_BITMAP_RANGE;
@@ -116,14 +116,14 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len,
bitmap_port_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
if (tb[IPSET_ATTR_PORT])
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
if (port < map->first_port || port > map->last_port)
return -IPSET_ERR_BITMAP_RANGE;
@@ -246,11 +246,11 @@ bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
const struct bitmap_port *x = a->data;
const struct bitmap_port *y = b->data;
return x->first_port == y->first_port
&& x->last_port == y->last_port;
return x->first_port == y->first_port &&
x->last_port == y->last_port;
}
const struct ip_set_type_variant bitmap_port = {
static const struct ip_set_type_variant bitmap_port = {
.kadt = bitmap_port_kadt,
.uadt = bitmap_port_uadt,
.destroy = bitmap_port_destroy,
@@ -308,12 +308,13 @@ bitmap_port_timeout_kadt(struct ip_set *set, const struct sk_buff *skb,
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
{
struct bitmap_port_timeout *map = set->data;
__be16 __port;
u16 port = 0;
if (!get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &port))
if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
return -EINVAL;
port = ntohs(port);
port = ntohs(__port);
if (port < map->first_port || port > map->last_port)
return -IPSET_ERR_BITMAP_RANGE;
@@ -346,14 +347,15 @@ bitmap_port_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
bitmap_port_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
if (tb[IPSET_ATTR_PORT])
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
if (port < map->first_port || port > map->last_port)
return -IPSET_ERR_BITMAP_RANGE;
@@ -483,12 +485,12 @@ bitmap_port_timeout_same_set(const struct ip_set *a, const struct ip_set *b)
const struct bitmap_port_timeout *x = a->data;
const struct bitmap_port_timeout *y = b->data;
return x->first_port == y->first_port
&& x->last_port == y->last_port
&& x->timeout == y->timeout;
return x->first_port == y->first_port &&
x->last_port == y->last_port &&
x->timeout == y->timeout;
}
const struct ip_set_type_variant bitmap_port_timeout = {
static const struct ip_set_type_variant bitmap_port_timeout = {
.kadt = bitmap_port_timeout_kadt,
.uadt = bitmap_port_timeout_uadt,
.destroy = bitmap_port_timeout_destroy,
@@ -519,7 +521,7 @@ bitmap_port_gc(unsigned long ul_set)
add_timer(&map->gc);
}
static inline void
static void
bitmap_port_gc_init(struct ip_set *set)
{
struct bitmap_port_timeout *map = set->data;
@@ -567,21 +569,19 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len,
bitmap_port_create_policy))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_PORT])
first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
else
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_PORT_TO]) {
last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
if (first_port > last_port) {
u16 tmp = first_port;
first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
if (first_port > last_port) {
u16 tmp = first_port;
first_port = last_port;
last_port = tmp;
}
} else
return -IPSET_ERR_PROTOCOL;
first_port = last_port;
last_port = tmp;
}
if (tb[IPSET_ATTR_TIMEOUT]) {
struct bitmap_port_timeout *map;
@@ -611,7 +611,7 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len,
return -ENOMEM;
map->memsize = bitmap_bytes(0, last_port - first_port);
pr_debug("memsize: %zu", map->memsize);
pr_debug("memsize: %zu\n", map->memsize);
if (!init_map_port(set, map, first_port, last_port)) {
kfree(map);
return -ENOMEM;
@@ -622,7 +622,7 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len,
return 0;
}
struct ip_set_type bitmap_port_type = {
static struct ip_set_type bitmap_port_type = {
.name = "bitmap:port",
.protocol = IPSET_PROTOCOL,
.features = IPSET_TYPE_PORT,

View File

@@ -9,7 +9,6 @@
/* Kernel module for IP set management */
#include "ip_set_kernel.h"
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -26,7 +25,7 @@
#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 */
@@ -34,7 +33,7 @@ static ip_set_id_t ip_set_max = LCONFIG_IP_SET_MAX; /* max number of sets */
#define STREQ(a, b) (strncmp(a, b, IPSET_MAXNAMELEN) == 0)
static int max_sets;
static unsigned int max_sets;
module_param(max_sets, int, 0600);
MODULE_PARM_DESC(max_sets, "maximal number of sets");
@@ -64,60 +63,77 @@ ip_set_type_unlock(void)
/* Register and deregister settype */
static inline struct ip_set_type *
static struct ip_set_type *
find_set_type(const char *name, u8 family, u8 revision)
{
struct ip_set_type *type;
list_for_each_entry_rcu(type, &ip_set_type_list, list)
if (STREQ(type->name, name)
&& (type->family == family || type->family == AF_UNSPEC)
&& type->revision == revision)
if (STREQ(type->name, name) &&
(type->family == family || type->family == AF_UNSPEC) &&
type->revision == revision)
return type;
return NULL;
}
/* Find a set type so that rcu_read_lock() is called by the function.
* If we succeeded, the RCU lock is NOT released and the caller
* must release it later.
*/
static struct ip_set_type *
find_set_type_rcu(const char *name, u8 family, u8 revision)
/* Unlock, try to load a set type module and lock again */
static int
try_to_load_type(const char *name)
{
struct ip_set_type *type;
nfnl_unlock();
pr_debug("try to load ip_set_%s\n", name);
if (request_module("ip_set_%s", name) < 0) {
pr_warning("Can't find ip_set type %s\n", name);
nfnl_lock();
return -IPSET_ERR_FIND_TYPE;
}
nfnl_lock();
return -EAGAIN;
}
/* Find a set type and reference it */
static int
find_set_type_get(const char *name, u8 family, u8 revision,
struct ip_set_type **found)
{
rcu_read_lock();
type = find_set_type(name, family, revision);
if (type == NULL)
*found = find_set_type(name, family, revision);
if (*found) {
int err = !try_module_get((*found)->me);
rcu_read_unlock();
return err ? -EFAULT : 0;
}
rcu_read_unlock();
return type;
return try_to_load_type(name);
}
/* Find a given set type by name and family.
* If we succeeded, the supported minimal and maximum revisions are
* filled out.
*/
static bool
static int
find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
{
struct ip_set_type *type;
bool ret = false;
bool found = false;
*min = *max = 0;
rcu_read_lock();
list_for_each_entry_rcu(type, &ip_set_type_list, list)
if (STREQ(type->name, name)
&& (type->family == family || type->family == AF_UNSPEC)) {
ret = true;
if (STREQ(type->name, name) &&
(type->family == family || type->family == AF_UNSPEC)) {
found = true;
if (type->revision < *min)
*min = type->revision;
else if (type->revision > *max)
*max = type->revision;
}
rcu_read_unlock();
if (found)
return 0;
return ret;
return try_to_load_type(name);
}
#define family_name(f) ((f) == AF_INET ? "inet" : \
@@ -149,7 +165,7 @@ ip_set_type_register(struct ip_set_type *type)
goto unlock;
}
list_add_rcu(&type->list, &ip_set_type_list);
pr_debug("type %s, family %s, revision %u registered.",
pr_debug("type %s, family %s, revision %u registered.\n",
type->name, family_name(type->family), type->revision);
unlock:
ip_set_type_unlock();
@@ -169,7 +185,7 @@ ip_set_type_unregister(struct ip_set_type *type)
goto unlock;
}
list_del_rcu(&type->list);
pr_debug("type %s, family %s, revision %u unregistered.",
pr_debug("type %s, family %s, revision %u unregistered.\n",
type->name, family_name(type->family), type->revision);
unlock:
ip_set_type_unlock();
@@ -178,6 +194,92 @@ unlock:
}
EXPORT_SYMBOL_GPL(ip_set_type_unregister);
/* Utility functions */
void *
ip_set_alloc(size_t size, gfp_t gfp_mask)
{
void *members = NULL;
if (size < KMALLOC_MAX_SIZE)
members = kzalloc(size, gfp_mask | __GFP_NOWARN);
if (members) {
pr_debug("%p: allocated with kmalloc\n", members);
return members;
}
members = __vmalloc(size, gfp_mask | __GFP_ZERO | __GFP_HIGHMEM,
PAGE_KERNEL);
if (!members)
return NULL;
pr_debug("%p: allocated with vmalloc\n", members);
return members;
}
EXPORT_SYMBOL_GPL(ip_set_alloc);
void
ip_set_free(void *members)
{
pr_debug("%p: free with %s\n", members,
is_vmalloc_addr(members) ? "vfree" : "kfree");
if (is_vmalloc_addr(members))
vfree(members);
else
kfree(members);
}
EXPORT_SYMBOL_GPL(ip_set_free);
static inline bool
flag_nested(const struct nlattr *nla)
{
return nla->nla_type & NLA_F_NESTED;
}
static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
[IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 },
[IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY,
.len = sizeof(struct in6_addr) },
};
int
ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr)
{
struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
if (unlikely(!flag_nested(nla)))
return -IPSET_ERR_PROTOCOL;
if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, nla_data(nla), nla_len(nla),
ipaddr_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4)))
return -IPSET_ERR_PROTOCOL;
*ipaddr = nla_get_be32(tb[IPSET_ATTR_IPADDR_IPV4]);
return 0;
}
EXPORT_SYMBOL_GPL(ip_set_get_ipaddr4);
int
ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
{
struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
if (unlikely(!flag_nested(nla)))
return -IPSET_ERR_PROTOCOL;
if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, nla_data(nla), nla_len(nla),
ipaddr_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6)))
return -IPSET_ERR_PROTOCOL;
memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]),
sizeof(struct in6_addr));
return 0;
}
EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
/*
* Creating/destroying/renaming/swapping affect the existence and
* the properties of a set. All of these can be executed from userspace
@@ -216,10 +318,10 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
int ret = 0;
BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
pr_debug("set %s, index %u", set->name, index);
pr_debug("set %s, index %u\n", set->name, index);
if (dim < set->type->dimension
|| !(family == set->family || set->family == AF_UNSPEC))
if (dim < set->type->dimension ||
!(family == set->family || set->family == AF_UNSPEC))
return 0;
read_lock_bh(&set->lock);
@@ -228,7 +330,7 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
if (ret == -EAGAIN) {
/* Type requests element to be completed */
pr_debug("element must be competed, ADD is triggered");
pr_debug("element must be competed, ADD is triggered\n");
write_lock_bh(&set->lock);
set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags);
write_unlock_bh(&set->lock);
@@ -248,10 +350,10 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
int ret;
BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
pr_debug("set %s, index %u", set->name, index);
pr_debug("set %s, index %u\n", set->name, index);
if (dim < set->type->dimension
|| !(family == set->family || set->family == AF_UNSPEC))
if (dim < set->type->dimension ||
!(family == set->family || set->family == AF_UNSPEC))
return 0;
write_lock_bh(&set->lock);
@@ -270,10 +372,10 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
int ret = 0;
BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
pr_debug("set %s, index %u", set->name, index);
pr_debug("set %s, index %u\n", set->name, index);
if (dim < set->type->dimension
|| !(family == set->family || set->family == AF_UNSPEC))
if (dim < set->type->dimension ||
!(family == set->family || set->family == AF_UNSPEC))
return 0;
write_lock_bh(&set->lock);
@@ -423,8 +525,8 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
static inline bool
protocol_failed(struct nlattr *const *tb)
{
return !tb[IPSET_ATTR_PROTOCOL]
|| nla_get_u8(tb[IPSET_ATTR_PROTOCOL]) != IPSET_PROTOCOL;
return !tb[IPSET_ATTR_PROTOCOL] ||
nla_get_u8(tb[IPSET_ATTR_PROTOCOL]) != IPSET_PROTOCOL;
}
static inline u32
@@ -433,13 +535,7 @@ flag_exist(const struct genlmsghdr *ghdr)
return ghdr->reserved & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST;
}
static inline bool
flag_nested(const struct nlattr *nla)
{
return nla->nla_type & NLA_F_NESTED;
}
static void *
static struct nlmsghdr *
start_msg(struct sk_buff *skb, u32 pid, u32 seq, unsigned int flags,
enum ipset_cmd cmd)
{
@@ -508,13 +604,6 @@ find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set)
return 0;
}
static inline void
load_type_module(const char *typename)
{
pr_debug("try to load ip_set_%s", typename);
request_module("ip_set_%s", typename);
}
static int
ip_set_create(struct sk_buff *skb, struct genl_info *info)
{
@@ -527,20 +616,20 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info)
u32 flags = flag_exist(info->genlhdr);
int ret = 0, len;
if (unlikely(protocol_failed(attr)
|| attr[IPSET_ATTR_SETNAME] == NULL
|| attr[IPSET_ATTR_TYPENAME] == NULL
|| attr[IPSET_ATTR_REVISION] == NULL
|| attr[IPSET_ATTR_FAMILY] == NULL
|| (attr[IPSET_ATTR_DATA] != NULL
&& !flag_nested(attr[IPSET_ATTR_DATA]))))
if (unlikely(protocol_failed(attr) ||
attr[IPSET_ATTR_SETNAME] == NULL ||
attr[IPSET_ATTR_TYPENAME] == NULL ||
attr[IPSET_ATTR_REVISION] == NULL ||
attr[IPSET_ATTR_FAMILY] == NULL ||
(attr[IPSET_ATTR_DATA] != NULL &&
!flag_nested(attr[IPSET_ATTR_DATA]))))
return -IPSET_ERR_PROTOCOL;
name = nla_data(attr[IPSET_ATTR_SETNAME]);
typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
revision = nla_get_u8(attr[IPSET_ATTR_REVISION]);
pr_debug("setname: %s, typename: %s, family: %s, revision: %u",
pr_debug("setname: %s, typename: %s, family: %s, revision: %u\n",
name, typename, family_name(family), revision);
/*
@@ -563,32 +652,15 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info)
* After referencing the type, we try to create the type
* specific part of the set without holding any locks.
*/
set->type = find_set_type_rcu(typename, family, revision);
if (set->type == NULL) {
/* Try loading the module */
load_type_module(typename);
set->type = find_set_type_rcu(typename, family, revision);
if (set->type == NULL) {
pr_warning("Can't find ip_set type %s, family %s, "
"revision %u: set '%s' not created",
typename, family_name(family), revision,
name);
ret = -IPSET_ERR_FIND_TYPE;
goto out;
}
}
if (!try_module_get(set->type->me)) {
rcu_read_unlock();
ret = -EFAULT;
ret = find_set_type_get(typename, family, revision, &(set->type));
if (ret)
goto out;
}
rcu_read_unlock();
/*
* Without holding any locks, create private part.
*/
len = attr[IPSET_ATTR_DATA] ? nla_len(attr[IPSET_ATTR_DATA]) : 0;
pr_debug("data len: %u", len);
pr_debug("data len: %u\n", len);
ret = set->type->create(set, attr[IPSET_ATTR_DATA] ?
nla_data(attr[IPSET_ATTR_DATA]) : NULL, len,
flags);
@@ -604,12 +676,12 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info)
*/
if ((ret = find_free_id(set->name, &index, &clash)) != 0) {
/* If this is the same set and requested, ignore error */
if (ret == -EEXIST
&& (flags & IPSET_FLAG_EXIST)
&& STREQ(set->type->name, clash->type->name)
&& set->type->family == clash->type->family
&& set->type->revision == clash->type->revision
&& set->variant->same_set(set, clash))
if (ret == -EEXIST &&
(flags & IPSET_FLAG_EXIST) &&
STREQ(set->type->name, clash->type->name) &&
set->type->family == clash->type->family &&
set->type->revision == clash->type->revision &&
set->variant->same_set(set, clash))
ret = 0;
goto cleanup;
}
@@ -617,7 +689,7 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info)
/*
* Finally! Add our shiny new set to the list, and be done.
*/
pr_debug("create: '%s' created with index %u!", set->name, index);
pr_debug("create: '%s' created with index %u!\n", set->name, index);
ip_set_list[index] = set;
return ret;
@@ -640,12 +712,12 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = {
.len = IPSET_MAXNAMELEN - 1 },
};
static inline void
static void
ip_set_destroy_set(ip_set_id_t index)
{
struct ip_set *set = ip_set_list[index];
pr_debug("set: %s", set->name);
pr_debug("set: %s\n", set->name);
ip_set_list[index] = NULL;
/* Must call it without holding any lock */
@@ -666,8 +738,8 @@ ip_set_destroy(struct sk_buff *skb, struct genl_info *info)
/* References are protected by the nfnl mutex */
if (!attr[IPSET_ATTR_SETNAME]) {
for (i = 0; i < ip_set_max; i++) {
if (ip_set_list[i] != NULL
&& (atomic_read(&ip_set_list[i]->ref)))
if (ip_set_list[i] != NULL &&
(atomic_read(&ip_set_list[i]->ref)))
return -IPSET_ERR_BUSY;
}
for (i = 0; i < ip_set_max; i++) {
@@ -688,10 +760,10 @@ ip_set_destroy(struct sk_buff *skb, struct genl_info *info)
/* Flush sets */
static inline void
static void
ip_set_flush_set(struct ip_set *set)
{
pr_debug("set: %s", set->name);
pr_debug("set: %s\n", set->name);
write_lock_bh(&set->lock);
set->variant->flush(set);
@@ -741,9 +813,9 @@ ip_set_rename(struct sk_buff *skb, struct genl_info *info)
const char *name2;
ip_set_id_t i;
if (unlikely(protocol_failed(attr)
|| attr[IPSET_ATTR_SETNAME] == NULL
|| attr[IPSET_ATTR_SETNAME2] == NULL))
if (unlikely(protocol_failed(attr) ||
attr[IPSET_ATTR_SETNAME] == NULL ||
attr[IPSET_ATTR_SETNAME2] == NULL))
return -IPSET_ERR_PROTOCOL;
set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
@@ -754,8 +826,8 @@ ip_set_rename(struct sk_buff *skb, struct genl_info *info)
name2 = nla_data(attr[IPSET_ATTR_SETNAME2]);
for (i = 0; i < ip_set_max; i++) {
if (ip_set_list[i] != NULL
&& STREQ(ip_set_list[i]->name, name2))
if (ip_set_list[i] != NULL &&
STREQ(ip_set_list[i]->name, name2))
return -IPSET_ERR_EXIST_SETNAME2;
}
strncpy(set->name, name2, IPSET_MAXNAMELEN);
@@ -781,9 +853,9 @@ ip_set_swap(struct sk_buff *skb, struct genl_info *info)
char from_name[IPSET_MAXNAMELEN];
u32 from_ref;
if (unlikely(protocol_failed(attr)
|| attr[IPSET_ATTR_SETNAME] == NULL
|| attr[IPSET_ATTR_SETNAME2] == NULL))
if (unlikely(protocol_failed(attr) ||
attr[IPSET_ATTR_SETNAME] == NULL ||
attr[IPSET_ATTR_SETNAME2] == NULL))
return -IPSET_ERR_PROTOCOL;
from_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
@@ -800,8 +872,8 @@ ip_set_swap(struct sk_buff *skb, struct genl_info *info)
/* Features must not change.
* Not an artifical restriction anymore, as we must prevent
* possible loops created by swapping in setlist type of sets. */
if (!(from->type->features == to->type->features
&& from->type->family == to->type->family))
if (!(from->type->features == to->type->features &&
from->type->family == to->type->family))
return -IPSET_ERR_TYPE_MISMATCH;
/* No magic here: ref munging protected by the nfnl_lock */
@@ -830,7 +902,7 @@ static int
ip_set_dump_done(struct netlink_callback *cb)
{
if (cb->args[2]) {
pr_debug("release set %s", ip_set_list[cb->args[1]]->name);
pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name);
__ip_set_put((ip_set_id_t) cb->args[1]);
}
return 0;
@@ -843,14 +915,13 @@ dump_attrs(void *phdr)
const struct nlmsghdr *nlh = phdr - GENL_HDRLEN - NLMSG_HDRLEN;
int rem;
pr_debug("nlmsg_len: %u", nlh->nlmsg_len);
pr_debug("dump nlmsg");
pr_debug("dump nlmsg\n");
nlmsg_for_each_attr(attr, nlh, sizeof(struct genlmsghdr), rem) {
pr_debug("type: %u, len %u", nla_type(attr), attr->nla_len);
pr_debug("type: %u, len %u\n", nla_type(attr), attr->nla_len);
}
}
static inline int
static int
dump_init(struct netlink_callback *cb)
{
struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
@@ -919,14 +990,14 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
/* When dumping all sets, we must dump "sorted"
* so that lists (unions of sets) are dumped last.
*/
if (cb->args[0] != DUMP_ONE
&& !((cb->args[0] == DUMP_ALL)
^ (set->type->features & IPSET_DUMP_LAST)))
if (cb->args[0] != DUMP_ONE &&
!((cb->args[0] == DUMP_ALL) ^
(set->type->features & IPSET_DUMP_LAST)))
continue;
pr_debug("List set: %s", set->name);
pr_debug("List set: %s\n", set->name);
if (!cb->args[2]) {
/* Start listing: make sure set won't be destroyed */
pr_debug("reference set");
pr_debug("reference set\n");
__ip_set_get(index);
}
nlh = start_msg(skb, NETLINK_CB(cb->skb).pid,
@@ -972,7 +1043,7 @@ nla_put_failure:
release_refcount:
/* If there was an error or set is done, release set */
if (ret || !cb->args[2]) {
pr_debug("release set %s", ip_set_list[index]->name);
pr_debug("release set %s\n", ip_set_list[index]->name);
__ip_set_put(index);
}
@@ -983,6 +1054,7 @@ release_refcount:
out:
if (nlh) {
genlmsg_end(skb, nlh);
pr_debug("nlmsg_len: %u\n", skb->len);
dump_attrs(nlh);
}
@@ -1034,9 +1106,9 @@ call_ad(struct sk_buff *skb, struct nlattr *const attr[],
ret = set->variant->uadt(set, head, len, adt,
&lineno, flags);
write_unlock_bh(&set->lock);
} while (ret == -EAGAIN
&& set->variant->resize
&& (ret = set->variant->resize(set, retried++)) == 0);
} while (ret == -EAGAIN &&
set->variant->resize &&
(ret = set->variant->resize(set, retried++)) == 0);
if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
return 0;
@@ -1060,15 +1132,15 @@ ip_set_uadd(struct sk_buff *skb, struct genl_info *info)
u32 flags = flag_exist(info->genlhdr);
int ret = 0;
if (unlikely(protocol_failed(attr)
|| attr[IPSET_ATTR_SETNAME] == NULL
|| !((attr[IPSET_ATTR_DATA] != NULL)
^ (attr[IPSET_ATTR_ADT] != NULL))
|| (attr[IPSET_ATTR_DATA] != NULL
&& !flag_nested(attr[IPSET_ATTR_DATA]))
|| (attr[IPSET_ATTR_ADT] != NULL
&& (!flag_nested(attr[IPSET_ATTR_ADT])
|| attr[IPSET_ATTR_LINENO] == NULL))))
if (unlikely(protocol_failed(attr) ||
attr[IPSET_ATTR_SETNAME] == NULL ||
!((attr[IPSET_ATTR_DATA] != NULL) ^
(attr[IPSET_ATTR_ADT] != NULL)) ||
(attr[IPSET_ATTR_DATA] != NULL &&
!flag_nested(attr[IPSET_ATTR_DATA])) ||
(attr[IPSET_ATTR_ADT] != NULL &&
(!flag_nested(attr[IPSET_ATTR_ADT]) ||
attr[IPSET_ATTR_LINENO] == NULL))))
return -IPSET_ERR_PROTOCOL;
set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
@@ -1082,8 +1154,8 @@ ip_set_uadd(struct sk_buff *skb, struct genl_info *info)
int nla_rem;
nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
if (nla_type(nla) != IPSET_ATTR_DATA
|| !flag_nested(nla))
if (nla_type(nla) != IPSET_ATTR_DATA ||
!flag_nested(nla))
return -IPSET_ERR_PROTOCOL;
ret = call_ad(skb, attr,
set, nla, IPSET_ADD, flags);
@@ -1104,15 +1176,15 @@ ip_set_udel(struct sk_buff *skb, struct genl_info *info)
u32 flags = flag_exist(info->genlhdr);
int ret = 0;
if (unlikely(protocol_failed(attr)
|| attr[IPSET_ATTR_SETNAME] == NULL
|| !((attr[IPSET_ATTR_DATA] != NULL)
^ (attr[IPSET_ATTR_ADT] != NULL))
|| (attr[IPSET_ATTR_DATA] != NULL
&& !flag_nested(attr[IPSET_ATTR_DATA]))
|| (attr[IPSET_ATTR_ADT] != NULL
&& (!flag_nested(attr[IPSET_ATTR_ADT])
|| attr[IPSET_ATTR_LINENO] == NULL))))
if (unlikely(protocol_failed(attr) ||
attr[IPSET_ATTR_SETNAME] == NULL ||
!((attr[IPSET_ATTR_DATA] != NULL) ^
(attr[IPSET_ATTR_ADT] != NULL)) ||
(attr[IPSET_ATTR_DATA] != NULL &&
!flag_nested(attr[IPSET_ATTR_DATA])) ||
(attr[IPSET_ATTR_ADT] != NULL &&
(!flag_nested(attr[IPSET_ATTR_ADT]) ||
attr[IPSET_ATTR_LINENO] == NULL))))
return -IPSET_ERR_PROTOCOL;
set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
@@ -1126,8 +1198,8 @@ ip_set_udel(struct sk_buff *skb, struct genl_info *info)
int nla_rem;
nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
if (nla_type(nla) != IPSET_ATTR_DATA
|| !flag_nested(nla))
if (nla_type(nla) != IPSET_ATTR_DATA ||
!flag_nested(nla))
return -IPSET_ERR_PROTOCOL;
ret = call_ad(skb, attr,
set, nla, IPSET_DEL, flags);
@@ -1146,10 +1218,10 @@ ip_set_utest(struct sk_buff *skb, struct genl_info *info)
struct ip_set *set;
int ret = 0;
if (unlikely(protocol_failed(attr)
|| attr[IPSET_ATTR_SETNAME] == NULL
|| attr[IPSET_ATTR_DATA] == NULL
|| !flag_nested(attr[IPSET_ATTR_DATA])))
if (unlikely(protocol_failed(attr) ||
attr[IPSET_ATTR_SETNAME] == NULL ||
attr[IPSET_ATTR_DATA] == NULL ||
!flag_nested(attr[IPSET_ATTR_DATA])))
return -IPSET_ERR_PROTOCOL;
set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
@@ -1182,8 +1254,8 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info)
ip_set_id_t index;
int ret = 0;
if (unlikely(protocol_failed(attr)
|| attr[IPSET_ATTR_SETNAME] == NULL))
if (unlikely(protocol_failed(attr) ||
attr[IPSET_ATTR_SETNAME] == NULL))
return -IPSET_ERR_PROTOCOL;
index = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
@@ -1240,22 +1312,16 @@ ip_set_type(struct sk_buff *skb, struct genl_info *info)
const char *typename;
int ret = 0;
if (unlikely(protocol_failed(attr)
|| attr[IPSET_ATTR_TYPENAME] == NULL
|| attr[IPSET_ATTR_FAMILY] == NULL))
if (unlikely(protocol_failed(attr) ||
attr[IPSET_ATTR_TYPENAME] == NULL ||
attr[IPSET_ATTR_FAMILY] == NULL))
return -IPSET_ERR_PROTOCOL;
family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
if (!find_set_type_minmax(typename, family, &min, &max)) {
/* Try to load in the type module */
load_type_module(typename);
if (!find_set_type_minmax(typename, family, &min, &max)) {
pr_debug("can't find: %s, family: %u",
typename, family);
return -EEXIST;
}
}
ret = find_set_type_minmax(typename, family, &min, &max);
if (ret)
return ret;
skb2 = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (skb2 == NULL)
@@ -1272,6 +1338,7 @@ ip_set_type(struct sk_buff *skb, struct genl_info *info)
NLA_PUT_U8(skb2, IPSET_ATTR_REVISION_MIN, min);
genlmsg_end(skb2, nlh2);
pr_debug("Send TYPE, nlmsg_len: %u\n", skb2->len);
ret = genlmsg_unicast(genl_info_net(info), skb2, NETLINK_CB(skb).pid);
if (ret < 0)
return -EFAULT;
@@ -1421,7 +1488,7 @@ static struct genl_family ip_set_netlink_subsys __read_mostly = {
/* Interface to iptables/ip6tables */
static int
ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len)
ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
{
unsigned *op;
void *data;
@@ -1482,8 +1549,8 @@ ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len)
case IP_SET_OP_GET_BYINDEX: {
struct ip_set_req_get_set *req_get = data;
if (*len != sizeof(struct ip_set_req_get_set)
|| req_get->set.index >= ip_set_max) {
if (*len != sizeof(struct ip_set_req_get_set) ||
req_get->set.index >= ip_set_max) {
ret = -EINVAL;
goto done;
}
@@ -1531,12 +1598,10 @@ ip_set_init(void)
ip_set_list = kzalloc(sizeof(struct ip_set *) * ip_set_max,
GFP_KERNEL);
if (!ip_set_list) {
pr_err("ip_set: Unable to create ip_set_list");
pr_err("ip_set: Unable to create ip_set_list\n");
return -ENOMEM;
}
INIT_LIST_HEAD(&ip_set_type_list);
ret = genl_register_family_with_ops(&ip_set_netlink_subsys,
ip_set_netlink_subsys_cb, ARRAY_SIZE(ip_set_netlink_subsys_cb));
if (ret != 0) {
@@ -1546,13 +1611,13 @@ ip_set_init(void)
}
ret = nf_register_sockopt(&so_set);
if (ret != 0) {
pr_err("SO_SET registry failed: %d", ret);
pr_err("SO_SET registry failed: %d\n", ret);
genl_unregister_family(&ip_set_netlink_subsys);
kfree(ip_set_list);
return ret;
}
pr_notice("ip_set: protocol %u", IPSET_PROTOCOL);
pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL);
return 0;
}
@@ -1563,7 +1628,7 @@ ip_set_fini(void)
nf_unregister_sockopt(&so_set);
genl_unregister_family(&ip_set_netlink_subsys);
kfree(ip_set_list);
pr_debug("these are the famous last words");
pr_debug("these are the famous last words\n");
}
module_init(ip_set_init);

View File

@@ -0,0 +1,136 @@
/* 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);

View File

@@ -1,126 +1,11 @@
#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*/

View File

@@ -7,7 +7,6 @@
/* 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>
@@ -46,12 +45,12 @@ hash_ip_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_ip4_elem {
u32 ip;
__be32 ip;
};
/* Member elements with timeout support */
struct hash_ip4_telem {
u32 ip;
__be32 ip;
unsigned long timeout;
};
@@ -74,12 +73,6 @@ hash_ip4_data_copy(struct hash_ip4_elem *dst, const struct hash_ip4_elem *src)
dst->ip = src->ip;
}
static inline void
hash_ip4_data_swap(struct hash_ip4_elem *dst, struct hash_ip4_elem *src)
{
swap(dst->ip, src->ip);
}
/* Zero valued IP addresses cannot be stored */
static inline void
hash_ip4_data_zero_out(struct hash_ip4_elem *elem)
@@ -97,7 +90,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data)
{
const struct hash_ip4_telem *tdata =
@@ -124,10 +117,10 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
u32 ip;
__be32 ip;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip);
ip &= NETMASK(h->netmask);
ip &= ip_set_netmask(h->netmask);
if (ip == 0)
return -EINVAL;
@@ -149,23 +142,26 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
const struct ip_set_hash *h = set->data;
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
ipset_adtfn adtfn = set->variant->adt[adt];
u32 ip, nip, ip_to, hosts, timeout = h->timeout;
u32 ip, ip_to, hosts, timeout = h->timeout;
__be32 nip;
int ret = 0;
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
hash_ip4_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &ip);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
ip &= NETMASK(h->netmask);
if (ip == 0)
return -IPSET_ERR_HASH_ELEM;
ip &= ip_set_hostmask(h->netmask);
if (tb[IPSET_ATTR_TIMEOUT]) {
if (!with_timeout(h->timeout))
@@ -173,15 +169,17 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST)
return adtfn(set, &ip, timeout);
if (adt == IPSET_TEST) {
nip = htonl(ip);
if (nip == 0)
return -IPSET_ERR_HASH_ELEM;
return adtfn(set, &nip, timeout);
}
ip = ntohl(ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to)
swap(ip, ip_to);
} else if (tb[IPSET_ATTR_CIDR]) {
@@ -189,8 +187,8 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -198,6 +196,8 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
for (; !before(ip_to, ip); ip += hosts) {
nip = htonl(ip);
if (nip == 0)
return -IPSET_ERR_HASH_ELEM;
ret = adtfn(set, &nip, timeout);
if (ret && !ip_set_eexist(ret, flags))
@@ -215,9 +215,9 @@ hash_ip_same_set(const struct ip_set *a, const struct ip_set *b)
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout
&& x->netmask == y->netmask;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout &&
x->netmask == y->netmask;
}
/* The type variant functions: IPv6 */
@@ -250,16 +250,6 @@ hash_ip6_data_copy(struct hash_ip6_elem *dst, const struct hash_ip6_elem *src)
ipv6_addr_copy(&dst->ip.in6, &src->ip.in6);
}
static inline void
hash_ip6_data_swap(struct hash_ip6_elem *dst, struct hash_ip6_elem *src)
{
struct in6_addr tmp;
ipv6_addr_copy(&tmp, &dst->ip.in6);
ipv6_addr_copy(&dst->ip.in6, &src->ip.in6);
ipv6_addr_copy(&src->ip.in6, &tmp);
}
static inline void
hash_ip6_data_zero_out(struct hash_ip6_elem *elem)
{
@@ -269,13 +259,13 @@ hash_ip6_data_zero_out(struct hash_ip6_elem *elem)
static inline void
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
{
ip->ip6[0] &= NETMASK6(prefix)[0];
ip->ip6[1] &= NETMASK6(prefix)[1];
ip->ip6[2] &= NETMASK6(prefix)[2];
ip->ip6[3] &= NETMASK6(prefix)[3];
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
}
static inline bool
static bool
hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *data)
{
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
@@ -285,7 +275,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data)
{
const struct hash_ip6_telem *e =
@@ -344,10 +334,14 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ip6_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
@@ -389,13 +383,18 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
if (!(set->family == AF_INET || set->family == AF_INET6))
return -IPSET_ERR_INVALID_FAMILY;
netmask = set->family == AF_INET ? 32 : 128;
pr_debug("Create set %s with family %s",
pr_debug("Create set %s with family %s\n",
set->name, set->family == AF_INET ? "inet" : "inet6");
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
hash_ip_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -408,9 +407,9 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
if (tb[IPSET_ATTR_NETMASK]) {
netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
if ((set->family == AF_INET && netmask > 32)
|| (set->family == AF_INET6 && netmask > 128)
|| netmask == 0)
if ((set->family == AF_INET && netmask > 32) ||
(set->family == AF_INET6 && netmask > 128) ||
netmask == 0)
return -IPSET_ERR_INVALID_NETMASK;
}
@@ -451,7 +450,7 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
? &hash_ip4_variant : &hash_ip6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);

View File

@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the hash:ip,port type */
#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
@@ -47,16 +46,16 @@ hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_ipport4_elem {
u32 ip;
u16 port;
__be32 ip;
__be16 port;
u8 proto;
u8 padding;
};
/* Member elements with timeout support */
struct hash_ipport4_telem {
u32 ip;
u16 port;
__be32 ip;
__be16 port;
u8 proto;
u8 padding;
unsigned long timeout;
@@ -66,9 +65,9 @@ static inline bool
hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
const struct hash_ipport4_elem *ip2)
{
return ip1->ip == ip2->ip
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ip1->ip == ip2->ip &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -86,22 +85,13 @@ hash_ipport4_data_copy(struct hash_ipport4_elem *dst,
dst->proto = src->proto;
}
static inline void
hash_ipport4_data_swap(struct hash_ipport4_elem *dst,
struct hash_ipport4_elem *src)
{
swap(dst->ip, src->ip);
swap(dst->port, src->port);
swap(dst->proto, src->proto);
}
static inline void
hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem)
{
elem->proto = 0;
}
static inline bool
static bool
hash_ipport4_data_list(struct sk_buff *skb,
const struct hash_ipport4_elem *data)
{
@@ -114,7 +104,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipport4_data_tlist(struct sk_buff *skb,
const struct hash_ipport4_elem *data)
{
@@ -145,8 +135,8 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport4_elem data = { };
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
@@ -182,15 +172,21 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipport_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -218,20 +214,19 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR]
|| tb[IPSET_ATTR_PORT_TO])) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
tb[IPSET_ATTR_PORT_TO])) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
ip = ntohl(data.ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to)
swap(ip, ip_to);
} else if (tb[IPSET_ATTR_CIDR]) {
@@ -239,8 +234,8 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -273,22 +268,22 @@ hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout;
}
/* The type variant functions: IPv6 */
struct hash_ipport6_elem {
union nf_inet_addr ip;
u16 port;
__be16 port;
u8 proto;
u8 padding;
};
struct hash_ipport6_telem {
union nf_inet_addr ip;
u16 port;
__be16 port;
u8 proto;
u8 padding;
unsigned long timeout;
@@ -298,9 +293,9 @@ static inline bool
hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
const struct hash_ipport6_elem *ip2)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -316,24 +311,13 @@ hash_ipport6_data_copy(struct hash_ipport6_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_ipport6_data_swap(struct hash_ipport6_elem *dst,
struct hash_ipport6_elem *src)
{
struct hash_ipport6_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem)
{
elem->proto = 0;
}
static inline bool
static bool
hash_ipport6_data_list(struct sk_buff *skb,
const struct hash_ipport6_elem *data)
{
@@ -346,7 +330,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipport6_data_tlist(struct sk_buff *skb,
const struct hash_ipport6_elem *data)
{
@@ -379,8 +363,8 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport6_elem data = { };
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
@@ -404,15 +388,21 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipport_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -440,9 +430,9 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !tb[IPSET_ATTR_PORT_TO]) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -491,6 +481,11 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
hash_ipport_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -536,7 +531,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
? &hash_ipport4_variant : &hash_ipport6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);

View File

@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the hash:ip,port,ip type */
#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
@@ -47,18 +46,18 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_ipportip4_elem {
u32 ip;
u32 ip2;
u16 port;
__be32 ip;
__be32 ip2;
__be16 port;
u8 proto;
u8 padding;
};
/* Member elements with timeout support */
struct hash_ipportip4_telem {
u32 ip;
u32 ip2;
u16 port;
__be32 ip;
__be32 ip2;
__be16 port;
u8 proto;
u8 padding;
unsigned long timeout;
@@ -68,10 +67,10 @@ static inline bool
hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
const struct hash_ipportip4_elem *ip2)
{
return ip1->ip == ip2->ip
&& ip1->ip2 == ip2->ip2
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ip1->ip == ip2->ip &&
ip1->ip2 == ip2->ip2 &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -87,24 +86,13 @@ hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_ipportip4_data_swap(struct hash_ipportip4_elem *dst,
struct hash_ipportip4_elem *src)
{
struct hash_ipportip4_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem)
{
elem->proto = 0;
}
static inline bool
static bool
hash_ipportip4_data_list(struct sk_buff *skb,
const struct hash_ipportip4_elem *data)
{
@@ -118,7 +106,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipportip4_data_tlist(struct sk_buff *skb,
const struct hash_ipportip4_elem *data)
{
@@ -150,8 +138,8 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip4_elem data = { };
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
@@ -189,19 +177,25 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipportip_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP2, &data.ip2);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
if (ret)
return ret;
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -229,20 +223,19 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR]
|| tb[IPSET_ATTR_PORT_TO])) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
tb[IPSET_ATTR_PORT_TO])) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
ip = ntohl(data.ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to)
swap(ip, ip_to);
} else if (tb[IPSET_ATTR_CIDR]) {
@@ -250,8 +243,8 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -284,8 +277,8 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout;
}
/* The type variant functions: IPv6 */
@@ -293,7 +286,7 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
struct hash_ipportip6_elem {
union nf_inet_addr ip;
union nf_inet_addr ip2;
u16 port;
__be16 port;
u8 proto;
u8 padding;
};
@@ -301,7 +294,7 @@ struct hash_ipportip6_elem {
struct hash_ipportip6_telem {
union nf_inet_addr ip;
union nf_inet_addr ip2;
u16 port;
__be16 port;
u8 proto;
u8 padding;
unsigned long timeout;
@@ -311,10 +304,10 @@ static inline bool
hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
const struct hash_ipportip6_elem *ip2)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
&& ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -330,24 +323,13 @@ hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_ipportip6_data_swap(struct hash_ipportip6_elem *dst,
struct hash_ipportip6_elem *src)
{
struct hash_ipportip6_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem)
{
elem->proto = 0;
}
static inline bool
static bool
hash_ipportip6_data_list(struct sk_buff *skb,
const struct hash_ipportip6_elem *data)
{
@@ -361,7 +343,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipportip6_data_tlist(struct sk_buff *skb,
const struct hash_ipportip6_elem *data)
{
@@ -395,8 +377,8 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip6_elem data = { };
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
@@ -421,19 +403,25 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipportip_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP2, &data.ip2);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
if (ret)
return ret;
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -461,9 +449,9 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !tb[IPSET_ATTR_PORT_TO]) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -512,6 +500,11 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
hash_ipportip_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -557,7 +550,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
? &hash_ipportip4_variant : &hash_ipportip6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);

View File

@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the hash:ip,port,net type */
#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
@@ -47,18 +46,18 @@ hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_ipportnet4_elem {
u32 ip;
u32 ip2;
u16 port;
__be32 ip;
__be32 ip2;
__be16 port;
u8 cidr;
u8 proto;
};
/* Member elements with timeout support */
struct hash_ipportnet4_telem {
u32 ip;
u32 ip2;
u16 port;
__be32 ip;
__be32 ip2;
__be16 port;
u8 cidr;
u8 proto;
unsigned long timeout;
@@ -68,11 +67,11 @@ static inline bool
hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
const struct hash_ipportnet4_elem *ip2)
{
return ip1->ip == ip2->ip
&& ip1->ip2 == ip2->ip2
&& ip1->cidr == ip2->cidr
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ip1->ip == ip2->ip &&
ip1->ip2 == ip2->ip2 &&
ip1->cidr == ip2->cidr &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -88,21 +87,10 @@ hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_ipportnet4_data_swap(struct hash_ipportnet4_elem *dst,
struct hash_ipportnet4_elem *src)
{
struct hash_ipportnet4_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
{
elem->ip2 &= NETMASK(cidr);
elem->ip2 &= ip_set_netmask(cidr);
elem->cidr = cidr;
}
@@ -112,7 +100,7 @@ hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
elem->proto = 0;
}
static inline bool
static bool
hash_ipportnet4_data_list(struct sk_buff *skb,
const struct hash_ipportnet4_elem *data)
{
@@ -127,7 +115,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipportnet4_data_tlist(struct sk_buff *skb,
const struct hash_ipportnet4_elem *data)
{
@@ -169,13 +157,13 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
data.ip2 &= NETMASK(data.cidr);
data.ip2 &= ip_set_netmask(data.cidr);
return adtfn(set, &data, h->timeout);
}
@@ -210,14 +198,20 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipportnet_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP2, &data.ip2);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
if (ret)
return ret;
@@ -227,16 +221,16 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (!data.cidr)
return -IPSET_ERR_INVALID_CIDR;
data.ip2 &= NETMASK(data.cidr);
data.ip2 &= ip_set_netmask(data.cidr);
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_PROTO]) {
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
if (data.proto == 0)
return -IPSET_ERR_INVALID_PROTO;
} else
@@ -258,20 +252,19 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR]
|| tb[IPSET_ATTR_PORT_TO])) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
tb[IPSET_ATTR_PORT_TO])) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
ip = ntohl(data.ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to)
swap(ip, ip_to);
} else if (tb[IPSET_ATTR_CIDR]) {
@@ -279,8 +272,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -311,10 +304,10 @@ hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
{
const struct ip_set_hash *x = a->data;
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout;
}
/* The type variant functions: IPv6 */
@@ -322,7 +315,7 @@ hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
struct hash_ipportnet6_elem {
union nf_inet_addr ip;
union nf_inet_addr ip2;
u16 port;
__be16 port;
u8 cidr;
u8 proto;
};
@@ -330,7 +323,7 @@ struct hash_ipportnet6_elem {
struct hash_ipportnet6_telem {
union nf_inet_addr ip;
union nf_inet_addr ip2;
u16 port;
__be16 port;
u8 cidr;
u8 proto;
unsigned long timeout;
@@ -340,11 +333,11 @@ static inline bool
hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
const struct hash_ipportnet6_elem *ip2)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
&& ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0
&& ip1->cidr == ip2->cidr
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
ip1->cidr == ip2->cidr &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -360,17 +353,6 @@ hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_ipportnet6_data_swap(struct hash_ipportnet6_elem *dst,
struct hash_ipportnet6_elem *src)
{
struct hash_ipportnet6_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
{
@@ -380,10 +362,10 @@ hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
static inline void
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
{
ip->ip6[0] &= NETMASK6(prefix)[0];
ip->ip6[1] &= NETMASK6(prefix)[1];
ip->ip6[2] &= NETMASK6(prefix)[2];
ip->ip6[3] &= NETMASK6(prefix)[3];
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
}
static inline void
@@ -393,7 +375,7 @@ hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
elem->cidr = cidr;
}
static inline bool
static bool
hash_ipportnet6_data_list(struct sk_buff *skb,
const struct hash_ipportnet6_elem *data)
{
@@ -408,13 +390,13 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipportnet6_data_tlist(struct sk_buff *skb,
const struct hash_ipportnet6_elem *data)
{
const struct hash_ipportnet6_telem *e =
const struct hash_ipportnet6_telem *e =
(const struct hash_ipportnet6_telem *)data;
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
@@ -449,8 +431,8 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
@@ -476,14 +458,20 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipportnet_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP2, &data.ip2);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
if (ret)
return ret;
@@ -496,7 +484,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len,
ip6_netmask(&data.ip2, data.cidr);
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -524,9 +512,9 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !tb[IPSET_ATTR_PORT_TO]) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -575,6 +563,11 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
hash_ipportnet_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -609,7 +602,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
if (tb[IPSET_ATTR_TIMEOUT]) {
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
set->variant = set->family == AF_INET
? &hash_ipportnet4_tvariant
: &hash_ipportnet6_tvariant;
@@ -622,11 +615,11 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
set->variant = set->family == AF_INET
? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);
return 0;
}

View File

@@ -7,7 +7,6 @@
/* 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>
@@ -45,7 +44,7 @@ hash_net_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_net4_elem {
u32 ip;
__be32 ip;
u16 padding0;
u8 padding1;
u8 cidr;
@@ -53,7 +52,7 @@ struct hash_net4_elem {
/* Member elements with timeout support */
struct hash_net4_telem {
u32 ip;
__be32 ip;
u16 padding0;
u8 padding1;
u8 cidr;
@@ -81,18 +80,10 @@ hash_net4_data_copy(struct hash_net4_elem *dst,
dst->cidr = src->cidr;
}
static inline void
hash_net4_data_swap(struct hash_net4_elem *dst,
struct hash_net4_elem *src)
{
swap(dst->ip, src->ip);
swap(dst->cidr, src->cidr);
}
static inline void
hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr)
{
elem->ip &= NETMASK(cidr);
elem->ip &= ip_set_netmask(cidr);
elem->cidr = cidr;
}
@@ -103,7 +94,7 @@ hash_net4_data_zero_out(struct hash_net4_elem *elem)
elem->cidr = 0;
}
static inline bool
static bool
hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data)
{
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
@@ -114,7 +105,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_net4_data_tlist(struct sk_buff *skb, const struct hash_net4_elem *data)
{
const struct hash_net4_telem *tdata =
@@ -151,7 +142,7 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
data.cidr = HOST_MASK;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
data.ip &= NETMASK(data.cidr);
data.ip &= ip_set_netmask(data.cidr);
return adtfn(set, &data, h->timeout);
}
@@ -177,10 +168,14 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_net_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
@@ -190,7 +185,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (!data.cidr)
return -IPSET_ERR_INVALID_CIDR;
data.ip &= NETMASK(data.cidr);
data.ip &= ip_set_netmask(data.cidr);
if (tb[IPSET_ATTR_TIMEOUT]) {
if (!with_timeout(h->timeout))
@@ -210,8 +205,8 @@ hash_net_same_set(const struct ip_set *a, const struct ip_set *b)
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout;
}
/* The type variant functions: IPv6 */
@@ -235,8 +230,8 @@ static inline bool
hash_net6_data_equal(const struct hash_net6_elem *ip1,
const struct hash_net6_elem *ip2)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
&& ip1->cidr == ip2->cidr;
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->cidr == ip2->cidr;
}
static inline bool
@@ -253,16 +248,6 @@ hash_net6_data_copy(struct hash_net6_elem *dst,
dst->cidr = src->cidr;
}
static inline void
hash_net6_data_swap(struct hash_net6_elem *dst, struct hash_net6_elem *src)
{
struct hash_net6_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_net6_data_zero_out(struct hash_net6_elem *elem)
{
@@ -272,10 +257,10 @@ hash_net6_data_zero_out(struct hash_net6_elem *elem)
static inline void
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
{
ip->ip6[0] &= NETMASK6(prefix)[0];
ip->ip6[1] &= NETMASK6(prefix)[1];
ip->ip6[2] &= NETMASK6(prefix)[2];
ip->ip6[3] &= NETMASK6(prefix)[3];
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
}
static inline void
@@ -285,7 +270,7 @@ hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr)
elem->cidr = cidr;
}
static inline bool
static bool
hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data)
{
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
@@ -296,7 +281,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_net6_data_tlist(struct sk_buff *skb, const struct hash_net6_elem *data)
{
const struct hash_net6_telem *e =
@@ -353,10 +338,14 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_net_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
@@ -405,6 +394,11 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
hash_net_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -452,7 +446,7 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
? &hash_net4_variant : &hash_net6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);

View File

@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the hash:net,port type */
#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
@@ -46,16 +45,16 @@ hash_netport_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_netport4_elem {
u32 ip;
u16 port;
__be32 ip;
__be16 port;
u8 proto;
u8 cidr;
};
/* Member elements with timeout support */
struct hash_netport4_telem {
u32 ip;
u16 port;
__be32 ip;
__be16 port;
u8 proto;
u8 cidr;
unsigned long timeout;
@@ -65,10 +64,10 @@ static inline bool
hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
const struct hash_netport4_elem *ip2)
{
return ip1->ip == ip2->ip
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto
&& ip1->cidr == ip2->cidr;
return ip1->ip == ip2->ip &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto &&
ip1->cidr == ip2->cidr;
}
static inline bool
@@ -87,20 +86,10 @@ hash_netport4_data_copy(struct hash_netport4_elem *dst,
dst->cidr = src->cidr;
}
static inline void
hash_netport4_data_swap(struct hash_netport4_elem *dst,
struct hash_netport4_elem *src)
{
swap(dst->ip, src->ip);
swap(dst->port, src->port);
swap(dst->proto, src->proto);
swap(dst->cidr, src->cidr);
}
static inline void
hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr)
{
elem->ip &= NETMASK(cidr);
elem->ip &= ip_set_netmask(cidr);
elem->cidr = cidr;
}
@@ -110,7 +99,7 @@ hash_netport4_data_zero_out(struct hash_netport4_elem *elem)
elem->proto = 0;
}
static inline bool
static bool
hash_netport4_data_list(struct sk_buff *skb,
const struct hash_netport4_elem *data)
{
@@ -124,7 +113,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_netport4_data_tlist(struct sk_buff *skb,
const struct hash_netport4_elem *data)
{
@@ -165,12 +154,12 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
data.ip &= NETMASK(data.cidr);
data.ip &= ip_set_netmask(data.cidr);
return adtfn(set, &data, h->timeout);
}
@@ -202,10 +191,16 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_netport_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
@@ -213,10 +208,10 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len,
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
if (!data.cidr)
return -IPSET_ERR_INVALID_CIDR;
data.ip &= NETMASK(data.cidr);
data.ip &= ip_set_netmask(data.cidr);
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -244,9 +239,9 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !tb[IPSET_ATTR_PORT_TO]) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -275,22 +270,22 @@ hash_netport_same_set(const struct ip_set *a, const struct ip_set *b)
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout;
}
/* The type variant functions: IPv6 */
struct hash_netport6_elem {
union nf_inet_addr ip;
u16 port;
__be16 port;
u8 proto;
u8 cidr;
};
struct hash_netport6_telem {
union nf_inet_addr ip;
u16 port;
__be16 port;
u8 proto;
u8 cidr;
unsigned long timeout;
@@ -300,10 +295,10 @@ static inline bool
hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
const struct hash_netport6_elem *ip2)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto
&& ip1->cidr == ip2->cidr;
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto &&
ip1->cidr == ip2->cidr;
}
static inline bool
@@ -319,17 +314,6 @@ hash_netport6_data_copy(struct hash_netport6_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_netport6_data_swap(struct hash_netport6_elem *dst,
struct hash_netport6_elem *src)
{
struct hash_netport6_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_netport6_data_zero_out(struct hash_netport6_elem *elem)
{
@@ -339,10 +323,10 @@ hash_netport6_data_zero_out(struct hash_netport6_elem *elem)
static inline void
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
{
ip->ip6[0] &= NETMASK6(prefix)[0];
ip->ip6[1] &= NETMASK6(prefix)[1];
ip->ip6[2] &= NETMASK6(prefix)[2];
ip->ip6[3] &= NETMASK6(prefix)[3];
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
}
static inline void
@@ -352,7 +336,7 @@ hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr)
elem->cidr = cidr;
}
static inline bool
static bool
hash_netport6_data_list(struct sk_buff *skb,
const struct hash_netport6_elem *data)
{
@@ -366,7 +350,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_netport6_data_tlist(struct sk_buff *skb,
const struct hash_netport6_elem *data)
{
@@ -406,8 +390,8 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
@@ -432,10 +416,16 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_netport_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
@@ -446,7 +436,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len,
ip6_netmask(&data.ip, data.cidr);
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -474,9 +464,9 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !tb[IPSET_ATTR_PORT_TO]) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -525,6 +515,11 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
hash_netport_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -572,7 +567,7 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
? &hash_netport4_variant : &hash_netport6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);

View File

@@ -1,15 +0,0 @@
#ifndef _IP_SET_KERNEL_H
#define _IP_SET_KERNEL_H
#ifdef __KERNEL__
#ifdef CONFIG_DEBUG_KERNEL
/* Complete debug messages */
#define pr_fmt(fmt) "%s %s[%i]: " fmt "\n", __FILE__, __func__, __LINE__
#endif
#include <linux/kernel.h>
#endif /* __KERNEL__ */
#endif /*_IP_SET_H */

View File

@@ -7,7 +7,6 @@
/* 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>
@@ -68,8 +67,8 @@ list_set_expired(const struct list_set *map, u32 id)
static inline int
list_set_exist(const struct set_telem *elem)
{
return elem->id != IPSET_INVALID_ID
&& !ip_set_timeout_expired(elem->timeout);
return elem->id != IPSET_INVALID_ID &&
!ip_set_timeout_expired(elem->timeout);
}
/* Set list without and with timeout */
@@ -122,22 +121,22 @@ static const struct nla_policy list_set_adt_policy[IPSET_ATTR_ADT_MAX+1] = {
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
};
static inline bool
static bool
next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
{
const struct set_elem *elem;
if (i + 1 < map->size) {
elem = list_set_elem(map, i + 1);
return !!(elem->id == id
&& !(with_timeout(map->timeout)
&& list_set_expired(map, i + 1)));
return !!(elem->id == id &&
!(with_timeout(map->timeout) &&
list_set_expired(map, i + 1)));
}
return 0;
}
static inline void
static void
list_elem_add(struct list_set *map, u32 i, ip_set_id_t id)
{
struct set_elem *e;
@@ -150,7 +149,7 @@ list_elem_add(struct list_set *map, u32 i, ip_set_id_t id)
}
}
static inline void
static void
list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id,
unsigned long timeout)
{
@@ -223,20 +222,22 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
list_set_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_NAME] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
if (tb[IPSET_ATTR_NAME]) {
id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s);
if (id == IPSET_INVALID_ID)
return -IPSET_ERR_NAME;
/* "Loop detection" */
if (s->type->features & IPSET_TYPE_NAME) {
ret = -IPSET_ERR_LOOP;
goto finish;
}
} else
return -IPSET_ERR_PROTOCOL;
id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s);
if (id == IPSET_INVALID_ID)
return -IPSET_ERR_NAME;
/* "Loop detection" */
if (s->type->features & IPSET_TYPE_NAME) {
ret = -IPSET_ERR_LOOP;
goto finish;
}
if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
@@ -270,8 +271,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
case IPSET_TEST:
for (i = 0; i < map->size && !ret; i++) {
elem = list_set_elem(map, i);
if (elem->id == IPSET_INVALID_ID
|| (before != 0 && i + 1 >= map->size))
if (elem->id == IPSET_INVALID_ID ||
(before != 0 && i + 1 >= map->size))
break;
else if (with_timeout && list_set_expired(map, i))
continue;
@@ -286,8 +287,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
case IPSET_ADD:
for (i = 0; i < map->size && !ret; i++) {
elem = list_set_elem(map, i);
if (elem->id == id
&& !(with_timeout && list_set_expired(map, i)))
if (elem->id == id &&
!(with_timeout && list_set_expired(map, i)))
ret = -IPSET_ERR_EXIST;
}
if (ret == -IPSET_ERR_EXIST)
@@ -318,14 +319,14 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
break;
} else if (with_timeout && list_set_expired(map, i))
continue;
else if (elem->id == id
&& (before == 0
|| (before > 0
&& next_id_eq(map, i, refid))))
else if (elem->id == id &&
(before == 0 ||
(before > 0 &&
next_id_eq(map, i, refid))))
ret = list_set_del(map, id, i);
else if (before < 0
&& elem->id == refid
&& next_id_eq(map, i, id))
else if (before < 0 &&
elem->id == refid &&
next_id_eq(map, i, id))
ret = list_set_del(map, id, i + 1);
}
break;
@@ -449,8 +450,8 @@ list_set_same_set(const struct ip_set *a, const struct ip_set *b)
const struct list_set *x = a->data;
const struct list_set *y = b->data;
return x->size == y->size
&& x->timeout == y->timeout;
return x->size == y->size &&
x->timeout == y->timeout;
}
static const struct ip_set_type_variant list_set = {
@@ -476,8 +477,8 @@ list_set_gc(unsigned long ul_set)
read_lock_bh(&set->lock);
for (i = map->size - 1; i >= 0; i--) {
e = (struct set_telem *) list_set_elem(map, i);
if (e->id != IPSET_INVALID_ID
&& list_set_expired(map, i))
if (e->id != IPSET_INVALID_ID &&
list_set_expired(map, i))
list_set_del(map, e->id, i);
}
read_unlock_bh(&set->lock);
@@ -486,7 +487,7 @@ list_set_gc(unsigned long ul_set)
add_timer(&map->gc);
}
static inline void
static void
list_set_gc_init(struct ip_set *set)
{
struct list_set *map = set->data;
@@ -506,7 +507,7 @@ list_set_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
};
static inline bool
static bool
init_list_set(struct ip_set *set, u32 size, size_t dsize,
unsigned long timeout)
{
@@ -542,6 +543,10 @@ list_set_create(struct ip_set *set, struct nlattr *head, int len,
list_set_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_SIZE])
size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]);
if (size < IP_SET_LIST_MIN_SIZE)

View File

@@ -43,17 +43,17 @@ ip_set_timeout_uget(struct nlattr *tb)
static inline bool
ip_set_timeout_test(unsigned long timeout)
{
return timeout != IPSET_ELEM_UNSET
&& (timeout == IPSET_ELEM_PERMANENT
|| time_after(timeout, jiffies));
return timeout != IPSET_ELEM_UNSET &&
(timeout == IPSET_ELEM_PERMANENT ||
time_after(timeout, jiffies));
}
static inline bool
ip_set_timeout_expired(unsigned long timeout)
{
return timeout != IPSET_ELEM_UNSET
&& timeout != IPSET_ELEM_PERMANENT
&& time_before(timeout, jiffies);
return timeout != IPSET_ELEM_UNSET &&
timeout != IPSET_ELEM_PERMANENT &&
time_before(timeout, jiffies);
}
static inline unsigned long
@@ -88,15 +88,15 @@ ip_set_timeout_get(unsigned long timeout)
static inline bool
ip_set_timeout_test(unsigned long timeout)
{
return timeout == IPSET_ELEM_PERMANENT
|| time_after(timeout, jiffies);
return timeout == IPSET_ELEM_PERMANENT ||
time_after(timeout, jiffies);
}
static inline bool
ip_set_timeout_expired(unsigned long timeout)
{
return timeout != IPSET_ELEM_PERMANENT
&& time_before(timeout, jiffies);
return timeout != IPSET_ELEM_PERMANENT &&
time_before(timeout, jiffies);
}
static inline unsigned long

View File

@@ -14,7 +14,7 @@
* This table works for both IPv4 and IPv6;
* just use prefixlen_netmask_map[prefixlength].ip.
*/
const union nf_inet_addr prefixlen_netmask_map[] = {
const union nf_inet_addr ip_set_netmask_map[] = {
E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
@@ -145,17 +145,19 @@ const union nf_inet_addr prefixlen_netmask_map[] = {
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
};
EXPORT_SYMBOL_GPL(prefixlen_netmask_map);
EXPORT_SYMBOL_GPL(ip_set_netmask_map);
#undef E
#define E(a, b, c, d) \
{.ip6 = { a, b, c, d } }
#define E(a, b, c, d) \
{.ip6 = { (__force __be32) a, (__force __be32) b, \
(__force __be32) c, (__force __be32) d, \
} }
/*
* This table works for both IPv4 and IPv6;
* just use prefixlen_hostmask_map[prefixlength].ip.
*/
const union nf_inet_addr prefixlen_hostmask_map[] = {
const union nf_inet_addr ip_set_hostmask_map[] = {
E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
@@ -286,4 +288,4 @@ const union nf_inet_addr prefixlen_hostmask_map[] = {
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
};
EXPORT_SYMBOL_GPL(prefixlen_hostmask_map);
EXPORT_SYMBOL_GPL(ip_set_hostmask_map);

View File

@@ -5,12 +5,31 @@
#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 */

View File

@@ -108,12 +108,12 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par)
index = ip_set_nfnl_get_byindex(info->match_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("Cannot find set indentified by id %u to match",
pr_warning("Cannot find set indentified by id %u to match\n",
info->match_set.index);
return CHECK_FAIL; /* error */
}
if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
pr_warning("That's nasty!");
pr_warning("That's nasty!\n");
return CHECK_FAIL; /* error */
}
@@ -167,7 +167,7 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
if (info->add_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(info->add_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find add_set index %u as target",
pr_warning("cannot find add_set index %u as target\n",
info->add_set.index);
return CHECK_FAIL; /* error */
}
@@ -176,14 +176,14 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
if (info->del_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(info->del_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find del_set index %u as target",
pr_warning("cannot find del_set index %u as target\n",
info->del_set.index);
return CHECK_FAIL; /* error */
}
}
if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0
|| info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
pr_warning("That's nasty!");
if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0 ||
info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
pr_warning("That's nasty!\n");
return CHECK_FAIL; /* error */
}
@@ -237,12 +237,12 @@ set_match_checkentry(const struct xt_mtchk_param *par)
index = ip_set_nfnl_get_byindex(info->match_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("Cannot find set indentified by id %u to match",
pr_warning("Cannot find set indentified by id %u to match\n",
info->match_set.index);
return CHECK_FAIL; /* error */
}
if (info->match_set.dim > IPSET_DIM_MAX) {
pr_warning("That's nasty!");
pr_warning("That's nasty!\n");
return CHECK_FAIL; /* error */
}
@@ -295,7 +295,7 @@ set_target_checkentry(const struct xt_tgchk_param *par)
if (info->add_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(info->add_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find add_set index %u as target",
pr_warning("cannot find add_set index %u as target\n",
info->add_set.index);
return CHECK_FAIL; /* error */
}
@@ -304,14 +304,14 @@ set_target_checkentry(const struct xt_tgchk_param *par)
if (info->del_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(info->del_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find del_set index %u as target",
pr_warning("cannot find del_set index %u as target\n",
info->del_set.index);
return CHECK_FAIL; /* error */
}
}
if (info->add_set.dim > IPSET_DIM_MAX
|| info->del_set.flags > IPSET_DIM_MAX) {
pr_warning("That's nasty!");
if (info->add_set.dim > IPSET_DIM_MAX ||
info->del_set.flags > IPSET_DIM_MAX) {
pr_warning("That's nasty!\n");
return CHECK_FAIL; /* error */
}