summaryrefslogtreecommitdiffstats
path: root/kernel/include/linux/netfilter/ip_set_getport.h
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/ip_set_getport.h
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/ip_set_getport.h')
-rw-r--r--kernel/include/linux/netfilter/ip_set_getport.h99
1 files changed, 59 insertions, 40 deletions
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*/