summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAnton Danilov <littlesmilingcloud@gmail.com>2014-08-28 10:11:31 +0400
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2014-09-14 20:35:36 +0200
commitc1dd8442aac6cadb29110f763f23cafc63135a79 (patch)
treeac73bf1e0feab1ff602e3450058048c69686022e /lib
parent89798a24cafa8f1bea391ea577a296f0468971db (diff)
libipset: Add userspace code for the skbinfo extension support.
Add userspace code to support of the skbinfo extension independly of set types. Defines constants, flag and function for print/parse/send/recieve of skbinfo parameters. Signed-off-by: Anton Danilov <littlesmilingcloud@gmail.com> Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Diffstat (limited to 'lib')
-rw-r--r--lib/data.c30
-rw-r--r--lib/debug.c9
-rw-r--r--lib/errcode.c2
-rw-r--r--lib/parse.c66
-rw-r--r--lib/print.c49
-rw-r--r--lib/session.c12
6 files changed, 167 insertions, 1 deletions
diff --git a/lib/data.c b/lib/data.c
index c214bec..8372a2f 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -78,6 +78,9 @@ struct ipset_data {
uint64_t packets;
uint64_t bytes;
char comment[IPSET_MAX_COMMENT_SIZE+1];
+ uint64_t skbmark;
+ uint32_t skbprio;
+ uint16_t skbqueue;
} adt;
};
};
@@ -312,6 +315,9 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
case IPSET_OPT_FORCEADD:
cadt_flag_type_attr(data, opt, IPSET_FLAG_WITH_FORCEADD);
break;
+ case IPSET_OPT_SKBINFO:
+ cadt_flag_type_attr(data, opt, IPSET_FLAG_WITH_SKBINFO);
+ break;
/* Create-specific options, filled out by the kernel */
case IPSET_OPT_ELEMENTS:
data->create.elements = *(const uint32_t *) value;
@@ -374,6 +380,15 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
ipset_strlcpy(data->adt.comment, value,
IPSET_MAX_COMMENT_SIZE + 1);
break;
+ case IPSET_OPT_SKBMARK:
+ data->adt.skbmark = *(const uint64_t *) value;
+ break;
+ case IPSET_OPT_SKBPRIO:
+ data->adt.skbprio = *(const uint32_t *) value;
+ break;
+ case IPSET_OPT_SKBQUEUE:
+ data->adt.skbqueue = *(const uint16_t *) value;
+ break;
/* Swap/rename */
case IPSET_OPT_SETNAME2:
ipset_strlcpy(data->setname2, value, IPSET_MAXNAMELEN);
@@ -410,7 +425,10 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
IPSET_FLAG(IPSET_OPT_COUNTERS));
if (data->cadt_flags & IPSET_FLAG_WITH_COMMENT)
ipset_data_flags_set(data,
- IPSET_FLAG(IPSET_OPT_CREATE_COMMENT));
+ IPSET_FLAG(IPSET_OPT_CREATE_COMMENT));
+ if (data->cadt_flags & IPSET_FLAG_WITH_SKBINFO)
+ ipset_data_flags_set(data,
+ IPSET_FLAG(IPSET_OPT_SKBINFO));
break;
default:
return -1;
@@ -519,6 +537,12 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
return &data->adt.bytes;
case IPSET_OPT_ADT_COMMENT:
return &data->adt.comment;
+ case IPSET_OPT_SKBMARK:
+ return &data->adt.skbmark;
+ case IPSET_OPT_SKBPRIO:
+ return &data->adt.skbprio;
+ case IPSET_OPT_SKBQUEUE:
+ return &data->adt.skbqueue;
/* Swap/rename */
case IPSET_OPT_SETNAME2:
return data->setname2;
@@ -533,6 +557,7 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
case IPSET_OPT_COUNTERS:
case IPSET_OPT_CREATE_COMMENT:
case IPSET_OPT_FORCEADD:
+ case IPSET_OPT_SKBINFO:
return &data->cadt_flags;
default:
return NULL;
@@ -562,6 +587,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
return sizeof(uint32_t);
case IPSET_OPT_PORT:
case IPSET_OPT_PORT_TO:
+ case IPSET_OPT_SKBQUEUE:
return sizeof(uint16_t);
case IPSET_SETNAME:
case IPSET_OPT_NAME:
@@ -576,9 +602,11 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
case IPSET_OPT_ELEMENTS:
case IPSET_OPT_REFERENCES:
case IPSET_OPT_MEMSIZE:
+ case IPSET_OPT_SKBPRIO:
return sizeof(uint32_t);
case IPSET_OPT_PACKETS:
case IPSET_OPT_BYTES:
+ case IPSET_OPT_SKBMARK:
return sizeof(uint64_t);
case IPSET_OPT_CIDR:
case IPSET_OPT_CIDR2:
diff --git a/lib/debug.c b/lib/debug.c
index 1240e22..b2c5003 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -67,6 +67,9 @@ static const struct ipset_attrname adtattr2name[] = {
[IPSET_ATTR_IP2_TO] = { .name = "IP2_TO" },
[IPSET_ATTR_IFACE] = { .name = "IFACE" },
[IPSET_ATTR_COMMENT] = { .name = "COMMENT" },
+ [IPSET_ATTR_SKBMARK] = { .name = "SKBMARK" },
+ [IPSET_ATTR_SKBPRIO] = { .name = "SKBPRIO" },
+ [IPSET_ATTR_SKBQUEUE] = { .name = "SKBQUEUE" },
};
static void
@@ -98,6 +101,12 @@ debug_cadt_attrs(int max, const struct ipset_attr_policy *policy,
fprintf(stderr, "\t\t%s: %u\n",
attr2name[i].name, ntohl(v));
break;
+ case MNL_TYPE_U64:
+ fprintf(stderr, "\t\t%s: 0x%llx\n",
+ attr2name[i].name, (long long int)
+ be64toh(*(uint64_t *)
+ mnl_attr_get_payload(nla[i])));
+ break;
case MNL_TYPE_NUL_STRING:
fprintf(stderr, "\t\t%s: %s\n",
attr2name[i].name,
diff --git a/lib/errcode.c b/lib/errcode.c
index 86eeabd..8eb275b 100644
--- a/lib/errcode.c
+++ b/lib/errcode.c
@@ -76,6 +76,8 @@ static const struct ipset_errcode_table core_errcode_table[] = {
"Packet/byte counters cannot be used: set was created without counter support" },
{ IPSET_ERR_COMMENT, 0,
"Comment string is too long!" },
+ { IPSET_ERR_SKBINFO, 0,
+ "Skbinfo mapping cannot be used: set was created without skbinfo support" },
/* ADD specific error codes */
{ IPSET_ERR_EXIST, IPSET_CMD_ADD,
diff --git a/lib/parse.c b/lib/parse.c
index 6ed65cb..88d2888 100644
--- a/lib/parse.c
+++ b/lib/parse.c
@@ -1609,6 +1609,23 @@ ipset_parse_uint32(struct ipset_session *session,
return err;
}
+int
+ipset_parse_uint16(struct ipset_session *session,
+ enum ipset_opt opt, const char *str)
+{
+ uint16_t value;
+ int err;
+
+ assert(session);
+ assert(str);
+
+ err = string_to_u16(session, str, &value);
+ if (err == 0)
+ return ipset_session_data_set(session, opt, &value);
+
+ return err;
+}
+
/**
* ipset_parse_uint8 - parse string as an unsigned short integer
* @session: session structure
@@ -1806,6 +1823,55 @@ int ipset_parse_comment(struct ipset_session *session,
return ipset_data_set(data, opt, str);
}
+int
+ipset_parse_skbmark(struct ipset_session *session,
+ enum ipset_opt opt, const char *str)
+{
+ struct ipset_data *data;
+ uint64_t result = 0;
+ unsigned long mark, mask;
+ int ret = 0;
+
+ assert(session);
+ assert(opt == IPSET_OPT_SKBMARK);
+ assert(str);
+
+ data = ipset_session_data(session);
+ ret = sscanf(str, "0x%lx/0x%lx", &mark, &mask);
+ if (ret != 2) {
+ mask = 0xffffffff;
+ ret = sscanf(str, "0x%lx", &mark);
+ if (ret != 1)
+ return syntax_err("Invalid skbmark format, "
+ "it should be: "
+ " MARK/MASK or MARK (see manpage)");
+ }
+ result = ((uint64_t)(mark) << 32) | (mask & 0xffffffff);
+ return ipset_data_set(data, IPSET_OPT_SKBMARK, &result);
+}
+
+int
+ipset_parse_skbprio(struct ipset_session *session,
+ enum ipset_opt opt, const char *str)
+{
+ struct ipset_data *data;
+ unsigned maj, min;
+ uint32_t major;
+ int err;
+
+ assert(session);
+ assert(opt == IPSET_OPT_SKBPRIO);
+ assert(str);
+
+ data = ipset_session_data(session);
+ err = sscanf(str, "%x:%x", &maj, &min);
+ if (err != 2)
+ return syntax_err("Invalid skbprio format, it should be:"\
+ "MAJOR:MINOR (see manpage)");
+ major = ((uint32_t)maj << 16) | (min & 0xffff);
+ return ipset_data_set(data, IPSET_OPT_SKBPRIO, &major);
+}
+
/**
* ipset_parse_output - parse output format name
* @session: session structure
diff --git a/lib/print.c b/lib/print.c
index a7abdcf..7f42434 100644
--- a/lib/print.c
+++ b/lib/print.c
@@ -596,6 +596,55 @@ int ipset_print_comment(char *buf, unsigned int len,
return offset;
}
+int
+ipset_print_skbmark(char *buf, unsigned int len,
+ const struct ipset_data *data, enum ipset_opt opt,
+ uint8_t env UNUSED)
+{
+ int size, offset = 0;
+ const uint64_t *skbmark;
+ uint32_t mark, mask;
+
+ assert(buf);
+ assert(len > 0);
+ assert(data);
+ assert(opt == IPSET_OPT_SKBMARK);
+
+ skbmark = ipset_data_get(data, IPSET_OPT_SKBMARK);
+ assert(skbmark);
+ mark = *skbmark >> 32;
+ mask = *skbmark & 0xffffffff;
+ if (mask == 0xffffffff)
+ size = snprintf(buf + offset, len, "0x%"PRIx32, mark);
+ else
+ size = snprintf(buf + offset, len,
+ "0x%"PRIx32"/0x%"PRIx32, mark, mask);
+ SNPRINTF_FAILURE(size, len, offset);
+ return offset;
+}
+
+int
+ipset_print_skbprio(char *buf, unsigned int len,
+ const struct ipset_data *data, enum ipset_opt opt,
+ uint8_t env UNUSED)
+{
+ int size, offset = 0;
+ const uint32_t *skbprio;
+
+ assert(buf);
+ assert(len > 0);
+ assert(data);
+ assert(opt == IPSET_OPT_SKBPRIO);
+
+ skbprio = ipset_data_get(data, opt);
+ assert(skbprio);
+ size = snprintf(buf + offset, len, "%x:%x",
+ *skbprio >> 16, *skbprio & 0xffff);
+ SNPRINTF_FAILURE(size, len, offset);
+ return offset;
+}
+
+
/**
* ipset_print_proto - print protocol name
* @buf: printing buffer
diff --git a/lib/session.c b/lib/session.c
index d2957a5..33ce4de 100644
--- a/lib/session.c
+++ b/lib/session.c
@@ -501,6 +501,18 @@ static const struct ipset_attr_policy adt_attrs[] = {
.opt = IPSET_OPT_ADT_COMMENT,
.len = IPSET_MAX_COMMENT_SIZE + 1,
},
+ [IPSET_ATTR_SKBMARK] = {
+ .type = MNL_TYPE_U64,
+ .opt = IPSET_OPT_SKBMARK,
+ },
+ [IPSET_ATTR_SKBPRIO] = {
+ .type = MNL_TYPE_U32,
+ .opt = IPSET_OPT_SKBPRIO,
+ },
+ [IPSET_ATTR_SKBQUEUE] = {
+ .type = MNL_TYPE_U16,
+ .opt = IPSET_OPT_SKBQUEUE,
+ },
};
static const struct ipset_attr_policy ipaddr_attrs[] = {