summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/data.c8
-rw-r--r--lib/debug.c1
-rw-r--r--lib/ipset_hash_ipmark.c168
-rw-r--r--lib/libipset.map6
-rw-r--r--lib/parse.c30
-rw-r--r--lib/print.c35
-rw-r--r--lib/session.c4
8 files changed, 253 insertions, 0 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 2234670..6398be4 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -6,6 +6,7 @@ IPSET_SETTYPE_LIST = \
ipset_bitmap_port.c \
ipset_hash_ip.c \
ipset_hash_ipport.c \
+ ipset_hash_ipmark.c \
ipset_hash_ipportip.c \
ipset_hash_ipportnet.c \
ipset_hash_net.c \
diff --git a/lib/data.c b/lib/data.c
index ba4ed57..1f74cd5 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -41,6 +41,7 @@ struct ipset_data {
uint32_t timeout;
union nf_inet_addr ip;
union nf_inet_addr ip_to;
+ uint32_t mark;
uint16_t port;
uint16_t port_to;
union {
@@ -264,6 +265,9 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
case IPSET_OPT_CIDR:
data->cidr = *(const uint8_t *) value;
break;
+ case IPSET_OPT_MARK:
+ data->mark = *(const uint32_t *) value;
+ break;
case IPSET_OPT_PORT:
data->port = *(const uint16_t *) value;
break;
@@ -448,6 +452,8 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
return &data->ip_to;
case IPSET_OPT_CIDR:
return &data->cidr;
+ case IPSET_OPT_MARK:
+ return &data->mark;
case IPSET_OPT_PORT:
return &data->port;
case IPSET_OPT_PORT_TO:
@@ -542,6 +548,8 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
case IPSET_OPT_IP2_TO:
return family == NFPROTO_IPV4 ? sizeof(uint32_t)
: sizeof(struct in6_addr);
+ case IPSET_OPT_MARK:
+ return sizeof(uint32_t);
case IPSET_OPT_PORT:
case IPSET_OPT_PORT_TO:
return sizeof(uint16_t);
diff --git a/lib/debug.c b/lib/debug.c
index a204940..9a3c6b8 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -51,6 +51,7 @@ static const struct ipset_attrname adtattr2name[] = {
[IPSET_ATTR_IP] = { .name = "IP" },
[IPSET_ATTR_IP_TO] = { .name = "IP_TO" },
[IPSET_ATTR_CIDR] = { .name = "CIDR" },
+ [IPSET_ATTR_MARK] = { .name = "MARK" },
[IPSET_ATTR_PORT] = { .name = "PORT" },
[IPSET_ATTR_PORT_TO] = { .name = "PORT_TO" },
[IPSET_ATTR_TIMEOUT] = { .name = "TIMEOUT" },
diff --git a/lib/ipset_hash_ipmark.c b/lib/ipset_hash_ipmark.c
new file mode 100644
index 0000000..6976371
--- /dev/null
+++ b/lib/ipset_hash_ipmark.c
@@ -0,0 +1,168 @@
+/* Copyright 2007-2013 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+ * Copyright 2013 Smoothwall Ltd. (vytas.dauksa@smoothwall.net)
+ *
+ * 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
+ * published by the Free Software Foundation.
+ */
+#include <libipset/data.h> /* IPSET_OPT_* */
+#include <libipset/parse.h> /* parser functions */
+#include <libipset/print.h> /* printing functions */
+#include <libipset/types.h> /* prototypes */
+
+/* Parse commandline arguments */
+static const struct ipset_arg hash_ipmark_create_args0[] = {
+ { .name = { "family", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
+ .parse = ipset_parse_family, .print = ipset_print_family,
+ },
+ /* Alias: family inet */
+ { .name = { "-4", NULL },
+ .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
+ .parse = ipset_parse_family,
+ },
+ /* Alias: family inet6 */
+ { .name = { "-6", NULL },
+ .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
+ .parse = ipset_parse_family,
+ },
+ { .name = { "hashsize", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
+ .parse = ipset_parse_uint32, .print = ipset_print_number,
+ },
+ { .name = { "maxelem", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
+ .parse = ipset_parse_uint32, .print = ipset_print_number,
+ },
+ { .name = { "timeout", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
+ .parse = ipset_parse_timeout, .print = ipset_print_number,
+ },
+ { .name = { "counters", NULL },
+ .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_COUNTERS,
+ .parse = ipset_parse_flag, .print = ipset_print_flag,
+ },
+ { .name = { "comment", NULL },
+ .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_CREATE_COMMENT,
+ .parse = ipset_parse_flag, .print = ipset_print_flag,
+ },
+ /* Backward compatibility */
+ { .name = { "probes", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES,
+ .parse = ipset_parse_ignored, .print = ipset_print_number,
+ },
+ { .name = { "resize", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE,
+ .parse = ipset_parse_ignored, .print = ipset_print_number,
+ },
+ { .name = { "from", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
+ .parse = ipset_parse_ignored,
+ },
+ { .name = { "to", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO,
+ .parse = ipset_parse_ignored,
+ },
+ { .name = { "network", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
+ .parse = ipset_parse_ignored,
+ },
+ { },
+};
+
+static const struct ipset_arg hash_ipmark_add_args0[] = {
+ { .name = { "timeout", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
+ .parse = ipset_parse_timeout, .print = ipset_print_number,
+ },
+ { .name = { "packets", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PACKETS,
+ .parse = ipset_parse_uint64, .print = ipset_print_number,
+ },
+ { .name = { "bytes", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_BYTES,
+ .parse = ipset_parse_uint64, .print = ipset_print_number,
+ },
+ { .name = { "comment", NULL },
+ .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_ADT_COMMENT,
+ .parse = ipset_parse_comment, .print = ipset_print_comment,
+ },
+ { },
+};
+
+static const char hash_ipmark_usage0[] =
+"create SETNAME hash:ip,mark\n"
+" [family inet|inet6]\n"
+" [hashsize VALUE] [maxelem VALUE]\n"
+" [timeout VALUE] [counters] [comment]\n"
+"add SETNAME IP,MARK [timeout VALUE]\n"
+" [packets VALUE] [bytes VALUE] [comment \"string\"]\n"
+"del SETNAME IP,MARK\n"
+"test SETNAME IP,MARK\n\n"
+"where depending on the INET family\n"
+" IP is a valid IPv4 or IPv6 address (or hostname).\n"
+" Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
+" is supported for IPv4.\n"
+" Adding/deleting single mark element\n"
+" is supported both for IPv4 and IPv6.\n";
+
+static struct ipset_type ipset_hash_ipmark0 = {
+ .name = "hash:ip,mark",
+ .alias = { "ipmarkhash", NULL },
+ .revision = 0,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_TWO,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_single6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_mark,
+ .print = ipset_print_mark,
+ .opt = IPSET_OPT_MARK
+ },
+ },
+ .args = {
+ [IPSET_CREATE] = hash_ipmark_create_args0,
+ [IPSET_ADD] = hash_ipmark_add_args0,
+ },
+ .mandatory = {
+ [IPSET_CREATE] = 0,
+ [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_MARK),
+ [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_MARK),
+ [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_MARK),
+ },
+ .full = {
+ [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
+ | IPSET_FLAG(IPSET_OPT_MAXELEM)
+ | IPSET_FLAG(IPSET_OPT_TIMEOUT)
+ | IPSET_FLAG(IPSET_OPT_COUNTERS)
+ | IPSET_FLAG(IPSET_OPT_CREATE_COMMENT),
+ [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_MARK)
+ | IPSET_FLAG(IPSET_OPT_TIMEOUT)
+ | IPSET_FLAG(IPSET_OPT_PACKETS)
+ | IPSET_FLAG(IPSET_OPT_BYTES)
+ | IPSET_FLAG(IPSET_OPT_ADT_COMMENT),
+ [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_MARK),
+ [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_MARK),
+ },
+
+ .usage = hash_ipmark_usage0,
+ .description = "initial revision",
+};
+
+void _init(void);
+void _init(void)
+{
+ ipset_type_add(&ipset_hash_ipmark0);
+}
diff --git a/lib/libipset.map b/lib/libipset.map
index 1080f0d..a035115 100644
--- a/lib/libipset.map
+++ b/lib/libipset.map
@@ -138,3 +138,9 @@ global:
ipset_print_comment;
ipset_strlcat;
} LIBIPSET_4.0;
+
+LIBIPSET_4.2 {
+global:
+ ipset_parse_mark;
+ ipset_print_mark;
+} LIBIPSET_4.1;
diff --git a/lib/parse.c b/lib/parse.c
index 440ef8f..f1c1f0e 100644
--- a/lib/parse.c
+++ b/lib/parse.c
@@ -328,6 +328,36 @@ ipset_parse_port(struct ipset_session *session,
}
/**
+ * ipset_parse_mark - parse a mark
+ * @session: session structure
+ * @opt: option kind of the data
+ * @str: string to parse
+ *
+ * Parse string as a mark. The parsed mark number is
+ * stored in the data blob of the session.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int
+ipset_parse_mark(struct ipset_session *session,
+ enum ipset_opt opt, const char *str)
+{
+ uint32_t mark;
+ int err;
+
+ assert(session);
+ assert(str);
+
+ if ((err = string_to_u32(session, str, &mark)) == 0)
+ err = ipset_session_data_set(session, opt, &mark);
+
+ if (!err)
+ /* No error, so reset false error messages! */
+ ipset_session_report_reset(session);
+ return err;
+}
+
+/**
* ipset_parse_tcpudp_port - parse TCP/UDP port name, number, or range of them
* @session: session structure
* @opt: option kind of the data
diff --git a/lib/print.c b/lib/print.c
index 6988fdf..3c43443 100644
--- a/lib/print.c
+++ b/lib/print.c
@@ -491,6 +491,41 @@ ipset_print_port(char *buf, unsigned int len,
}
/**
+ * ipset_print_mark - print mark to string
+ * @buf: printing buffer
+ * @len: length of available buffer space
+ * @data: data blob
+ * @opt: the option kind
+ * @env: environment flags
+ *
+ * Print mark to output buffer.
+ *
+ * Return lenght of printed string or error size.
+ */
+int
+ipset_print_mark(char *buf, unsigned int len,
+ const struct ipset_data *data,
+ enum ipset_opt opt ASSERT_UNUSED,
+ uint8_t env UNUSED)
+{
+ const uint32_t *mark;
+ int size, offset = 0;
+
+ assert(buf);
+ assert(len > 0);
+ assert(data);
+ assert(opt == IPSET_OPT_MARK);
+
+ mark = ipset_data_get(data, IPSET_OPT_MARK);
+ assert(mark);
+
+ size = snprintf(buf, len, "%u", *mark);
+ SNPRINTF_FAILURE(size, len, offset);
+
+ return offset;
+}
+
+/**
* ipset_print_iface - print interface element string
* @buf: printing buffer
* @len: length of available buffer space
diff --git a/lib/session.c b/lib/session.c
index 6f89281..cf65960 100644
--- a/lib/session.c
+++ b/lib/session.c
@@ -424,6 +424,10 @@ static const struct ipset_attr_policy adt_attrs[] = {
.type = MNL_TYPE_U8,
.opt = IPSET_OPT_CIDR,
},
+ [IPSET_ATTR_MARK] = {
+ .type = MNL_TYPE_U32,
+ .opt = IPSET_OPT_MARK,
+ },
[IPSET_ATTR_PORT] = {
.type = MNL_TYPE_U16,
.opt = IPSET_OPT_PORT,