summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/data.c23
-rw-r--r--lib/errcode.c2
-rw-r--r--lib/libipset.map5
-rw-r--r--lib/parse.c28
-rw-r--r--lib/print.c3
-rw-r--r--lib/session.c30
6 files changed, 89 insertions, 2 deletions
diff --git a/lib/data.c b/lib/data.c
index 1973307..04a5997 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -73,6 +73,8 @@ struct ipset_data {
char name[IPSET_MAXNAMELEN];
char nameref[IPSET_MAXNAMELEN];
char iface[IFNAMSIZ];
+ uint64_t packets;
+ uint64_t bytes;
} adt;
};
};
@@ -273,6 +275,9 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
case IPSET_OPT_SIZE:
data->create.size = *(const uint32_t *) value;
break;
+ case IPSET_OPT_COUNTERS:
+ cadt_flag_type_attr(data, opt, IPSET_FLAG_WITH_COUNTERS);
+ break;
/* Create-specific options, filled out by the kernel */
case IPSET_OPT_ELEMENTS:
data->create.elements = *(const uint32_t *) value;
@@ -325,6 +330,12 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
case IPSET_OPT_IFACE:
ipset_strlcpy(data->adt.iface, value, IFNAMSIZ);
break;
+ case IPSET_OPT_PACKETS:
+ data->adt.packets = *(const uint64_t *) value;
+ break;
+ case IPSET_OPT_BYTES:
+ data->adt.bytes = *(const uint64_t *) value;
+ break;
/* Swap/rename */
case IPSET_OPT_SETNAME2:
ipset_strlcpy(data->setname2, value, IPSET_MAXNAMELEN);
@@ -356,6 +367,9 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
if (data->cadt_flags & IPSET_FLAG_NOMATCH)
ipset_data_flags_set(data,
IPSET_FLAG(IPSET_OPT_NOMATCH));
+ if (data->cadt_flags & IPSET_FLAG_WITH_COUNTERS)
+ ipset_data_flags_set(data,
+ IPSET_FLAG(IPSET_OPT_COUNTERS));
break;
default:
return -1;
@@ -454,6 +468,10 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
return &data->adt.proto;
case IPSET_OPT_IFACE:
return &data->adt.iface;
+ case IPSET_OPT_PACKETS:
+ return &data->adt.packets;
+ case IPSET_OPT_BYTES:
+ return &data->adt.bytes;
/* Swap/rename */
case IPSET_OPT_SETNAME2:
return data->setname2;
@@ -465,6 +483,7 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
case IPSET_OPT_BEFORE:
case IPSET_OPT_PHYSDEV:
case IPSET_OPT_NOMATCH:
+ case IPSET_OPT_COUNTERS:
return &data->cadt_flags;
default:
return NULL;
@@ -506,6 +525,9 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
case IPSET_OPT_REFERENCES:
case IPSET_OPT_MEMSIZE:
return sizeof(uint32_t);
+ case IPSET_OPT_PACKETS:
+ case IPSET_OPT_BYTES:
+ return sizeof(uint64_t);
case IPSET_OPT_CIDR:
case IPSET_OPT_CIDR2:
case IPSET_OPT_NETMASK:
@@ -519,6 +541,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
case IPSET_OPT_BEFORE:
case IPSET_OPT_PHYSDEV:
case IPSET_OPT_NOMATCH:
+ case IPSET_OPT_COUNTERS:
return sizeof(uint32_t);
default:
return 0;
diff --git a/lib/errcode.c b/lib/errcode.c
index 1ce5c00..027a736 100644
--- a/lib/errcode.c
+++ b/lib/errcode.c
@@ -70,6 +70,8 @@ static const struct ipset_errcode_table core_errcode_table[] = {
"An IPv4 address is expected, but not received" },
{ IPSET_ERR_IPADDR_IPV6, 0,
"An IPv6 address is expected, but not received" },
+ { IPSET_ERR_COUNTER, 0,
+ "Packet/byte counters cannot be used: set was created without counter support" },
/* ADD specific error codes */
{ IPSET_ERR_EXIST, IPSET_CMD_ADD,
diff --git a/lib/libipset.map b/lib/libipset.map
index 689ccb0..271fe59 100644
--- a/lib/libipset.map
+++ b/lib/libipset.map
@@ -122,3 +122,8 @@ LIBIPSET_3.0 {
global:
ipset_session_outfn;
} LIBIPSET_2.0;
+
+LIBIPSET_4.0 {
+global:
+ ipset_parse_uint64;
+} LIBIPSET_3.0;
diff --git a/lib/parse.c b/lib/parse.c
index 679aefc..0058369 100644
--- a/lib/parse.c
+++ b/lib/parse.c
@@ -1479,6 +1479,34 @@ ipset_parse_after(struct ipset_session *session,
}
/**
+ * ipset_parse_uint64 - parse string as an unsigned long integer
+ * @session: session structure
+ * @opt: option kind of the data
+ * @str: string to parse
+ *
+ * Parse string as an unsigned long integer number.
+ * The value is stored in the data blob of the session.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int
+ipset_parse_uint64(struct ipset_session *session,
+ enum ipset_opt opt, const char *str)
+{
+ unsigned long long value = 0;
+ int err;
+
+ assert(session);
+ assert(str);
+
+ err = string_to_number_ll(session, str, 0, ULLONG_MAX - 1, &value);
+ if (err)
+ return err;
+
+ return ipset_session_data_set(session, opt, &value);
+}
+
+/**
* ipset_parse_uint32 - parse string as an unsigned integer
* @session: session structure
* @opt: option kind of the data
diff --git a/lib/print.c b/lib/print.c
index 1bd8392..86a7674 100644
--- a/lib/print.c
+++ b/lib/print.c
@@ -387,6 +387,9 @@ ipset_print_number(char *buf, unsigned int len,
else if (maxsize == sizeof(uint32_t))
return snprintf(buf, len, "%lu",
(long unsigned) *(const uint32_t *) number);
+ else if (maxsize == sizeof(uint64_t))
+ return snprintf(buf, len, "%llu",
+ (long long unsigned) *(const uint64_t *) number);
else
assert(0);
return 0;
diff --git a/lib/session.c b/lib/session.c
index 03c1098..4f0b802 100644
--- a/lib/session.c
+++ b/lib/session.c
@@ -5,6 +5,7 @@
* published by the Free Software Foundation.
*/
#include <assert.h> /* assert */
+#include <endian.h> /* htobe64 */
#include <errno.h> /* errno */
#include <setjmp.h> /* setjmp, longjmp */
#include <stdio.h> /* snprintf */
@@ -479,6 +480,14 @@ static const struct ipset_attr_policy adt_attrs[] = {
.opt = IPSET_OPT_IFACE,
.len = IFNAMSIZ,
},
+ [IPSET_ATTR_PACKETS] = {
+ .type = MNL_TYPE_U64,
+ .opt = IPSET_OPT_PACKETS,
+ },
+ [IPSET_ATTR_BYTES] = {
+ .type = MNL_TYPE_U64,
+ .opt = IPSET_OPT_BYTES,
+ },
};
static const struct ipset_attr_policy ipaddr_attrs[] = {
@@ -550,6 +559,7 @@ attr2data(struct ipset_session *session, struct nlattr *nla[],
struct ipset_data *data = session->data;
const struct ipset_attr_policy *attr;
const void *d;
+ uint64_t v64;
uint32_t v32;
uint16_t v16;
int ret;
@@ -599,6 +609,11 @@ attr2data(struct ipset_session *session, struct nlattr *nla[],
} else if (nla[type]->nla_type & NLA_F_NET_BYTEORDER) {
D("netorder attr type %u", type);
switch (attr->type) {
+ case MNL_TYPE_U64: {
+ v64 = be64toh(*(const uint64_t *)d);
+ d = &v64;
+ break;
+ }
case MNL_TYPE_U32: {
v32 = ntohl(*(const uint32_t *)d);
d = &v32;
@@ -773,8 +788,10 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
safe_dprintf(session, ipset_print_elem, IPSET_OPT_ELEM);
- for (arg = type->args[IPSET_ADD]; arg != NULL && arg->print; arg++) {
- if (!ipset_data_test(data, arg->opt))
+ for (arg = type->args[IPSET_ADD]; arg != NULL && arg->opt; arg++) {
+ D("print arg opt %u %s\n", arg->opt,
+ ipset_data_test(data, arg->opt) ? "(yes)" : "(missing)");
+ if (!(arg->print && ipset_data_test(data, arg->opt)))
continue;
switch (session->mode) {
case IPSET_LIST_SAVE:
@@ -1413,6 +1430,9 @@ attr_len(const struct ipset_attr_policy *attr, uint8_t family, uint16_t *flags)
*flags = NLA_F_NET_BYTEORDER;
return family == NFPROTO_IPV4 ? sizeof(uint32_t)
: sizeof(struct in6_addr);
+ case MNL_TYPE_U64:
+ *flags = NLA_F_NET_BYTEORDER;
+ return sizeof(uint64_t);
case MNL_TYPE_U32:
*flags = NLA_F_NET_BYTEORDER;
return sizeof(uint32_t);
@@ -1465,6 +1485,12 @@ rawdata2attr(struct ipset_session *session, struct nlmsghdr *nlh,
return 1;
switch (attr->type) {
+ case MNL_TYPE_U64: {
+ uint64_t value = htobe64(*(const uint64_t *)d);
+
+ mnl_attr_put(nlh, type | flags, alen, &value);
+ return 0;
+ }
case MNL_TYPE_U32: {
uint32_t value = htonl(*(const uint32_t *)d);