From 280fe2d4eecb2a546087fbf28bb45168f96d8d52 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Mon, 21 Sep 2020 20:13:07 +0200 Subject: Expose the initval hash parameter to userspace It makes possible to reproduce exactly the same set after a save/restore. Signed-off-by: Jozsef Kadlecsik --- lib/args.c | 8 ++++++++ lib/data.c | 12 ++++++------ lib/debug.c | 2 +- lib/ipset_hash_ip.c | 3 ++- lib/ipset_hash_ipmac.c | 3 ++- lib/ipset_hash_ipmark.c | 3 ++- lib/ipset_hash_ipport.c | 3 ++- lib/ipset_hash_ipportip.c | 3 ++- lib/ipset_hash_ipportnet.c | 3 ++- lib/ipset_hash_mac.c | 3 ++- lib/ipset_hash_net.c | 3 ++- lib/ipset_hash_netiface.c | 3 ++- lib/ipset_hash_netnet.c | 3 ++- lib/ipset_hash_netport.c | 3 ++- lib/ipset_hash_netportnet.c | 3 ++- lib/libipset.map | 6 ++++++ lib/print.c | 46 ++++++++++++++++++++++++++++++++++++++++++++- lib/session.c | 4 ++-- 18 files changed, 92 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/args.c b/lib/args.c index ab1022e..bab3b13 100644 --- a/lib/args.c +++ b/lib/args.c @@ -292,6 +292,14 @@ static const struct ipset_arg ipset_args[] = { .print = ipset_print_number, .help = "[bucketsize VALUE]", }, + [IPSET_ARG_INITVAL] = { + .name = { "initval", NULL }, + .has_arg = IPSET_MANDATORY_ARG, + .opt = IPSET_OPT_INITVAL, + .parse = ipset_parse_uint32, + .print = ipset_print_hexnumber, + .help = "[initval VALUE]", + }, }; const struct ipset_arg * diff --git a/lib/data.c b/lib/data.c index 43b6f71..7720178 100644 --- a/lib/data.c +++ b/lib/data.c @@ -56,7 +56,7 @@ struct ipset_data { uint32_t hashsize; uint32_t maxelem; uint32_t markmask; - uint32_t gc; + uint32_t initval; uint32_t size; /* Filled out by kernel */ uint32_t references; @@ -286,8 +286,8 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value) data->index = *(const uint16_t *) value; break; /* Create-specific options */ - case IPSET_OPT_GC: - data->create.gc = *(const uint32_t *) value; + case IPSET_OPT_INITVAL: + data->create.initval = *(const uint32_t *) value; break; case IPSET_OPT_HASHSIZE: data->create.hashsize = *(const uint32_t *) value; @@ -498,8 +498,8 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt) case IPSET_OPT_INDEX: return &data->index; /* Create-specific options */ - case IPSET_OPT_GC: - return &data->create.gc; + case IPSET_OPT_INITVAL: + return &data->create.initval; case IPSET_OPT_HASHSIZE: return &data->create.hashsize; case IPSET_OPT_MAXELEM: @@ -608,7 +608,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family) case IPSET_OPT_NAMEREF: return IPSET_MAXNAMELEN; case IPSET_OPT_TIMEOUT: - case IPSET_OPT_GC: + case IPSET_OPT_INITVAL: case IPSET_OPT_HASHSIZE: case IPSET_OPT_MAXELEM: case IPSET_OPT_MARKMASK: diff --git a/lib/debug.c b/lib/debug.c index 89073b8..bf57a41 100644 --- a/lib/debug.c +++ b/lib/debug.c @@ -35,7 +35,7 @@ static const struct ipset_attrname createattr2name[] = { [IPSET_ATTR_PROTO] = { .name = "PROTO" }, [IPSET_ATTR_CADT_FLAGS] = { .name = "CADT_FLAGS" }, [IPSET_ATTR_CADT_LINENO] = { .name = "CADT_LINENO" }, - [IPSET_ATTR_GC] = { .name = "GC" }, + [IPSET_ATTR_INITVAL] = { .name = "INITVAL" }, [IPSET_ATTR_HASHSIZE] = { .name = "HASHSIZE" }, [IPSET_ATTR_MAXELEM] = { .name = "MAXELEM" }, [IPSET_ATTR_MARKMASK] = { .name = "MARKMASK" }, diff --git a/lib/ipset_hash_ip.c b/lib/ipset_hash_ip.c index 470a807..ea85700 100644 --- a/lib/ipset_hash_ip.c +++ b/lib/ipset_hash_ip.c @@ -423,6 +423,7 @@ static struct ipset_type ipset_hash_ip5 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, /* Ignored options: backward compatibilty */ IPSET_ARG_PROBES, IPSET_ARG_RESIZE, @@ -473,7 +474,7 @@ static struct ipset_type ipset_hash_ip5 = { " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" " is supported for IPv4.", - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/ipset_hash_ipmac.c b/lib/ipset_hash_ipmac.c index e491e64..c15897b 100644 --- a/lib/ipset_hash_ipmac.c +++ b/lib/ipset_hash_ipmac.c @@ -125,6 +125,7 @@ static struct ipset_type ipset_hash_ipmac1 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, }, .need = 0, .full = 0, @@ -171,7 +172,7 @@ static struct ipset_type ipset_hash_ipmac1 = { .usage = "where depending on the INET family\n" " IP is a valid IPv4 or IPv6 address (or hostname),\n" " MAC is a MAC address.", - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/ipset_hash_ipmark.c b/lib/ipset_hash_ipmark.c index 941ce5d..7d6d977 100644 --- a/lib/ipset_hash_ipmark.c +++ b/lib/ipset_hash_ipmark.c @@ -324,6 +324,7 @@ static struct ipset_type ipset_hash_ipmark3 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, /* Ignored options: backward compatibilty */ IPSET_ARG_PROBES, IPSET_ARG_RESIZE, @@ -383,7 +384,7 @@ static struct ipset_type ipset_hash_ipmark3 = { " is supported for IPv4.\n" " Adding/deleting single mark element\n" " is supported both for IPv4 and IPv6.", - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/ipset_hash_ipport.c b/lib/ipset_hash_ipport.c index cb8832e..288be10 100644 --- a/lib/ipset_hash_ipport.c +++ b/lib/ipset_hash_ipport.c @@ -533,6 +533,7 @@ static struct ipset_type ipset_hash_ipport6 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, /* Ignored options: backward compatibilty */ IPSET_ARG_PROBES, IPSET_ARG_RESIZE, @@ -600,7 +601,7 @@ static struct ipset_type ipset_hash_ipport6 = { " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" " port range is supported both for IPv4 and IPv6.", .usagefn = ipset_port_usage, - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/ipset_hash_ipportip.c b/lib/ipset_hash_ipportip.c index bc23c21..6b2e92e 100644 --- a/lib/ipset_hash_ipportip.c +++ b/lib/ipset_hash_ipportip.c @@ -593,6 +593,7 @@ static struct ipset_type ipset_hash_ipportip6 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, /* Ignored options: backward compatibilty */ IPSET_ARG_PROBES, IPSET_ARG_RESIZE, @@ -666,7 +667,7 @@ static struct ipset_type ipset_hash_ipportip6 = { " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" " port range is supported both for IPv4 and IPv6.", .usagefn = ipset_port_usage, - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/ipset_hash_ipportnet.c b/lib/ipset_hash_ipportnet.c index b2b4651..2552cdb 100644 --- a/lib/ipset_hash_ipportnet.c +++ b/lib/ipset_hash_ipportnet.c @@ -851,6 +851,7 @@ static struct ipset_type ipset_hash_ipportnet8 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, /* Ignored options: backward compatibilty */ IPSET_ARG_PROBES, IPSET_ARG_RESIZE, @@ -932,7 +933,7 @@ static struct ipset_type ipset_hash_ipportnet8 = { " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" " port range is supported both for IPv4 and IPv6.", .usagefn = ipset_port_usage, - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/ipset_hash_mac.c b/lib/ipset_hash_mac.c index b1e7991..4b20247 100644 --- a/lib/ipset_hash_mac.c +++ b/lib/ipset_hash_mac.c @@ -100,6 +100,7 @@ static struct ipset_type ipset_hash_mac1 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, IPSET_ARG_NONE, }, .need = 0, @@ -139,7 +140,7 @@ static struct ipset_type ipset_hash_mac1 = { }, }, .usage = "", - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/ipset_hash_net.c b/lib/ipset_hash_net.c index a943ea6..1da95bf 100644 --- a/lib/ipset_hash_net.c +++ b/lib/ipset_hash_net.c @@ -560,6 +560,7 @@ static struct ipset_type ipset_hash_net7 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, /* Ignored options: backward compatibilty */ IPSET_ARG_PROBES, IPSET_ARG_RESIZE, @@ -611,7 +612,7 @@ static struct ipset_type ipset_hash_net7 = { .usage = "where depending on the INET family\n" " IP is an IPv4 or IPv6 address (or hostname),\n" " CIDR is a valid IPv4 or IPv6 CIDR prefix.", - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/ipset_hash_netiface.c b/lib/ipset_hash_netiface.c index 7a720c6..172c2a9 100644 --- a/lib/ipset_hash_netiface.c +++ b/lib/ipset_hash_netiface.c @@ -749,6 +749,7 @@ static struct ipset_type ipset_hash_netiface8 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, IPSET_ARG_NONE, }, .need = 0, @@ -808,7 +809,7 @@ static struct ipset_type ipset_hash_netiface8 = { " IP is a valid IPv4 or IPv6 address (or hostname),\n" " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" " Adding/deleting multiple elements with IPv4 is supported.", - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/ipset_hash_netnet.c b/lib/ipset_hash_netnet.c index e1da9ec..df993b8 100644 --- a/lib/ipset_hash_netnet.c +++ b/lib/ipset_hash_netnet.c @@ -323,6 +323,7 @@ static struct ipset_type ipset_hash_netnet3 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, IPSET_ARG_NONE, }, .need = 0, @@ -383,7 +384,7 @@ static struct ipset_type ipset_hash_netnet3 = { " IP is an IPv4 or IPv6 address (or hostname),\n" " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" " IP range is not supported with IPv6.", - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/ipset_hash_netport.c b/lib/ipset_hash_netport.c index 2d08085..f09de83 100644 --- a/lib/ipset_hash_netport.c +++ b/lib/ipset_hash_netport.c @@ -699,6 +699,7 @@ static struct ipset_type ipset_hash_netport8 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, IPSET_ARG_NONE, }, .need = 0, @@ -764,7 +765,7 @@ static struct ipset_type ipset_hash_netport8 = { " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" " port range is supported both for IPv4 and IPv6.", .usagefn = ipset_port_usage, - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/ipset_hash_netportnet.c b/lib/ipset_hash_netportnet.c index e456fb1..a4a7240 100644 --- a/lib/ipset_hash_netportnet.c +++ b/lib/ipset_hash_netportnet.c @@ -397,6 +397,7 @@ static struct ipset_type ipset_hash_netportnet3 = { IPSET_ARG_FORCEADD, IPSET_ARG_SKBINFO, IPSET_ARG_BUCKETSIZE, + IPSET_ARG_INITVAL, IPSET_ARG_NONE, }, .need = 0, @@ -475,7 +476,7 @@ static struct ipset_type ipset_hash_netportnet3 = { " Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" " port range is supported both for IPv4 and IPv6.", .usagefn = ipset_port_usage, - .description = "bucketsize support", + .description = "bucketsize, initval support", }; void _init(void); diff --git a/lib/libipset.map b/lib/libipset.map index 7a4a33c..12d16a4 100644 --- a/lib/libipset.map +++ b/lib/libipset.map @@ -202,3 +202,9 @@ global: ipset_session_report_msg; ipset_session_report_type; } LIBIPSET_4.8; + +LIBIPSET_4.10 { +global: + ipset_print_hexnumber; +} LIBIPSET_4.9; + diff --git a/lib/print.c b/lib/print.c index d1d5a20..0d86a98 100644 --- a/lib/print.c +++ b/lib/print.c @@ -396,6 +396,50 @@ ipset_print_number(char *buf, unsigned int len, return 0; } +/** + * ipset_print_hexnumber - print number in hex to string + * @buf: printing buffer + * @len: length of available buffer space + * @data: data blob + * @opt: the option kind + * @env: environment flags + * + * Print number in hex to output buffer. + * + * Return lenght of printed string or error size. + */ +int +ipset_print_hexnumber(char *buf, unsigned int len, + const struct ipset_data *data, enum ipset_opt opt, + uint8_t env UNUSED) +{ + size_t maxsize; + const void *number; + + assert(buf); + assert(len > 0); + assert(data); + + number = ipset_data_get(data, opt); + maxsize = ipset_data_sizeof(opt, AF_INET); + D("opt: %u, maxsize %zu", opt, maxsize); + if (maxsize == sizeof(uint8_t)) + return snprintf(buf, len, "0x%02"PRIx8, + *(const uint8_t *) number); + else if (maxsize == sizeof(uint16_t)) + return snprintf(buf, len, "0x%04"PRIx16, + *(const uint16_t *) number); + else if (maxsize == sizeof(uint32_t)) + return snprintf(buf, len, "0x%08"PRIx32, + (long unsigned) *(const uint32_t *) number); + else if (maxsize == sizeof(uint64_t)) + return snprintf(buf, len, "0x016lx", + (long long unsigned) *(const uint64_t *) number); + else + assert(0); + return 0; +} + /** * ipset_print_name - print setname element string * @buf: printing buffer @@ -940,7 +984,7 @@ ipset_print_data(char *buf, unsigned int len, case IPSET_OPT_IFACE: size = ipset_print_iface(buf, len, data, opt, env); break; - case IPSET_OPT_GC: + case IPSET_OPT_INITVAL: case IPSET_OPT_HASHSIZE: case IPSET_OPT_MAXELEM: case IPSET_OPT_MARKMASK: diff --git a/lib/session.c b/lib/session.c index 8416308..b088bc8 100644 --- a/lib/session.c +++ b/lib/session.c @@ -418,9 +418,9 @@ static const struct ipset_attr_policy create_attrs[] = { .type = MNL_TYPE_U32, .opt = IPSET_OPT_CADT_FLAGS, }, - [IPSET_ATTR_GC] = { + [IPSET_ATTR_INITVAL] = { .type = MNL_TYPE_U32, - .opt = IPSET_OPT_GC, + .opt = IPSET_OPT_INITVAL, }, [IPSET_ATTR_HASHSIZE] = { .type = MNL_TYPE_U32, -- cgit v1.2.3