It makes possible to reproduce exactly the same set after a save/restore.
Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
        /* Reserve empty slots */
        IPSET_ATTR_CADT_MAX = 16,
        /* Create-only specific attributes */
-       IPSET_ATTR_GC,
+       IPSET_ATTR_INITVAL,     /* was unused IPSET_ATTR_GC */
        IPSET_ATTR_HASHSIZE,
        IPSET_ATTR_MAXELEM,
        IPSET_ATTR_NETMASK,
 
        if (nla_put_u32(skb, IPSET_ATTR_MARKMASK, h->markmask))
                goto nla_put_failure;
 #endif
-       if (set->flags & IPSET_CREATE_FLAG_BUCKETSIZE &&
-           nla_put_u8(skb, IPSET_ATTR_BUCKETSIZE, h->bucketsize))
-               goto nla_put_failure;
+       if (set->flags & IPSET_CREATE_FLAG_BUCKETSIZE) {
+               if (nla_put_u8(skb, IPSET_ATTR_BUCKETSIZE, h->bucketsize) ||
+                   nla_put_net32(skb, IPSET_ATTR_INITVAL, htonl(h->initval)))
+                       goto nla_put_failure;
+       }
        if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) ||
            nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) ||
            nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(elements)))
 #ifdef IP_SET_HASH_WITH_MARKMASK
        h->markmask = markmask;
 #endif
-       get_random_bytes(&h->initval, sizeof(h->initval));
+       if (tb[IPSET_ATTR_INITVAL])
+               h->initval = ntohl(nla_get_be32(tb[IPSET_ATTR_INITVAL]));
+       else
+               get_random_bytes(&h->initval, sizeof(h->initval));
        h->bucketsize = AHASH_MAX_SIZE;
        if (tb[IPSET_ATTR_BUCKETSIZE]) {
                h->bucketsize = nla_get_u8(tb[IPSET_ATTR_BUCKETSIZE]);
 
 /*                             2          Comments support */
 /*                             3          Forceadd support */
 /*                             4          skbinfo support */
-#define IPSET_TYPE_REV_MAX     5       /* bucketsize support  */
+#define IPSET_TYPE_REV_MAX     5       /* bucketsize, initval support  */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
        .create_policy  = {
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 
 #include <linux/netfilter/ipset/ip_set_hash.h>
 
 #define IPSET_TYPE_REV_MIN     0
-#define IPSET_TYPE_REV_MAX     1       /* bucketsize support  */
+#define IPSET_TYPE_REV_MAX     1       /* bucketsize, initval support  */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tomasz Chilinski <tomasz.chilinski@chilan.com>");
        .create_policy  = {
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 
 #define IPSET_TYPE_REV_MIN     0
 /*                             1          Forceadd support */
 /*                             2          skbinfo support */
-#define IPSET_TYPE_REV_MAX     3       /* bucketsize support  */
+#define IPSET_TYPE_REV_MAX     3       /* bucketsize, initval support  */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Vytas Dauksa <vytas.dauksa@smoothwall.net>");
                [IPSET_ATTR_MARKMASK]   = { .type = NLA_U32 },
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 
 /*                             3    Comments support added */
 /*                             4    Forceadd support added */
 /*                             5    skbinfo support added */
-#define IPSET_TYPE_REV_MAX     6 /* bucketsize support added */
+#define IPSET_TYPE_REV_MAX     6 /* bucketsize, initval support added */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
        .create_policy  = {
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
 
 /*                             3    Comments support added */
 /*                             4    Forceadd support added */
 /*                             5    skbinfo support added */
-#define IPSET_TYPE_REV_MAX     6 /* bucketsize support added */
+#define IPSET_TYPE_REV_MAX     6 /* bucketsize, initval support added */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
        .create_policy  = {
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 
 /*                             5    Comments support added */
 /*                             6    Forceadd support added */
 /*                             7    skbinfo support added */
-#define IPSET_TYPE_REV_MAX     8 /* bucketsize support added */
+#define IPSET_TYPE_REV_MAX     8 /* bucketsize, initval support added */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
        .create_policy  = {
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 
 #include <linux/netfilter/ipset/ip_set_hash.h>
 
 #define IPSET_TYPE_REV_MIN     0
-#define IPSET_TYPE_REV_MAX     1       /* bucketsize support */
+#define IPSET_TYPE_REV_MAX     1       /* bucketsize, initval support */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
        .create_policy  = {
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 
 /*                             4    Comments support added */
 /*                             5    Forceadd support added */
 /*                             6    skbinfo support added */
-#define IPSET_TYPE_REV_MAX     7 /* bucketsize support added */
+#define IPSET_TYPE_REV_MAX     7 /* bucketsize, initval support added */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
        .create_policy  = {
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 
 /*                             5    Forceadd support added */
 /*                             6    skbinfo support added */
 /*                             7    interface wildcard support added */
-#define IPSET_TYPE_REV_MAX     8 /* bucketsize support added */
+#define IPSET_TYPE_REV_MAX     8 /* bucketsize, initval support added */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
        .create_policy  = {
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
 
 #define IPSET_TYPE_REV_MIN     0
 /*                             1          Forceadd support added */
 /*                             2          skbinfo support added */
-#define IPSET_TYPE_REV_MAX     3       /* bucketsize support added */
+#define IPSET_TYPE_REV_MAX     3       /* bucketsize, initval support added */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>");
        .create_policy  = {
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 
 /*                             5    Comments support added */
 /*                             6    Forceadd support added */
 /*                             7    skbinfo support added */
-#define IPSET_TYPE_REV_MAX     8 /* bucketsize support added */
+#define IPSET_TYPE_REV_MAX     8 /* bucketsize, initval support added */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
        .create_policy  = {
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
 
 /*                             0    Comments support added */
 /*                             1    Forceadd support added */
 /*                             2    skbinfo support added */
-#define IPSET_TYPE_REV_MAX     3 /* bucketsize support added */
+#define IPSET_TYPE_REV_MAX     3 /* bucketsize, initval support added */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>");
        .create_policy  = {
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
+               [IPSET_ATTR_INITVAL]    = { .type = NLA_U32 },
                [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 },
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },