From: Patrick McHardy <kaber@trash.net>
To: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Cc: netfilter-devel@vger.kernel.org, Pablo Neira Ayuso <pablo@netfilter.org>
Subject: Re: [PATCH 03/13] bitmap:ip set type support
Date: Tue, 25 Jan 2011 16:05:26 +0100 [thread overview]
Message-ID: <4D3EE6B6.8090008@trash.net> (raw)
In-Reply-To: <1295618527-9583-4-git-send-email-kadlec@blackhole.kfki.hu>
On 21.01.2011 15:01, Jozsef Kadlecsik wrote:
> diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c
> new file mode 100644
> index 0000000..4fbb360
> --- /dev/null
> +++ b/net/netfilter/ipset/ip_set_bitmap_ip.c
> +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,
> + enum ipset_adt adt, u32 *lineno, u32 flags)
> +{
> + struct bitmap_ip *map = set->data;
> + struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
> + u32 ip, ip_to, id;
> + int ret = 0;
> +
> + if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
> + bitmap_ip_adt_policy))
You can simply pass the container attribute instead of the
contents and length from ip_set_core.c and use nla_parse_nested().
This could even be done centrally in ip_set_core.c and you
just hand a set of parsed and validated attributes to this
function. Basically what you would do is:
- add nla_policy member to the ip_set_type_variant structure
- add type/variant specific max_attribute member to the
ip_set_type_variant structure
initialize both appropriately for each set type variant.
In ip_set_core.c, do:
struct nlattr *nla[set->variant->maxattr + 1];
err = nla_parse_nested(nla, set->variant->maxattr,
attr[IPSET_ATTR_DATA],
set->variant->policy);
if (err < 0)
return err;
set->variant->uadt(..., nla, ...)
That way you avoid duplicating the parsing in every set type.
> + return -IPSET_ERR_PROTOCOL;
> +
> + if (unlikely(!tb[IPSET_ATTR_IP]))
> + return -IPSET_ERR_PROTOCOL;
> +
> + if (tb[IPSET_ATTR_LINENO])
> + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
> +
> + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
> + if (ret)
> + return ret;
> +
> + 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 (adt == IPSET_TEST)
> + return bitmap_ip_test(map, ip_to_id(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;
> +
> + 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);
> +
> + if (ret && !ip_set_eexist(ret, flags))
> + return ret;
> + else
> + ret = 0;
> + }
> + return ret;
> +}
> +
> +static void
> +bitmap_ip_destroy(struct ip_set *set)
> +{
> + struct bitmap_ip *map = set->data;
> +
> + ip_set_free(map->members);
> + kfree(map);
> +
> + set->data = NULL;
> +}
> +
> +static void
> +bitmap_ip_flush(struct ip_set *set)
> +{
> + struct bitmap_ip *map = set->data;
> +
> + memset(map->members, 0, map->memsize);
> +}
> +
> +static int
> +bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
> +{
> + const struct bitmap_ip *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_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;
Same as in ip_set_core, this should be EMSGSIZE (probably applies
to all set types).
> +}
> +
> +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;
Same here.
> + 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;
And here.
> + } 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;
Doesn't this need to return an errno value to indicate that the
dump is incomplete?
> +/* 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 */
There's a lot of duplicated code just because the structures are
different. It seems this could be avoided if the common members
were in a common structure and just the timeout and timer_list
members were specific to the timeout variant.
next prev parent reply other threads:[~2011-01-25 15:05 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-01-21 14:01 [PATCH 00/13] ipset kernel patches v2 Jozsef Kadlecsik
2011-01-21 14:01 ` [PATCH 01/13] NFNL_SUBSYS_IPSET id and NLA_PUT_NET* macros Jozsef Kadlecsik
2011-01-21 14:01 ` [PATCH 02/13] IP set core support Jozsef Kadlecsik
2011-01-21 14:01 ` [PATCH 03/13] bitmap:ip set type support Jozsef Kadlecsik
2011-01-21 14:01 ` [PATCH 04/13] bitmap:ip,mac " Jozsef Kadlecsik
2011-01-21 14:01 ` [PATCH 05/13] bitmap:port set " Jozsef Kadlecsik
2011-01-21 14:01 ` [PATCH 06/13] hash:ip " Jozsef Kadlecsik
2011-01-21 14:02 ` [PATCH 07/13] hash:ip,port " Jozsef Kadlecsik
2011-01-21 14:02 ` [PATCH 08/13] hash:ip,port,ip " Jozsef Kadlecsik
2011-01-21 14:02 ` [PATCH 09/13] hash:ip,port,net " Jozsef Kadlecsik
2011-01-21 14:02 ` [PATCH 10/13] hash:net " Jozsef Kadlecsik
2011-01-21 14:02 ` [PATCH 11/13] hash:net,port " Jozsef Kadlecsik
2011-01-21 14:02 ` [PATCH 12/13] list:set " Jozsef Kadlecsik
2011-01-21 14:02 ` [PATCH 13/13] "set" match and "SET" target support Jozsef Kadlecsik
2011-01-25 15:18 ` Patrick McHardy
2011-01-25 21:40 ` Jozsef Kadlecsik
2011-01-25 15:05 ` Patrick McHardy [this message]
2011-01-25 21:34 ` [PATCH 03/13] bitmap:ip set type support Jozsef Kadlecsik
2011-01-27 9:06 ` Jozsef Kadlecsik
2011-01-27 9:08 ` Patrick McHardy
2011-01-21 21:39 ` [PATCH 02/13] IP set core support Jozsef Kadlecsik
2011-01-25 14:47 ` Patrick McHardy
2011-01-25 21:23 ` Jozsef Kadlecsik
2011-01-26 11:57 ` Patrick McHardy
2011-01-26 11:57 ` Patrick McHardy
2011-01-25 15:06 ` Patrick McHardy
2011-01-25 21:28 ` Jozsef Kadlecsik
2011-01-27 8:58 ` Jozsef Kadlecsik
2011-01-25 15:38 ` [PATCH 00/13] ipset kernel patches v2 Patrick McHardy
2011-01-25 21:41 ` Jozsef Kadlecsik
-- strict thread matches above, loose matches on Subject: below --
2011-01-31 22:52 [PATCH 00/13] ipset kernel patches v3 Jozsef Kadlecsik
2011-01-31 22:52 ` [PATCH 01/13] NFNL_SUBSYS_IPSET id and NLA_PUT_NET* macros Jozsef Kadlecsik
2011-01-31 22:52 ` [PATCH 02/13] IP set core support Jozsef Kadlecsik
2011-01-31 22:52 ` [PATCH 03/13] bitmap:ip set type support Jozsef Kadlecsik
2011-02-01 14:34 ` Patrick McHardy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4D3EE6B6.8090008@trash.net \
--to=kaber@trash.net \
--cc=kadlec@blackhole.kfki.hu \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).