summaryrefslogtreecommitdiffstats
path: root/kernel/include/linux/netfilter
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2010-06-22 10:49:41 +0200
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2010-06-22 10:49:41 +0200
commit020936c8c3375e1efe44a3087c891a4b2cbfe044 (patch)
treea94751e6f1f11bcf118129c343d1942bbf53e808 /kernel/include/linux/netfilter
parent97a12ba3f184a76c406eb5622ec21a4d4d6fc8bf (diff)
ipset 5: last new feature addedv5.0-pre3
- 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
Diffstat (limited to 'kernel/include/linux/netfilter')
-rw-r--r--kernel/include/linux/netfilter/ip_set.h80
-rw-r--r--kernel/include/linux/netfilter/ip_set_chash.h12
-rw-r--r--kernel/include/linux/netfilter/ip_set_getport.h99
-rw-r--r--kernel/include/linux/netfilter/ip_set_hash.h2
4 files changed, 116 insertions, 77 deletions
diff --git a/kernel/include/linux/netfilter/ip_set.h b/kernel/include/linux/netfilter/ip_set.h
index e700503..f306859 100644
--- a/kernel/include/linux/netfilter/ip_set.h
+++ b/kernel/include/linux/netfilter/ip_set.h
@@ -20,47 +20,47 @@
/* 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)
diff --git a/kernel/include/linux/netfilter/ip_set_chash.h b/kernel/include/linux/netfilter/ip_set_chash.h
index 0d77a5d..e0e16bd 100644
--- a/kernel/include/linux/netfilter/ip_set_chash.h
+++ b/kernel/include/linux/netfilter/ip_set_chash.h
@@ -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,
@@ -507,6 +511,10 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb)
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));
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize));
diff --git a/kernel/include/linux/netfilter/ip_set_getport.h b/kernel/include/linux/netfilter/ip_set_getport.h
index ffa89f1..680a89a 100644
--- a/kernel/include/linux/netfilter/ip_set_getport.h
+++ b/kernel/include/linux/netfilter/ip_set_getport.h
@@ -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*/
diff --git a/kernel/include/linux/netfilter/ip_set_hash.h b/kernel/include/linux/netfilter/ip_set_hash.h
index c1a6964..4003af0 100644
--- a/kernel/include/linux/netfilter/ip_set_hash.h
+++ b/kernel/include/linux/netfilter/ip_set_hash.h
@@ -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__