]> git.ipfire.org Git - thirdparty/ipset.git/commitdiff
libipset: Add userspace code for the skbinfo extension support.
authorAnton Danilov <littlesmilingcloud@gmail.com>
Thu, 28 Aug 2014 06:11:31 +0000 (10:11 +0400)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Sun, 14 Sep 2014 18:35:36 +0000 (20:35 +0200)
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>
include/libipset/data.h
include/libipset/linux_ip_set.h
include/libipset/parse.h
include/libipset/print.h
lib/data.c
lib/debug.c
lib/errcode.c
lib/parse.c
lib/print.c
lib/session.c

index 06ece1e320f6120d9e12d0768fd672894bea2c23..945df54f793b28bdec1dd4b9a01d1b3ff8434870 100644 (file)
@@ -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;
 
index 7272b2b17c15daa478f80648402beb6dfdbd8208..ae4127de24e635ce729c544e414e8a711e9c6111 100644 (file)
@@ -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,
 };
 
index 55981f2eb7de3516c5d35c8bb572bf444482a9fc..810ea2860af154445b23794a846ee4f54ba97957 100644 (file)
@@ -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,
index b8fa709ec9da8c8ff1be961077998bc0ea5196ad..8f672c312cec58bbe8e0702347bf89f2ebe4737e 100644 (file)
@@ -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);
index c214bece6566417d4541fe98ddc0d5b8f70f7c51..8372a2ffb8c4e6639e5561e8e28f191c661bca1a 100644 (file)
@@ -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:
index 1240e2296d0a7e74599199aaeaa10d6e767efe25..b2c5003d3b7d18b2a11b1694b3e9a00655c40110 100644 (file)
@@ -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,
index 86eeabd5e68c325dbe199748d4213d1c4a294f5b..8eb275bfe135c64f8281ef03963d6f42b73d75e0 100644 (file)
@@ -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,
index 6ed65cb78717f7c1ced9d7457658c879f168c828..88d288815147cccaa57f11505c835abf5db67159 100644 (file)
@@ -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
index a7abdcf0eff0f78153d90e5030a74be18d2b570d..7f42434f78e4fdef025e7ee3e7d9a5e9e820326f 100644 (file)
@@ -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
index d2957a5af7cf8f63b4e35383b869f87de278d29b..33ce4dec0a9dde1f530cb421b6f934ca7cb77d80 100644 (file)
@@ -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[] = {