mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-07 05:05:12 +02:00
ipset: update to 6.0
This commit is contained in:
@@ -1,6 +1,20 @@
|
||||
|
||||
HEAD
|
||||
====
|
||||
Enhancements:
|
||||
- update to ipset 6.0
|
||||
* allow "new" as a commad alias to "create"
|
||||
* ipset: improve command argument parsing
|
||||
* ipset: avoid the unnecessary argv[] loop
|
||||
* ipset: pass ipset_arg argument pointer
|
||||
* separate ipset errnos completely from system ones and bump protocol version
|
||||
* resolving IP addresses did not work at listing/saving sets, fixed
|
||||
* ipset: fix spelling error
|
||||
* ipset: fix the Netlink sequence number
|
||||
* ipset: turn Set name[] into a const pointer
|
||||
* check ICMP and ICMPv6 with the set match and target in the testsuite
|
||||
* avoid possible syntax clashing at saving hostnames
|
||||
* fix linking with CONFIG_IPV6=n
|
||||
|
||||
|
||||
v1.33 (2011-02-02)
|
||||
|
88
extensions/ipset-6/README
Normal file
88
extensions/ipset-6/README
Normal file
@@ -0,0 +1,88 @@
|
||||
This is the ipset source tree. Follow the next steps to install ipset.
|
||||
If you upgrade from an earlier 5.x release, please read the UPGRADE
|
||||
instructions too.
|
||||
|
||||
0. You need the source tree of your kernel (version >= 2.6.34)
|
||||
and it have to be configured with ip6tables support enabled,
|
||||
modules compiled. Please apply the netlink.patch against your kernel
|
||||
tree, which adds the new subsystem identifier for ipset.
|
||||
|
||||
Recompile and install the patched kernel and its modules. Please note,
|
||||
you have to run the patched kernel for ipset to work.
|
||||
|
||||
The ipset source code depends on the libmnl library so the library
|
||||
must be installed. You can download the libmnl library from
|
||||
|
||||
git://git.netfilter.org/libmnl.git
|
||||
|
||||
1. Initialize the compiling environment for ipset. The packages automake,
|
||||
autoconf and libtool are required.
|
||||
|
||||
% ./autogen.sh
|
||||
|
||||
2. Run `./configure` and then compile the ipset binary and the kernel
|
||||
modules.
|
||||
|
||||
Configure parameters can be used to to override the default path
|
||||
to the kernel source tree (/lib/modules/`uname -r`/build),
|
||||
the maximum number of sets (256), the default hash sizes (1024).
|
||||
See `./configure --help`.
|
||||
|
||||
% ./configure
|
||||
% make
|
||||
% make modules
|
||||
|
||||
3. Install the binary and the kernel modules
|
||||
|
||||
# make install
|
||||
# make modules_install
|
||||
|
||||
After installing the modules, you can run the testsuite as well.
|
||||
Please note, several assumptions must be met for the testsuite:
|
||||
|
||||
- no sets defined
|
||||
- iptables/ip6tables rules are not set up
|
||||
- the destination for kernel logs is /var/log/kern.log
|
||||
- the networks 10.255.255.0/24 and 1002:1002:1002:1002::/64
|
||||
are not in use
|
||||
- sendip utility is installed
|
||||
|
||||
# make tests
|
||||
|
||||
4. Cleanup the source tree
|
||||
|
||||
% make clean
|
||||
% make modules_clean
|
||||
|
||||
That's it!
|
||||
|
||||
Read the ipset(8) and iptables(8), ip6tables(8) manpages on how to use
|
||||
ipset and its match and target from iptables.
|
||||
|
||||
Compatibilities and incompatibilities:
|
||||
|
||||
- The ipset 6.x userspace utility contains a backward compatibility
|
||||
interface to support the commandline syntax of ipset 4.x.
|
||||
The commandline syntax of ipset 6.x is fully compatible with 5.x.
|
||||
- The ipset 6.x userspace utility can't talk to the kernel part of ipset 5.x
|
||||
or 4.x.
|
||||
- The ipset 6.x kernel part can't talk to the userspace utility from
|
||||
ipset 5.x or 4.x.
|
||||
- The ipset 6.x kernel part can work together with the set match and SET
|
||||
target from iptables 1.4.7 and below, however if you need the IPv6 support
|
||||
from ipset 6.x, then you have to use iptables 1.4.8 or above.
|
||||
|
||||
The ipset 6.x can interpret the commandline syntax of ipset 4.x, however
|
||||
some internal changes mean different behaviour:
|
||||
|
||||
- The "--matchunset" flag for the macipmap type is ignored and not used
|
||||
anymore.
|
||||
- The "--probes" and "--resize" parameters of the hash types are ignored
|
||||
and not used anymore.
|
||||
- The "--from", "--to" and "--network" parameters of the ipporthash,
|
||||
ipportiphash and ipportnethash types are ignored and not used anymore.
|
||||
- The hash types are not resized when new entries are added by the SET
|
||||
target. If you use a set together with the SET target, create it with
|
||||
the proper size because it won't be resized automatically.
|
||||
- The iptree, iptreemap types are not implemented in ipset 6.x. The types
|
||||
are automatically substituted with the hash:ip type.
|
@@ -4,7 +4,7 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
* 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
|
||||
@@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
/* The protocol version */
|
||||
#define IPSET_PROTOCOL 5
|
||||
#define IPSET_PROTOCOL 60
|
||||
|
||||
/* The max length of strings including NUL: set and type identifiers */
|
||||
#define IPSET_MAXNAMELEN 32
|
||||
@@ -118,7 +118,7 @@ enum {
|
||||
|
||||
/* Error codes */
|
||||
enum ipset_errno {
|
||||
IPSET_ERR_PRIVATE = 128,
|
||||
IPSET_ERR_PRIVATE = 4096,
|
||||
IPSET_ERR_PROTOCOL,
|
||||
IPSET_ERR_FIND_TYPE,
|
||||
IPSET_ERR_MAX_SETS,
|
||||
@@ -135,7 +135,7 @@ enum ipset_errno {
|
||||
IPSET_ERR_IPADDR_IPV6,
|
||||
|
||||
/* Type specific error codes */
|
||||
IPSET_ERR_TYPE_SPECIFIC = 160,
|
||||
IPSET_ERR_TYPE_SPECIFIC = 4352,
|
||||
};
|
||||
|
||||
/* Flags at command level */
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#define IPSET_PROTO_SEPARATOR ":"
|
||||
|
||||
struct ipset_session;
|
||||
struct ipset_arg;
|
||||
|
||||
typedef int (*ipset_parsefn)(struct ipset_session *s,
|
||||
enum ipset_opt opt, const char *str);
|
||||
@@ -84,8 +85,8 @@ extern int ipset_parse_ignored(struct ipset_session *session,
|
||||
extern int ipset_parse_elem(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_call_parser(struct ipset_session *session,
|
||||
ipset_parsefn parse, const char *optstr,
|
||||
enum ipset_opt optional, const char *str);
|
||||
const struct ipset_arg *arg,
|
||||
const char *str);
|
||||
|
||||
/* Compatibility parser functions */
|
||||
extern int ipset_parse_iptimeout(struct ipset_session *session,
|
||||
|
@@ -70,7 +70,7 @@ struct ipset_elem {
|
||||
* but for the readability the full list is supported.
|
||||
*/
|
||||
struct ipset_type {
|
||||
char name[IPSET_MAXNAMELEN]; /* type name */
|
||||
const char *name;
|
||||
uint8_t revision; /* revision number */
|
||||
uint8_t family; /* supported family */
|
||||
uint8_t dimension; /* elem dimension */
|
||||
|
@@ -14,7 +14,7 @@
|
||||
#include <linux/netlink.h>
|
||||
|
||||
/* The protocol version */
|
||||
#define IPSET_PROTOCOL 5
|
||||
#define IPSET_PROTOCOL 60
|
||||
|
||||
/* The max length of strings including NUL: set and type identifiers */
|
||||
#define IPSET_MAXNAMELEN 32
|
||||
@@ -120,7 +120,7 @@ enum {
|
||||
|
||||
/* Error codes */
|
||||
enum ipset_errno {
|
||||
IPSET_ERR_PRIVATE = 128,
|
||||
IPSET_ERR_PRIVATE = 4096,
|
||||
IPSET_ERR_PROTOCOL,
|
||||
IPSET_ERR_FIND_TYPE,
|
||||
IPSET_ERR_MAX_SETS,
|
||||
@@ -137,7 +137,7 @@ enum ipset_errno {
|
||||
IPSET_ERR_IPADDR_IPV6,
|
||||
|
||||
/* Type specific error codes */
|
||||
IPSET_ERR_TYPE_SPECIFIC = 160,
|
||||
IPSET_ERR_TYPE_SPECIFIC = 4352,
|
||||
};
|
||||
|
||||
/* Flags at command level */
|
||||
@@ -231,7 +231,7 @@ struct ip_set_type_variant {
|
||||
* returns negative error code,
|
||||
* zero for no match/success to add/delete
|
||||
* positive for matching element */
|
||||
int (*uadt)(struct ip_set *set, struct nlattr *head, int len,
|
||||
int (*uadt)(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags);
|
||||
|
||||
/* Low level add/del/test functions */
|
||||
@@ -274,8 +274,11 @@ struct ip_set_type {
|
||||
u8 revision;
|
||||
|
||||
/* Create set */
|
||||
int (*create)(struct ip_set *set,
|
||||
struct nlattr *head, int len, u32 flags);
|
||||
int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags);
|
||||
|
||||
/* Attribute policies */
|
||||
const struct nla_policy create_policy[IPSET_ATTR_CREATE_MAX + 1];
|
||||
const struct nla_policy adt_policy[IPSET_ATTR_ADT_MAX + 1];
|
||||
|
||||
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
|
||||
struct module *me;
|
||||
@@ -320,7 +323,7 @@ extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
|
||||
u8 family, u8 dim, u8 flags);
|
||||
|
||||
/* Utility functions */
|
||||
extern void * ip_set_alloc(size_t size, gfp_t gfp_mask);
|
||||
extern void * ip_set_alloc(size_t size);
|
||||
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);
|
||||
|
@@ -311,8 +311,7 @@ retry:
|
||||
/* In case we have plenty of memory :-) */
|
||||
return -IPSET_ERR_HASH_FULL;
|
||||
t = ip_set_alloc(sizeof(*t)
|
||||
+ jhash_size(htable_bits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
+ jhash_size(htable_bits) * sizeof(struct hbucket));
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
t->htable_bits = htable_bits;
|
||||
@@ -525,7 +524,7 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb)
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/* Reply a LIST/SAVE request: dump the elements of the specified set */
|
||||
@@ -545,7 +544,7 @@ type_pf_list(const struct ip_set *set,
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
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);
|
||||
@@ -559,7 +558,7 @@ type_pf_list(const struct ip_set *set,
|
||||
if (!nested) {
|
||||
if (cb->args[2] == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
@@ -581,6 +580,7 @@ nla_put_failure:
|
||||
pr_warning("Can't list set %s: one bucket does not fit into "
|
||||
"a message. Please report it!\n", set->name);
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -589,7 +589,7 @@ static int
|
||||
type_pf_kadt(struct ip_set *set, const struct sk_buff * skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
|
||||
static int
|
||||
type_pf_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
type_pf_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags);
|
||||
|
||||
static const struct ip_set_type_variant type_pf_variant = {
|
||||
@@ -742,8 +742,7 @@ retry:
|
||||
/* In case we have plenty of memory :-) */
|
||||
return -IPSET_ERR_HASH_FULL;
|
||||
t = ip_set_alloc(sizeof(*t)
|
||||
+ jhash_size(htable_bits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
+ jhash_size(htable_bits) * sizeof(struct hbucket));
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
t->htable_bits = htable_bits;
|
||||
@@ -946,7 +945,7 @@ type_pf_tlist(const struct ip_set *set,
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) {
|
||||
incomplete = skb_tail_pointer(skb);
|
||||
n = hbucket(t, cb->args[2]);
|
||||
@@ -960,7 +959,7 @@ type_pf_tlist(const struct ip_set *set,
|
||||
if (!nested) {
|
||||
if (cb->args[2] == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
@@ -982,6 +981,7 @@ nla_put_failure:
|
||||
pr_warning("Can't list set %s: one bucket does not fit into "
|
||||
"a message. Please report it!\n", set->name);
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@@ -13,7 +13,6 @@
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/netlink.h>
|
||||
@@ -33,8 +32,7 @@ MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:ip type of IP sets");
|
||||
MODULE_ALIAS("ip_set_bitmap:ip");
|
||||
|
||||
/* Base variant */
|
||||
|
||||
/* Type structure */
|
||||
struct bitmap_ip {
|
||||
void *members; /* the set members */
|
||||
u32 first_ip; /* host byte order, included in range */
|
||||
@@ -43,43 +41,188 @@ struct bitmap_ip {
|
||||
u32 hosts; /* number of hosts in a subnet */
|
||||
size_t memsize; /* members size */
|
||||
u8 netmask; /* subnet netmask */
|
||||
u32 timeout; /* timeout parameter */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
};
|
||||
|
||||
/* Base variant */
|
||||
|
||||
static inline u32
|
||||
ip_to_id(const struct bitmap_ip *m, u32 ip)
|
||||
{
|
||||
return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_test(const struct bitmap_ip *map, u32 id)
|
||||
static int
|
||||
bitmap_ip_test(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
return !!test_bit(id, map->members);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_add(struct bitmap_ip *map, u32 id)
|
||||
static int
|
||||
bitmap_ip_add(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (test_and_set_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_del(struct bitmap_ip *map, u32 id)
|
||||
static int
|
||||
bitmap_ip_del(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (!test_and_clear_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] < map->elements; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!test_bit(id, map->members))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id * map->hosts));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
if (unlikely(id == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
static int
|
||||
bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
const unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
return ip_set_timeout_test(members[id]);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (ip_set_timeout_test(members[id]))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
members[id] = ip_set_timeout_set(timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
int ret = -IPSET_ERR_EXIST;
|
||||
|
||||
if (ip_set_timeout_test(members[id]))
|
||||
ret = 0;
|
||||
|
||||
members[id] = IPSET_ELEM_UNSET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_tlist(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
struct nlattr *adt, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
const unsigned long *members = map->members;
|
||||
|
||||
adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!adt)
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] < map->elements; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!ip_set_timeout_test(members[id]))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, adt);
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id * map->hosts));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(members[id])));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, adt);
|
||||
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, adt);
|
||||
if (unlikely(id == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
u32 ip;
|
||||
|
||||
ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
|
||||
@@ -88,40 +231,21 @@ bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
|
||||
ip = ip_to_id(map, ip);
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_ip_test(map, ip);
|
||||
case IPSET_ADD:
|
||||
return bitmap_ip_add(map, ip);
|
||||
case IPSET_DEL:
|
||||
return bitmap_ip_del(map, ip);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return adtfn(set, &ip, map->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy bitmap_ip_adt_policy[IPSET_ATTR_ADT_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 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
u32 timeout = map->timeout;
|
||||
u32 ip, ip_to, id;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
bitmap_ip_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP]))
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
@@ -134,13 +258,16 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
/* Set was defined without timeout support:
|
||||
* don't ignore the attribute silently */
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(map->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_ip_test(map, ip_to_id(map, ip));
|
||||
if (adt == IPSET_TEST) {
|
||||
id = ip_to_id(map, ip);
|
||||
return adtfn(set, &id, timeout);
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
@@ -166,8 +293,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
|
||||
for (; !before(ip_to, ip); ip += map->hosts) {
|
||||
id = ip_to_id(map, ip);
|
||||
ret = adt == IPSET_ADD ? bitmap_ip_add(map, id)
|
||||
: bitmap_ip_del(map, id);
|
||||
ret = adtfn(set, &id, timeout);;
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -182,6 +308,9 @@ bitmap_ip_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
|
||||
if (with_timeout(map->timeout))
|
||||
del_timer_sync(&map->gc);
|
||||
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
@@ -213,49 +342,13 @@ bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
if (with_timeout(map->timeout))
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] < map->elements; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!bitmap_ip_test(map, id))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id * map->hosts));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -266,12 +359,18 @@ bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
|
||||
return x->first_ip == y->first_ip &&
|
||||
x->last_ip == y->last_ip &&
|
||||
x->netmask == y->netmask;
|
||||
x->netmask == y->netmask &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_ip = {
|
||||
.kadt = bitmap_ip_kadt,
|
||||
.uadt = bitmap_ip_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_ip_add,
|
||||
[IPSET_DEL] = bitmap_ip_del,
|
||||
[IPSET_TEST] = bitmap_ip_test,
|
||||
},
|
||||
.destroy = bitmap_ip_destroy,
|
||||
.flush = bitmap_ip_flush,
|
||||
.head = bitmap_ip_head,
|
||||
@@ -279,261 +378,26 @@ static const struct ip_set_type_variant bitmap_ip = {
|
||||
.same_set = bitmap_ip_same_set,
|
||||
};
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
struct bitmap_ip_timeout {
|
||||
unsigned long *members; /* the set members */
|
||||
u32 first_ip; /* host byte order, included in range */
|
||||
u32 last_ip; /* host byte order, included in range */
|
||||
u32 elements; /* number of max elements in the set */
|
||||
u32 hosts; /* number of hosts in a subnet */
|
||||
size_t memsize; /* members size */
|
||||
u8 netmask; /* subnet netmask */
|
||||
|
||||
u32 timeout; /* timeout parameter */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
};
|
||||
|
||||
static inline bool
|
||||
bitmap_ip_timeout_test(const struct bitmap_ip_timeout *map, u32 id)
|
||||
{
|
||||
return ip_set_timeout_test(map->members[id]);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_timeout_add(struct bitmap_ip_timeout *map,
|
||||
u32 id, u32 timeout)
|
||||
{
|
||||
if (bitmap_ip_timeout_test(map, id))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
map->members[id] = ip_set_timeout_set(timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_timeout_del(struct bitmap_ip_timeout *map, u32 id)
|
||||
{
|
||||
int ret = -IPSET_ERR_EXIST;
|
||||
|
||||
if (bitmap_ip_timeout_test(map, id))
|
||||
ret = 0;
|
||||
|
||||
map->members[id] = IPSET_ELEM_UNSET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
u32 ip;
|
||||
|
||||
ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
ip = ip_to_id((const struct bitmap_ip *)map, ip);
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_ip_timeout_test(map, ip);
|
||||
case IPSET_ADD:
|
||||
return bitmap_ip_timeout_add(map, ip, map->timeout);
|
||||
case IPSET_DEL:
|
||||
return bitmap_ip_timeout_del(map, ip);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
u32 ip, ip_to, id, timeout = map->timeout;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_ip_timeout_test(map,
|
||||
ip_to_id((const struct bitmap_ip *)map, ip));
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip > ip_to) {
|
||||
swap(ip, ip_to);
|
||||
if (ip < map->first_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip &= ip_set_hostmask(cidr);
|
||||
ip_to = ip | ~ip_set_hostmask(cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
if (ip_to > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
for (; !before(ip_to, ip); ip += map->hosts) {
|
||||
id = ip_to_id((const struct bitmap_ip *)map, ip);
|
||||
ret = adt == IPSET_ADD
|
||||
? bitmap_ip_timeout_add(map, id, timeout)
|
||||
: bitmap_ip_timeout_del(map, id);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_timeout_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
|
||||
del_timer_sync(&map->gc);
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_timeout_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
|
||||
memset(map->members, IPSET_ELEM_UNSET, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_ip_timeout *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
|
||||
if (map->netmask != 32)
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ip_timeout *map = set->data;
|
||||
struct nlattr *adt, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
const unsigned long *table = map->members;
|
||||
|
||||
adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!adt)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] < map->elements; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!bitmap_ip_timeout_test(map, id))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, adt);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id * map->hosts));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(table[id])));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, adt);
|
||||
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, adt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
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;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_ip_timeout = {
|
||||
.kadt = bitmap_ip_timeout_kadt,
|
||||
.uadt = bitmap_ip_timeout_uadt,
|
||||
.destroy = bitmap_ip_timeout_destroy,
|
||||
.flush = bitmap_ip_timeout_flush,
|
||||
.head = bitmap_ip_timeout_head,
|
||||
.list = bitmap_ip_timeout_list,
|
||||
.same_set = bitmap_ip_timeout_same_set,
|
||||
static const struct ip_set_type_variant bitmap_tip = {
|
||||
.kadt = bitmap_ip_kadt,
|
||||
.uadt = bitmap_ip_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_ip_tadd,
|
||||
[IPSET_DEL] = bitmap_ip_tdel,
|
||||
[IPSET_TEST] = bitmap_ip_ttest,
|
||||
},
|
||||
.destroy = bitmap_ip_destroy,
|
||||
.flush = bitmap_ip_flush,
|
||||
.head = bitmap_ip_head,
|
||||
.list = bitmap_ip_tlist,
|
||||
.same_set = bitmap_ip_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
bitmap_ip_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
struct bitmap_ip *map = set->data;
|
||||
unsigned long *table = map->members;
|
||||
u32 id;
|
||||
|
||||
@@ -552,7 +416,7 @@ bitmap_ip_gc(unsigned long ul_set)
|
||||
static void
|
||||
bitmap_ip_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
struct bitmap_ip *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
@@ -563,21 +427,12 @@ bitmap_ip_gc_init(struct ip_set *set)
|
||||
|
||||
/* Create bitmap:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
bitmap_ip_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_NETMASK] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static bool
|
||||
init_map_ip(struct ip_set *set, struct bitmap_ip *map,
|
||||
u32 first_ip, u32 last_ip,
|
||||
u32 elements, u32 hosts, u8 netmask)
|
||||
{
|
||||
map->members = ip_set_alloc(map->memsize, GFP_KERNEL);
|
||||
map->members = ip_set_alloc(map->memsize);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_ip = first_ip;
|
||||
@@ -585,6 +440,7 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map,
|
||||
map->elements = elements;
|
||||
map->hosts = hosts;
|
||||
map->netmask = netmask;
|
||||
map->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
set->data = map;
|
||||
set->family = AF_INET;
|
||||
@@ -593,18 +449,13 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map,
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
u32 flags)
|
||||
bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
struct bitmap_ip *map;
|
||||
u32 first_ip, last_ip, hosts, elements;
|
||||
u8 netmask = 32;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
bitmap_ip_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
@@ -664,37 +515,27 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
|
||||
pr_debug("hosts %u, elements %u\n", hosts, elements);
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
struct bitmap_ip_timeout *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = elements * sizeof(unsigned long);
|
||||
|
||||
if (!init_map_ip(set, (struct bitmap_ip *)map,
|
||||
first_ip, last_ip,
|
||||
if (!init_map_ip(set, map, first_ip, last_ip,
|
||||
elements, hosts, netmask)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
set->variant = &bitmap_ip_timeout;
|
||||
set->variant = &bitmap_tip;
|
||||
|
||||
bitmap_ip_gc_init(set);
|
||||
} else {
|
||||
struct bitmap_ip *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = bitmap_bytes(0, elements - 1);
|
||||
|
||||
if (!init_map_ip(set, map,
|
||||
first_ip, last_ip,
|
||||
if (!init_map_ip(set, map, first_ip, last_ip,
|
||||
elements, hosts, netmask)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
@@ -713,6 +554,20 @@ static struct ip_set_type bitmap_ip_type __read_mostly = {
|
||||
.family = AF_INET,
|
||||
.revision = 0,
|
||||
.create = bitmap_ip_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[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 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@@ -15,9 +15,6 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
@@ -175,7 +172,7 @@ bitmap_ipmac_list(const struct ip_set *set,
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
elem = bitmap_ipmac_elem(map, id);
|
||||
@@ -185,7 +182,7 @@ bitmap_ipmac_list(const struct ip_set *set,
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
@@ -205,6 +202,10 @@ bitmap_ipmac_list(const struct ip_set *set,
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
if (unlikely(id == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -298,7 +299,7 @@ bitmap_ipmac_tlist(const struct ip_set *set,
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
elem = bitmap_ipmac_elem(map, id);
|
||||
@@ -308,7 +309,7 @@ bitmap_ipmac_tlist(const struct ip_set *set,
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
@@ -331,7 +332,7 @@ bitmap_ipmac_tlist(const struct ip_set *set,
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -357,29 +358,16 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
return adtfn(set, &data, map->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
bitmap_ipmac_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_ETHER] = { .type = NLA_BINARY, .len = ETH_ALEN },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct ipmac data;
|
||||
u32 timeout = map->timeout;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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;
|
||||
@@ -457,7 +445,7 @@ bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -538,20 +526,11 @@ bitmap_ipmac_gc_init(struct ip_set *set)
|
||||
|
||||
/* Create bitmap:ip,mac type of sets */
|
||||
|
||||
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 },
|
||||
};
|
||||
|
||||
static bool
|
||||
init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
|
||||
u32 first_ip, u32 last_ip)
|
||||
{
|
||||
map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize,
|
||||
GFP_KERNEL);
|
||||
map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_ip = first_ip;
|
||||
@@ -565,18 +544,13 @@ init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
|
||||
u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u32 first_ip, last_ip, elements;
|
||||
struct bitmap_ipmac *map;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
bitmap_ipmac_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
@@ -647,6 +621,18 @@ static struct ip_set_type bitmap_ipmac_type = {
|
||||
.family = AF_INET,
|
||||
.revision = 0,
|
||||
.create = bitmap_ipmac_create,
|
||||
.create_policy = {
|
||||
[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 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_ETHER] = { .type = NLA_BINARY, .len = ETH_ALEN },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@@ -9,13 +9,8 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
@@ -32,24 +27,33 @@ MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:port type of IP sets");
|
||||
MODULE_ALIAS("ip_set_bitmap:port");
|
||||
|
||||
/* Base variant */
|
||||
|
||||
/* Type structure */
|
||||
struct bitmap_port {
|
||||
void *members; /* the set members */
|
||||
u16 first_port; /* host byte order, included in range */
|
||||
u16 last_port; /* host byte order, included in range */
|
||||
size_t memsize; /* members size */
|
||||
u32 timeout; /* timeout parameter */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
};
|
||||
|
||||
static inline int
|
||||
bitmap_port_test(const struct bitmap_port *map, u16 id)
|
||||
/* Base variant */
|
||||
|
||||
static int
|
||||
bitmap_port_test(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
return !!test_bit(id, map->members);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_port_add(struct bitmap_port *map, u16 id)
|
||||
static int
|
||||
bitmap_port_add(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (test_and_set_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
@@ -57,19 +61,157 @@ bitmap_port_add(struct bitmap_port *map, u16 id)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_del(struct bitmap_port *map, u16 id)
|
||||
bitmap_port_del(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (!test_and_clear_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u16 id, first = cb->args[2];
|
||||
u16 last = map->last_port - map->first_port;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!test_bit(id, map->members))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
|
||||
htons(map->first_port + id));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
if (unlikely(id == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
static int
|
||||
bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
const unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
return ip_set_timeout_test(members[id]);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (ip_set_timeout_test(members[id]))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
members[id] = ip_set_timeout_set(timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
int ret = -IPSET_ERR_EXIST;
|
||||
|
||||
if (ip_set_timeout_test(members[id]))
|
||||
ret = 0;
|
||||
|
||||
members[id] = IPSET_ELEM_UNSET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_tlist(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
struct nlattr *adt, *nested;
|
||||
u16 id, first = cb->args[2];
|
||||
u16 last = map->last_port - map->first_port;
|
||||
const unsigned long *members = map->members;
|
||||
|
||||
adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!adt)
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!ip_set_timeout_test(members[id]))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, adt);
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
|
||||
htons(map->first_port + id));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(members[id])));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, adt);
|
||||
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, adt);
|
||||
if (unlikely(id == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
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;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
__be16 __port;
|
||||
u16 port = 0;
|
||||
|
||||
@@ -83,41 +225,23 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
|
||||
port -= map->first_port;
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_port_test(map, port);
|
||||
case IPSET_ADD:
|
||||
return bitmap_port_add(map, port);
|
||||
case IPSET_DEL:
|
||||
return bitmap_port_del(map, port);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return adtfn(set, &port, map->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy bitmap_port_adt_policy[IPSET_ATTR_ADT_MAX+1] = {
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
u32 timeout = map->timeout;
|
||||
u32 port; /* wraparound */
|
||||
u16 id, port_to;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
@@ -127,11 +251,16 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(map->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_port_test(map, port - map->first_port);
|
||||
if (adt == IPSET_TEST) {
|
||||
id = port - map->first_port;
|
||||
return adtfn(set, &id, timeout);
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
@@ -148,8 +277,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
id = port - map->first_port;
|
||||
ret = adt == IPSET_ADD ? bitmap_port_add(map, id)
|
||||
: bitmap_port_del(map, id);
|
||||
ret = adtfn(set, &id, timeout);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -164,6 +292,9 @@ bitmap_port_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
|
||||
if (with_timeout(map->timeout))
|
||||
del_timer_sync(&map->gc);
|
||||
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
@@ -193,51 +324,13 @@ bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
if (with_timeout(map->timeout))
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u16 id, first = cb->args[2];
|
||||
u16 last = map->last_port - map->first_port;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!test_bit(id, map->members))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
|
||||
htons(map->first_port + id));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -247,12 +340,18 @@ bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
const struct bitmap_port *y = b->data;
|
||||
|
||||
return x->first_port == y->first_port &&
|
||||
x->last_port == y->last_port;
|
||||
x->last_port == y->last_port &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_port = {
|
||||
.kadt = bitmap_port_kadt,
|
||||
.uadt = bitmap_port_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_port_add,
|
||||
[IPSET_DEL] = bitmap_port_del,
|
||||
[IPSET_TEST] = bitmap_port_test,
|
||||
},
|
||||
.destroy = bitmap_port_destroy,
|
||||
.flush = bitmap_port_flush,
|
||||
.head = bitmap_port_head,
|
||||
@@ -260,251 +359,26 @@ static const struct ip_set_type_variant bitmap_port = {
|
||||
.same_set = bitmap_port_same_set,
|
||||
};
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
struct bitmap_port_timeout {
|
||||
unsigned long *members; /* the set members */
|
||||
u16 first_port; /* host byte order, included in range */
|
||||
u16 last_port; /* host byte order, included in range */
|
||||
size_t memsize; /* members size */
|
||||
|
||||
u32 timeout; /* timeout parameter */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
};
|
||||
|
||||
static inline bool
|
||||
bitmap_port_timeout_test(const struct bitmap_port_timeout *map, u16 id)
|
||||
{
|
||||
return ip_set_timeout_test(map->members[id]);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_add(const struct bitmap_port_timeout *map,
|
||||
u16 id, u32 timeout)
|
||||
{
|
||||
if (bitmap_port_timeout_test(map, id))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
map->members[id] = ip_set_timeout_set(timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_del(const struct bitmap_port_timeout *map,
|
||||
u16 id)
|
||||
{
|
||||
int ret = -IPSET_ERR_EXIST;
|
||||
|
||||
if (bitmap_port_timeout_test(map, id))
|
||||
ret = 0;
|
||||
|
||||
map->members[id] = IPSET_ELEM_UNSET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
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 (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
|
||||
return -EINVAL;
|
||||
|
||||
port = ntohs(__port);
|
||||
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
port -= map->first_port;
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_port_timeout_test(map, port);
|
||||
case IPSET_ADD:
|
||||
return bitmap_port_timeout_add(map, port, map->timeout);
|
||||
case IPSET_DEL:
|
||||
return bitmap_port_timeout_del(map, port);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct bitmap_port_timeout *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
u16 id, port_to;
|
||||
u32 port, timeout = map->timeout; /* wraparound */
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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]);
|
||||
|
||||
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_port_timeout_test(map, port - map->first_port);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to) {
|
||||
swap(port, port_to);
|
||||
if (port < map->first_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else
|
||||
port_to = port;
|
||||
|
||||
if (port_to > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
id = port - map->first_port;
|
||||
ret = adt == IPSET_ADD
|
||||
? bitmap_port_timeout_add(map, id, timeout)
|
||||
: bitmap_port_timeout_del(map, id);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_timeout_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
|
||||
del_timer_sync(&map->gc);
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_timeout_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
|
||||
memset(map->members, 0, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_port_timeout *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port));
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT , htonl(map->timeout));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_port_timeout *map = set->data;
|
||||
struct nlattr *adt, *nested;
|
||||
u16 id, first = cb->args[2];
|
||||
u16 last = map->last_port - map->first_port;
|
||||
const unsigned long *table = map->members;
|
||||
|
||||
adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!adt)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!bitmap_port_timeout_test(map, id))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, adt);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
|
||||
htons(map->first_port + id));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(table[id])));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, adt);
|
||||
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, adt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
.flush = bitmap_port_timeout_flush,
|
||||
.head = bitmap_port_timeout_head,
|
||||
.list = bitmap_port_timeout_list,
|
||||
.same_set = bitmap_port_timeout_same_set,
|
||||
static const struct ip_set_type_variant bitmap_tport = {
|
||||
.kadt = bitmap_port_kadt,
|
||||
.uadt = bitmap_port_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_port_tadd,
|
||||
[IPSET_DEL] = bitmap_port_tdel,
|
||||
[IPSET_TEST] = bitmap_port_ttest,
|
||||
},
|
||||
.destroy = bitmap_port_destroy,
|
||||
.flush = bitmap_port_flush,
|
||||
.head = bitmap_port_head,
|
||||
.list = bitmap_port_tlist,
|
||||
.same_set = bitmap_port_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
bitmap_port_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
struct bitmap_port *map = set->data;
|
||||
unsigned long *table = map->members;
|
||||
u32 id; /* wraparound */
|
||||
u16 last = map->last_port - map->first_port;
|
||||
@@ -524,7 +398,7 @@ bitmap_port_gc(unsigned long ul_set)
|
||||
static void
|
||||
bitmap_port_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
struct bitmap_port *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
@@ -535,22 +409,16 @@ bitmap_port_gc_init(struct ip_set *set)
|
||||
|
||||
/* Create bitmap:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
bitmap_port_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static bool
|
||||
init_map_port(struct ip_set *set, struct bitmap_port *map,
|
||||
u16 first_port, u16 last_port)
|
||||
{
|
||||
map->members = ip_set_alloc(map->memsize, GFP_KERNEL);
|
||||
map->members = ip_set_alloc(map->memsize);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_port = first_port;
|
||||
map->last_port = last_port;
|
||||
map->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
set->data = map;
|
||||
set->family = AF_UNSPEC;
|
||||
@@ -559,16 +427,12 @@ init_map_port(struct ip_set *set, struct bitmap_port *map,
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
bitmap_port_create(struct ip_set *set, struct nlattr *tb[],
|
||||
u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
struct bitmap_port *map;
|
||||
u16 first_port, last_port;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
bitmap_port_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
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)))
|
||||
@@ -583,33 +447,24 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
last_port = tmp;
|
||||
}
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
struct bitmap_port_timeout *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = (last_port - first_port + 1)
|
||||
* sizeof(unsigned long);
|
||||
|
||||
if (!init_map_port(set, (struct bitmap_port *) map,
|
||||
first_port, last_port)) {
|
||||
if (!init_map_port(set, map, first_port, last_port)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
set->variant = &bitmap_port_timeout;
|
||||
set->variant = &bitmap_tport;
|
||||
|
||||
bitmap_port_gc_init(set);
|
||||
} else {
|
||||
struct bitmap_port *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = bitmap_bytes(0, last_port - first_port);
|
||||
pr_debug("memsize: %zu\n", map->memsize);
|
||||
if (!init_map_port(set, map, first_port, last_port)) {
|
||||
@@ -630,6 +485,17 @@ static struct ip_set_type bitmap_port_type = {
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = bitmap_port_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/version.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
@@ -196,20 +197,24 @@ EXPORT_SYMBOL_GPL(ip_set_type_unregister);
|
||||
|
||||
/* Utility functions */
|
||||
void *
|
||||
ip_set_alloc(size_t size, gfp_t gfp_mask)
|
||||
ip_set_alloc(size_t size)
|
||||
{
|
||||
void *members = NULL;
|
||||
|
||||
if (size < KMALLOC_MAX_SIZE)
|
||||
members = kzalloc(size, gfp_mask | __GFP_NOWARN);
|
||||
members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
|
||||
|
||||
if (members) {
|
||||
pr_debug("%p: allocated with kmalloc\n", members);
|
||||
return members;
|
||||
}
|
||||
|
||||
members = __vmalloc(size, gfp_mask | __GFP_ZERO | __GFP_HIGHMEM,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
|
||||
members = __vmalloc(size, GFP_KERNEL | __GFP_ZERO | __GFP_HIGHMEM,
|
||||
PAGE_KERNEL);
|
||||
#else
|
||||
members = vzalloc(size);
|
||||
#endif
|
||||
if (!members)
|
||||
return NULL;
|
||||
pr_debug("%p: allocated with vmalloc\n", members);
|
||||
@@ -249,8 +254,7 @@ ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr)
|
||||
|
||||
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))
|
||||
if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
@@ -268,8 +272,7 @@ ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
|
||||
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))
|
||||
if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
@@ -611,10 +614,11 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
struct ip_set *set, *clash;
|
||||
ip_set_id_t index = IPSET_INVALID_ID;
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1] = {};
|
||||
const char *name, *typename;
|
||||
u8 family, revision;
|
||||
u32 flags = flag_exist(info->genlhdr);
|
||||
int ret = 0, len;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(protocol_failed(attr) ||
|
||||
attr[IPSET_ATTR_SETNAME] == NULL ||
|
||||
@@ -659,11 +663,14 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info)
|
||||
/*
|
||||
* Without holding any locks, create private part.
|
||||
*/
|
||||
len = attr[IPSET_ATTR_DATA] ? nla_len(attr[IPSET_ATTR_DATA]) : 0;
|
||||
pr_debug("data len: %u\n", len);
|
||||
ret = set->type->create(set, attr[IPSET_ATTR_DATA] ?
|
||||
nla_data(attr[IPSET_ATTR_DATA]) : NULL, len,
|
||||
flags);
|
||||
if (attr[IPSET_ATTR_DATA] &&
|
||||
nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA],
|
||||
set->type->create_policy)) {
|
||||
ret = -IPSET_ERR_PROTOCOL;
|
||||
goto put_out;
|
||||
}
|
||||
|
||||
ret = set->type->create(set, tb, flags);
|
||||
if (ret != 0)
|
||||
goto put_out;
|
||||
|
||||
@@ -749,7 +756,7 @@ ip_set_destroy(struct sk_buff *skb, struct genl_info *info)
|
||||
} else {
|
||||
i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
|
||||
if (i == IPSET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
return -ENOENT;
|
||||
else if (atomic_read(&ip_set_list[i]->ref))
|
||||
return -IPSET_ERR_BUSY;
|
||||
|
||||
@@ -786,7 +793,7 @@ ip_set_flush(struct sk_buff *skb, struct genl_info *info)
|
||||
} else {
|
||||
i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
|
||||
if (i == IPSET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
return -ENOENT;
|
||||
|
||||
ip_set_flush_set(ip_set_list[i]);
|
||||
}
|
||||
@@ -820,7 +827,7 @@ ip_set_rename(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
|
||||
if (set == NULL)
|
||||
return -EEXIST;
|
||||
return -ENOENT;
|
||||
if (atomic_read(&set->ref) != 0)
|
||||
return -IPSET_ERR_REFERENCED;
|
||||
|
||||
@@ -860,7 +867,7 @@ ip_set_swap(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
from_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
|
||||
if (from_id == IPSET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
return -ENOENT;
|
||||
|
||||
to_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME2]));
|
||||
if (to_id == IPSET_INVALID_ID)
|
||||
@@ -946,7 +953,7 @@ dump_init(struct netlink_callback *cb)
|
||||
|
||||
index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
|
||||
if (index == IPSET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
return -ENOENT;
|
||||
|
||||
cb->args[0] = DUMP_ONE;
|
||||
cb->args[1] = index;
|
||||
@@ -958,16 +965,18 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
ip_set_id_t index = IPSET_INVALID_ID, max;
|
||||
struct ip_set *set = NULL;
|
||||
void *nlh = NULL;
|
||||
struct nlmsghdr *nlh = NULL;
|
||||
unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0;
|
||||
int ret = 0;
|
||||
|
||||
if (cb->args[0] == DUMP_INIT) {
|
||||
ret = dump_init(cb);
|
||||
if (ret < 0) {
|
||||
nlh = nlmsg_hdr(cb->skb);
|
||||
/* We have to create and send the error message
|
||||
* manually :-( */
|
||||
netlink_ack(cb->skb, nlmsg_hdr(cb->skb), ret);
|
||||
if (nlh->nlmsg_flags & NLM_F_ACK)
|
||||
netlink_ack(cb->skb, nlh, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -982,7 +991,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
set = ip_set_list[index];
|
||||
if (set == NULL) {
|
||||
if (cb->args[0] == DUMP_ONE) {
|
||||
ret = -EEXIST;
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
continue;
|
||||
@@ -1004,7 +1013,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
cb->nlh->nlmsg_seq, flags,
|
||||
IPSET_CMD_LIST);
|
||||
if (!nlh) {
|
||||
ret = -EFAULT;
|
||||
ret = -EMSGSIZE;
|
||||
goto release_refcount;
|
||||
}
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
|
||||
@@ -1092,19 +1101,17 @@ static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = {
|
||||
};
|
||||
|
||||
static int
|
||||
call_ad(struct sk_buff *skb, struct nlattr *const attr[],
|
||||
struct ip_set *set, const struct nlattr *nla,
|
||||
enum ipset_adt adt, u32 flags)
|
||||
call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
|
||||
struct nlattr *tb[], enum ipset_adt adt,
|
||||
u32 flags, bool use_lineno)
|
||||
{
|
||||
struct nlattr *head = nla_data(nla);
|
||||
int ret, len = nla_len(nla), retried = 0;
|
||||
int ret, retried = 0;
|
||||
u32 lineno = 0;
|
||||
bool eexist = flags & IPSET_FLAG_EXIST;
|
||||
|
||||
do {
|
||||
write_lock_bh(&set->lock);
|
||||
ret = set->variant->uadt(set, head, len, adt,
|
||||
&lineno, flags);
|
||||
ret = set->variant->uadt(set, tb, adt, &lineno, flags);
|
||||
write_unlock_bh(&set->lock);
|
||||
} while (ret == -EAGAIN &&
|
||||
set->variant->resize &&
|
||||
@@ -1112,11 +1119,38 @@ call_ad(struct sk_buff *skb, struct nlattr *const attr[],
|
||||
|
||||
if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
|
||||
return 0;
|
||||
if (lineno && attr[IPSET_ATTR_LINENO]) {
|
||||
if (lineno && use_lineno) {
|
||||
/* Error in restore/batch mode: send back lineno */
|
||||
u32 *errline = nla_data(attr[IPSET_ATTR_LINENO]);
|
||||
struct nlmsghdr *rep, *nlh = nlmsg_hdr(skb);
|
||||
struct sk_buff *skb2;
|
||||
struct nlmsgerr *errmsg;
|
||||
size_t payload = sizeof(*errmsg) + nlmsg_len(nlh);
|
||||
int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
|
||||
struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
|
||||
struct nlattr *cmdattr;
|
||||
u32 *errline;
|
||||
|
||||
skb2 = nlmsg_new(payload, GFP_KERNEL);
|
||||
if (skb2 == NULL)
|
||||
return -ENOMEM;
|
||||
rep = __nlmsg_put(skb2, NETLINK_CB(skb).pid,
|
||||
nlh->nlmsg_seq, NLMSG_ERROR, payload, 0);
|
||||
errmsg = nlmsg_data(rep);
|
||||
errmsg->error = ret;
|
||||
memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
|
||||
cmdattr = (void *)&errmsg->msg + min_len;
|
||||
|
||||
nla_parse(cda, IPSET_ATTR_CMD_MAX,
|
||||
cmdattr, nlh->nlmsg_len - min_len,
|
||||
ip_set_adt_policy);
|
||||
|
||||
errline = nla_data(cda[IPSET_ATTR_LINENO]);
|
||||
|
||||
*errline = lineno;
|
||||
|
||||
netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
|
||||
/* Signal netlink not to send its ACK/errmsg. */
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1126,10 +1160,13 @@ static int
|
||||
ip_set_uadd(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *const *attr = info->attrs;
|
||||
struct sock *ctnl = genl_info_net(info)->genl_sock;
|
||||
|
||||
struct ip_set *set;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
|
||||
const struct nlattr *nla;
|
||||
u32 flags = flag_exist(info->genlhdr);
|
||||
bool use_lineno;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(protocol_failed(attr) ||
|
||||
@@ -1145,20 +1182,28 @@ ip_set_uadd(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
|
||||
if (set == NULL)
|
||||
return -EEXIST;
|
||||
return -ENOENT;
|
||||
|
||||
use_lineno = !!attr[IPSET_ATTR_LINENO];
|
||||
if (attr[IPSET_ATTR_DATA]) {
|
||||
ret = call_ad(skb, attr,
|
||||
set, attr[IPSET_ATTR_DATA], IPSET_ADD, flags);
|
||||
if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
|
||||
attr[IPSET_ATTR_DATA],
|
||||
set->type->adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, flags,
|
||||
use_lineno);
|
||||
} else {
|
||||
int nla_rem;
|
||||
|
||||
nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
|
||||
memset(tb, 0, sizeof(tb));
|
||||
if (nla_type(nla) != IPSET_ATTR_DATA ||
|
||||
!flag_nested(nla))
|
||||
!flag_nested(nla) ||
|
||||
nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
|
||||
set->type->adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
ret = call_ad(skb, attr,
|
||||
set, nla, IPSET_ADD, flags);
|
||||
ret = call_ad(ctnl, skb, set, tb, IPSET_ADD,
|
||||
flags, use_lineno);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -1170,10 +1215,13 @@ static int
|
||||
ip_set_udel(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *const *attr = info->attrs;
|
||||
struct sock *ctnl = genl_info_net(info)->genl_sock;
|
||||
|
||||
struct ip_set *set;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
|
||||
const struct nlattr *nla;
|
||||
u32 flags = flag_exist(info->genlhdr);
|
||||
bool use_lineno;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(protocol_failed(attr) ||
|
||||
@@ -1189,20 +1237,28 @@ ip_set_udel(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
|
||||
if (set == NULL)
|
||||
return -EEXIST;
|
||||
return -ENOENT;
|
||||
|
||||
use_lineno = !!attr[IPSET_ATTR_LINENO];
|
||||
if (attr[IPSET_ATTR_DATA]) {
|
||||
ret = call_ad(skb, attr,
|
||||
set, attr[IPSET_ATTR_DATA], IPSET_DEL, flags);
|
||||
if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
|
||||
attr[IPSET_ATTR_DATA],
|
||||
set->type->adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, flags,
|
||||
use_lineno);
|
||||
} else {
|
||||
int nla_rem;
|
||||
|
||||
nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
|
||||
memset(tb, 0, sizeof(*tb));
|
||||
if (nla_type(nla) != IPSET_ATTR_DATA ||
|
||||
!flag_nested(nla))
|
||||
!flag_nested(nla) ||
|
||||
nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
|
||||
set->type->adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
ret = call_ad(skb, attr,
|
||||
set, nla, IPSET_DEL, flags);
|
||||
ret = call_ad(ctnl, skb, set, tb, IPSET_DEL,
|
||||
flags, use_lineno);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -1216,6 +1272,7 @@ ip_set_utest(struct sk_buff *skb, struct genl_info *info)
|
||||
struct nlattr *const *attr = info->attrs;
|
||||
|
||||
struct ip_set *set;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(protocol_failed(attr) ||
|
||||
@@ -1226,13 +1283,14 @@ ip_set_utest(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
|
||||
if (set == NULL)
|
||||
return -EEXIST;
|
||||
return -ENOENT;
|
||||
|
||||
if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA],
|
||||
set->type->adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
read_lock_bh(&set->lock);
|
||||
ret = set->variant->uadt(set,
|
||||
nla_data(attr[IPSET_ATTR_DATA]),
|
||||
nla_len(attr[IPSET_ATTR_DATA]),
|
||||
IPSET_TEST, NULL, 0);
|
||||
ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0);
|
||||
read_unlock_bh(&set->lock);
|
||||
/* Userspace can't trigger element to be re-added */
|
||||
if (ret == -EAGAIN)
|
||||
@@ -1260,7 +1318,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
index = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
|
||||
if (index == IPSET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
return -ENOENT;
|
||||
set = ip_set_list[index];
|
||||
|
||||
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
@@ -1280,7 +1338,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
ret = genlmsg_unicast(genl_info_net(info), skb2, NETLINK_CB(skb).pid);
|
||||
if (ret < 0)
|
||||
return -EFAULT;
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1288,7 +1346,7 @@ nla_put_failure:
|
||||
nlmsg_cancel(skb2, nlh2);
|
||||
nlmsg_failure:
|
||||
kfree_skb(skb2);
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/* Get type data */
|
||||
@@ -1341,7 +1399,7 @@ ip_set_type(struct sk_buff *skb, struct genl_info *info)
|
||||
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;
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1349,7 +1407,7 @@ nla_put_failure:
|
||||
genlmsg_cancel(skb2, nlh2);
|
||||
nlmsg_failure:
|
||||
kfree_skb(skb2);
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/* Get protocol version */
|
||||
@@ -1385,7 +1443,7 @@ ip_set_protocol(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
ret = genlmsg_unicast(genl_info_net(info), skb2, NETLINK_CB(skb).pid);
|
||||
if (ret < 0)
|
||||
return -EFAULT;
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1393,7 +1451,7 @@ nla_put_failure:
|
||||
genlmsg_cancel(skb2, nlh2);
|
||||
nlmsg_failure:
|
||||
kfree_skb(skb2);
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static struct genl_ops ip_set_netlink_subsys_cb[] __read_mostly = {
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
@@ -93,21 +94,23 @@ ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_set_get_ip4_port);
|
||||
|
||||
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
|
||||
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;
|
||||
int protoff;
|
||||
u8 nexthdr;
|
||||
|
||||
protocol = ipv6_find_hdr(skb, &protooff, -1, &fragoff);
|
||||
if (protocol <= 0 || fragoff)
|
||||
nexthdr = ipv6_hdr(skb)->nexthdr;
|
||||
protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr);
|
||||
if (protoff < 0)
|
||||
return false;
|
||||
|
||||
return get_port(skb, protocol, protooff, src, port, proto);
|
||||
return get_port(skb, nexthdr, protoff, src, port, proto);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_set_get_ip6_port);
|
||||
#endif
|
||||
|
||||
bool
|
||||
ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port)
|
||||
@@ -118,8 +121,10 @@ ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port)
|
||||
switch (pf) {
|
||||
case AF_INET:
|
||||
ret = ip_set_get_ip4_port(skb, src, port, &proto);
|
||||
break;
|
||||
case AF_INET6:
|
||||
ret = ip_set_get_ip6_port(skb, src, port, &proto);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@@ -3,8 +3,18 @@
|
||||
|
||||
extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
|
||||
__be16 *port, u8 *proto);
|
||||
|
||||
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
|
||||
extern bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
|
||||
__be16 *port, u8 *proto);
|
||||
#else
|
||||
static inline bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
|
||||
__be16 *port, u8 *proto)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src,
|
||||
__be16 *port);
|
||||
|
||||
|
@@ -12,9 +12,6 @@
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
@@ -127,29 +124,16 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
return adtfn(set, &ip, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy hash_ip4_adt_policy[IPSET_ATTR_ADT_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 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
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, 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;
|
||||
@@ -320,22 +304,19 @@ static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ip6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
union nf_inet_addr ip;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_ip6_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
|
||||
tb[IPSET_ATTR_IP_TO] ||
|
||||
tb[IPSET_ATTR_CIDR]))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
@@ -362,20 +343,9 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ip_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 netmask, hbits;
|
||||
struct ip_set_hash *h;
|
||||
@@ -386,10 +356,6 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
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)))
|
||||
@@ -425,8 +391,7 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
@@ -465,6 +430,21 @@ static struct ip_set_type hash_ip_type __read_mostly = {
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_ip_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[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 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@@ -12,9 +12,6 @@
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
@@ -144,34 +141,17 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipport_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipport4_elem data = { };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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) ||
|
||||
@@ -373,25 +353,22 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipport6_elem data = { };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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)))
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
|
||||
tb[IPSET_ATTR_IP_TO] ||
|
||||
tb[IPSET_ATTR_CIDR]))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
@@ -456,20 +433,9 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipport_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
@@ -477,10 +443,6 @@ hash_ipport_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;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
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)))
|
||||
@@ -506,8 +468,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
@@ -546,6 +507,24 @@ static struct ip_set_type hash_ipport_type __read_mostly = {
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_ipport_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@@ -12,9 +12,6 @@
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
@@ -148,35 +145,17 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipportip_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP2] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportip4_elem data = { };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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) ||
|
||||
@@ -388,25 +367,22 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportip6_elem data = { };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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)))
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
|
||||
tb[IPSET_ATTR_IP_TO] ||
|
||||
tb[IPSET_ATTR_CIDR]))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
@@ -475,20 +451,9 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipportip_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipportip_create(struct ip_set *set, struct nlattr *head,
|
||||
int len, u32 flags)
|
||||
hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
@@ -496,10 +461,6 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
|
||||
if (!(set->family == AF_INET || set->family == AF_INET6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
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)))
|
||||
@@ -525,8 +486,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
@@ -565,6 +525,24 @@ static struct ip_set_type hash_ipportip_type __read_mostly = {
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_ipportip_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP2] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@@ -12,9 +12,6 @@
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
@@ -168,36 +165,17 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipportnet_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP2] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_CIDR2] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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) ||
|
||||
@@ -443,25 +421,22 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportnet6_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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)))
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
|
||||
tb[IPSET_ATTR_IP_TO] ||
|
||||
tb[IPSET_ATTR_CIDR]))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
@@ -538,20 +513,9 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipportnet_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
|
||||
int len, u32 flags)
|
||||
hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
@@ -559,10 +523,6 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
|
||||
if (!(set->family == AF_INET || set->family == AF_INET6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
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)))
|
||||
@@ -590,8 +550,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
@@ -631,6 +590,25 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = {
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_ipportnet_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP2] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_CIDR2] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@@ -12,9 +12,6 @@
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
@@ -147,27 +144,16 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy hash_net_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_net4_elem data = { .cidr = HOST_MASK };
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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;
|
||||
@@ -324,20 +310,15 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
}
|
||||
|
||||
static int
|
||||
hash_net6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_net6_elem data = { .cidr = HOST_MASK };
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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;
|
||||
@@ -370,19 +351,9 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_net_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
struct ip_set_hash *h;
|
||||
u8 hbits;
|
||||
@@ -390,10 +361,6 @@ hash_net_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;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
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)))
|
||||
@@ -421,8 +388,7 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
@@ -461,6 +427,18 @@ static struct ip_set_type hash_net_type __read_mostly = {
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_net_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@@ -12,9 +12,6 @@
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
@@ -164,33 +161,17 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
hash_netport_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netport4_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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) ||
|
||||
@@ -401,21 +382,16 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
}
|
||||
|
||||
static int
|
||||
hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netport6_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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) ||
|
||||
@@ -490,20 +466,9 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_netport_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
@@ -511,10 +476,6 @@ hash_netport_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;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
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)))
|
||||
@@ -542,8 +503,7 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
@@ -582,6 +542,23 @@ static struct ip_set_type hash_netport_type __read_mostly = {
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_netport_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@@ -111,16 +111,6 @@ list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct nla_policy list_set_adt_policy[IPSET_ATTR_ADT_MAX+1] = {
|
||||
[IPSET_ATTR_NAME] = { .type = NLA_STRING,
|
||||
.len = IPSET_MAXNAMELEN },
|
||||
[IPSET_ATTR_NAMEREF] = { .type = NLA_STRING,
|
||||
.len = IPSET_MAXNAMELEN },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static bool
|
||||
next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
|
||||
{
|
||||
@@ -204,11 +194,10 @@ list_set_del(struct list_set *map, ip_set_id_t id, u32 i)
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
list_set_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
bool with_timeout = with_timeout(map->timeout);
|
||||
int before = 0;
|
||||
u32 timeout = map->timeout;
|
||||
@@ -218,10 +207,6 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
u32 i;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, 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)))
|
||||
@@ -392,7 +377,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb)
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -406,7 +391,7 @@ list_set_list(const struct ip_set *set,
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] < map->size; cb->args[2]++) {
|
||||
i = cb->args[2];
|
||||
e = list_set_elem(map, i);
|
||||
@@ -418,7 +403,7 @@ list_set_list(const struct ip_set *set,
|
||||
if (!nested) {
|
||||
if (i == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
@@ -441,6 +426,10 @@ finish:
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
if (unlikely(i == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -501,12 +490,6 @@ list_set_gc_init(struct ip_set *set)
|
||||
|
||||
/* Create list:set type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
list_set_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_SIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static bool
|
||||
init_list_set(struct ip_set *set, u32 size, size_t dsize,
|
||||
unsigned long timeout)
|
||||
@@ -533,16 +516,10 @@ init_list_set(struct ip_set *set, u32 size, size_t dsize,
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
u32 flags)
|
||||
list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u32 size = IP_SET_LIST_DEFAULT_SIZE;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, 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;
|
||||
@@ -575,6 +552,19 @@ static struct ip_set_type list_set_type __read_mostly = {
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = list_set_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_SIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_NAME] = { .type = NLA_STRING,
|
||||
.len = IPSET_MAXNAMELEN },
|
||||
[IPSET_ATTR_NAMEREF] = { .type = NLA_STRING,
|
||||
.len = IPSET_MAXNAMELEN },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@@ -43,8 +43,8 @@ static const uint16_t cmdflags[] = {
|
||||
[IPSET_CMD_FLUSH-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_RENAME-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_SWAP-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_LIST-1] = NLM_F_REQUEST,
|
||||
[IPSET_CMD_SAVE-1] = NLM_F_REQUEST,
|
||||
[IPSET_CMD_LIST-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_SAVE-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_ADD-1] = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL,
|
||||
[IPSET_CMD_DEL-1] = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL,
|
||||
[IPSET_CMD_TEST-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
@@ -83,7 +83,7 @@ ipset_mnl_fill_hdr(struct ipset_handle *handle, enum ipset_cmd cmd,
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||
if (cmdflags[cmd-1] & NLM_F_ACK)
|
||||
nlh->nlmsg_flags |= NLM_F_ACK;
|
||||
nlh->nlmsg_seq = handle->seq = time(NULL);
|
||||
nlh->nlmsg_seq = ++handle->seq;
|
||||
|
||||
ghdr = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
|
||||
ghdr->cmd = cmd;
|
||||
@@ -225,6 +225,7 @@ ipset_mnl_init(mnl_cb_t *cb_ctl, void *data)
|
||||
handle->portid = mnl_socket_get_portid(handle->h);
|
||||
handle->cb_ctl = cb_ctl;
|
||||
handle->data = data;
|
||||
handle->seq = time(NULL);
|
||||
|
||||
if (ipset_mnl_getid(handle, false) < 0)
|
||||
goto close_nl;
|
||||
|
@@ -1416,15 +1416,14 @@ ipset_parse_ignored(struct ipset_session *session,
|
||||
*/
|
||||
int
|
||||
ipset_call_parser(struct ipset_session *session,
|
||||
ipset_parsefn parse, const char *optstr,
|
||||
enum ipset_opt opt, const char *str)
|
||||
const struct ipset_arg *arg,
|
||||
const char *str)
|
||||
{
|
||||
if (ipset_data_flags_test(ipset_session_data(session),
|
||||
IPSET_FLAG(opt)))
|
||||
syntax_err("%s already specified", optstr);
|
||||
IPSET_FLAG(arg->opt)))
|
||||
syntax_err("%s already specified", arg->name[0]);
|
||||
|
||||
return parse(session, opt, parse == ipset_parse_ignored
|
||||
? optstr : str);
|
||||
return arg->parse(session, arg->opt, str);
|
||||
}
|
||||
|
||||
#define parse_elem(s, t, d, str) \
|
||||
|
@@ -158,7 +158,8 @@ __getnameinfo##f(char *buf, unsigned int len, \
|
||||
sizeof(saddr), \
|
||||
buf, len, NULL, 0, flags); \
|
||||
\
|
||||
if (err == EAI_AGAIN && !(flags & NI_NUMERICHOST)) \
|
||||
if (!(flags & NI_NUMERICHOST) && \
|
||||
(err == EAI_AGAIN || (err == 0 && strchr(buf, '-') != NULL))) \
|
||||
err = getnameinfo((const struct sockaddr *)&saddr, \
|
||||
sizeof(saddr), \
|
||||
buf, len, NULL, 0, \
|
||||
@@ -229,7 +230,7 @@ ipset_print_ip(char *buf, unsigned int len,
|
||||
D("CIDR: %u", cidr);
|
||||
} else
|
||||
cidr = family == AF_INET6 ? 128 : 32;
|
||||
flags = env & (1 << IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
|
||||
flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
|
||||
|
||||
ip = ipset_data_get(data, opt);
|
||||
assert(ip);
|
||||
@@ -296,7 +297,7 @@ ipset_print_ipaddr(char *buf, unsigned int len,
|
||||
cidr = *(const uint8_t *) ipset_data_get(data, cidropt);
|
||||
else
|
||||
cidr = family == AF_INET6 ? 128 : 32;
|
||||
flags = env & (1 << IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
|
||||
flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
|
||||
|
||||
ip = ipset_data_get(data, opt);
|
||||
assert(ip);
|
||||
|
@@ -441,13 +441,15 @@ ipset_type_add(struct ipset_type *type)
|
||||
|
||||
assert(type);
|
||||
|
||||
if (strlen(type->name) > IPSET_MAXNAMELEN - 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* Add to the list: higher revision numbers first */
|
||||
for (t = typelist, prev = NULL; t != NULL; t = t->next) {
|
||||
if (STREQ(t->name, type->name)) {
|
||||
if (t->revision == type->revision) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
} else if (t->revision < type->revision) {
|
||||
if (t->revision == type->revision)
|
||||
return -EEXIST;
|
||||
else if (t->revision < type->revision) {
|
||||
type->next = t;
|
||||
if (prev)
|
||||
prev->next = type;
|
||||
@@ -457,10 +459,9 @@ ipset_type_add(struct ipset_type *type)
|
||||
}
|
||||
}
|
||||
if (t->next != NULL && STREQ(t->next->name, type->name)) {
|
||||
if (t->next->revision == type->revision) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
} else if (t->next->revision < type->revision) {
|
||||
if (t->next->revision == type->revision)
|
||||
return -EEXIST;
|
||||
else if (t->next->revision < type->revision) {
|
||||
type->next = t->next;
|
||||
t->next = type;
|
||||
return 0;
|
||||
|
@@ -21,8 +21,10 @@
|
||||
/* Core kernel error codes */
|
||||
static const struct ipset_errcode_table core_errcode_table[] = {
|
||||
/* Generic error codes */
|
||||
{ EEXIST, 0,
|
||||
{ ENOENT, 0,
|
||||
"The set with the given name does not exist" },
|
||||
{ EMSGSIZE, 0,
|
||||
"Kernel error received: message could not be created" },
|
||||
{ IPSET_ERR_PROTOCOL, 0,
|
||||
"Kernel error received: ipset protocol error" },
|
||||
|
||||
@@ -30,14 +32,14 @@ static const struct ipset_errcode_table core_errcode_table[] = {
|
||||
{ EEXIST, IPSET_CMD_CREATE,
|
||||
"Set cannot be created: set with the same name already exists" },
|
||||
{ IPSET_ERR_FIND_TYPE, 0,
|
||||
"Kernel error received: set type does not supported" },
|
||||
"Kernel error received: set type not supported" },
|
||||
{ IPSET_ERR_MAX_SETS, 0,
|
||||
"Kernel error received: maximal number of sets reached, "
|
||||
"cannot create more." },
|
||||
{ IPSET_ERR_INVALID_NETMASK, 0,
|
||||
"The value of the netmask parameter is invalid" },
|
||||
{ IPSET_ERR_INVALID_FAMILY, 0,
|
||||
"The protocol family not supported by the set type" },
|
||||
"Protocol family not supported by the set type" },
|
||||
|
||||
/* DESTROY specific error codes */
|
||||
{ IPSET_ERR_BUSY, IPSET_CMD_DESTROY,
|
||||
|
@@ -206,62 +206,54 @@ restore(char *argv0)
|
||||
static int
|
||||
call_parser(int *argc, char *argv[], const struct ipset_arg *args)
|
||||
{
|
||||
int i = 1, ret = 0;
|
||||
int ret = 0;
|
||||
const struct ipset_arg *arg;
|
||||
const char *optstr;
|
||||
|
||||
/* Currently CREATE and ADT may have got additional arguments */
|
||||
if (!args)
|
||||
goto done;
|
||||
for (arg = args; arg->opt; arg++) {
|
||||
for (i = 1; i < *argc; ) {
|
||||
D("argc: %u, i: %u: %s vs %s",
|
||||
*argc, i, argv[i], arg->name[0]);
|
||||
if (!(ipset_match_option(argv[i], arg->name))) {
|
||||
i++;
|
||||
if (!args && *argc > 1)
|
||||
goto err_unknown;
|
||||
while (*argc > 1) {
|
||||
for (arg = args; arg->opt; arg++) {
|
||||
D("argc: %u, %s vs %s", *argc, argv[1], arg->name[0]);
|
||||
if (!(ipset_match_option(argv[1], arg->name)))
|
||||
continue;
|
||||
}
|
||||
optstr = argv[i];
|
||||
|
||||
optstr = argv[1];
|
||||
/* Shift off matched option */
|
||||
D("match %s", arg->name[0]);
|
||||
ipset_shift_argv(argc, argv, i);
|
||||
D("argc: %u, i: %u", *argc, i);
|
||||
ipset_shift_argv(argc, argv, 1);
|
||||
switch (arg->has_arg) {
|
||||
case IPSET_MANDATORY_ARG:
|
||||
if (i + 1 > *argc)
|
||||
if (*argc < 2)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Missing mandatory argument "
|
||||
"of option `%s'",
|
||||
arg->name[0]);
|
||||
/* Fall through */
|
||||
case IPSET_OPTIONAL_ARG:
|
||||
if (i + 1 <= *argc) {
|
||||
ret = ipset_call_parser(session,
|
||||
arg->parse,
|
||||
optstr, arg->opt,
|
||||
argv[i]);
|
||||
if (*argc >= 2) {
|
||||
ret = ipset_call_parser(session, arg, argv[1]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ipset_shift_argv(argc, argv, i);
|
||||
ipset_shift_argv(argc, argv, 1);
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
ret = ipset_call_parser(session,
|
||||
arg->parse,
|
||||
optstr, arg->opt,
|
||||
optstr);
|
||||
ret = ipset_call_parser(session, arg, optstr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!arg->opt)
|
||||
goto err_unknown;
|
||||
}
|
||||
done:
|
||||
if (i < *argc)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Unknown argument: `%s'",
|
||||
argv[i]);
|
||||
return ret;
|
||||
|
||||
err_unknown:
|
||||
return exit_error(PARAMETER_PROBLEM, "Unknown argument: `%s'", argv[1]);
|
||||
}
|
||||
|
||||
static enum ipset_adt
|
||||
@@ -476,61 +468,57 @@ parse_commandline(int argc, char *argv[])
|
||||
|
||||
/* Second: parse command */
|
||||
for (command = ipset_commands;
|
||||
command->cmd && cmd == IPSET_CMD_NONE;
|
||||
argc > 1 && command->cmd && cmd == IPSET_CMD_NONE;
|
||||
command++) {
|
||||
for (i = 1; i < argc; ) {
|
||||
if (!ipset_match_cmd(argv[1], command->name)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (restore_line != 0
|
||||
&& (command->cmd == IPSET_CMD_RESTORE
|
||||
|| command->cmd == IPSET_CMD_VERSION
|
||||
|| command->cmd == IPSET_CMD_HELP))
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Command `%s' is invalid "
|
||||
"in restore mode.",
|
||||
command->name[0]);
|
||||
if (interactive
|
||||
&& command->cmd == IPSET_CMD_RESTORE) {
|
||||
printf("Restore command ignored "
|
||||
"in interactive mode\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ipset_match_cmd(argv[1], command->name))
|
||||
continue;
|
||||
|
||||
/* Shift off matched command arg */
|
||||
ipset_shift_argv(&argc, argv, i);
|
||||
cmd = command->cmd;
|
||||
switch (command->has_arg) {
|
||||
case IPSET_MANDATORY_ARG:
|
||||
case IPSET_MANDATORY_ARG2:
|
||||
if (i + 1 > argc)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Missing mandatory argument "
|
||||
"to command %s",
|
||||
command->name[0]);
|
||||
/* Fall through */
|
||||
case IPSET_OPTIONAL_ARG:
|
||||
arg0 = argv[i];
|
||||
if (i + 1 <= argc)
|
||||
/* Shift off first arg */
|
||||
ipset_shift_argv(&argc, argv, i);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (command->has_arg == IPSET_MANDATORY_ARG2) {
|
||||
if (i + 1 > argc)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Missing second mandatory "
|
||||
"argument to command %s",
|
||||
command->name[0]);
|
||||
arg1 = argv[i];
|
||||
/* Shift off second arg */
|
||||
ipset_shift_argv(&argc, argv, i);
|
||||
}
|
||||
if (restore_line != 0
|
||||
&& (command->cmd == IPSET_CMD_RESTORE
|
||||
|| command->cmd == IPSET_CMD_VERSION
|
||||
|| command->cmd == IPSET_CMD_HELP))
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Command `%s' is invalid "
|
||||
"in restore mode.",
|
||||
command->name[0]);
|
||||
if (interactive && command->cmd == IPSET_CMD_RESTORE) {
|
||||
printf("Restore command ignored "
|
||||
"in interactive mode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Shift off matched command arg */
|
||||
ipset_shift_argv(&argc, argv, 1);
|
||||
cmd = command->cmd;
|
||||
switch (command->has_arg) {
|
||||
case IPSET_MANDATORY_ARG:
|
||||
case IPSET_MANDATORY_ARG2:
|
||||
if (argc < 2)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Missing mandatory argument "
|
||||
"to command %s",
|
||||
command->name[0]);
|
||||
/* Fall through */
|
||||
case IPSET_OPTIONAL_ARG:
|
||||
arg0 = argv[1];
|
||||
if (argc >= 2)
|
||||
/* Shift off first arg */
|
||||
ipset_shift_argv(&argc, argv, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (command->has_arg == IPSET_MANDATORY_ARG2) {
|
||||
if (argc < 2)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Missing second mandatory "
|
||||
"argument to command %s",
|
||||
command->name[0]);
|
||||
arg1 = argv[1];
|
||||
/* Shift off second arg */
|
||||
ipset_shift_argv(&argc, argv, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Third: catch interactive mode, handle help, version */
|
||||
@@ -565,7 +553,8 @@ parse_commandline(int argc, char *argv[])
|
||||
argv[1]);
|
||||
return exit_error(PARAMETER_PROBLEM, "No command specified.");
|
||||
case IPSET_CMD_VERSION:
|
||||
printf("%s v%s.\n", program_name, program_version);
|
||||
printf("%s v%s, protocol version: %u\n",
|
||||
program_name, program_version, IPSET_PROTOCOL);
|
||||
if (interactive)
|
||||
return 0;
|
||||
return exit_error(NO_PROBLEM, NULL);
|
||||
|
@@ -23,9 +23,9 @@
|
||||
const struct ipset_commands ipset_commands[] = {
|
||||
/* Order is important */
|
||||
|
||||
{ /* c[reate], --create, n, -N */
|
||||
{ /* c[reate], --create, n[ew], -N */
|
||||
.cmd = IPSET_CMD_CREATE,
|
||||
.name = { "create", "n" },
|
||||
.name = { "create", "new" },
|
||||
.has_arg = IPSET_MANDATORY_ARG2,
|
||||
.help = "SETNAME TYPENAME [type-specific-options]\n"
|
||||
" Create a new set",
|
||||
@@ -143,14 +143,14 @@ ipset_match_cmd(const char *arg, const char * const name[])
|
||||
|
||||
if (len > strlen(name[0]) || !len)
|
||||
return false;
|
||||
else if (strncmp(arg, name[0], len) == 0)
|
||||
else if (len > 1 &&
|
||||
((strncmp(arg, name[0], len) == 0) ||
|
||||
(name[1] != NULL && (strncmp(arg, name[1], len) == 0))))
|
||||
return true;
|
||||
else if (len != 1)
|
||||
return false;
|
||||
else if (name[1] == NULL)
|
||||
return tolower(arg[0]) == name[0][0];
|
||||
else
|
||||
return tolower(arg[0]) == name[1][0];
|
||||
else return tolower(arg[0]) == name[0][0] ||
|
||||
(name[1] != NULL && tolower(arg[0]) == name[1][0]);
|
||||
}
|
||||
|
||||
const struct ipset_envopts ipset_envopts[] = {
|
||||
|
@@ -56,10 +56,10 @@ match_set(ip_set_id_t index, const struct sk_buff *skb,
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
#define CHECK_OK 1
|
||||
#define CHECK_FAIL 0
|
||||
#define CHECK_FAIL(err) 0
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
|
||||
#define CHECK_OK 0
|
||||
#define CHECK_FAIL (-EINVAL)
|
||||
#define CHECK_FAIL(err) (err)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
@@ -110,11 +110,12 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par)
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("Cannot find set indentified by id %u to match\n",
|
||||
info->match_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
return CHECK_FAIL(-ENOENT); /* error */
|
||||
}
|
||||
if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
|
||||
pr_warning("That's nasty!\n");
|
||||
return CHECK_FAIL; /* error */
|
||||
pr_warning("Protocol error: set match dimension "
|
||||
"is over the limit!\n");
|
||||
return CHECK_FAIL(-ERANGE); /* error */
|
||||
}
|
||||
|
||||
/* Fill out compatibility data */
|
||||
@@ -167,24 +168,25 @@ 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\n",
|
||||
pr_warning("Cannot find add_set index %u as target\n",
|
||||
info->add_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
return CHECK_FAIL(-ENOENT); /* error */
|
||||
}
|
||||
}
|
||||
|
||||
if (info->del_set.index != IPSET_INVALID_ID) {
|
||||
index = ip_set_nfnl_get_byindex(info->del_set.index);
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("cannot find del_set index %u as target\n",
|
||||
pr_warning("Cannot find del_set index %u as target\n",
|
||||
info->del_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
return CHECK_FAIL(-ENOENT); /* 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!\n");
|
||||
return CHECK_FAIL; /* error */
|
||||
pr_warning("Protocol error: SET target dimension "
|
||||
"is over the limit!\n");
|
||||
return CHECK_FAIL(-ERANGE); /* error */
|
||||
}
|
||||
|
||||
/* Fill out compatibility data */
|
||||
@@ -239,11 +241,12 @@ set_match_checkentry(const struct xt_mtchk_param *par)
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("Cannot find set indentified by id %u to match\n",
|
||||
info->match_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
return CHECK_FAIL(-ENOENT); /* error */
|
||||
}
|
||||
if (info->match_set.dim > IPSET_DIM_MAX) {
|
||||
pr_warning("That's nasty!\n");
|
||||
return CHECK_FAIL; /* error */
|
||||
pr_warning("Protocol error: set match dimension "
|
||||
"is over the limit!\n");
|
||||
return CHECK_FAIL(-ERANGE); /* error */
|
||||
}
|
||||
|
||||
return CHECK_OK;
|
||||
@@ -295,24 +298,25 @@ 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\n",
|
||||
pr_warning("Cannot find add_set index %u as target\n",
|
||||
info->add_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
return CHECK_FAIL(-ENOENT); /* error */
|
||||
}
|
||||
}
|
||||
|
||||
if (info->del_set.index != IPSET_INVALID_ID) {
|
||||
index = ip_set_nfnl_get_byindex(info->del_set.index);
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("cannot find del_set index %u as target\n",
|
||||
pr_warning("Cannot find del_set index %u as target\n",
|
||||
info->del_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
return CHECK_FAIL(-ENOENT); /* error */
|
||||
}
|
||||
}
|
||||
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 */
|
||||
pr_warning("Protocol error: SET target dimension "
|
||||
"is over the limit!\n");
|
||||
return CHECK_FAIL(-ERANGE); /* error */
|
||||
}
|
||||
|
||||
return CHECK_OK;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#ifndef _XT_SET_H
|
||||
#define _XT_SET_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "ip_set.h"
|
||||
|
||||
/* Revision 0 interface: backward compatible with netfilter/iptables */
|
||||
|
29
mconfig
29
mconfig
@@ -1,30 +1,3 @@
|
||||
# -*- Makefile -*-
|
||||
#
|
||||
build_ACCOUNT=m
|
||||
build_CHAOS=m
|
||||
build_CHECKSUM=
|
||||
build_DELUDE=m
|
||||
build_DHCPMAC=m
|
||||
build_DNETMAP=
|
||||
build_ECHO=
|
||||
build_IPMARK=m
|
||||
build_LOGMARK=m
|
||||
build_RAWNAT=m
|
||||
build_STEAL=m
|
||||
build_SYSRQ=m
|
||||
build_TARPIT=m
|
||||
build_TEE=
|
||||
build_condition=m
|
||||
build_fuzzy=m
|
||||
build_geoip=m
|
||||
build_gradm=m
|
||||
build_iface=m
|
||||
build_ipp2p=m
|
||||
build_ipset4=m
|
||||
build_ipset6=
|
||||
build_ipv4options=m
|
||||
build_length2=m
|
||||
build_lscan=m
|
||||
build_pknock=m
|
||||
build_psd=m
|
||||
build_quota2=m
|
||||
build_ipset6=m
|
||||
|
Reference in New Issue
Block a user