summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/libipset/data.h12
-rw-r--r--include/libipset/linux_ip_set.h12
-rw-r--r--include/libipset/parse.h6
-rw-r--r--include/libipset/print.h6
-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
10 files changed, 201 insertions, 3 deletions
diff --git a/include/libipset/data.h b/include/libipset/data.h
index 06ece1e..945df54 100644
--- a/include/libipset/data.h
+++ b/include/libipset/data.h
@@ -62,6 +62,10 @@ enum ipset_opt {
IPSET_OPT_BYTES,
IPSET_OPT_CREATE_COMMENT,
IPSET_OPT_ADT_COMMENT,
+ IPSET_OPT_SKBINFO,
+ IPSET_OPT_SKBMARK,
+ IPSET_OPT_SKBPRIO,
+ IPSET_OPT_SKBQUEUE,
/* Internal options */
IPSET_OPT_FLAGS = 48, /* IPSET_FLAG_EXIST| */
IPSET_OPT_CADT_FLAGS, /* IPSET_FLAG_BEFORE| */
@@ -96,7 +100,8 @@ enum ipset_opt {
| IPSET_FLAG(IPSET_OPT_SIZE) \
| IPSET_FLAG(IPSET_OPT_COUNTERS)\
| IPSET_FLAG(IPSET_OPT_CREATE_COMMENT)\
- | IPSET_FLAG(IPSET_OPT_FORCEADD))
+ | IPSET_FLAG(IPSET_OPT_FORCEADD)\
+ | IPSET_FLAG(IPSET_OPT_SKBINFO))
#define IPSET_ADT_FLAGS \
(IPSET_FLAG(IPSET_OPT_IP) \
@@ -119,7 +124,10 @@ enum ipset_opt {
| IPSET_FLAG(IPSET_OPT_NOMATCH) \
| IPSET_FLAG(IPSET_OPT_PACKETS) \
| IPSET_FLAG(IPSET_OPT_BYTES) \
- | IPSET_FLAG(IPSET_OPT_ADT_COMMENT))
+ | IPSET_FLAG(IPSET_OPT_ADT_COMMENT)\
+ | IPSET_FLAG(IPSET_OPT_SKBMARK) \
+ | IPSET_FLAG(IPSET_OPT_SKBPRIO) \
+ | IPSET_FLAG(IPSET_OPT_SKBQUEUE))
struct ipset_data;
diff --git a/include/libipset/linux_ip_set.h b/include/libipset/linux_ip_set.h
index 7272b2b..ae4127d 100644
--- a/include/libipset/linux_ip_set.h
+++ b/include/libipset/linux_ip_set.h
@@ -116,6 +116,9 @@ enum {
IPSET_ATTR_BYTES,
IPSET_ATTR_PACKETS,
IPSET_ATTR_COMMENT,
+ IPSET_ATTR_SKBMARK,
+ IPSET_ATTR_SKBPRIO,
+ IPSET_ATTR_SKBQUEUE,
__IPSET_ATTR_ADT_MAX,
};
#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
@@ -148,6 +151,7 @@ enum ipset_errno {
IPSET_ERR_COUNTER,
IPSET_ERR_COMMENT,
IPSET_ERR_INVALID_MARKMASK,
+ IPSET_ERR_SKBINFO,
/* Type specific error codes */
IPSET_ERR_TYPE_SPECIFIC = 4352,
@@ -171,6 +175,12 @@ enum ipset_cmd_flags {
IPSET_FLAG_MATCH_COUNTERS = (1 << IPSET_FLAG_BIT_MATCH_COUNTERS),
IPSET_FLAG_BIT_RETURN_NOMATCH = 7,
IPSET_FLAG_RETURN_NOMATCH = (1 << IPSET_FLAG_BIT_RETURN_NOMATCH),
+ IPSET_FLAG_BIT_MAP_SKBMARK = 8,
+ IPSET_FLAG_MAP_SKBMARK = (1 << IPSET_FLAG_BIT_MAP_SKBMARK),
+ IPSET_FLAG_BIT_MAP_SKBPRIO = 9,
+ IPSET_FLAG_MAP_SKBPRIO = (1 << IPSET_FLAG_BIT_MAP_SKBPRIO),
+ IPSET_FLAG_BIT_MAP_SKBQUEUE = 10,
+ IPSET_FLAG_MAP_SKBQUEUE = (1 << IPSET_FLAG_BIT_MAP_SKBQUEUE),
IPSET_FLAG_CMD_MAX = 15,
};
@@ -188,6 +198,8 @@ enum ipset_cadt_flags {
IPSET_FLAG_WITH_COMMENT = (1 << IPSET_FLAG_BIT_WITH_COMMENT),
IPSET_FLAG_BIT_WITH_FORCEADD = 5,
IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD),
+ IPSET_FLAG_BIT_WITH_SKBINFO = 6,
+ IPSET_FLAG_WITH_SKBINFO = (1 << IPSET_FLAG_BIT_WITH_SKBINFO),
IPSET_FLAG_CADT_MAX = 15,
};
diff --git a/include/libipset/parse.h b/include/libipset/parse.h
index 55981f2..810ea28 100644
--- a/include/libipset/parse.h
+++ b/include/libipset/parse.h
@@ -82,6 +82,8 @@ extern int ipset_parse_uint64(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_uint32(struct ipset_session *session,
enum ipset_opt opt, const char *str);
+extern int ipset_parse_uint16(struct ipset_session *session,
+ enum ipset_opt opt, const char *str);
extern int ipset_parse_uint8(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_netmask(struct ipset_session *session,
@@ -94,6 +96,10 @@ extern int ipset_parse_iface(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_comment(struct ipset_session *session,
enum ipset_opt opt, const char *str);
+extern int ipset_parse_skbmark(struct ipset_session *session,
+ enum ipset_opt opt, const char *str);
+extern int ipset_parse_skbprio(struct ipset_session *session,
+ enum ipset_opt opt, const char *str);
extern int ipset_parse_output(struct ipset_session *session,
int opt, const char *str);
extern int ipset_parse_ignored(struct ipset_session *session,
diff --git a/include/libipset/print.h b/include/libipset/print.h
index b8fa709..8f672c3 100644
--- a/include/libipset/print.h
+++ b/include/libipset/print.h
@@ -46,6 +46,12 @@ extern int ipset_print_iface(char *buf, unsigned int len,
extern int ipset_print_comment(char *buf, unsigned int len,
const struct ipset_data *data,
enum ipset_opt opt, uint8_t env);
+extern int ipset_print_skbmark(char *buf, unsigned int len,
+ const struct ipset_data *data,
+ enum ipset_opt opt, uint8_t env);
+extern int ipset_print_skbprio(char *buf, unsigned int len,
+ const struct ipset_data *data,
+ enum ipset_opt opt, uint8_t env);
extern int ipset_print_proto(char *buf, unsigned int len,
const struct ipset_data *data,
enum ipset_opt opt, uint8_t env);
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[] = {