From 4902415c1e95003068343d69206887be0e202615 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Tue, 7 Dec 2010 17:46:40 +0100 Subject: Create include/linux/netfilter/ipset/ directory Separate the ipset header files from netfilter header files. --- .../include/linux/netfilter/ipset/ip_set_getport.h | 126 +++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 kernel/include/linux/netfilter/ipset/ip_set_getport.h (limited to 'kernel/include/linux/netfilter/ipset/ip_set_getport.h') diff --git a/kernel/include/linux/netfilter/ipset/ip_set_getport.h b/kernel/include/linux/netfilter/ipset/ip_set_getport.h new file mode 100644 index 0000000..1597fa9 --- /dev/null +++ b/kernel/include/linux/netfilter/ipset/ip_set_getport.h @@ -0,0 +1,126 @@ +#ifndef _IP_SET_GETPORT_H +#define _IP_SET_GETPORT_H + +#ifdef __KERNEL__ +#include +#include +#include +#include + +#define IPSET_INVALID_PORT 65536 + +/* We must handle non-linear skbs */ +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, 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, protooff, sizeof(_udph), &_udph); + if (uh == NULL) + /* No choice either */ + return false; + + *port = src ? uh->source : uh->dest; + break; + } + case IPPROTO_ICMP: { + struct icmphdr _icmph; + const struct icmphdr *ic; + + ic = skb_header_pointer(skb, protooff, sizeof(_icmph), &_icmph); + if (ic == NULL) + return false; + + *port = (ic->type << 8) & ic->code; + break; + } + case IPPROTO_ICMPV6: { + struct icmp6hdr _icmph; + const struct icmp6hdr *ic; + + ic = skb_header_pointer(skb, protooff, sizeof(_icmph), &_icmph); + if (ic == NULL) + return false; + + *port = (ic->icmp6_type << 8) & ic->icmp6_code; + break; + } + default: + break; + } + *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; + + /* 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; + + 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) +{ + bool ret; + u8 proto; + + switch (pf) { + case AF_INET: + ret = get_ip4_port(skb, src, port, &proto); + case AF_INET6: + ret = get_ip6_port(skb, src, port, &proto); + default: + return false; + } + if (!ret) + return ret; + switch (proto) { + case IPPROTO_TCP: + case IPPROTO_UDP: + return true; + default: + return false; + } +} +#endif /* __KERNEL__ */ + +#endif /*_IP_SET_GETPORT_H*/ -- cgit v1.2.3