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>
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| */
| 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) \
| 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;
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)
IPSET_ERR_COUNTER,
IPSET_ERR_COMMENT,
IPSET_ERR_INVALID_MARKMASK,
+ IPSET_ERR_SKBINFO,
/* Type specific error codes */
IPSET_ERR_TYPE_SPECIFIC = 4352,
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,
};
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,
};
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,
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,
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);
uint64_t packets;
uint64_t bytes;
char comment[IPSET_MAX_COMMENT_SIZE+1];
+ uint64_t skbmark;
+ uint32_t skbprio;
+ uint16_t skbqueue;
} adt;
};
};
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;
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);
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;
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;
case IPSET_OPT_COUNTERS:
case IPSET_OPT_CREATE_COMMENT:
case IPSET_OPT_FORCEADD:
+ case IPSET_OPT_SKBINFO:
return &data->cadt_flags;
default:
return NULL;
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:
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:
[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
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,
"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,
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
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
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
.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[] = {