Skip to content

Commit

Permalink
netfilter: ipset: options and flags support added to the kernel API
Browse files Browse the repository at this point in the history
The support makes possible to specify the timeout value for
the SET target and a flag to reset the timeout for already existing
entries.

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>
  • Loading branch information
Jozsef Kadlecsik authored and Patrick McHardy committed Jun 16, 2011
1 parent 483e9ea commit ac8cc92
Show file tree
Hide file tree
Showing 16 changed files with 206 additions and 134 deletions.
18 changes: 14 additions & 4 deletions include/linux/netfilter/ipset/ip_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,14 +217,23 @@ struct ip_set;
typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
u32 timeout, u32 flags);

/* Kernel API function options */
struct ip_set_adt_opt {
u8 family; /* Actual protocol family */
u8 dim; /* Dimension of match/target */
u8 flags; /* Direction and negation flags */
u32 cmdflags; /* Command-like flags */
u32 timeout; /* Timeout value */
};

/* Set type, variant-specific part */
struct ip_set_type_variant {
/* Kernelspace: test/add/del entries
* returns negative error code,
* zero for no match/success to add/delete
* positive for matching element */
int (*kadt)(struct ip_set *set, const struct sk_buff * skb,
enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
enum ipset_adt adt, const struct ip_set_adt_opt *opt);

/* Userspace: test/add/del entries
* returns negative error code,
Expand Down Expand Up @@ -314,12 +323,13 @@ extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);
extern void ip_set_nfnl_put(ip_set_id_t index);

/* API for iptables set match, and SET target */

extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,
u8 family, u8 dim, u8 flags);
const struct ip_set_adt_opt *opt);
extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
u8 family, u8 dim, u8 flags);
const struct ip_set_adt_opt *opt);
extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
u8 family, u8 dim, u8 flags);
const struct ip_set_adt_opt *opt);

/* Utility functions */
extern void * ip_set_alloc(size_t size);
Expand Down
2 changes: 1 addition & 1 deletion include/linux/netfilter/ipset/ip_set_ahash.h
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ type_pf_list(const struct ip_set *set,

static int
type_pf_kadt(struct ip_set *set, const struct sk_buff * skb,
enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
enum ipset_adt adt, const struct ip_set_adt_opt *opt);
static int
type_pf_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags);
Expand Down
3 changes: 3 additions & 0 deletions include/linux/netfilter/ipset/ip_set_timeout.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@

#define with_timeout(timeout) ((timeout) != IPSET_NO_TIMEOUT)

#define opt_timeout(opt, map) \
(with_timeout((opt)->timeout) ? (opt)->timeout : (map)->timeout)

static inline unsigned int
ip_set_timeout_uget(struct nlattr *tb)
{
Expand Down
15 changes: 12 additions & 3 deletions include/linux/netfilter/xt_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct xt_set_info_target_v0 {
struct xt_set_info_v0 del_set;
};

/* Revision 1: current interface to netfilter/iptables */
/* Revision 1 match and target */

struct xt_set_info {
ip_set_id_t index;
Expand All @@ -44,13 +44,22 @@ struct xt_set_info {
};

/* match and target infos */
struct xt_set_info_match {
struct xt_set_info_match_v1 {
struct xt_set_info match_set;
};

struct xt_set_info_target {
struct xt_set_info_target_v1 {
struct xt_set_info add_set;
struct xt_set_info del_set;
};

/* Revision 2 target */

struct xt_set_info_target_v2 {
struct xt_set_info add_set;
struct xt_set_info del_set;
u32 flags;
u32 timeout;
};

#endif /*_XT_SET_H*/
6 changes: 3 additions & 3 deletions net/netfilter/ipset/ip_set_bitmap_ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,19 +219,19 @@ bitmap_ip_tlist(const struct ip_set *set,

static int
bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
struct bitmap_ip *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
u32 ip;

ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
if (ip < map->first_ip || ip > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;

ip = ip_to_id(map, ip);

return adtfn(set, &ip, map->timeout, flags);
return adtfn(set, &ip, opt_timeout(opt, map), opt->cmdflags);
}

static int
Expand Down
8 changes: 4 additions & 4 deletions net/netfilter/ipset/ip_set_bitmap_ipmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,17 +338,17 @@ bitmap_ipmac_tlist(const struct ip_set *set,

static int
bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
struct bitmap_ipmac *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct ipmac data;

/* MAC can be src only */
if (!(flags & IPSET_DIM_TWO_SRC))
if (!(opt->flags & IPSET_DIM_TWO_SRC))
return 0;

data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
data.id = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
if (data.id < map->first_ip || data.id > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;

Expand All @@ -360,7 +360,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
data.id -= map->first_ip;
data.ether = eth_hdr(skb)->h_source;

return adtfn(set, &data, map->timeout, flags);
return adtfn(set, &data, opt_timeout(opt, map), opt->cmdflags);
}

static int
Expand Down
7 changes: 4 additions & 3 deletions net/netfilter/ipset/ip_set_bitmap_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,15 @@ bitmap_port_tlist(const struct ip_set *set,

static int
bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
struct bitmap_port *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
__be16 __port;
u16 port = 0;

if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
if (!ip_set_get_ip_port(skb, opt->family,
opt->flags & IPSET_DIM_ONE_SRC, &__port))
return -EINVAL;

port = ntohs(__port);
Expand All @@ -225,7 +226,7 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,

port -= map->first_port;

return adtfn(set, &port, map->timeout, flags);
return adtfn(set, &port, opt_timeout(opt, map), opt->cmdflags);
}

static int
Expand Down
26 changes: 13 additions & 13 deletions net/netfilter/ipset/ip_set_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,27 +325,27 @@ __ip_set_put(ip_set_id_t index)

int
ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
u8 family, u8 dim, u8 flags)
const struct ip_set_adt_opt *opt)
{
struct ip_set *set = ip_set_list[index];
int ret = 0;

BUG_ON(set == NULL);
pr_debug("set %s, index %u\n", set->name, index);

if (dim < set->type->dimension ||
!(family == set->family || set->family == AF_UNSPEC))
if (opt->dim < set->type->dimension ||
!(opt->family == set->family || set->family == AF_UNSPEC))
return 0;

read_lock_bh(&set->lock);
ret = set->variant->kadt(set, skb, IPSET_TEST, family, dim, flags);
ret = set->variant->kadt(set, skb, IPSET_TEST, opt);
read_unlock_bh(&set->lock);

if (ret == -EAGAIN) {
/* Type requests element to be completed */
pr_debug("element must be competed, ADD is triggered\n");
write_lock_bh(&set->lock);
set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags);
set->variant->kadt(set, skb, IPSET_ADD, opt);
write_unlock_bh(&set->lock);
ret = 1;
}
Expand All @@ -357,20 +357,20 @@ EXPORT_SYMBOL_GPL(ip_set_test);

int
ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
u8 family, u8 dim, u8 flags)
const struct ip_set_adt_opt *opt)
{
struct ip_set *set = ip_set_list[index];
int ret;

BUG_ON(set == NULL);
pr_debug("set %s, index %u\n", set->name, index);

if (dim < set->type->dimension ||
!(family == set->family || set->family == AF_UNSPEC))
if (opt->dim < set->type->dimension ||
!(opt->family == set->family || set->family == AF_UNSPEC))
return 0;

write_lock_bh(&set->lock);
ret = set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags);
ret = set->variant->kadt(set, skb, IPSET_ADD, opt);
write_unlock_bh(&set->lock);

return ret;
Expand All @@ -379,20 +379,20 @@ EXPORT_SYMBOL_GPL(ip_set_add);

int
ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
u8 family, u8 dim, u8 flags)
const struct ip_set_adt_opt *opt)
{
struct ip_set *set = ip_set_list[index];
int ret = 0;

BUG_ON(set == NULL);
pr_debug("set %s, index %u\n", set->name, index);

if (dim < set->type->dimension ||
!(family == set->family || set->family == AF_UNSPEC))
if (opt->dim < set->type->dimension ||
!(opt->family == set->family || set->family == AF_UNSPEC))
return 0;

write_lock_bh(&set->lock);
ret = set->variant->kadt(set, skb, IPSET_DEL, family, dim, flags);
ret = set->variant->kadt(set, skb, IPSET_DEL, opt);
write_unlock_bh(&set->lock);

return ret;
Expand Down
12 changes: 6 additions & 6 deletions net/netfilter/ipset/ip_set_hash_ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,18 @@ hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data)

static int
hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
__be32 ip;

ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip);
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip);
ip &= ip_set_netmask(h->netmask);
if (ip == 0)
return -EINVAL;

return adtfn(set, &ip, h->timeout, flags);
return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags);
}

static int
Expand Down Expand Up @@ -283,18 +283,18 @@ hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data)

static int
hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
union nf_inet_addr ip;

ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip.in6);
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip.in6);
ip6_netmask(&ip, h->netmask);
if (ipv6_addr_any(&ip.in6))
return -EINVAL;

return adtfn(set, &ip, h->timeout, flags);
return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags);
}

static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
Expand Down
16 changes: 8 additions & 8 deletions net/netfilter/ipset/ip_set_hash_ipport.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,19 +126,19 @@ hash_ipport4_data_tlist(struct sk_buff *skb,

static int
hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport4_elem data = { };

if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;

ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);

return adtfn(set, &data, h->timeout, flags);
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}

static int
Expand Down Expand Up @@ -330,19 +330,19 @@ hash_ipport6_data_tlist(struct sk_buff *skb,

static int
hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport6_elem data = { };

if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;

ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);

return adtfn(set, &data, h->timeout, flags);
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}

static int
Expand Down
Loading

0 comments on commit ac8cc92

Please sign in to comment.