]> granicus.if.org Git - ipset/commitdiff
ipset 5: last new feature added v5.0-pre3
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Tue, 22 Jun 2010 08:49:41 +0000 (10:49 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Tue, 22 Jun 2010 08:49:41 +0000 (10:49 +0200)
- the hash types can now store protocol together port, not only port
- lots of fixes everywhere: parser, error reporting, manpage

The last bits on the todo list before announcing ipset 5:

- recheck all the error messages
- add possibly more tests
- polish manpage

44 files changed:
Make_global.am
include/libipset/data.h
include/libipset/linux_ip_set.h
include/libipset/linux_ip_set_hash.h
include/libipset/parse.h
include/libipset/print.h
include/libipset/session.h
kernel/include/linux/netfilter/ip_set.h
kernel/include/linux/netfilter/ip_set_chash.h
kernel/include/linux/netfilter/ip_set_getport.h
kernel/include/linux/netfilter/ip_set_hash.h
kernel/ip_set.c
kernel/ip_set_bitmap_ip.c
kernel/ip_set_bitmap_ipmac.c
kernel/ip_set_bitmap_port.c
kernel/ip_set_hash_ip.c
kernel/ip_set_hash_ipport.c
kernel/ip_set_hash_ipportip.c
kernel/ip_set_hash_ipportnet.c
kernel/ip_set_hash_net.c
kernel/ip_set_list_set.c
lib/data.c
lib/parse.c
lib/print.c
lib/session.c
src/errcode.c
src/ipset.8
src/ipset.c
src/ipset_hash_ipport.c
src/ipset_hash_ipportip.c
src/ipset_hash_ipportnet.c
tests/hash:ip,port,ip.t
tests/hash:ip,port.t
tests/hash:ip,port.t.list2 [new file with mode: 0644]
tests/hash:ip6,port,ip6.t
tests/hash:ip6,port.t
tests/hash:net.t
tests/hash:net6.t
tests/init.t
tests/ipmap.t
tests/ipporthash.t
tests/ipportiphash.t
tests/nethash.t
tests/setlist.t

index 857d0de2b55545162efdd32e13df93cf699bdca8..5b2ec6ff443afbf727fea88f5f8f45d2ede75a46 100644 (file)
@@ -38,12 +38,11 @@ AM_CFLAGS = -std=gnu99 \
        -Wundef \
        -Wwrite-strings \
        -Wno-missing-field-initializers \
-       -Werror \
-       -g -ggdb -gdwarf-2 -g3
+       -Werror
 endif
 
 if ENABLE_DEBUG
-AM_CFLAGS += -DIPSET_DEBUG
+AM_CFLAGS += -g -ggdb -gdwarf-2 -g3 -DIPSET_DEBUG
 endif
 
 if ! ENABLE_VERBOSE
index 936b807c52b4b6dbaa9bd6b4cc6fd7466d9c8f3b..cb3539330100e30a8f3e763c19b5fcca4e1bc850 100644 (file)
@@ -44,6 +44,7 @@ enum ipset_opt {
        IPSET_OPT_NAMEREF,
        IPSET_OPT_IP2,
        IPSET_OPT_CIDR2,
+       IPSET_OPT_PROTO,
        /* Swap/rename to */
        IPSET_OPT_SETNAME2,
        /* Flags */
@@ -93,6 +94,7 @@ enum ipset_opt {
        | IPSET_FLAG(IPSET_OPT_NAMEREF) \
        | IPSET_FLAG(IPSET_OPT_IP2)     \
        | IPSET_FLAG(IPSET_OPT_CIDR2)   \
+       | IPSET_FLAG(IPSET_OPT_PROTO)   \
        | IPSET_FLAG(IPSET_OPT_CADT_FLAGS)\
        | IPSET_FLAG(IPSET_OPT_BEFORE))
 
index 4af75baa3afbb9aee2592b1f93c924aec523b484..0ad2b14524eaebf2c3fac470a1067b87378430d3 100644 (file)
 /* Message types and commands */
 enum ipset_cmd {
        IPSET_CMD_NONE,
-       IPSET_CMD_CREATE,       /* Create a new (empty) set */
-       IPSET_CMD_DESTROY,      /* Remove a (empty) set */
-       IPSET_CMD_FLUSH,        /* Remove all elements from a set */
-       IPSET_CMD_RENAME,       /* Rename a set */
-       IPSET_CMD_SWAP,         /* Swap two sets */
-       IPSET_CMD_LIST,         /* List sets */
-       IPSET_CMD_SAVE,         /* Save sets */
-       IPSET_CMD_ADD,          /* Add an element to a set */
-       IPSET_CMD_DEL,          /* Delete an element from a set */
-       IPSET_CMD_TEST,         /* Test an element in a set */
-       IPSET_CMD_HEADER,       /* Get set header data only */
-       IPSET_CMD_TYPE,         /* Get set type */
-       IPSET_CMD_PROTOCOL,     /* Return protocol version */
+       IPSET_CMD_CREATE,       /* 1: Create a new (empty) set */
+       IPSET_CMD_DESTROY,      /* 2: Remove a (empty) set */
+       IPSET_CMD_FLUSH,        /* 3: Remove all elements from a set */
+       IPSET_CMD_RENAME,       /* 4: Rename a set */
+       IPSET_CMD_SWAP,         /* 5: Swap two sets */
+       IPSET_CMD_LIST,         /* 6: List sets */
+       IPSET_CMD_SAVE,         /* 7: Save sets */
+       IPSET_CMD_ADD,          /* 8: Add an element to a set */
+       IPSET_CMD_DEL,          /* 9: Delete an element from a set */
+       IPSET_CMD_TEST,         /* 10: Test an element in a set */
+       IPSET_CMD_HEADER,       /* 11: Get set header data only */
+       IPSET_CMD_TYPE,         /* 12: Get set type */
+       IPSET_CMD_PROTOCOL,     /* 13: Return protocol version */
        IPSET_MSG_MAX,          /* Netlink message commands */
 
        /* Commands in userspace: */
-       IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* Enter restore mode */     
-       IPSET_CMD_HELP,         /* Get help */
-       IPSET_CMD_VERSION,      /* Get program version */
-       IPSET_CMD_QUIT,         /* Quit from interactive mode */
+       IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */ 
+       IPSET_CMD_HELP,         /* 15: Get help */
+       IPSET_CMD_VERSION,      /* 16: Get program version */
+       IPSET_CMD_QUIT,         /* 17: Quit from interactive mode */
 
        IPSET_CMD_MAX,
 
-       IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* Commit buffered commands */
+       IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
 };
 
 /* Attributes at command level */
 enum {
        IPSET_ATTR_UNSPEC,
-       IPSET_ATTR_PROTOCOL,    /* Protocol version */
-       IPSET_ATTR_SETNAME,     /* Name of the set */
-       IPSET_ATTR_TYPENAME,    /* Typename */
+       IPSET_ATTR_PROTOCOL,    /* 1: Protocol version */
+       IPSET_ATTR_SETNAME,     /* 2: Name of the set */
+       IPSET_ATTR_TYPENAME,    /* 3: Typename */
        IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* rename/swap */
-       IPSET_ATTR_REVISION,    /* Settype revision */
-       IPSET_ATTR_FAMILY,      /* Settype family */
-       IPSET_ATTR_FLAGS,       /* Flags at command level */
-       IPSET_ATTR_DATA,        /* Nested attributes */
-       IPSET_ATTR_ADT,         /* Multiple data containers */
-       IPSET_ATTR_LINENO,      /* Restore lineno */
-       IPSET_ATTR_PROTOCOL_MIN,/* Minimal supported version number */
-       IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
+       IPSET_ATTR_REVISION,    /* 4: Settype revision */
+       IPSET_ATTR_FAMILY,      /* 5: Settype family */
+       IPSET_ATTR_FLAGS,       /* 6: Flags at command level */
+       IPSET_ATTR_DATA,        /* 7: Nested attributes */
+       IPSET_ATTR_ADT,         /* 8: Multiple data containers */
+       IPSET_ATTR_LINENO,      /* 9: Restore lineno */
+       IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
+       IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
        __IPSET_ATTR_CMD_MAX,
 };
 #define IPSET_ATTR_CMD_MAX     (__IPSET_ATTR_CMD_MAX - 1)
@@ -69,13 +69,14 @@ enum {
 enum {
        IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
        IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
-       IPSET_ATTR_IP_TO,
-       IPSET_ATTR_CIDR,
-       IPSET_ATTR_PORT,
+       IPSET_ATTR_IP_TO,       /* 2 */
+       IPSET_ATTR_CIDR,        /* 3 */
+       IPSET_ATTR_PORT,        /* 4 */
        IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
-       IPSET_ATTR_PORT_TO,
-       IPSET_ATTR_TIMEOUT,
-       IPSET_ATTR_CADT_FLAGS,
+       IPSET_ATTR_PORT_TO,     /* 5 */
+       IPSET_ATTR_TIMEOUT,     /* 6 */
+       IPSET_ATTR_PROTO,       /* 7 */
+       IPSET_ATTR_CADT_FLAGS,  /* 8 */
        IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO,
        /* Reserve empty slots */
        IPSET_ATTR_CADT_MAX = 16,
@@ -147,4 +148,7 @@ enum ipset_adt {
        IPSET_CADT_MAX,
 };
 
+#define IPSET_IPPROTO_ANY      255
+#define IPSET_IPPROTO_TCPUDP   254
+
 #endif /* __IP_SET_H */
index 76d24894ba34b7b1c5d895cf955f8a9165f9477c..db6977bfd941995d734bafa8015bab6cdf5d8b06 100644 (file)
@@ -5,6 +5,8 @@
 enum {
        IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
        IPSET_ERR_HASH_ELEM,
+       IPSET_ERR_INVALID_PROTO,
+       IPSET_ERR_MISSING_PROTO,
 };
 
 #endif /* __IP_SET_HASH_H */
index 143e2b37784f69587a03c01f4ab8e85a58ef49cc..1e055eef74023837a3d82e64525d5269554314d6 100644 (file)
@@ -14,6 +14,7 @@
 #define IPSET_RANGE_SEPARATOR  "-"
 #define IPSET_ELEM_SEPARATOR   ","
 #define IPSET_NAME_SEPARATOR   ","
+#define IPSET_PROTO_SEPARATOR  ":"
 
 struct ipset_session;
 
@@ -26,6 +27,10 @@ extern int ipset_parse_single_port(struct ipset_session *session,
                                   enum ipset_opt opt, const char *str);
 extern int ipset_parse_port(struct ipset_session *session,
                             enum ipset_opt opt, const char *str);
+extern int ipset_parse_proto(struct ipset_session *session,
+                             enum ipset_opt opt, const char *str);
+extern int ipset_parse_proto_port(struct ipset_session *session,
+                                 enum ipset_opt opt, const char *str);
 extern int ipset_parse_family(struct ipset_session *session,
                               enum ipset_opt opt, const char *str);
 extern int ipset_parse_ip(struct ipset_session *session,
index dbb70f3796cd1956696929f03010f809c5e968ba..1fc5abca25ecee163c6e7a86b779358982ac81b1 100644 (file)
@@ -37,6 +37,12 @@ extern int ipset_print_name(char *buf, unsigned int len,
 extern int ipset_print_port(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);
+extern int ipset_print_proto_port(char *buf, unsigned int len,
+                                 const struct ipset_data *data,
+                                 enum ipset_opt opt, uint8_t env);
 extern int ipset_print_flag(char *buf, unsigned int len,
                            const struct ipset_data *data, enum ipset_opt opt,
                            uint8_t env);
index cc0940e2a19c803cb1e69c429a31a27babcccc84..02e8b36de974c12c85675a3ca0b932d76ab1c81f 100644 (file)
@@ -23,6 +23,7 @@ struct ipset_handle;
 
 extern struct ipset_data * ipset_session_data(const struct ipset_session *session);
 extern struct ipset_handle * ipset_session_handle(const struct ipset_session *session);
+extern const struct ipset_type * ipset_saved_type(const struct ipset_session *session);
 
 enum ipset_err_type {
        IPSET_ERROR,
index e7005039a7b01be1700e8c9f4981bc50cbc9167f..f306859c230a334a641e0bbaaa35dcad7756fc33 100644 (file)
 /* Message types and commands */
 enum ipset_cmd {
        IPSET_CMD_NONE,
-       IPSET_CMD_CREATE,       /* Create a new (empty) set */
-       IPSET_CMD_DESTROY,      /* Remove a (empty) set */
-       IPSET_CMD_FLUSH,        /* Remove all elements from a set */
-       IPSET_CMD_RENAME,       /* Rename a set */
-       IPSET_CMD_SWAP,         /* Swap two sets */
-       IPSET_CMD_LIST,         /* List sets */
-       IPSET_CMD_SAVE,         /* Save sets */
-       IPSET_CMD_ADD,          /* Add an element to a set */
-       IPSET_CMD_DEL,          /* Delete an element from a set */
-       IPSET_CMD_TEST,         /* Test an element in a set */
-       IPSET_CMD_HEADER,       /* Get set header data only */
-       IPSET_CMD_TYPE,         /* Get set type */
-       IPSET_CMD_PROTOCOL,     /* Return protocol version */
+       IPSET_CMD_CREATE,       /* 1: Create a new (empty) set */
+       IPSET_CMD_DESTROY,      /* 2: Remove a (empty) set */
+       IPSET_CMD_FLUSH,        /* 3: Remove all elements from a set */
+       IPSET_CMD_RENAME,       /* 4: Rename a set */
+       IPSET_CMD_SWAP,         /* 5: Swap two sets */
+       IPSET_CMD_LIST,         /* 6: List sets */
+       IPSET_CMD_SAVE,         /* 7: Save sets */
+       IPSET_CMD_ADD,          /* 8: Add an element to a set */
+       IPSET_CMD_DEL,          /* 9: Delete an element from a set */
+       IPSET_CMD_TEST,         /* 10: Test an element in a set */
+       IPSET_CMD_HEADER,       /* 11: Get set header data only */
+       IPSET_CMD_TYPE,         /* 12: Get set type */
+       IPSET_CMD_PROTOCOL,     /* 13: Return protocol version */
        IPSET_MSG_MAX,          /* Netlink message commands */
 
        /* Commands in userspace: */
-       IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* Enter restore mode */     
-       IPSET_CMD_HELP,         /* Get help */
-       IPSET_CMD_VERSION,      /* Get program version */
-       IPSET_CMD_QUIT,         /* Quit from interactive mode */
+       IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */ 
+       IPSET_CMD_HELP,         /* 15: Get help */
+       IPSET_CMD_VERSION,      /* 16: Get program version */
+       IPSET_CMD_QUIT,         /* 17: Quit from interactive mode */
 
        IPSET_CMD_MAX,
 
-       IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* Commit buffered commands */
+       IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
 };
 
 /* Attributes at command level */
 enum {
        IPSET_ATTR_UNSPEC,
-       IPSET_ATTR_PROTOCOL,    /* Protocol version */
-       IPSET_ATTR_SETNAME,     /* Name of the set */
-       IPSET_ATTR_TYPENAME,    /* Typename */
+       IPSET_ATTR_PROTOCOL,    /* 1: Protocol version */
+       IPSET_ATTR_SETNAME,     /* 2: Name of the set */
+       IPSET_ATTR_TYPENAME,    /* 3: Typename */
        IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* rename/swap */
-       IPSET_ATTR_REVISION,    /* Settype revision */
-       IPSET_ATTR_FAMILY,      /* Settype family */
-       IPSET_ATTR_FLAGS,       /* Flags at command level */
-       IPSET_ATTR_DATA,        /* Nested attributes */
-       IPSET_ATTR_ADT,         /* Multiple data containers */
-       IPSET_ATTR_LINENO,      /* Restore lineno */
-       IPSET_ATTR_PROTOCOL_MIN,/* Minimal supported version number */
-       IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
+       IPSET_ATTR_REVISION,    /* 4: Settype revision */
+       IPSET_ATTR_FAMILY,      /* 5: Settype family */
+       IPSET_ATTR_FLAGS,       /* 6: Flags at command level */
+       IPSET_ATTR_DATA,        /* 7: Nested attributes */
+       IPSET_ATTR_ADT,         /* 8: Multiple data containers */
+       IPSET_ATTR_LINENO,      /* 9: Restore lineno */
+       IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
+       IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
        __IPSET_ATTR_CMD_MAX,
 };
 #define IPSET_ATTR_CMD_MAX     (__IPSET_ATTR_CMD_MAX - 1)
@@ -69,13 +69,14 @@ enum {
 enum {
        IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
        IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
-       IPSET_ATTR_IP_TO,
-       IPSET_ATTR_CIDR,
-       IPSET_ATTR_PORT,
+       IPSET_ATTR_IP_TO,       /* 2 */
+       IPSET_ATTR_CIDR,        /* 3 */
+       IPSET_ATTR_PORT,        /* 4 */
        IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
-       IPSET_ATTR_PORT_TO,
-       IPSET_ATTR_TIMEOUT,
-       IPSET_ATTR_CADT_FLAGS,
+       IPSET_ATTR_PORT_TO,     /* 5 */
+       IPSET_ATTR_TIMEOUT,     /* 6 */
+       IPSET_ATTR_PROTO,       /* 7 */
+       IPSET_ATTR_CADT_FLAGS,  /* 8 */
        IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO,
        /* Reserve empty slots */
        IPSET_ATTR_CADT_MAX = 16,
@@ -147,6 +148,9 @@ enum ipset_adt {
        IPSET_CADT_MAX,
 };
 
+#define IPSET_IPPROTO_ANY      255
+#define IPSET_IPPROTO_TCPUDP   254
+
 #ifdef __KERNEL__
 #include <linux/ip.h>
 #include <linux/ipv6.h>
@@ -343,6 +347,12 @@ ip_set_free(void *members, u8 flags)
                vfree(members);
 }
 
+static inline bool
+ip_set_eexist(int ret, u32 flags)
+{
+       return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
+}
+
 /* Useful converters */
 static inline u32
 ip_set_get_h32(const struct nlattr *attr)
index 0d77a5de733dcb9ae8c5a1588d77354c527e6950..e0e16bd7b12610f8283696e73ffbb2c7219d2461 100644 (file)
@@ -37,6 +37,9 @@ struct chash {
 #ifdef IP_SET_HASH_WITH_NETMASK
        u8 netmask;             /* netmask value for subnets to store */
 #endif
+#ifdef IP_SET_HASH_WITH_PROTO
+       u8 proto;               /* default protocol for SET target */
+#endif
 #ifdef IP_SET_HASH_WITH_NETS
        struct chash_nets nets[0]; /* book keeping of networks */
 #endif
@@ -205,8 +208,9 @@ jhash2((u32 *)(data), sizeof(struct type_pf_elem)/sizeof(u32), initval)     \
 
 /* Flavour without timeout */
 
-#define chash_data(n, i) \
-(struct type_pf_elem *)((char *)(n) + sizeof(struct slist) + (i)*sizeof(struct type_pf_elem))
+#define chash_data(n, i)                                       \
+(struct type_pf_elem *)((char *)(n) + sizeof(struct slist)     \
+                       + (i)*sizeof(struct type_pf_elem))
 
 static int
 type_pf_chash_readd(struct chash *h, struct slist *t, u8 htable_bits,
@@ -506,6 +510,10 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb)
 #ifdef IP_SET_HASH_WITH_NETMASK
        if (h->netmask != HOST_MASK)
                NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, h->netmask);
+#endif
+#ifdef IP_SET_HASH_WITH_PROTO
+       if (h->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, h->proto);
 #endif
        NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
                      htonl(atomic_read(&set->ref) - 1));
index ffa89f115eea7faa5b4380ff5dc398dbfe62b133..680a89a01d9f11648aac15cef7d70183c77f1b99 100644 (file)
@@ -8,72 +8,91 @@
 #define IPSET_INVALID_PORT     65536
 
 /* We must handle non-linear skbs */
-static bool
-get_port(u8 pf, const struct sk_buff *skb, bool src, u16 *port)
-{
-       unsigned short protocol;
-       unsigned int protoff;
-       int fragoff;
-       
-       switch (pf) {
-       case AF_INET: {
-               const struct iphdr *iph = ip_hdr(skb);
-
-               protocol = iph->protocol;
-               fragoff = ntohs(iph->frag_off) & IP_OFFSET;
-               protoff = ip_hdrlen(skb);
-               break;
-       }
-       case AF_INET6: {
-               int protohdr;
-               unsigned short frag_off;
-               
-               protohdr = ipv6_find_hdr(skb, &protoff, -1, &frag_off);
-               if (protohdr < 0)
-                       return false;
-
-               protocol = protohdr;
-               fragoff = frag_off;
-               break;
-       }
-       default:
-               return false;
-       }
-
-       /* See comments at tcp_match in ip_tables.c */
-       if (fragoff)
-               return false;
 
+static inline bool
+get_port(const struct sk_buff *skb, int protocol, unsigned int protooff,
+        bool src, u16 *port, u8 *proto)
+{
        switch (protocol) {
        case IPPROTO_TCP: {
                struct tcphdr _tcph;
                const struct tcphdr *th;
                
-               th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
+               th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph);
                if (th == NULL)
                        /* No choice either */
                        return false;
                
                *port = src ? th->source : th->dest;
                break;
-           }
+       }
        case IPPROTO_UDP: {
                struct udphdr _udph;
                const struct udphdr *uh;
 
-               uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
+               uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph);
                if (uh == NULL)
                        /* No choice either */
                        return false;
                
                *port = src ? uh->source : uh->dest;
                break;
-           }
+       }
        default:
-               return false;
+               if (*proto == IPSET_IPPROTO_TCPUDP)
+                       return false;
+               break;
        }
+       if (*proto != IPSET_IPPROTO_TCPUDP)
+               *proto = protocol;
+
        return true;
 }
+
+static inline bool
+get_ip4_port(const struct sk_buff *skb, bool src, u16 *port, u8 *proto)
+{
+       const struct iphdr *iph = ip_hdr(skb);
+       unsigned int protooff = ip_hdrlen(skb);
+       int protocol = iph->protocol;
+
+       if (!(*proto >= IPSET_IPPROTO_TCPUDP || *proto == protocol))
+               return false;
+
+       /* See comments at tcp_match in ip_tables.c */
+       if (ntohs(iph->frag_off) & IP_OFFSET)
+               return false;
+
+       return get_port(skb, protocol, protooff, src, port, proto);
+}
+
+static inline bool
+get_ip6_port(const struct sk_buff *skb, bool src, u16 *port, u8 *proto)
+{
+       unsigned int *protooff = 0;
+       int protocol;
+       unsigned short fragoff;
+
+       protocol = ipv6_find_hdr(skb, protooff, -1, &fragoff);
+       if (protocol < 0 || fragoff)
+               return false;
+
+       if (!(*proto >= IPSET_IPPROTO_TCPUDP || *proto == protocol))
+               return false;
+
+       return get_port(skb, protocol, *protooff, src, port, proto);
+}
+
+static inline bool
+get_ip_port(const struct sk_buff *skb, u8 pf, bool src, u16 *port)
+{
+       u8 proto = IPSET_IPPROTO_TCPUDP;
+
+       if (pf == AF_INET)
+               return get_ip4_port(skb, src, port, &proto);
+       else
+               return get_ip6_port(skb, src, port, &proto);
+}
 #endif /* __KERNEL__ */
 
 #endif /*_IP_SET_GETPORT_H*/
index c1a69646396d16cb064560fb3e04e4ca03bc13f5..4003af07a042a26c3f2ff19a428cbbb13101c528 100644 (file)
@@ -5,6 +5,8 @@
 enum {
        IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
        IPSET_ERR_HASH_ELEM,
+       IPSET_ERR_INVALID_PROTO,
+       IPSET_ERR_MISSING_PROTO,
 };
 
 #ifdef __KERNEL__
index 5bf331e565e72e5de2ec6c96919b6ab6e2a8d39a..9d7093c8318331a2cfecc0c89404e559c10ec528 100644 (file)
@@ -474,7 +474,6 @@ ip_set_create_policy[IPSET_ATTR_CMD_MAX + 1] __read_mostly = {
                                    .len = IPSET_MAXNAMELEN - 1},
        [IPSET_ATTR_REVISION]   = { .type = NLA_U8 },
        [IPSET_ATTR_FAMILY]     = { .type = NLA_U8 },
-       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
        [IPSET_ATTR_DATA]       = { .type = NLA_NESTED },
 };
 
index 66d39799e71a6ddf41e804c744bd15c04fee0081..27b96656f39fcbabd495cb4b1b27bb19f90416bc 100644 (file)
@@ -107,6 +107,7 @@ bitmap_ip_adt_policy[IPSET_ATTR_ADT_MAX+1] __read_mostly = {
        [IPSET_ATTR_IP_TO]      = { .type = NLA_U32 },
        [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -115,7 +116,6 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
 {
        struct bitmap_ip *map = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
-       bool eexist = flags & IPSET_FLAG_EXIST;
        u32 ip, ip_to, id;
        int ret = 0;
 
@@ -123,6 +123,9 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
                      bitmap_ip_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                ip = ip_set_get_h32(tb[IPSET_ATTR_IP]);
        else
@@ -164,11 +167,10 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
                ret = adt == IPSET_ADD ? bitmap_ip_add(map, id)
                                       : bitmap_ip_del(map, id);
 
-               if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
-                       if (tb[IPSET_ATTR_LINENO])
-                               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+               if (ret && !ip_set_eexist(ret, flags))
                        return ret;
-               }
+               else
+                       ret = 0;
        }
        return ret;
 }
@@ -356,7 +358,6 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
 {
        struct bitmap_ip_timeout *map = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
-       bool eexist = flags & IPSET_FLAG_EXIST;
        u32 ip, ip_to, id, timeout = map->timeout;
        int ret = 0;
 
@@ -364,6 +365,9 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
                      bitmap_ip_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                ip = ip_set_get_h32(tb[IPSET_ATTR_IP]);
        else
@@ -405,11 +409,10 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
                        ? bitmap_ip_timeout_add(map, id, timeout)
                        : bitmap_ip_timeout_del(map, id);
 
-               if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
-                       if (tb[IPSET_ATTR_LINENO])
-                               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+               if (ret && !ip_set_eexist(ret, flags))
                        return ret;
-               }
+               else
+                       ret = 0;
        }
        return ret;
 }
index d036862d381ed223b95824363040f6cdb1b0717e..3c94975aae80441d55fcd1bfc89cbec466d3f98a 100644 (file)
@@ -368,6 +368,7 @@ bitmap_ipmac_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = {
        [IPSET_ATTR_IP]         = { .type = NLA_U32 },
        [IPSET_ATTR_ETHER]      = { .type = NLA_BINARY, .len  = ETH_ALEN },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -377,7 +378,6 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len,
        struct bitmap_ipmac *map = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
        ipset_adtfn adtfn = set->variant->adt[adt];
-       bool eexist = flags & IPSET_FLAG_EXIST;
        struct ipmac data;
        u32 timeout = map->timeout;
        int ret = 0;
@@ -386,6 +386,9 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len,
                      bitmap_ipmac_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                data.id = ip_set_get_h32(tb[IPSET_ATTR_IP]);
        else
@@ -409,11 +412,7 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len,
 
        ret = adtfn(set, &data, GFP_KERNEL, timeout);
 
-       if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
-               if (tb[IPSET_ATTR_LINENO])
-                       *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-       }
-       return ret;
+       return ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
 static void
index f3e498a4a66d6fd7b2e35e920229c56364d3f458..6517252e4c370d5a50d2f3922b28a30702397448 100644 (file)
@@ -72,9 +72,9 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
                 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
 {
        struct bitmap_port *map = set->data;
-       u16 port;
+       u16 port = 0;
 
-       if (!get_port(pf, skb, flags & IPSET_DIM_ONE_SRC, &port))
+       if (!get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &port))
                return -EINVAL;
        
        port = ntohs(port);
@@ -101,6 +101,7 @@ bitmap_port_adt_policy[IPSET_ATTR_ADT_MAX+1] __read_mostly = {
        [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
        [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -109,7 +110,6 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len,
 {
        struct bitmap_port *map = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
-       bool eexist = flags & IPSET_FLAG_EXIST;
        u32 port;       /* wraparound */
        u16 id, port_to;
        int ret = 0;
@@ -118,6 +118,9 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len,
                      bitmap_port_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_PORT])
                port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
        else
@@ -150,11 +153,10 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len,
                ret = adt == IPSET_ADD ? bitmap_port_add(map, id)
                                       : bitmap_port_del(map, id);
 
-               if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
-                       if (tb[IPSET_ATTR_LINENO])
-                               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+               if (ret && !ip_set_eexist(ret, flags))
                        return ret;
-               }
+               else
+                       ret = 0;
        }
        return ret;
 }
@@ -313,9 +315,9 @@ bitmap_port_timeout_kadt(struct ip_set *set, const struct sk_buff *skb,
                         enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
 {
        struct bitmap_port_timeout *map = set->data;
-       u16 port;
+       u16 port = 0;
 
-       if (!get_port(pf, skb, flags & IPSET_DIM_ONE_SRC, &port))
+       if (!get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &port))
                return -EINVAL;
 
        port = ntohs(port);
@@ -343,7 +345,6 @@ bitmap_port_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
 {
        const struct bitmap_port_timeout *map = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
-       bool eexist = flags & IPSET_FLAG_EXIST;
        u16 id, port_to;
        u32 port, timeout = map->timeout;       /* wraparound */
        int ret = 0;
@@ -352,6 +353,9 @@ bitmap_port_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
                      bitmap_port_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_PORT])
                port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
        else
@@ -385,11 +389,10 @@ bitmap_port_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
                        ? bitmap_port_timeout_add(map, id, timeout)
                        : bitmap_port_timeout_del(map, id);
                
-               if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
-                       if (tb[IPSET_ATTR_LINENO])
-                               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+               if (ret && !ip_set_eexist(ret, flags))
                        return ret;
-               }
+               else
+                       ret = 0;
        }
        return ret;
 }
index e5ce6a42428ec38d2d067d4f894855d1fe660ba4..d73a5da81215aba34a4ce06464be997a861d043f 100644 (file)
@@ -140,6 +140,7 @@ hash_ip4_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = {
        [IPSET_ATTR_IP_TO]      = { .type = NLA_U32 },
        [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -148,7 +149,6 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
 {
        struct chash *h = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
-       bool eexist = flags & IPSET_FLAG_EXIST;
        ipset_adtfn adtfn = set->variant->adt[adt];
        u32 ip, nip, ip_to, hosts, timeout = h->timeout;
        int ret = 0;
@@ -157,6 +157,9 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
                      hash_ip4_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                ip = ip_set_get_n32(tb[IPSET_ATTR_IP]);
        else
@@ -196,11 +199,10 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
                nip = htonl(ip);
                ret = adtfn(set, &nip, GFP_KERNEL, timeout);
 
-               if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
-                       if (tb[IPSET_ATTR_LINENO])
-                               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+               if (ret && !ip_set_eexist(ret, flags))
                        return ret;
-               }
+               else
+                       ret = 0;
        }
        return ret;
 }
@@ -213,10 +215,10 @@ hash_ip_same_set(const struct ip_set *a, const struct ip_set *b)
        
        return x->maxelem == y->maxelem
               && x->timeout == y->timeout
+              && x->netmask == y->netmask
               && x->htable_bits == y->htable_bits      /* resizing ? */
               && x->array_size == y->array_size
-              && x->chain_limit == y->chain_limit
-              && x->netmask == y->netmask;
+              && x->chain_limit == y->chain_limit;
 }
 
 /* The type variant functions: IPv6 */
@@ -327,6 +329,7 @@ hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = {
        [IPSET_ATTR_IP]         = { .type = NLA_BINARY,
                                    .len = sizeof(struct in6_addr) },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -338,11 +341,15 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *head, int len,
        ipset_adtfn adtfn = set->variant->adt[adt];
        union nf_inet_addr *ip;
        u32 timeout = h->timeout;
+       int ret;
 
        if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
                      hash_ip6_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                ip = nla_data(tb[IPSET_ATTR_IP]);
        else
@@ -358,7 +365,9 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *head, int len,
                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
        }
 
-       return adtfn(set, ip, GFP_KERNEL, timeout);
+       ret = adtfn(set, ip, GFP_KERNEL, timeout);
+
+       return ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
 /* Create hash:ip type of sets */
index 8210f67555bb1813f7b35194378deddc13a7ca49..cb319d2cf14c2fab7503ccbb3869f0e84e179221 100644 (file)
@@ -48,14 +48,16 @@ hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b);
 struct hash_ipport4_elem {
        u32 ip;
        u16 port;
-       u16 match;
+       u8 proto;
+       u8 padding;
 };
 
 /* Member elements with timeout support */
 struct hash_ipport4_telem {
        u32 ip;
        u16 port;
-       u16 match;
+       u8 proto;
+       u8 padding;
        unsigned long timeout;
 };
 
@@ -63,13 +65,15 @@ static inline bool
 hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
                        const struct hash_ipport4_elem *ip2)
 {
-       return ip1->ip == ip2->ip && ip1->port == ip2->port;
+       return ip1->ip == ip2->ip
+              && ip1->port == ip2->port
+              && ip1->proto == ip2->proto;
 }
 
 static inline bool
 hash_ipport4_data_isnull(const struct hash_ipport4_elem *elem)
 {
-       return elem->match == 0;
+       return elem->proto == 0;
 }
 
 static inline void
@@ -78,7 +82,7 @@ hash_ipport4_data_copy(struct hash_ipport4_elem *dst,
 {
        dst->ip = src->ip;
        dst->port = src->port;
-       dst->match = 1;
+       dst->proto = src->proto;
 }
 
 static inline void
@@ -87,12 +91,13 @@ hash_ipport4_data_swap(struct hash_ipport4_elem *dst,
 {
        swap(dst->ip, src->ip);
        swap(dst->port, src->port);
+       swap(dst->proto, src->proto);
 }
 
 static inline void
 hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem)
 {
-       elem->match = 0;
+       elem->proto = 0;
 }
 
 static inline bool
@@ -101,6 +106,8 @@ hash_ipport4_data_list(struct sk_buff *skb,
 {
        NLA_PUT_NET32(skb, IPSET_ATTR_IP, data->ip);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        return 0;
 
 nla_put_failure:
@@ -116,6 +123,8 @@ hash_ipport4_data_tlist(struct sk_buff *skb,
 
        NLA_PUT_NET32(skb, IPSET_ATTR_IP, tdata->ip);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
                      htonl(ip_set_timeout_get(tdata->timeout)));
 
@@ -125,6 +134,8 @@ nla_put_failure:
        return 1;
 }
 
+#define IP_SET_HASH_WITH_PROTO
+
 #define PF             4
 #define HOST_MASK      32
 #include <linux/netfilter/ip_set_chash.h>
@@ -135,12 +146,14 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
 {
        struct chash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
-       struct hash_ipport4_elem data = {};
+       struct hash_ipport4_elem data = { .proto = h->proto };
 
-       ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
-       if (!get_port(AF_INET, skb, flags & IPSET_DIM_TWO_SRC, &data.port))
+       if (!get_ip4_port(skb, flags & IPSET_DIM_ONE_SRC,
+                         &data.port, &data.proto))
                return -EINVAL;
 
+       ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+
        return adtfn(set, &data, GFP_ATOMIC, h->timeout);
 }
 
@@ -148,7 +161,9 @@ static const struct nla_policy
 hash_ipport4_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = {
        [IPSET_ATTR_IP]         = { .type = NLA_U32 },
        [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
+       [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -157,9 +172,8 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
 {
        struct chash *h = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
-       bool eexist = flags & IPSET_FLAG_EXIST;
        ipset_adtfn adtfn = set->variant->adt[adt];
-       struct hash_ipport4_elem data = {};
+       struct hash_ipport4_elem data = { .proto = h->proto };
        u32 timeout = h->timeout;
        int ret;
 
@@ -167,6 +181,9 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
                      hash_ipport4_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                data.ip = ip_set_get_n32(tb[IPSET_ATTR_IP]);
        else
@@ -177,6 +194,24 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
        else
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_PROTO]) {
+               data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+               
+               if (data.proto == 0 || data.proto >= IPSET_IPPROTO_TCPUDP)
+                       return -IPSET_ERR_INVALID_PROTO;
+       } else if (data.proto == IPSET_IPPROTO_ANY)
+               return -IPSET_ERR_MISSING_PROTO;
+
+       switch (data.proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPSET_IPPROTO_TCPUDP:
+               break;
+       default:
+               data.port = 0;
+               break;
+       }
+
        if (tb[IPSET_ATTR_TIMEOUT]) {
                if (!with_timeout(h->timeout))
                        return -IPSET_ERR_TIMEOUT;
@@ -185,11 +220,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
 
        ret = adtfn(set, &data, GFP_KERNEL, timeout);
 
-       if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
-               if (tb[IPSET_ATTR_LINENO])
-                       *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-       }
-       return ret;
+       return ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
 static bool
@@ -200,6 +231,7 @@ hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
        
        return x->maxelem == y->maxelem
               && x->timeout == y->timeout
+              && x->proto == y->proto
               && x->htable_bits == y->htable_bits      /* resizing ? */
               && x->array_size == y->array_size
               && x->chain_limit == y->chain_limit;
@@ -210,13 +242,15 @@ hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
 struct hash_ipport6_elem {
        union nf_inet_addr ip;
        u16 port;
-       u16 match;
+       u8 proto;
+       u8 padding;
 };
 
 struct hash_ipport6_telem {
        union nf_inet_addr ip;
        u16 port;
-       u16 match;
+       u8 proto;
+       u8 padding;
        unsigned long timeout;
 };
 
@@ -225,13 +259,14 @@ hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
                        const struct hash_ipport6_elem *ip2)
 {
        return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
-              && ip1->port == ip2->port;
+              && ip1->port == ip2->port
+              && ip1->proto == ip2->proto;
 }
 
 static inline bool
 hash_ipport6_data_isnull(const struct hash_ipport6_elem *elem)
 {
-       return elem->match == 0;
+       return elem->proto == 0;
 }
 
 static inline void
@@ -239,7 +274,6 @@ hash_ipport6_data_copy(struct hash_ipport6_elem *dst,
                       const struct hash_ipport6_elem *src)
 {
        memcpy(dst, src, sizeof(*dst));
-       dst->match = 1;
 }
 
 static inline void
@@ -256,7 +290,7 @@ hash_ipport6_data_swap(struct hash_ipport6_elem *dst,
 static inline void
 hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem)
 {
-       elem->match = 0;
+       elem->proto = 0;
 }
 
 static inline bool
@@ -265,6 +299,8 @@ hash_ipport6_data_list(struct sk_buff *skb,
 {
        NLA_PUT(skb, IPSET_ATTR_IP, sizeof(struct in6_addr), &data->ip);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        return 0;
 
 nla_put_failure:
@@ -280,6 +316,8 @@ hash_ipport6_data_tlist(struct sk_buff *skb,
        
        NLA_PUT(skb, IPSET_ATTR_IP, sizeof(struct in6_addr), &e->ip);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
                      htonl(ip_set_timeout_get(e->timeout)));
        return 0;
@@ -301,12 +339,14 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
 {
        struct chash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
-       struct hash_ipport6_elem data = {};
+       struct hash_ipport6_elem data = { .proto = h->proto };
 
-       ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
-       if (!get_port(AF_INET, skb, flags & IPSET_DIM_TWO_SRC, &data.port))
+       if (!get_ip6_port(skb, flags & IPSET_DIM_ONE_SRC,
+                         &data.port, &data.proto))
                return -EINVAL;
 
+       ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+
        return adtfn(set, &data, GFP_ATOMIC, h->timeout);
 }
 
@@ -315,7 +355,9 @@ hash_ipport6_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = {
        [IPSET_ATTR_IP]         = { .type = NLA_BINARY,
                                    .len = sizeof(struct in6_addr) },
        [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
+       [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -325,13 +367,17 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len,
        struct chash *h = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
        ipset_adtfn adtfn = set->variant->adt[adt];
-       struct hash_ipport6_elem data = {};
+       struct hash_ipport6_elem data = { .proto = h->proto };
        u32 timeout = h->timeout;
+       int ret;
 
        if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
                      hash_ipport6_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                memcpy(&data.ip, nla_data(tb[IPSET_ATTR_IP]),
                       sizeof(struct in6_addr));
@@ -343,13 +389,33 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len,
        else
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_PROTO]) {
+               data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+
+               if (data.proto == 0 || data.proto >= IPSET_IPPROTO_TCPUDP)
+                       return -IPSET_ERR_INVALID_PROTO;
+       } else if (data.proto == IPSET_IPPROTO_ANY)
+               return -IPSET_ERR_MISSING_PROTO;
+
+       switch (data.proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPSET_IPPROTO_TCPUDP:
+               break;
+       default:
+               data.port = 0;
+               break;
+       }
+
        if (tb[IPSET_ATTR_TIMEOUT]) {
                if (!with_timeout(h->timeout))
                        return -IPSET_ERR_TIMEOUT;
                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
        }
 
-       return adtfn(set, &data, GFP_KERNEL, timeout);
+       ret = adtfn(set, &data, GFP_KERNEL, timeout);
+       
+       return ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
 /* Create hash:ip type of sets */
@@ -360,6 +426,7 @@ hash_ipport_create_policy[IPSET_ATTR_CREATE_MAX+1] __read_mostly = {
        [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
        [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
        [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
+       [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 };
 
@@ -367,8 +434,9 @@ static int
 hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
 {
        struct nlattr *tb[IPSET_ATTR_CREATE_MAX];
-       u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
        struct chash *h;
+       u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+       u8 proto = IPSET_IPPROTO_TCPUDP;        /* Backward compatibility */
 
        if (!(set->family == AF_INET || set->family == AF_INET6))
                return -IPSET_ERR_INVALID_FAMILY;
@@ -386,6 +454,12 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
        if (tb[IPSET_ATTR_MAXELEM])
                maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
 
+       if (tb[IPSET_ATTR_PROTO]) {
+               proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+               if (!proto)
+                       return -IPSET_ERR_INVALID_PROTO;
+       }
+
        h = kzalloc(sizeof(*h), GFP_KERNEL);
        if (!h)
                return -ENOMEM;
@@ -395,6 +469,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
        h->array_size = CHASH_DEFAULT_ARRAY_SIZE;
        h->chain_limit = CHASH_DEFAULT_CHAIN_LIMIT;
        get_random_bytes(&h->initval, sizeof(h->initval));
+       h->proto = proto;
        h->timeout = IPSET_NO_TIMEOUT;
 
        h->htable = ip_set_alloc(jhash_size(h->htable_bits) * sizeof(struct slist),
index fbf278010b40ed9f753b07b7e9b20386d10d714e..2c3cf9ba2437ae0634c698acf39c03396febd2a4 100644 (file)
@@ -49,7 +49,8 @@ struct hash_ipportip4_elem {
        u32 ip;
        u32 ip2;
        u16 port;
-       u16 match;
+       u8 proto;
+       u8 padding;
 };
 
 /* Member elements with timeout support */
@@ -57,7 +58,8 @@ struct hash_ipportip4_telem {
        u32 ip;
        u32 ip2;
        u16 port;
-       u16 match;
+       u8 proto;
+       u8 padding;
        unsigned long timeout;
 };
 
@@ -67,13 +69,14 @@ hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
 {
        return ip1->ip == ip2->ip
               && ip1->ip2 == ip2->ip2
-              && ip1->port == ip2->port;
+              && ip1->port == ip2->port
+              && ip1->proto == ip2->proto;
 }
 
 static inline bool
 hash_ipportip4_data_isnull(const struct hash_ipportip4_elem *elem)
 {
-       return elem->match == 0;
+       return elem->proto == 0;
 }
 
 static inline void
@@ -81,7 +84,6 @@ hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst,
                         const struct hash_ipportip4_elem *src)
 {
        memcpy(dst, src, sizeof(*dst));
-       dst->match = 1;
 }
 
 static inline void
@@ -98,7 +100,7 @@ hash_ipportip4_data_swap(struct hash_ipportip4_elem *dst,
 static inline void
 hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem)
 {
-       elem->match = 0;
+       elem->proto = 0;
 }
 
 static inline bool
@@ -108,6 +110,8 @@ hash_ipportip4_data_list(struct sk_buff *skb,
        NLA_PUT_NET32(skb, IPSET_ATTR_IP, data->ip);
        NLA_PUT_NET32(skb, IPSET_ATTR_IP2, data->ip2);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        return 0;
 
 nla_put_failure:
@@ -124,6 +128,8 @@ hash_ipportip4_data_tlist(struct sk_buff *skb,
        NLA_PUT_NET32(skb, IPSET_ATTR_IP, tdata->ip);
        NLA_PUT_NET32(skb, IPSET_ATTR_IP2, tdata->ip2);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
                      htonl(ip_set_timeout_get(tdata->timeout)));
 
@@ -133,6 +139,8 @@ nla_put_failure:
        return 1;
 }
 
+#define IP_SET_HASH_WITH_PROTO
+
 #define PF             4
 #define HOST_MASK      32
 #include <linux/netfilter/ip_set_chash.h>
@@ -143,11 +151,13 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
 {
        struct chash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
-       struct hash_ipportip4_elem data = {};
+       struct hash_ipportip4_elem data = { .proto = h->proto };
        
-       ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
-       if (!get_port(AF_INET, skb, flags & IPSET_DIM_TWO_SRC, &data.port))
+       if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+                         &data.port, &data.proto))
                return -EINVAL;
+
+       ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
        ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
 
        return adtfn(set, &data, GFP_ATOMIC, h->timeout);
@@ -158,7 +168,9 @@ hash_ipportip4_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = {
        [IPSET_ATTR_IP]         = { .type = NLA_U32 },
        [IPSET_ATTR_IP2]        = { .type = NLA_U32 },
        [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
+       [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -167,9 +179,8 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
 {
        struct chash *h = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
-       bool eexist = flags & IPSET_FLAG_EXIST;
        ipset_adtfn adtfn = set->variant->adt[adt];
-       struct hash_ipportip4_elem data = {};
+       struct hash_ipportip4_elem data = { .proto = h->proto };
        u32 timeout = h->timeout;
        int ret;
 
@@ -177,6 +188,9 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
                      hash_ipportip4_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                data.ip = ip_set_get_n32(tb[IPSET_ATTR_IP]);
        else
@@ -192,6 +206,24 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
        else
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_PROTO]) {
+               data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+               
+               if (data.proto == 0 || data.proto >= IPSET_IPPROTO_TCPUDP)
+                       return -IPSET_ERR_INVALID_PROTO;
+       } else if (data.proto == IPSET_IPPROTO_ANY)
+               return -IPSET_ERR_MISSING_PROTO;
+
+       switch (data.proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPSET_IPPROTO_TCPUDP:
+               break;
+       default:
+               data.port = 0;
+               break;
+       }
+
        if (tb[IPSET_ATTR_TIMEOUT]) {
                if (!with_timeout(h->timeout))
                        return -IPSET_ERR_TIMEOUT;
@@ -200,11 +232,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
 
        ret = adtfn(set, &data, GFP_KERNEL, timeout);
 
-       if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
-               if (tb[IPSET_ATTR_LINENO])
-                       *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-       }
-       return ret;
+       return ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
 static bool
@@ -215,6 +243,7 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
        
        return x->maxelem == y->maxelem
               && x->timeout == y->timeout
+              && x->proto == y->proto
               && x->htable_bits == y->htable_bits      /* resizing ? */
               && x->array_size == y->array_size
               && x->chain_limit == y->chain_limit;
@@ -226,14 +255,16 @@ struct hash_ipportip6_elem {
        union nf_inet_addr ip;
        union nf_inet_addr ip2;
        u16 port;
-       u16 match;
+       u8 proto;
+       u8 padding;
 };
 
 struct hash_ipportip6_telem {
        union nf_inet_addr ip;
        union nf_inet_addr ip2;
        u16 port;
-       u16 match;
+       u8 proto;
+       u8 padding;
        unsigned long timeout;
 };
 
@@ -243,13 +274,14 @@ hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
 {
        return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
               && ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0
-              && ip1->port == ip2->port;
+              && ip1->port == ip2->port
+              && ip1->proto == ip2->proto;
 }
 
 static inline bool
 hash_ipportip6_data_isnull(const struct hash_ipportip6_elem *elem)
 {
-       return elem->match == 0;
+       return elem->proto == 0;
 }
 
 static inline void
@@ -257,7 +289,6 @@ hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst,
                         const struct hash_ipportip6_elem *src)
 {
        memcpy(dst, src, sizeof(*dst));
-       dst->match = 1;
 }
 
 static inline void
@@ -274,7 +305,7 @@ hash_ipportip6_data_swap(struct hash_ipportip6_elem *dst,
 static inline void
 hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem)
 {
-       elem->match = 0;
+       elem->proto = 0;
 }
 
 static inline bool
@@ -284,6 +315,8 @@ hash_ipportip6_data_list(struct sk_buff *skb,
        NLA_PUT(skb, IPSET_ATTR_IP, sizeof(struct in6_addr), &data->ip);
        NLA_PUT(skb, IPSET_ATTR_IP2, sizeof(struct in6_addr), &data->ip2);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        return 0;
 
 nla_put_failure:
@@ -300,6 +333,8 @@ hash_ipportip6_data_tlist(struct sk_buff *skb,
        NLA_PUT(skb, IPSET_ATTR_IP, sizeof(struct in6_addr), &e->ip);
        NLA_PUT(skb, IPSET_ATTR_IP2, sizeof(struct in6_addr), &data->ip2);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
                      htonl(ip_set_timeout_get(e->timeout)));
        return 0;
@@ -321,11 +356,13 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
 {
        struct chash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
-       struct hash_ipportip6_elem data = {};
+       struct hash_ipportip6_elem data = { .proto = h->proto };
 
-       ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
-       if (!get_port(AF_INET, skb, flags & IPSET_DIM_TWO_SRC, &data.port))
+       if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+                         &data.port, &data.proto))
                return -EINVAL;
+
+       ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
        ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
 
        return adtfn(set, &data, GFP_ATOMIC, h->timeout);
@@ -338,7 +375,9 @@ hash_ipportip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = {
        [IPSET_ATTR_IP2]        = { .type = NLA_BINARY,
                                    .len = sizeof(struct in6_addr) },
        [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
+       [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -348,13 +387,17 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len,
        struct chash *h = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
        ipset_adtfn adtfn = set->variant->adt[adt];
-       struct hash_ipportip6_elem data = {};
+       struct hash_ipportip6_elem data = { .proto = h->proto };
        u32 timeout = h->timeout;
+       int ret;
 
        if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
                      hash_ipportip6_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                memcpy(&data.ip, nla_data(tb[IPSET_ATTR_IP]),
                       sizeof(struct in6_addr));
@@ -372,13 +415,33 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len,
        else
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_PROTO]) {
+               data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+
+               if (data.proto == 0 || data.proto >= IPSET_IPPROTO_TCPUDP)
+                       return -IPSET_ERR_INVALID_PROTO;
+       } else if (data.proto == IPSET_IPPROTO_ANY)
+               return -IPSET_ERR_MISSING_PROTO;
+
+       switch (data.proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPSET_IPPROTO_TCPUDP:
+               break;
+       default:
+               data.port = 0;
+               break;
+       }
+
        if (tb[IPSET_ATTR_TIMEOUT]) {
                if (!with_timeout(h->timeout))
                        return -IPSET_ERR_TIMEOUT;
                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
        }
 
-       return adtfn(set, &data, GFP_KERNEL, timeout);
+       ret = adtfn(set, &data, GFP_KERNEL, timeout);
+
+       return ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
 /* Create hash:ip type of sets */
@@ -389,6 +452,7 @@ hash_ipportip_create_policy[IPSET_ATTR_CREATE_MAX+1] __read_mostly = {
        [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
        [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
        [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
+       [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 };
 
@@ -397,8 +461,9 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
                     int len, u32 flags)
 {
        struct nlattr *tb[IPSET_ATTR_CREATE_MAX];
-       u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
        struct chash *h;
+       u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+       u8 proto = IPSET_IPPROTO_TCPUDP;        /* Backward compatibility */
 
        if (!(set->family == AF_INET || set->family == AF_INET6))
                return -IPSET_ERR_INVALID_FAMILY;
@@ -416,6 +481,12 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
        if (tb[IPSET_ATTR_MAXELEM])
                maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
 
+       if (tb[IPSET_ATTR_PROTO]) {
+               proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+               if (!proto)
+                       return -IPSET_ERR_INVALID_PROTO;
+       }
+
        h = kzalloc(sizeof(*h), GFP_KERNEL);
        if (!h)
                return -ENOMEM;
@@ -425,6 +496,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
        h->array_size = CHASH_DEFAULT_ARRAY_SIZE;
        h->chain_limit = CHASH_DEFAULT_CHAIN_LIMIT;
        get_random_bytes(&h->initval, sizeof(h->initval));
+       h->proto = proto;
        h->timeout = IPSET_NO_TIMEOUT;
 
        h->htable = ip_set_alloc(jhash_size(h->htable_bits) * sizeof(struct slist),
index dfe934898b6ab7fc8f3e6c00d966c1fcccb1bae2..4bc44f5214449225e1459ef6cd7bb2d0fa6b10f8 100644 (file)
@@ -50,7 +50,7 @@ struct hash_ipportnet4_elem {
        u32 ip2;
        u16 port;
        u8 cidr;
-       u8 match;
+       u8 proto;
 };
 
 /* Member elements with timeout support */
@@ -59,7 +59,7 @@ struct hash_ipportnet4_telem {
        u32 ip2;
        u16 port;
        u8 cidr;
-       u8 match;
+       u8 proto;
        unsigned long timeout;
 };
 
@@ -70,13 +70,14 @@ hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
        return ip1->ip == ip2->ip
               && ip1->ip2 == ip2->ip2
               && ip1->cidr == ip2->cidr
-              && ip1->port == ip2->port;
+              && ip1->port == ip2->port
+              && ip1->proto == ip2->proto;
 }
 
 static inline bool
 hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem *elem)
 {
-       return elem->match == 0;
+       return elem->proto == 0;
 }
 
 static inline void
@@ -84,7 +85,6 @@ hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst,
                          const struct hash_ipportnet4_elem *src)
 {
        memcpy(dst, src, sizeof(*dst));
-       dst->match = 1;
 }
 
 static inline void
@@ -108,7 +108,7 @@ hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
 static inline void
 hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
 {
-       elem->match = 0;
+       elem->proto = 0;
 }
 
 static inline bool
@@ -119,6 +119,8 @@ hash_ipportnet4_data_list(struct sk_buff *skb,
        NLA_PUT_NET32(skb, IPSET_ATTR_IP2, data->ip2);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
        NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        return 0;
 
 nla_put_failure:
@@ -136,6 +138,8 @@ hash_ipportnet4_data_tlist(struct sk_buff *skb,
        NLA_PUT_NET32(skb, IPSET_ATTR_IP2, tdata->ip2);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
        NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
                      htonl(ip_set_timeout_get(tdata->timeout)));
 
@@ -145,6 +149,7 @@ nla_put_failure:
        return 1;
 }
 
+#define IP_SET_HASH_WITH_PROTO
 #define IP_SET_HASH_WITH_NETS
 
 #define PF             4
@@ -158,16 +163,19 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
        struct chash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportnet4_elem data =
-               { .cidr = h->nets[0].cidr || HOST_MASK };
-       
+               { .cidr = h->nets[0].cidr || HOST_MASK,
+                 .proto = h->proto };
+
        if (data.cidr == 0)
                return -EINVAL;
        if (adt == IPSET_TEST)
                data.cidr = HOST_MASK;
 
-       ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
-       if (!get_port(AF_INET, skb, flags & IPSET_DIM_TWO_SRC, &data.port))
+       if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+                         &data.port, &data.proto))
                return -EINVAL;
+
+       ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
        ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
        data.ip2 &= NETMASK(data.cidr);
 
@@ -180,7 +188,9 @@ hash_ipportnet4_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = {
        [IPSET_ATTR_IP2]        = { .type = NLA_U32 },
        [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
        [IPSET_ATTR_CIDR2]      = { .type = NLA_U8 },
+       [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -189,9 +199,9 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
 {
        struct chash *h = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
-       bool eexist = flags & IPSET_FLAG_EXIST;
        ipset_adtfn adtfn = set->variant->adt[adt];
-       struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
+       struct hash_ipportnet4_elem data = { .cidr = HOST_MASK,
+                                            .proto = h->proto  };
        u32 timeout = h->timeout;
        int ret;
 
@@ -199,6 +209,9 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
                      hash_ipportnet4_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                data.ip = ip_set_get_n32(tb[IPSET_ATTR_IP]);
        else
@@ -222,6 +235,24 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
        else
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_PROTO]) {
+               data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+               
+               if (data.proto == 0 || data.proto >= IPSET_IPPROTO_TCPUDP)
+                       return -IPSET_ERR_INVALID_PROTO;
+       } else if (data.proto == IPSET_IPPROTO_ANY)
+               return -IPSET_ERR_MISSING_PROTO;
+
+       switch (data.proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPSET_IPPROTO_TCPUDP:
+               break;
+       default:
+               data.port = 0;
+               break;
+       }
+
        if (tb[IPSET_ATTR_TIMEOUT]) {
                if (!with_timeout(h->timeout))
                        return -IPSET_ERR_TIMEOUT;
@@ -230,11 +261,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
 
        ret = adtfn(set, &data, GFP_KERNEL, timeout);
 
-       if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
-               if (tb[IPSET_ATTR_LINENO])
-                       *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-       }
-       return ret;
+       return ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
 static bool
@@ -245,6 +272,7 @@ hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
        
        return x->maxelem == y->maxelem
               && x->timeout == y->timeout
+              && x->proto == y->proto
               && x->htable_bits == y->htable_bits      /* resizing ? */
               && x->array_size == y->array_size
               && x->chain_limit == y->chain_limit;
@@ -257,7 +285,7 @@ struct hash_ipportnet6_elem {
        union nf_inet_addr ip2;
        u16 port;
        u8 cidr;
-       u8 match;
+       u8 proto;
 };
 
 struct hash_ipportnet6_telem {
@@ -265,7 +293,7 @@ struct hash_ipportnet6_telem {
        union nf_inet_addr ip2;
        u16 port;
        u8 cidr;
-       u8 match;
+       u8 proto;
        unsigned long timeout;
 };
 
@@ -276,13 +304,14 @@ hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
        return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
               && ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0
               && ip1->cidr == ip2->cidr
-              && ip1->port == ip2->port;
+              && ip1->port == ip2->port
+              && ip1->proto == ip2->proto;
 }
 
 static inline bool
 hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem)
 {
-       return elem->match == 0;
+       return elem->proto == 0;
 }
 
 static inline void
@@ -290,7 +319,6 @@ hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
                          const struct hash_ipportnet6_elem *src)
 {
        memcpy(dst, src, sizeof(*dst));
-       dst->match = 1;
 }
 
 static inline void
@@ -307,7 +335,7 @@ hash_ipportnet6_data_swap(struct hash_ipportnet6_elem *dst,
 static inline void
 hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
 {
-       elem->match = 0;
+       elem->proto = 0;
 }
 
 static inline void
@@ -334,6 +362,8 @@ hash_ipportnet6_data_list(struct sk_buff *skb,
        NLA_PUT(skb, IPSET_ATTR_IP2, sizeof(struct in6_addr), &data->ip2);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
        NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        return 0;
 
 nla_put_failure:
@@ -351,6 +381,8 @@ hash_ipportnet6_data_tlist(struct sk_buff *skb,
        NLA_PUT(skb, IPSET_ATTR_IP2, sizeof(struct in6_addr), &data->ip2);
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
        NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
+       if (data->proto != IPSET_IPPROTO_TCPUDP)
+               NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
        NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
                      htonl(ip_set_timeout_get(e->timeout)));
        return 0;
@@ -373,16 +405,19 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
        struct chash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportnet6_elem data =
-               { .cidr = h->nets[0].cidr || HOST_MASK };
+               { .cidr = h->nets[0].cidr || HOST_MASK,
+                 .proto = h->proto };
 
        if (data.cidr == 0)
                return -EINVAL;
        if (adt == IPSET_TEST)
                data.cidr = HOST_MASK;
 
-       ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
-       if (!get_port(AF_INET, skb, flags & IPSET_DIM_TWO_SRC, &data.port))
+       if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+                         &data.port, &data.proto))
                return -EINVAL;
+
+       ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
        ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
        ip6_netmask(&data.ip2, data.cidr);
 
@@ -397,7 +432,9 @@ hash_ipportnet6_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = {
                                    .len = sizeof(struct in6_addr) },
        [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
        [IPSET_ATTR_CIDR2]      = { .type = NLA_U8 },
+       [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -407,13 +444,18 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len,
        struct chash *h = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
        ipset_adtfn adtfn = set->variant->adt[adt];
-       struct hash_ipportnet6_elem data = { .cidr = HOST_MASK };
+       struct hash_ipportnet6_elem data = { .cidr = HOST_MASK,
+                                            .proto = h->proto };
        u32 timeout = h->timeout;
+       int ret;
 
        if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
                      hash_ipportnet6_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                memcpy(&data.ip, nla_data(tb[IPSET_ATTR_IP]),
                       sizeof(struct in6_addr));
@@ -439,13 +481,33 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len,
        else
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_PROTO]) {
+               data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+
+               if (data.proto == 0 || data.proto >= IPSET_IPPROTO_TCPUDP)
+                       return -IPSET_ERR_INVALID_PROTO;
+       } else if (data.proto == IPSET_IPPROTO_ANY)
+               return -IPSET_ERR_MISSING_PROTO;
+
+       switch (data.proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPSET_IPPROTO_TCPUDP:
+               break;
+       default:
+               data.port = 0;
+               break;
+       }
+
        if (tb[IPSET_ATTR_TIMEOUT]) {
                if (!with_timeout(h->timeout))
                        return -IPSET_ERR_TIMEOUT;
                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
        }
 
-       return adtfn(set, &data, GFP_KERNEL, timeout);
+       ret = adtfn(set, &data, GFP_KERNEL, timeout);
+
+       return ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
 /* Create hash:ip type of sets */
@@ -456,6 +518,7 @@ hash_ipportnet_create_policy[IPSET_ATTR_CREATE_MAX+1] __read_mostly = {
        [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
        [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
        [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
+       [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 };
 
@@ -464,8 +527,9 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
                     int len, u32 flags)
 {
        struct nlattr *tb[IPSET_ATTR_CREATE_MAX];
-       u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
        struct chash *h;
+       u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+       u8 proto = IPSET_IPPROTO_TCPUDP;        /* Backward compatibility */
 
        if (!(set->family == AF_INET || set->family == AF_INET6))
                return -IPSET_ERR_INVALID_FAMILY;
@@ -483,6 +547,11 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
        if (tb[IPSET_ATTR_MAXELEM])
                maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
 
+       if (tb[IPSET_ATTR_PROTO]) {
+               proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+               if (!proto)
+                       return -IPSET_ERR_INVALID_PROTO;
+       }
        h = kzalloc(sizeof(*h)
                    + sizeof(struct chash_nets)
                      * (set->family == AF_INET ? 31 : 127), GFP_KERNEL);
@@ -494,6 +563,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
        h->array_size = CHASH_DEFAULT_ARRAY_SIZE;
        h->chain_limit = CHASH_DEFAULT_CHAIN_LIMIT;
        get_random_bytes(&h->initval, sizeof(h->initval));
+       h->proto = proto;
        h->timeout = IPSET_NO_TIMEOUT;
 
        h->htable = ip_set_alloc(jhash_size(h->htable_bits) * sizeof(struct slist),
index a8611c25eb83ec7ba7e1656b929b382894972ae3..9be9e2ccb4f7471d3d227a58adbdcccb3043ce9b 100644 (file)
@@ -46,13 +46,17 @@ hash_net_same_set(const struct ip_set *a, const struct ip_set *b);
 /* Member elements without timeout */
 struct hash_net4_elem {
        u32 ip;
-       u8 cidr;        /* Not hashed, zero for null value */
+       u16 padding0;
+       u8 padding1;
+       u8 cidr;
 };
 
 /* Member elements with timeout support */
 struct hash_net4_telem {
        u32 ip;
-       u8 cidr;        /* Not hashed, zero for null value */
+       u16 padding0;
+       u8 padding1;
+       u8 cidr;
        unsigned long timeout;
 };
 
@@ -60,10 +64,7 @@ static inline bool
 hash_net4_data_equal(const struct hash_net4_elem *ip1,
                    const struct hash_net4_elem *ip2)
 {
-       /* We don't have to check the cidr equality
-        * because overlapping nets cannot be added to the set
-        */
-       return ip1->ip == ip2->ip;
+       return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr;
 }
 
 static inline bool
@@ -168,7 +169,6 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len,
 {
        struct chash *h = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
-       bool eexist = flags & IPSET_FLAG_EXIST;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_net4_elem data = { .cidr = HOST_MASK };
        u32 timeout = h->timeout;
@@ -178,6 +178,9 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len,
                      hash_net4_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                data.ip = ip_set_get_n32(tb[IPSET_ATTR_IP]);
        else
@@ -199,11 +202,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len,
 
        ret = adtfn(set, &data, GFP_KERNEL, timeout);
 
-       if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
-               if (tb[IPSET_ATTR_LINENO])
-                       *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-       }
-       return ret;
+       return ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
 static bool
@@ -223,12 +222,16 @@ hash_net_same_set(const struct ip_set *a, const struct ip_set *b)
 
 struct hash_net6_elem {
        union nf_inet_addr ip;
-       u8 cidr;        /* Not hashed */
+       u16 padding0;
+       u8 padding1;
+       u8 cidr;
 };
 
 struct hash_net6_telem {
        union nf_inet_addr ip;
-       u8 cidr;        /* Not hashed */
+       u16 padding0;
+       u8 padding1;
+       u8 cidr;
        unsigned long timeout;
 };
 
@@ -236,7 +239,8 @@ static inline bool
 hash_net6_data_equal(const struct hash_net6_elem *ip1,
                     const struct hash_net6_elem *ip2)
 {
-       return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0;
+       return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
+              && ip1->cidr == ip2->cidr;
 }
 
 static inline bool
@@ -344,6 +348,7 @@ hash_net6_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = {
                                    .len = sizeof(struct in6_addr) },
        [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 };
 
 static int
@@ -355,11 +360,15 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *head, int len,
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_net6_elem data = { .cidr = HOST_MASK };
        u32 timeout = h->timeout;
+       int ret;
 
        if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
                      hash_net6_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_IP])
                memcpy(&data.ip, nla_data(tb[IPSET_ATTR_IP]),
                       sizeof(struct in6_addr));
@@ -380,7 +389,9 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *head, int len,
                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
        }
 
-       return adtfn(set, &data, GFP_KERNEL, timeout);
+       ret = adtfn(set, &data, GFP_KERNEL, timeout);
+       
+       return ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
 /* Create hash:ip type of sets */
index ce6c4d101af7f2f36cb823c2f5f74a3c35a4fdb5..94c5702b85eeddf47d0af0a4b1de2cb7466fe012 100644 (file)
@@ -119,6 +119,7 @@ list_set_adt_policy[IPSET_ATTR_ADT_MAX+1] __read_mostly = {
        [IPSET_ATTR_NAMEREF]    = { .type = NLA_STRING,
                                    .len = IPSET_MAXNAMELEN },
        [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+       [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
        [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
 };
 
@@ -210,8 +211,7 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
 {
        struct list_set *map = set->data;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX];
-       bool eexist = flags & IPSET_FLAG_EXIST,
-            with_timeout = with_timeout(map->timeout);
+       bool with_timeout = with_timeout(map->timeout);
        int before = 0;
        u32 timeout = map->timeout;
        ip_set_id_t id, refid = IPSET_INVALID_ID;
@@ -224,6 +224,9 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
                      list_set_adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
+       if (tb[IPSET_ATTR_LINENO])
+               *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
        if (tb[IPSET_ATTR_NAME]) {
                id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s);
                if (id == IPSET_INVALID_ID)
@@ -334,12 +337,7 @@ finish:
        if (adt != IPSET_ADD || ret)
                ip_set_put_byindex(id);
 
-       if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
-               if (tb[IPSET_ATTR_LINENO])
-                       *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-               return ret;
-       }
-       return ret;
+       return ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
 static void
@@ -565,7 +563,7 @@ list_set_create(struct ip_set *set, struct nlattr *head, int len,
 static struct ip_set_type list_set_type = {
        .name           = "list:set",
        .protocol       = IPSET_PROTOCOL,
-       .features       = IPSET_TYPE_NAME,
+       .features       = IPSET_TYPE_NAME | IPSET_DUMP_LAST,
        .dimension      = IPSET_DIM_ONE,
        .family         = AF_UNSPEC,
        .revision       = 0,
index f8ff4a9580944c1af3ef914a39f8879bad78e0e5..65ba2094d6e901c50d9fb1dd606eaf62e8f823f2 100644 (file)
@@ -66,6 +66,7 @@ struct ipset_data {
                struct {
                        union nf_inet_addr ip2;
                        uint8_t cidr2;
+                       uint8_t proto;
                        char ether[ETH_ALEN];
                        char name[IPSET_MAXNAMELEN];
                        char nameref[IPSET_MAXNAMELEN];
@@ -288,6 +289,9 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
        case IPSET_OPT_CIDR2:
                data->u.adt.cidr2 = *(const uint8_t *) value;
                break;
+       case IPSET_OPT_PROTO:
+               data->u.adt.proto = *(const uint8_t *) value;
+               break;
        /* Swap/rename */
        case IPSET_OPT_SETNAME2:
                ipset_strncpy(data->u.setname2, value, IPSET_MAXNAMELEN);
@@ -396,6 +400,8 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
                return &data->u.adt.ip2;
        case IPSET_OPT_CIDR2:
                return &data->u.adt.cidr2;
+       case IPSET_OPT_PROTO:
+               return &data->u.adt.proto;
        /* Swap/rename */
        case IPSET_OPT_SETNAME2:
                return data->u.setname2;
@@ -450,6 +456,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
        case IPSET_OPT_NETMASK:
        case IPSET_OPT_PROBES:
        case IPSET_OPT_RESIZE:
+       case IPSET_OPT_PROTO:
                return sizeof(uint8_t);
        case IPSET_OPT_ETHER:
                return ETH_ALEN;
index a07168d2cdfcbb22217eda67cb143b42b59e02d9..b1fecc7ce3ac1a1d9afbf6ac4d2b782262fcad0a 100644 (file)
@@ -31,6 +31,7 @@
 #define range_separator(str)   ipset_strchr(str, IPSET_RANGE_SEPARATOR)
 #define elem_separator(str)    ipset_strchr(str, IPSET_ELEM_SEPARATOR)
 #define name_separator(str)    ipset_strchr(str, IPSET_NAME_SEPARATOR)
+#define proto_separator(str)   ipset_strchr(str, IPSET_PROTO_SEPARATOR)
 
 #define syntax_err(fmt, args...) \
        ipset_err(session, "Syntax error: " fmt , ## args)
@@ -280,6 +281,88 @@ error:
        return err;
 }
 
+/**
+ * ipset_parse_proto - parse protocol name
+ * @session: session structure
+ * @opt: option kind of the data
+ * @str: string to parse
+ *
+ * Parse string as a protocol name. "any" is supported
+ * as a special protocol name for ipset itself.
+ * The parsed protocol are stored in the data blob of the session.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int
+ipset_parse_proto(struct ipset_session *session,
+                 enum ipset_opt opt, const char *str)
+{
+       uint8_t proto = 0;
+
+       assert(session);
+       assert(opt == IPSET_OPT_PROTO);
+       assert(str);
+       
+       if (STREQ(str, "any"))
+               proto = IPSET_IPPROTO_ANY;
+       else {
+               struct protoent *protoent = getprotobyname(str);
+               if (protoent == NULL)
+                       return syntax_err("cannot parse '%s' as a protocol name", str);
+               proto = protoent->p_proto;
+       }
+       if (!proto || proto == IPSET_IPPROTO_TCPUDP)
+               return syntax_err("invalid protocol '%s'", str);
+       
+       return ipset_session_data_set(session, opt, &proto);
+}
+
+/**
+ * ipset_parse_proto_port - parse (optional) protocol and a single port
+ * @session: session structure
+ * @opt: option kind of the data
+ * @str: string to parse
+ *
+ * Parse string as a protocol and port, separated by a colon.
+ * The protocol part is optional.
+ * The parsed protocol and port numbers are stored in the data
+ * blob of the session.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int
+ipset_parse_proto_port(struct ipset_session *session,
+                      enum ipset_opt opt, const char *str)
+{
+       char *a, *saved, *tmp;
+       int err = 0;
+
+       assert(session);
+       assert(opt == IPSET_OPT_PORT);
+       assert(str);
+
+       saved = tmp = strdup(str);
+       if (tmp == NULL)
+               return ipset_err(session,
+                                "Cannot allocate memory to duplicate %s.",
+                                str);
+
+       a = proto_separator(tmp);
+       if (a != NULL) {
+               /* proto:port */
+               *a++ = '\0';
+               err = ipset_parse_proto(session, IPSET_OPT_PROTO, tmp);
+               if (err)
+                       goto error;
+               tmp = a;
+       }
+       err = ipset_parse_single_port(session, opt, tmp);
+
+error:
+       free(saved);
+       return err;
+}
+
 /**
  * ipset_parse_family - parse INET|INET6 family names
  * @session: session structure
index d96e643f57c217b8153298d0d6e80aebdb84d52e..68f658a7b1d75ffbdb152871e0cf71d2f56d6092 100644 (file)
@@ -435,6 +435,79 @@ ipset_print_port(char *buf, unsigned int len,
        return offset;
 }
 
+/**
+ * ipset_print_proto - print protocol name
+ * @buf: printing buffer
+ * @len: length of available buffer space
+ * @data: data blob
+ * @opt: the option kind
+ * @env: environment flags
+ *
+ * Print protocol name to output buffer.
+ *
+ * Return lenght of printed string or error size.
+ */
+int
+ipset_print_proto(char *buf, unsigned int len,
+                 const struct ipset_data *data, enum ipset_opt opt,
+                 uint8_t env UNUSED)
+{
+       struct protoent *protoent;
+       uint8_t proto;
+
+       assert(buf);
+       assert(len > 0);
+       assert(data);
+       assert(opt == IPSET_OPT_PROTO);
+
+       proto = *(uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO);
+       assert(proto);
+       
+       if (proto == IPSET_IPPROTO_ANY)
+               return snprintf(buf, len, "any");
+       protoent = getprotobynumber(proto);
+       if (protoent)
+               return snprintf(buf, len, "%s", protoent->p_name);
+
+       /* Should not happen */ 
+       return snprintf(buf, len, "%u", proto);
+}
+
+/**
+ * ipset_print_proto_port - print proto:port
+ * @buf: printing buffer
+ * @len: length of available buffer space
+ * @data: data blob
+ * @opt: the option kind
+ * @env: environment flags
+ *
+ * Print protocol and port to output buffer.
+ *
+ * Return lenght of printed string or error size.
+ */
+int
+ipset_print_proto_port(char *buf, unsigned int len,
+                      const struct ipset_data *data, enum ipset_opt opt,
+                      uint8_t env UNUSED)
+{
+       int size, offset = 0;
+
+       assert(buf);
+       assert(len > 0);
+       assert(data);
+       assert(opt == IPSET_OPT_PORT);
+
+       if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_PROTO))) {
+               size = ipset_print_proto(buf, len, data, IPSET_OPT_PROTO, env);
+               SNPRINTF_FAILURE(size, len, offset);
+               if (len < 2)
+                       return -ENOSPC;
+               strcat(buf, ":");
+               SNPRINTF_FAILURE(1, len, offset);
+       }
+       return ipset_print_port(buf + offset, len, data, IPSET_OPT_PORT, env);
+}
+
 #define print_second(data)     \
 ipset_data_flags_test(data,    \
        IPSET_FLAG(IPSET_OPT_PORT)|IPSET_FLAG(IPSET_OPT_ETHER)) 
index 36716f094173b5f0810a1d00ee93c9067454ff03..fe1e178e61bb9d892388a2664a3e82a81f49a0b3 100644 (file)
@@ -35,6 +35,7 @@ struct ipset_session {
        enum ipset_cmd cmd;                     /* Current command */
        uint32_t lineno;                        /* Current lineno in restore mode */
        char saved_setname[IPSET_MAXNAMELEN];   /* Saved setname */
+       const struct ipset_type *saved_type;    /* Saved type */
        struct nlattr *nested[IPSET_NEST_MAX];  /* Pointer to nest levels */
        uint8_t nestid;                         /* Current nest level */
        bool version_checked;                   /* Version checked */
@@ -82,6 +83,20 @@ ipset_session_handle(const struct ipset_session *session)
        return session->handle;
 }
 
+/**
+ * ipset_saved_type - return pointer to the saved type
+ * @session: session structure
+ *
+ * Returns the pointer to the saved type from the last ipset_cmd
+ * It is required to decode type-specific error codes in restore mode.
+ */
+const struct ipset_type *
+ipset_saved_type(const struct ipset_session *session)
+{
+       assert(session);
+       return session->saved_type;
+}
+
 /*
  * Environment options
  */
@@ -327,6 +342,10 @@ const struct ipset_attr_policy create_attrs[] = {
                .type = MNL_TYPE_U32,
                .opt = IPSET_OPT_TIMEOUT,
        },
+       [IPSET_ATTR_PROTO] = {
+               .type = MNL_TYPE_U8,
+               .opt = IPSET_OPT_PROTO,
+       },
        [IPSET_ATTR_CADT_FLAGS] = {
                .type = MNL_TYPE_U32,
                .opt = IPSET_OPT_CADT_FLAGS,
@@ -394,6 +413,10 @@ const struct ipset_attr_policy adt_attrs[] = {
                .type = MNL_TYPE_U16,
                .opt = IPSET_OPT_PORT_TO,
        },
+       [IPSET_ATTR_PROTO] = {
+               .type = MNL_TYPE_U8,
+               .opt = IPSET_OPT_PROTO,
+       },
        [IPSET_ATTR_TIMEOUT] = {
                .type = MNL_TYPE_U32,
                .opt = IPSET_OPT_TIMEOUT,
@@ -1714,6 +1737,8 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
                goto cleanup;
        D("past: build_msg");
 
+       /* We have to save the type for error handling */
+       session->saved_type = ipset_data_get(data, IPSET_OPT_TYPE);
        /* Save setname for the next possible aggregated restore line */
        if (session->lineno != 0
            && (cmd == IPSET_CMD_ADD || cmd == IPSET_CMD_DEL)) {
index c30ecb666f0154dd54964bf2ed28f66f2ceef302..ae0d8c8d40eb885f5104410a0bc060de059d3d58 100644 (file)
@@ -102,6 +102,10 @@ static const struct ipset_errcode_table hash_errcode_table[] = {
          "Hash is full, cannot add more elements" },
        { IPSET_ERR_HASH_ELEM, 0,
          "Null-valued element, cannot be stored in a hash type of set" },
+       { IPSET_ERR_INVALID_PROTO, 0,
+         "Invalid protocol specified" },
+       { IPSET_ERR_MISSING_PROTO, 0,
+         "Protocol missing, but must be specified" },
        { },
 };
 
@@ -144,7 +148,7 @@ ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd, int errcode)
        if (errcode >= IPSET_ERR_TYPE_SPECIFIC) {
                const struct ipset_type *type;
                
-               type = ipset_session_data_get(session, IPSET_OPT_TYPE);
+               type = ipset_saved_type(session);
                if (type) {
                        if (MATCH_TYPENAME(type->name, "bitmap:"))
                                table = bitmap_errcode_table;
index 661d1b47d0ce1f11cd0349867d992f8c2bf15919..5b9e4ad9ca160375461bb24f9d0fb685591d740b 100644 (file)
@@ -112,12 +112,12 @@ If the set has got reference(s), nothing is done and no set destroyed.
 \fBlist\fP [ \fISETNAME\fP ]
 List the header data and the entries for the specified set, or for
 all sets if none is given. The
-\fB\-\-resolve\fP
+\fB\-resolve\fP
 option can be used to force name lookups (which may be slow). When the
-\fB\-\-sorted\fP
+\fB\-sorted\fP
 option is given, the entries are listed sorted (if the given set
 type supports the operation). The option
-\fB\-\-output\fR
+\fB\-output\fR
 can be used to control the format of the listing:
 \fBplain\fR, \fBsave\fR or \fBxml\fR.
 The default is
@@ -231,7 +231,7 @@ to 65536 entries.
 .PP 
 \fIDEL\-ENTRY\fR := { \fIipaddr\fR | \fIfromaddr\fR\-\fItoaddr\fR | \fIipaddr\fR/\fIcidr\fR }
 .PP 
-\fITEST\-ENTRY\fR := { \fIipaddr\fR }
+\fITEST\-ENTRY\fR := \fIipaddr\fR
 .PP 
 Mandatory \fBcreate\fR options:
 .TP 
@@ -262,13 +262,13 @@ The \fBbitmap:ip,mac\fR set type uses a memory range to store IPv4 and a MAC add
 .PP 
 \fICREATE\-OPTIONS\fR := \fBrange\fP \fIfrom\-ip\fP\-\fIto\-ip\fR|\fIip\fR/\fIcidr\fR [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIADD\-ENTRY\fR := { \fIipaddr\fR[,\fImac\-addr\fR] }
+\fIADD\-ENTRY\fR := \fIipaddr\fR[,\fImac\-addr\fR]
 .PP 
 \fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIDEL\-ENTRY\fR := { \fIipaddr\fR[,\fImac\-addr\fR] }
+\fIDEL\-ENTRY\fR := \fIipaddr\fR[,\fImac\-addr\fR]
 .PP 
-\fITEST\-ENTRY\fR := { \fIipaddr\fR[,\fImac\-addr\fR] }
+\fITEST\-ENTRY\fR := \fIipaddr\fR[,\fImac\-addr\fR]
 .PP 
 Mandatory options to use when creating a \fBbitmap:ip,mac\fR type of set:
 .TP 
@@ -307,7 +307,7 @@ and such a set can store up to 65536 ports.
 .PP 
 \fIDEL\-ENTRY\fR := {\fIport\fR | \fIfrom\-port\fR\-\fIto\-port\fR }
 .PP 
-\fITEST\-ENTRY\fR := { \fIport\fR }
+\fITEST\-ENTRY\fR := \fIport\fR
 .PP 
 Mandatory options to use when creating a \fBbitmap:port\fR type of set:
 .TP 
@@ -328,13 +328,13 @@ if that is exhausted, the doubling of the hash is performed.
 .PP 
 \fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIADD\-ENTRY\fR := { \fIipaddr\fR }
+\fIADD\-ENTRY\fR := \fIipaddr\fR
 .PP 
 \fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIDEL\-ENTRY\fR := { \fIipaddr\fR }
+\fIDEL\-ENTRY\fR := \fIipaddr\fR
 .PP 
-\fITEST\-ENTRY\fR := { \fIipaddr\fR }
+\fITEST\-ENTRY\fR := \fIipaddr\fR
 .PP 
 For the \fBinet\fR family one can add or delete multiple entries by specifying
 a range or a network:
@@ -378,13 +378,13 @@ if that is exhausted, the doubling of the hash is performed.
 .PP 
 \fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIADD\-ENTRY\fR := { \fIipaddr\fR[/\fIcidr\fR] }
+\fIADD\-ENTRY\fR := \fIipaddr\fR[/\fIcidr\fR]
 .PP 
 \fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIDEL\-ENTRY\fR := { \fIipaddr\fR[/\fIcidr\fR] }
+\fIDEL\-ENTRY\fR := \fIipaddr\fR[/\fIcidr\fR]
 .PP 
-\fITEST\-ENTRY\fR := { \fIipaddr\fR[/\fIcidr\fR] }
+\fITEST\-ENTRY\fR := \fIipaddr\fR[/\fIcidr\fR]
 .PP 
 Optional \fBcreate\fR options:
 .TP 
@@ -427,15 +427,15 @@ The \fBhash:ip,port\fR set type uses a hash to store IP address and port pairs.
 In order to avoid clashes in the hash a limited number of chaining, and then
 if that is exhausted, the doubling of the hash is performed.
 .PP 
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBproto\fR \fIvalue\fR ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIADD\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR }
+\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR
 .PP 
 \fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIDEL\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR }
+\fIDEL\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR
 .PP 
-\fITEST\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR }
+\fITEST\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR
 .PP 
 Optional \fBcreate\fR options:
 .TP 
@@ -443,6 +443,12 @@ Optional \fBcreate\fR options:
 The protocol family of the IP addresses to be stored in the set. The default is
 \fBinet\fR, i.e IPv4.
 .TP 
+\fBproto\fR \fIvalue\fR
+The default protocol for the port to be stored in the set. If no protocol is specified,
+then TCP/UDP ports are assumed as backward compatibility. The default protocol
+also defines which kind of ports are to be added to the set when the \fBSET\fR
+target is used.
+.TP 
 \fBhashsize\fR \fIvalue\fR
 The initial hash size for the set, default is 1024. The hash size must be a power
 of two, the kernel automatically rounds up non power of two hash sizes to the first
@@ -451,30 +457,37 @@ correct value.
 \fBmaxelem\fR \fIvalue\fR
 The maximal number of elements which can be stored in the set, default 65536.
 .PP 
-The \fBhash:ip,port\fR type of sets require two \fBsrc\fR/\fBdst\fR parameters of
-the \fBset\fR match and \fBSET\fR target kernel modules.
+When adding, deleting, testing entries the port value is interpreted
+for TCP and UDP only, for other protocols the port value currently is ignored and
+zeroed out, but must be specified. The \fBhash:ip,port\fR type of sets require
+two \fBsrc\fR/\fBdst\fR parameters of the \fBset\fR match and \fBSET\fR
+target kernel modules.
 .PP 
 Examples:
 .IP 
-ipset create foo hash:ip,port
+ipset create foo hash:ip,port proto tcp
 .IP 
 ipset add foo 192.168.1.1,80
 .IP 
+ipset add foo 192.168.1.1,udp:53
+.IP 
+ipset add foo 192.168.1.1,ospf:0
+.IP 
 ipset test foo 192.168.1.1,80
 .SS hash:ip,port,ip
 The \fBhash:ip,port,ip\fR set type uses a hash to store IP address, port and
 IP address triples. In order to avoid clashes in the hash a limited number of
 chaining, and then if that is exhausted, the doubling of the hash is performed.
 .PP 
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBproto\fR \fIvalue\fR ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIADD\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR }
+\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIipaddr\fR
 .PP 
 \fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIDEL\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR }
+\fIDEL\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIipaddr\fR
 .PP 
-\fITEST\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR }
+\fITEST\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIipaddr\fR
 .PP 
 Optional \fBcreate\fR options:
 .TP 
@@ -482,6 +495,12 @@ Optional \fBcreate\fR options:
 The protocol family of the IP addresses to be stored in the set. The default is
 \fBinet\fR, i.e IPv4.
 .TP 
+\fBproto\fR \fIvalue\fR
+The default protocol for the port to be stored in the set. If no protocol is specified,
+then TCP/UDP ports are assumed as backward compatibility. The default protocol
+also defines which kind of ports are to be added to the set when the \fBSET\fR
+target is used.
+.TP 
 \fBhashsize\fR \fIvalue\fR
 The initial hash size for the set, default is 1024. The hash size must be a power
 of two, the kernel automatically rounds up non power of two hash sizes to the first
@@ -490,8 +509,11 @@ correct value.
 \fBmaxelem\fR \fIvalue\fR
 The maximal number of elements which can be stored in the set, default 65536.
 .PP 
-The \fBhash:ip,port,ip\fR type of sets require three \fBsrc\fR/\fBdst\fR parameters of
-the \fBset\fR match and \fBSET\fR target kernel modules.
+When adding, deleting, testing entries the port value is interpreted
+for TCP and UDP only, for other protocols the port value currently is ignored and
+zeroed out, but must be specified. The \fBhash:ip,port,ip\fR type of sets require
+three \fBsrc\fR/\fBdst\fR parameters of the \fBset\fR match and \fBSET\fR
+target kernel modules.
 .PP 
 Examples:
 .IP 
@@ -499,22 +521,22 @@ ipset create foo hash:ip,port,ip
 .IP 
 ipset add foo 192.168.1.1,80,10.0.0.1
 .IP 
-ipset test foo 192.168.1.1,80,10.0.0.1
+ipset test foo 192.168.1.1,udp:53,10.0.0.1
 .SS hash:ip,port,net
 The \fBhash:ip,port,net\fR set type uses a hash to store IP address, port and
 IP network triples.
 In order to avoid clashes in the hash a limited number of chaining, and then
 if that is exhausted, the doubling of the hash is performed.
 .PP 
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR|\fBinet6\fR } ] | [ \fBproto\fR \fIvalue\fR ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIADD\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR[/\fIcidr\fR] }
+\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIipaddr\fR[/\fIcidr\fR]
 .PP 
 \fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
 .PP 
-\fIDEL\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR[/\fIcidr\fR] }
+\fIDEL\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIipaddr\fR[/\fIcidr\fR]
 .PP 
-\fITEST\-ENTRY\fR := { \fIipaddr\fR,\fIport\fR,\fIipaddr\fR[/\fIcidr\fR] }
+\fITEST\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIipaddr\fR[/\fIcidr\fR]
 .PP 
 Optional \fBcreate\fR options:
 .TP 
@@ -522,6 +544,12 @@ Optional \fBcreate\fR options:
 The protocol family of the IP addresses to be stored in the set. The default is
 \fBinet\fR, i.e IPv4.
 .TP 
+\fBproto\fR \fIvalue\fR
+The default protocol for the port to be stored in the set. If no protocol is specified,
+then TCP/UDP ports are assumed as backward compatibility. The default protocol
+also defines which kind of ports are to be added to the set when the \fBSET\fR
+target is used.
+.TP 
 \fBhashsize\fR \fIvalue\fR
 The initial hash size for the set, default is 1024. The hash size must be a power
 of two, the kernel automatically rounds up non power of two hash sizes to the first
@@ -531,7 +559,9 @@ correct value.
 The maximal number of elements which can be stored in the set, default 65536.
 .PP 
 When adding/deleting/testing entries, if the cidr parameter is not specified,
-then the host cidr value is assumed.
+then the host cidr value is assumed. The port value is interpreted
+for TCP and UDP only, for other protocols the port value currently is ignored and
+zeroed out, but must be specified. 
 .PP 
 From the \fBset\fR netfilter match point of view a triple will be in a \fBhash:ip,port,net\fR type of set (when the first IP and the port match)
 if the second IP belongs to any of the netblocks added to the set.
index 69fcd09602d3de0f542db3b60b3f9bb86ef5e7cf..c613b24626499f7ec085bfe04b8b957a50e6a526 100644 (file)
@@ -202,7 +202,7 @@ restore(char *argv0)
 }
 
 static int
-call_parser(int argc, char *argv[], const struct ipset_arg *args)
+call_parser(int *argc, char *argv[], const struct ipset_arg *args)
 {
        int i = 1, ret = 0;
        const struct ipset_arg *arg;
@@ -212,8 +212,8 @@ call_parser(int argc, char *argv[], const struct ipset_arg *args)
        if (!args)
                goto done;
        for (arg = args; arg->opt; arg++) {
-               for (i = 1; i < argc; ) {
-                       D("argc: %u, i: %u: %s vs %s", argc, i, argv[i], arg->name[0]);
+               for (i = 1; i < *argc; ) {
+                       D("argc: %u, i: %u: %s vs %s", *argc, i, argv[i], arg->name[0]);
                        if (!(ipset_match_option(argv[i], arg->name))) {
                                i++;
                                continue;
@@ -221,24 +221,24 @@ call_parser(int argc, char *argv[], const struct ipset_arg *args)
                        optstr = argv[i];
                        /* Shift off matched option */
                        D("match %s", arg->name[0]);
-                       ipset_shift_argv(&argc, argv, i);
-                       D("argc: %u, i: %u", argc, i);
+                       ipset_shift_argv(argc, argv, i);
+                       D("argc: %u, i: %u", *argc, i);
                        switch (arg->has_arg) {
                        case IPSET_MANDATORY_ARG:
-                               if (i + 1 > argc)
+                               if (i + 1 > *argc)
                                        return exit_error(PARAMETER_PROBLEM,
                                                "Missing mandatory argument of option `%s'",
                                                arg->name[0]);
                                /* Fall through */
                        case IPSET_OPTIONAL_ARG:
-                               if (i + 1 <= argc) {
+                               if (i + 1 <= *argc) {
                                        ret = ipset_call_parser(session,
                                                        arg->parse,
                                                        optstr, arg->opt,
                                                        argv[i]);
                                        if (ret < 0)
                                                return ret;
-                                       ipset_shift_argv(&argc, argv, i);
+                                       ipset_shift_argv(argc, argv, i);
                                        break;
                                }
                                /* Fall through */
@@ -253,7 +253,7 @@ call_parser(int argc, char *argv[], const struct ipset_arg *args)
                }
        }
 done:
-       if (i < argc)
+       if (i < *argc)
                return exit_error(PARAMETER_PROBLEM,
                                  "Unknown argument: `%s'",
                                  argv[i]);
@@ -458,6 +458,9 @@ parse_commandline(int argc, char *argv[])
                        }
                        return exit_error(NO_PROBLEM, NULL);
                }
+               if (argc > 1)
+                       return exit_error(PARAMETER_PROBLEM,
+                               "No command specified: unknown argument %s", argv[1]);
                return exit_error(PARAMETER_PROBLEM, "No command specified.");
        case IPSET_CMD_VERSION:
                printf("%s v%s.\n", program_name, program_version);
@@ -522,7 +525,7 @@ parse_commandline(int argc, char *argv[])
                        return handle_error();
 
                /* Parse create options */
-               ret = call_parser(argc, argv, type->args[IPSET_CREATE]);
+               ret = call_parser(&argc, argv, type->args[IPSET_CREATE]);
                if (ret < 0)
                        return handle_error();
                else if (ret)
@@ -557,6 +560,9 @@ parse_commandline(int argc, char *argv[])
 
        case IPSET_CMD_RESTORE:
                /* Restore mode */
+               if (argc > 1)
+                       return exit_error(PARAMETER_PROBLEM,
+                               "Unknown argument %s", argv[1]);
                return restore(argv[0]);
        case IPSET_CMD_ADD:
        case IPSET_CMD_DEL:
@@ -576,7 +582,7 @@ parse_commandline(int argc, char *argv[])
                        return handle_error();
                
                /* Parse additional ADT options */
-               ret = call_parser(argc, argv, type->args[cmd2cmd(cmd)]);
+               ret = call_parser(&argc, argv, type->args[cmd2cmd(cmd)]);
                if (ret < 0)
                        return handle_error();
                else if (ret)
@@ -590,6 +596,9 @@ parse_commandline(int argc, char *argv[])
                break;
        }
 
+       if (argc > 1)
+               return exit_error(PARAMETER_PROBLEM,
+                       "Unknown argument %s", argv[1]);
        ret = ipset_cmd(session, cmd, restore_line);
        D("ret %d", ret);
        /* Special case for TEST and non-quiet mode */
index 4a9b8cf19cf9f980a6bba60124426064b09b1f89..94a8cc64211beb8c6db3d3c6161f8eff0b41fae2 100644 (file)
@@ -37,6 +37,10 @@ static const struct ipset_arg hash_ipport_create_args[] = {
          .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
          .parse = ipset_parse_uint32,          .print = ipset_print_number,
        },
+       { .name = { "proto", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROTO,
+         .parse = ipset_parse_proto,           .print = ipset_print_proto,
+       },
        /* Backward compatibility */
        { .name = { "probes", NULL },
          .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
@@ -71,12 +75,12 @@ static const struct ipset_arg hash_ipport_add_args[] = {
 
 static const char hash_ipport_usage[] =
 "create SETNAME hash:ip,port\n"
-"              [family inet|inet6]\n"
+"              [family inet|inet6] [proto PROTO]\n"
 "               [hashsize VALUE] [maxelem VALUE]\n"
 "               [timeout VALUE]\n"
-"add    SETNAME IP,PORT [timeout VALUE]\n"
-"del    SETNAME IP,PORT\n"
-"test   SETNAME IP,PORT\n";
+"add    SETNAME IP,[PROTO:]PORT [timeout VALUE]\n"
+"del    SETNAME IP,[PROTO:]PORT\n"
+"test   SETNAME IP,[PROTO:]PORT\n";
 
 struct ipset_type ipset_hash_ipport0 = {
        .name = "hash:ip,port",
@@ -91,8 +95,8 @@ struct ipset_type ipset_hash_ipport0 = {
                        .opt = IPSET_OPT_IP
                },
                [IPSET_DIM_TWO] = { 
-                       .parse = ipset_parse_single_port,
-                       .print = ipset_print_port,
+                       .parse = ipset_parse_proto_port,
+                       .print = ipset_print_proto_port,
                        .opt = IPSET_OPT_PORT
                },
        },
@@ -112,14 +116,18 @@ struct ipset_type ipset_hash_ipport0 = {
        .full = {
                [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
                        | IPSET_FLAG(IPSET_OPT_MAXELEM)
+                       | IPSET_FLAG(IPSET_OPT_PROTO)
                        | IPSET_FLAG(IPSET_OPT_TIMEOUT),
                [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
                        | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PROTO)
                        | IPSET_FLAG(IPSET_OPT_TIMEOUT),
                [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
-                       | IPSET_FLAG(IPSET_OPT_PORT),
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PROTO),
                [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
-                       | IPSET_FLAG(IPSET_OPT_PORT),
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PROTO),
        },
 
        .usage = hash_ipport_usage,
index 299e36229e33e383bccc5891dfc63444da9420d2..dc121e4e8a1a01dd5cdf2adbe553098c0bcc8e72 100644 (file)
@@ -37,6 +37,10 @@ static const struct ipset_arg hash_ipportip_create_args[] = {
          .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
          .parse = ipset_parse_uint32,          .print = ipset_print_number,
        },
+       { .name = { "proto", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROTO,
+         .parse = ipset_parse_proto,           .print = ipset_print_proto,
+       },
        /* Backward compatibility */
        { .name = { "probes", NULL },
          .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
@@ -71,12 +75,12 @@ static const struct ipset_arg hash_ipportip_add_args[] = {
 
 static const char hash_ipportip_usage[] =
 "create SETNAME hash:ip,port,ip\n"
-"              [family inet|inet6]\n"
+"              [family inet|inet6] [proto PROTO]\n"
 "               [hashsize VALUE] [maxelem VALUE]\n"
 "               [timeout VALUE]\n"
-"add    SETNAME IP,PORT,IP [timeout VALUE]\n"
-"del    SETNAME IP,PORT,IP\n"
-"test   SETNAME IP,PORT,IP\n";
+"add    SETNAME IP,[PROTO:]PORT,IP [timeout VALUE]\n"
+"del    SETNAME IP,[PROTO:]PORT,IP\n"
+"test   SETNAME IP,[PROTO:]PORT,IP\n";
 
 struct ipset_type ipset_hash_ipportip0 = {
        .name = "hash:ip,port,ip",
@@ -91,8 +95,8 @@ struct ipset_type ipset_hash_ipportip0 = {
                        .opt = IPSET_OPT_IP
                },
                [IPSET_DIM_TWO] = { 
-                       .parse = ipset_parse_single_port,
-                       .print = ipset_print_port,
+                       .parse = ipset_parse_proto_port,
+                       .print = ipset_print_proto_port,
                        .opt = IPSET_OPT_PORT
                },
                [IPSET_DIM_THREE] = { 
@@ -120,16 +124,20 @@ struct ipset_type ipset_hash_ipportip0 = {
        .full = {
                [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
                        | IPSET_FLAG(IPSET_OPT_MAXELEM)
+                       | IPSET_FLAG(IPSET_OPT_PROTO)
                        | IPSET_FLAG(IPSET_OPT_TIMEOUT),
                [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
                        | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PROTO)
                        | IPSET_FLAG(IPSET_OPT_IP2)
                        | IPSET_FLAG(IPSET_OPT_TIMEOUT),
                [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
                        | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PROTO)
                        | IPSET_FLAG(IPSET_OPT_IP2),
                [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
                        | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PROTO)
                        | IPSET_FLAG(IPSET_OPT_IP2),
        },
 
index 13a048740851c31a2930070a82bf93f85dd5f604..a668c5e4fe4c821749d4761d52864adb68094414 100644 (file)
@@ -37,6 +37,10 @@ static const struct ipset_arg hash_ipportnet_create_args[] = {
          .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
          .parse = ipset_parse_uint32,          .print = ipset_print_number,
        },
+       { .name = { "proto", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROTO,
+         .parse = ipset_parse_proto,           .print = ipset_print_proto,
+       },
        /* Backward compatibility */
        { .name = { "probes", NULL },
          .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
@@ -71,12 +75,12 @@ static const struct ipset_arg hash_ipportnet_add_args[] = {
 
 static const char hash_ipportnet_usage[] =
 "create SETNAME hash:ip,port,net\n"
-"              [family inet|inet6]\n"
+"              [family inet|inet6] [proto PROTO]\n"
 "               [hashsize VALUE] [maxelem VALUE]\n"
 "               [timeout VALUE]\n"
-"add    SETNAME IP,PORT,IP[/CIDR] [timeout VALUE]\n"
-"del    SETNAME IP,PORT,IP[/CIDR]\n"
-"test   SETNAME IP,PORT,IP[/CIDR]\n";
+"add    SETNAME IP,[PROTO:]PORT,IP[/CIDR] [timeout VALUE]\n"
+"del    SETNAME IP,[PROTO:]PORT,IP[/CIDR]\n"
+"test   SETNAME IP,[PROTO:]PORT,IP[/CIDR]\n";
 
 struct ipset_type ipset_hash_ipportnet0 = {
        .name = "hash:ip,port,net",
@@ -91,8 +95,8 @@ struct ipset_type ipset_hash_ipportnet0 = {
                        .opt = IPSET_OPT_IP
                },
                [IPSET_DIM_TWO] = { 
-                       .parse = ipset_parse_single_port,
-                       .print = ipset_print_port,
+                       .parse = ipset_parse_proto_port,
+                       .print = ipset_print_proto_port,
                        .opt = IPSET_OPT_PORT
                },
                [IPSET_DIM_THREE] = { 
@@ -120,18 +124,22 @@ struct ipset_type ipset_hash_ipportnet0 = {
        .full = {
                [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
                        | IPSET_FLAG(IPSET_OPT_MAXELEM)
+                       | IPSET_FLAG(IPSET_OPT_PROTO)
                        | IPSET_FLAG(IPSET_OPT_TIMEOUT),
                [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
                        | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PROTO)
                        | IPSET_FLAG(IPSET_OPT_IP2)
                        | IPSET_FLAG(IPSET_OPT_CIDR2)
                        | IPSET_FLAG(IPSET_OPT_TIMEOUT),
                [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
                        | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PROTO)
                        | IPSET_FLAG(IPSET_OPT_IP2)
                        | IPSET_FLAG(IPSET_OPT_CIDR2),
                [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
                        | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PROTO)
                        | IPSET_FLAG(IPSET_OPT_IP2)
                        | IPSET_FLAG(IPSET_OPT_CIDR2),
        },
index 3c74cd91277a25db5fc4bf6ea070161dfed0dc32..cc6783bc1cc070e77083d524924ff8b047aa9760 100644 (file)
@@ -1,51 +1,51 @@
-# Range: Create a set with timeout
+# Create a set with timeout
 0 ipset create test hash:ip,port,ip timeout 5
-# Range: Add partly zero valued element
+# Add partly zero valued element
 0 ipset add test 2.0.0.1,0,0.0.0.0
-# Range: Test partly zero valued element
+# Test partly zero valued element
 0 ipset test test 2.0.0.1,0,0.0.0.0
-# Range: Delete party zero valued element
+# Delete party zero valued element
 0 ipset del test 2.0.0.1,0,0.0.0.0
-# Range: Add almost zero valued element
+# Add almost zero valued element
 0 ipset add test 2.0.0.1,0,0.0.0.1
-# Range: Test almost zero valued element
+# Test almost zero valued element
 0 ipset test test 2.0.0.1,0,0.0.0.1
-# Range: Delete almost zero valued element
+# Delete almost zero valued element
 0 ipset del test 2.0.0.1,0,0.0.0.1
-# Range: Add lower boundary
+# Add lower boundary
 0 ipset add test 2.0.0.1,5,1.1.1.1
-# Range: Add upper boundary
+# Add upper boundary
 0 ipset add test 2.1.0.0,128,2.2.2.2
-# Range: Test lower boundary
+# Test lower boundary
 0 ipset test test 2.0.0.1,5,1.1.1.1
-# Range: Test upper boundary
+# Test upper boundary
 0 ipset test test 2.1.0.0,128,2.2.2.2
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset test test 2.0.0.1,5,1.1.1.2
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset test test 2.0.0.1,6,1.1.1.1
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset test test 2.0.0.2,6,1.1.1.1
-# Range: Test value before lower boundary
+# Test value before lower boundary
 1 ipset test test 2.0.0.0,5,1.1.1.1
-# Range: Test value after upper boundary
+# Test value after upper boundary
 1 ipset test test 2.1.0.1,128,2.2.2.2
-# Range: Try to add value before lower boundary
+# Try to add value before lower boundary
 0 ipset add test 2.0.0.0,5,1.1.1.1
-# Range: Try to add value after upper boundary
+# Try to add value after upper boundary
 0 ipset add test 2.1.0.1,128,2.2.2.2
-# Range: List set
+# List set
 0 ipset list test | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo hash:ip,port,ip.t.list0 && rm .foo
-# Range: Sleep 6s so that elements can time out
+# Sleep 6s so that elements can time out
 0 sleep 6
-# Range: List set
+# List set
 0 ipset list test > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo hash:ip,port,ip.t.list1 && rm .foo
-# Range: Flush test set
+# Flush test set
 0 ipset flush test
-# Range: Delete test set
+# Delete test set
 0 ipset destroy test
 # eof
index cb88f965f42f44f4e303ba32fa3a8328c78e696c..e3b292b50670b79140b93dc78d0574d00b8738f6 100644 (file)
@@ -1,43 +1,65 @@
-# Range: Create a set with timeout
+# Create a set with timeout
 0 ipset create test hash:ip,port timeout 5
-# Range: Add partly zero valued element
+# Add partly zero valued element
 0 ipset add test 2.0.0.1,0
-# Range: Test partly zero valued element
+# Test partly zero valued element
 0 ipset test test 2.0.0.1,0
-# Range: Delete partly zero valued element
+# Delete partly zero valued element
 0 ipset del test 2.0.0.1,0
-# Range: Add lower boundary
+# Add lower boundary
 0 ipset add test 2.0.0.1,5
-# Range: Add upper boundary
+# Add upper boundary
 0 ipset add test 2.1.0.0,128
-# Range: Test lower boundary
+# Test lower boundary
 0 ipset test test 2.0.0.1,5
-# Range: Test upper boundary
+# Test upper boundary
 0 ipset test test 2.1.0.0,128
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset test test 2.0.0.1,4
-# Range: Delete value not added to the set
+# Delete value not added to the set
 1 ipset del test 2.0.0.1,6
-# Range: Test value before lower boundary
+# Test value before lower boundary
 1 ipset test test 2.0.0.0,5
-# Range: Test value after upper boundary
+# Test value after upper boundary
 1 ipset test test 2.1.0.1,128
-# Range: Try to add value before lower boundary
+# Try to add value before lower boundary
 0 ipset add test 2.0.0.0,5
-# Range: Try to add value after upper boundary
+# Try to add value after upper boundary
 0 ipset add test 2.1.0.1,128
-# Range: List set
+# List set
 0 ipset list test | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo hash:ip,port.t.list0 && rm .foo
-# Range: Sleep 6s so that elements can time out
+# Sleep 6s so that elements can time out
 0 sleep 6
-# Range: List set
+# List set
 0 ipset list test > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo hash:ip,port.t.list1 && rm .foo
-# Range: Flush test set
+# Flush test set
 0 ipset flush test
-# Range: Delete test set
+# Delete test set
+0 ipset destroy test
+# Create a set with default TCP protocol
+0 ipset create test hash:ip,port proto tcp
+# Add element without specifying protocol
+0 ipset add test 2.0.0.1,80
+# Add "same" element but with UDP protocol
+0 ipset add test 2.0.0.1,udp:80
+# Test element without specifying protocol
+0 ipset test test 2.0.0.1,80
+# Test element with TCP protocol
+0 ipset test test 2.0.0.1,tcp:80
+# Test element with UDP protocol
+0 ipset test test 2.0.0.1,udp:80
+# Add element with ospf
+0 ipset add test 2.0.0.1,ospf:0
+# Test element with ospf
+0 ipset test test 2.0.0.1,ospf:0
+# List set
+0 ipset list test > .foo0 && ./sort.sh .foo0
+# Check listing
+0 diff -I 'Size in memory.*' .foo hash:ip,port.t.list2 && rm .foo
+# Delete set
 0 ipset destroy test
 # eof
diff --git a/tests/hash:ip,port.t.list2 b/tests/hash:ip,port.t.list2
new file mode 100644 (file)
index 0000000..e8a9db0
--- /dev/null
@@ -0,0 +1,10 @@
+Name: test
+Type: hash:ip,port
+Header: family inet hashsize 1024 maxelem 65536 proto tcp 
+Size in memory: 8424
+References: 0
+Members:
+2.0.0.1,ospf:0
+2.0.0.1,tcp:80
+2.0.0.1,udp:80
+
index 84afdf95a52543cbc39c1b0c4895f3bafa96af9a..712db33ac19a2d9f650bcf7666853c871f45e19d 100644 (file)
@@ -1,51 +1,51 @@
-# Range: Create a set with timeout
+# Create a set with timeout
 0 ipset create test hash:ip,port,ip family inet6 timeout 5
-# Range: Add partly zero valued element
+# Add partly zero valued element
 0 ipset add test 2:0:0::1,0,0:0:0::0
-# Range: Test partly zero valued element
+# Test partly zero valued element
 0 ipset test test 2:0:0::1,0,0:0:0::0
-# Range: Delete party zero valued element
+# Delete party zero valued element
 0 ipset del test 2:0:0::1,0,0:0:0::0
-# Range: Add almost zero valued element
+# Add almost zero valued element
 0 ipset add test 2:0:0::1,0,0:0:0::1
-# Range: Test almost zero valued element
+# Test almost zero valued element
 0 ipset test test 2:0:0::1,0,0:0:0::1
-# Range: Delete almost zero valued element
+# Delete almost zero valued element
 0 ipset del test 2:0:0::1,0,0:0:0::1
-# Range: Add lower boundary
+# Add lower boundary
 0 ipset add test 2:0:0::1,5,1:1:1::1
-# Range: Add upper boundary
+# Add upper boundary
 0 ipset add test 2:1:0::0,128,2:2:2::2
-# Range: Test lower boundary
+# Test lower boundary
 0 ipset test test 2:0:0::1,5,1:1:1::1
-# Range: Test upper boundary
+# Test upper boundary
 0 ipset test test 2:1:0::0,128,2:2:2::2
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset test test 2:0:0::1,5,1:1:1::2
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset test test 2:0:0::1,6,1:1:1::1
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset test test 2:0:0::2,6,1:1:1::1
-# Range: Test value before lower boundary
+# Test value before lower boundary
 1 ipset test test 2:0:0::0,5,1:1:1::1
-# Range: Test value after upper boundary
+# Test value after upper boundary
 1 ipset test test 2:1:0::1,128,2:2:2::2
-# Range: Try to add value before lower boundary
+# Try to add value before lower boundary
 0 ipset add test 2:0:0::0,5,1:1:1::1
-# Range: Try to add value after upper boundary
+# Try to add value after upper boundary
 0 ipset add test 2:1:0::1,128,2:2:2::2
-# Range: List set
+# List set
 0 ipset list test | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo hash:ip6,port,ip6.t.list0 && rm .foo
-# Range: Sleep 6s so that elements can time out
+# Sleep 6s so that elements can time out
 0 sleep 6
-# Range: List set
+# List set
 0 ipset list test > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo hash:ip6,port,ip6.t.list1 && rm .foo
-# Range: Flush test set
+# Flush test set
 0 ipset flush test
-# Range: Delete test set
+# Delete test set
 0 ipset destroy test
 # eof
index feb525c91ed31af593a1d96b4938f2c996178b29..5b009428d245fc90c5bb18fa63146b275d75ca2d 100644 (file)
@@ -1,43 +1,43 @@
-# Range: Create a set with timeout
+# Create a set with timeout
 0 ipset create test hash:ip,port family inet6 timeout 5
-# Range: Add partly zero valued element
+# Add partly zero valued element
 0 ipset add test 2:0:0::1,0
-# Range: Test partly zero valued element
+# Test partly zero valued element
 0 ipset test test 2:0:0::1,0
-# Range: Delete partly zero valued element
+# Delete partly zero valued element
 0 ipset del test 2:0:0::1,0
-# Range: Add lower boundary
+# Add lower boundary
 0 ipset add test 2:0:0::1,5
-# Range: Add upper boundary
+# Add upper boundary
 0 ipset add test 2:1:0::0,128
-# Range: Test lower boundary
+# Test lower boundary
 0 ipset test test 2:0:0::1,5
-# Range: Test upper boundary
+# Test upper boundary
 0 ipset test test 2:1:0::0,128
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset test test 2:0:0::1,4
-# Range: Delete value not added to the set
+# Delete value not added to the set
 1 ipset del test 2:0:0::1,6
-# Range: Test value before lower boundary
+# Test value before lower boundary
 1 ipset test test 2:0:0::0,5
-# Range: Test value after upper boundary
+# Test value after upper boundary
 1 ipset test test 2:1:0::1,128
-# Range: Try to add value before lower boundary
+# Try to add value before lower boundary
 0 ipset add test 2:0:0::0,5
-# Range: Try to add value after upper boundary
+# Try to add value after upper boundary
 0 ipset add test 2:1:0::1,128
-# Range: List set
+# List set
 0 ipset list test | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo hash:ip6,port.t.list0 && rm .foo
-# Range: Sleep 6s so that elements can time out
+# Sleep 6s so that elements can time out
 0 sleep 6
-# Range: List set
+# List set
 0 ipset list test > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo hash:ip6,port.t.list1 && rm .foo
-# Range: Flush test set
+# Flush test set
 0 ipset flush test
-# Range: Delete test set
+# Delete test set
 0 ipset destroy test
 # eof
index b46ac86daaca487b0875840978e3a3d219547be4..c27bb65f775144880e63ea76f95fcb3ad351bb68 100644 (file)
@@ -1,40 +1,40 @@
 # Create a set with timeout
 0 ipset create test nethash hashsize 128 timeout 6
-# Range: Add zero valued element
+# Add zero valued element
 1 ipset add test 0.0.0.0/0
-# Range: Test zero valued element
+# Test zero valued element
 1 ipset test test 0.0.0.0/0
-# Range: Delete zero valued element
+# Delete zero valued element
 1 ipset del test 0.0.0.0/0
-# Range: Try to add /0
+# Try to add /0
 1 ipset add test 1.1.1.1/0
-# Range: Try to add /32
+# Try to add /32
 0 ipset add test 1.1.1.1/32
-# Range: Add almost zero valued element
+# Add almost zero valued element
 0 ipset add test 0.0.0.0/1
-# Range: Test almost zero valued element
+# Test almost zero valued element
 0 ipset test test 0.0.0.0/1
-# Range: Delete almost zero valued element
+# Delete almost zero valued element
 0 ipset del test 0.0.0.0/1
-# Range: Test deleted element
+# Test deleted element
 1 ipset test test 0.0.0.0/1
-# Range: Delete element not added to the set
+# Delete element not added to the set
 1 ipset del test 0.0.0.0/1
-# Range: Add first random network
+# Add first random network
 0 ipset add test 2.0.0.1/24
-# Range: Add second random network
+# Add second random network
 0 ipset add test 192.168.68.69/27
-# Range: Test first random value
+# Test first random value
 0 ipset test test 2.0.0.255
-# Range: Test second random value
+# Test second random value
 0 ipset test test 192.168.68.95
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset test test 2.0.1.0
-# Range: Try to add IP address
+# Try to add IP address
 0 ipset add test 2.0.0.1
-# Range: List set
+# List set
 0 ipset list test | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo hash:net.t.list0 && rm .foo
 # Sleep 6s so that element can time out
 0 sleep 6
index e4246d90271c704a502b117da144cfba17aa2248..5a575d195a9acbdc19c7aff036a24d30fb513af9 100644 (file)
@@ -1,40 +1,40 @@
 # Create a set with timeout
 0 ipset create test nethash family inet6 hashsize 128 timeout 6
-# Range: Add zero valued element
+# Add zero valued element
 1 ipset add test ::/0
-# Range: Test zero valued element
+# Test zero valued element
 1 ipset test test ::/0
-# Range: Delete zero valued element
+# Delete zero valued element
 1 ipset del test ::/0
-# Range: Try to add /0
+# Try to add /0
 1 ipset add test 1:1:1::1/0
-# Range: Try to add /32
+# Try to add /32
 0 ipset add test 1:1:1::1/128
-# Range: Add almost zero valued element
+# Add almost zero valued element
 0 ipset add test 0:0:0::0/1
-# Range: Test almost zero valued element
+# Test almost zero valued element
 0 ipset test test 0:0:0::0/1
-# Range: Delete almost zero valued element
+# Delete almost zero valued element
 0 ipset del test 0:0:0::0/1
-# Range: Test deleted element
+# Test deleted element
 1 ipset test test 0:0:0::0/1
-# Range: Delete element not added to the set
+# Delete element not added to the set
 1 ipset del test 0:0:0::0/1
-# Range: Add first random network
+# Add first random network
 0 ipset add test 2:0:0::1/24
-# Range: Add second random network
+# Add second random network
 0 ipset add test 192:168:68::69/27
-# Range: Test first random value
+# Test first random value
 0 ipset test test 2:0:0::255
-# Range: Test second random value
+# Test second random value
 0 ipset test test 192:168:68::95
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset test test 3:0:0::1
-# Range: Try to add IP address
+# Try to add IP address
 0 ipset add test 3:0:0::1
-# Range: List set
+# List set
 0 ipset list test | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo hash:net6.t.list0 && rm .foo
 # Sleep 6s so that element can time out
 0 sleep 6
index ac153111f1052e043522cdd9ab7aebab5afd3795..3311856ac75b99a4002180495a5a24f17261e4c7 100644 (file)
@@ -4,4 +4,6 @@
 1 ipset -L test >/dev/null
 # Delete our test set: the testsuite fails if it exists
 1 ipset -X test
+# Check mandatory create arguments
+2 ipset -N test
 # eof
index 00c35e8371ba5fccd2cfb097dec75573af095725..2373176eb085213709d94c6efd7411687e6e1fe4 100644 (file)
@@ -1,3 +1,11 @@
+# Range: Check syntax error: missing range/from-to
+2 ipset -N test ipmap
+# Range: Check syntax error: missing --from
+2 ipset -N test ipmap --to 2.1.0.1
+# Range: Check syntax error: missing --to
+2 ipset -N test ipmap --from 2.1.0.1
+# Range: Catch invalid IPv4 address
+1 ipset -N test ipmap --from 2.0.0.256 --to 2.1.0.1
 # Range: Try to create from an invalid range
 1 ipset -N test ipmap --from 2.0.0.1 --to 2.1.0.1
 # Range: Create a set from a valid range
 0 ipset -D test 2.0.0.128
 # Range: Add a range of elements
 0 ipset -A test 2.0.0.128-2.0.0.131
+# Range: Save set
+0 ipset -S test > ipmap.t.restore
+# Range: Destroy set
+0 ipset -X test
+# Range: Restore set and catch error
+1 sed 's/2.0.0.131/222.0.0.131/' < ipmap.t.restore | ipset -R
+# Range: Destroy set
+0 ipset -X test
+# Range: Restore set
+0 ipset -R < ipmap.t.restore && rm ipmap.t.restore
 # Range: List set
 0 ipset -L test > .foo
 # Range: Check listing
index dc35bcd971e5914ce60efd59f50bbf46660b1678..9847830358791b607d6ed1f683e88e8f9952406b 100644 (file)
@@ -1,71 +1,71 @@
-# Range: Create a set from a range (range ignored)
+# Create a set from a range (range ignored)
 0 ipset -N test ipporthash --from 2.0.0.1 --to 2.1.0.0
-# Range: Destroy set
+# Destroy set
 0 ipset -X test
-# Range: Create a set
+# Create a set
 0 ipset -N test ipporthash
-# Range: Add partly zero valued element
+# Add partly zero valued element
 0 ipset -A test 2.0.0.1,0
-# Range: Test partly zero valued element
+# Test partly zero valued element
 0 ipset -T test 2.0.0.1,0
-# Range: Delete partly zero valued element
+# Delete partly zero valued element
 0 ipset -D test 2.0.0.1,0
-# Range: Add lower boundary
+# Add lower boundary
 0 ipset -A test 2.0.0.1,5
-# Range: Add upper boundary
+# Add upper boundary
 0 ipset -A test 2.1.0.0,128
-# Range: Test lower boundary
+# Test lower boundary
 0 ipset -T test 2.0.0.1,5
-# Range: Test upper boundary
+# Test upper boundary
 0 ipset -T test 2.1.0.0,128
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset -T test 2.0.0.1,4
-# Range: Delete value not added to the set
+# Delete value not added to the set
 1 ipset -D test 2.0.0.1,6
-# Range: Test value before lower boundary
+# Test value before lower boundary
 1 ipset -T test 2.0.0.0,5
-# Range: Test value after upper boundary
+# Test value after upper boundary
 1 ipset -T test 2.1.0.1,128
-# Range: Try to add value before lower boundary
+# Try to add value before lower boundary
 0 ipset -A test 2.0.0.0,5
-# Range: Try to add value after upper boundary
+# Try to add value after upper boundary
 0 ipset -A test 2.1.0.1,128
-# Range: List set
+# List set
 0 ipset -L test > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo ipporthash.t.list0 && rm .foo
-# Range: Flush test set
+# Flush test set
 0 ipset -F test
-# Range: Delete test set
+# Delete test set
 0 ipset -X test
-# Network: Create a set from a network (network ignored)
+# Create a set from a network (network ignored)
 0 ipset -N test ipporthash --network 2.0.0.0/16
-# Network: Add lower boundary
+# Add lower boundary
 0 ipset -A test 2.0.0.0,5
-# Network: Add upper boundary
+# Add upper boundary
 0 ipset -A test 2.0.255.255,128
-# Network: Test lower boundary
+# Test lower boundary
 0 ipset -T test 2.0.0.0,5
-# Network: Test upper boundary
+# Test upper boundary
 0 ipset -T test 2.0.255.255,128
-# Network: Test value not added to the set
+# Test value not added to the set
 1 ipset -T test 2.0.0.0,4
-# Network: Delete value not added to the set
+# Delete value not added to the set
 1 ipset -D test 2.0.0.0,6
-# Network: Test value before lower boundary
+# Test value before lower boundary
 1 ipset -T test 1.255.255.255,5
-# Network: Test value after upper boundary
+# Test value after upper boundary
 1 ipset -T test 2.1.0.0,128
-# Network: Try to add value before lower boundary
+# Try to add value before lower boundary
 0 ipset -A test 1.255.255.255,5
-# Network: Try to add value after upper boundary
+# Try to add value after upper boundary
 0 ipset -A test 2.1.0.0,128
-# Network: List set
+# List set
 0 ipset -L test > .foo0 && ./sort.sh .foo0
-# Network: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo ipporthash.t.list1 && rm .foo
-# Network: Flush test set
+# Flush test set
 0 ipset -F test
-# Network: Delete test set
+# Delete test set
 0 ipset -X test
 # eof
index 3f619476d199a39904ab1a11a5f395ab9dd16240..f6e79cc9e6be353e948d42cf817b2644b0424665 100644 (file)
@@ -1,81 +1,81 @@
-# Range: Create a set from a range (range ignored)
+# Create a set from a range (range ignored)
 0 ipset -N test ipportiphash --from 2.0.0.1 --to 2.1.0.0
-# Range: Destroy set
+# Destroy set
 0 ipset -X test
-# Range: Create a set
+# Create a set
 0 ipset -N test ipportiphash
-# Range: Add partly zero valued element
+# Add partly zero valued element
 0 ipset -A test 2.0.0.1,0,0.0.0.0
-# Range: Test partly zero valued element
+# Test partly zero valued element
 0 ipset -T test 2.0.0.1,0,0.0.0.0
-# Range: Delete party zero valued element
+# Delete party zero valued element
 0 ipset -D test 2.0.0.1,0,0.0.0.0
-# Range: Add almost zero valued element
+# Add almost zero valued element
 0 ipset -A test 2.0.0.1,0,0.0.0.1
-# Range: Test almost zero valued element
+# Test almost zero valued element
 0 ipset -T test 2.0.0.1,0,0.0.0.1
-# Range: Delete almost zero valued element
+# Delete almost zero valued element
 0 ipset -D test 2.0.0.1,0,0.0.0.1
-# Range: Add lower boundary
+# Add lower boundary
 0 ipset -A test 2.0.0.1,5,1.1.1.1
-# Range: Add upper boundary
+# Add upper boundary
 0 ipset -A test 2.1.0.0,128,2.2.2.2
-# Range: Test lower boundary
+# Test lower boundary
 0 ipset -T test 2.0.0.1,5,1.1.1.1
-# Range: Test upper boundary
+# Test upper boundary
 0 ipset -T test 2.1.0.0,128,2.2.2.2
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset -T test 2.0.0.1,5,1.1.1.2
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset -T test 2.0.0.1,6,1.1.1.1
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset -T test 2.0.0.2,6,1.1.1.1
-# Range: Test value before lower boundary
+# Test value before lower boundary
 1 ipset -T test 2.0.0.0,5,1.1.1.1
-# Range: Test value after upper boundary
+# Test value after upper boundary
 1 ipset -T test 2.1.0.1,128,2.2.2.2
-# Range: Try to add value before lower boundary
+# Try to add value before lower boundary
 0 ipset -A test 2.0.0.0,5,1.1.1.1
-# Range: Try to add value after upper boundary
+# Try to add value after upper boundary
 0 ipset -A test 2.1.0.1,128,2.2.2.2
-# Range: List set
+# List set
 0 ipset -L test > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo ipportiphash.t.list0 && rm .foo
-# Range: Flush test set
+# Flush test set
 0 ipset -F test
-# Range: Delete test set
+# Delete test set
 0 ipset -X test
-# Network: Create a set from a valid network (network ignored)
+# Create a set from a valid network (network ignored)
 0 ipset -N test ipportiphash --network 2.0.0.0/16
-# Network: Add lower boundary
+# Add lower boundary
 0 ipset -A test 2.0.0.0,5,1.1.1.1
-# Network: Add upper boundary
+# Add upper boundary
 0 ipset -A test 2.0.255.255,128,2.2.2.2
-# Network: Test lower boundary
+# Test lower boundary
 0 ipset -T test 2.0.0.0,5,1.1.1.1
-# Network: Test upper boundary
+# Test upper boundary
 0 ipset -T test 2.0.255.255,128,2.2.2.2
-# Network: Test value not added to the set
+# Test value not added to the set
 1 ipset -T test 2.0.0.0,5,1.1.1.2
-# Network: Test value not added to the set
+# Test value not added to the set
 1 ipset -T test 2.0.0.0,6,1.1.1.1
-# Network: Test value before lower boundary
+# Test value before lower boundary
 1 ipset -T test 1.255.255.255,5,1.1.1.1
-# Network: Test value after upper boundary
+# Test value after upper boundary
 1 ipset -T test 2.1.0.0,128,2.2.2.2
-# Network: Try to add value before lower boundary
+# Try to add value before lower boundary
 0 ipset -A test 1.255.255.255,5,1.1.1.1
-# Network: Try to test value before lower boundary
+# Try to test value before lower boundary
 0 ipset -T test 1.255.255.255,5,1.1.1.1
-# Network: Try to del value before lower boundary
+# Try to del value before lower boundary
 0 ipset -D test 1.255.255.255,5,1.1.1.1
-# Network: List set
+# List set
 0 ipset -L test > .foo0 && ./sort.sh .foo0
-# Network: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo ipportiphash.t.list1 && rm .foo
-# Network: Flush test set
+# Flush test set
 0 ipset -F test
-# Network: Delete test set
+# Delete test set
 0 ipset -X test
 # eof
index 400e110202a24e924ebad4e719b28738c83ffb7b..537c0db3065b2871f551e488ea0b2e7b70883fef 100644 (file)
@@ -1,40 +1,40 @@
 # Create a set 
 0 ipset -N test nethash --hashsize 128 
-# Range: Add zero valued element
+# Add zero valued element
 1 ipset -A test 0.0.0.0/0
-# Range: Test zero valued element
+# Test zero valued element
 1 ipset -T test 0.0.0.0/0
-# Range: Delete zero valued element
+# Delete zero valued element
 1 ipset -D test 0.0.0.0/0
-# Range: Try to add /0
+# Try to add /0
 1 ipset -A test 1.1.1.1/0
-# Range: Try to add /32
+# Try to add /32
 0 ipset -A test 1.1.1.1/32
-# Range: Add almost zero valued element
+# Add almost zero valued element
 0 ipset -A test 0.0.0.0/1
-# Range: Test almost zero valued element
+# Test almost zero valued element
 0 ipset -T test 0.0.0.0/1
-# Range: Delete almost zero valued element
+# Delete almost zero valued element
 0 ipset -D test 0.0.0.0/1
-# Range: Test deleted element
+# Test deleted element
 1 ipset -T test 0.0.0.0/1
-# Range: Delete element not added to the set
+# Delete element not added to the set
 1 ipset -D test 0.0.0.0/1
-# Range: Add first random network
+# Add first random network
 0 ipset -A test 2.0.0.1/24
-# Range: Add second random network
+# Add second random network
 0 ipset -A test 192.168.68.69/27
-# Range: Test first random value
+# Test first random value
 0 ipset -T test 2.0.0.255
-# Range: Test second random value
+# Test second random value
 0 ipset -T test 192.168.68.95
-# Range: Test value not added to the set
+# Test value not added to the set
 1 ipset -T test 2.0.1.0
-# Range: Try to add IP address
+# Try to add IP address
 0 ipset -A test 2.0.0.1
-# Range: List set
+# List set
 0 ipset -L test > .foo0 && ./sort.sh .foo0
-# Range: Check listing
+# Check listing
 0 diff -I 'Size in memory.*' .foo nethash.t.list0 && rm .foo
 # Flush test set
 0 ipset -F test
index f80f5ae6642e1ef0e0d44f4f21c41c35bd62c2f9..d673e8eeac7b9755abeef55e6033f79edbde4217 100644 (file)
@@ -1,55 +1,55 @@
-# Setlist: Create dummy set
+# Create dummy set
 0 ipset -N dummy list:set
-# Setlist: Create base set foo
+# Create base set foo
 0 ipset -N foo ipmap --from 2.0.0.1 --to 2.1.0.0
-# Setlist: Create base set bar
+# Create base set bar
 0 ipset -N bar iphash
-# Setlist: Create setlist kind of set
+# Create setlist kind of set
 0 ipset -N test setlist
-# Setlist: Swap test and dumy sets
+# Swap test and dumy sets
 0 ipset -W test dummy
-# Setlist: Destroy dummy set
+# Destroy dummy set
 0 ipset -X dummy
-# Setlist: Add foo set to setlist
+# Add foo set to setlist
 0 ipset -A test foo
-# Setlist: Test foo set in setlist
+# Test foo set in setlist
 0 ipset -T test foo
-# Setlist: Test nonexistent set in setlist
+# Test nonexistent set in setlist
 1 ipset -T test nonexistent
-# Setlist: Try to delete foo set
+# Try to delete foo set
 1 ipset -X foo
-# Setlist: Add bar set to setlist, after foo
+# Add bar set to setlist, after foo
 0 ipset -A test bar
-# Setlist: Test bar,after,foo
+# Test bar,after,foo
 0 ipset -T test bar,after,foo
-# Setlist: Test foo,before,bar
+# Test foo,before,bar
 0 ipset -T test foo,before,bar
-# Setlist: Test bar,before,foo
+# Test bar,before,foo
 1 ipset -T test bar,before,foo
-# Setlist: Test foo,after,bar
+# Test foo,after,bar
 1 ipset -T test foo,after,bar
-# Setlist: Save sets
+# Save sets
 0 ipset -S > setlist.t.restore
-# Setlist: Delete bar,before,foo
+# Delete bar,before,foo
 1 ipset -D test bar,before,foo
-# Setlist: Delete foo,after,bar
+# Delete foo,after,bar
 1 ipset -D test foo,after,bar
-# Setlist: Delete bar,after,foo
+# Delete bar,after,foo
 0 ipset -D test bar,after,foo
-# Setlist: Flush test set
+# Flush test set
 0 ipset -F test
-# Setlist: Delete test set
+# Delete test set
 0 ipset -X test
-# Setlist: Delete all sets
+# Delete all sets
 0 ipset -X
-# Setlist: Restore saved sets
+# Restore saved sets
 0 ipset -R < setlist.t.restore
-# Setlist: List set
+# List set
 0 ipset -L test > .foo
-# Setlist: Check listing
+# Check listing
 0 diff .foo setlist.t.list0 && rm .foo
-# Setlist: Flush all sets
+# Flush all sets
 0 ipset -F
-# Setlist: Delete all sets
+# Delete all sets
 0 ipset -X && rm setlist.t.restore
 # eof