1 /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
8 /* Get Layer-4 data from the packets */
11 #include <linux/skbuff.h>
12 #include <linux/icmp.h>
13 #include <linux/icmpv6.h>
14 #include <linux/sctp.h>
15 #include <linux/netfilter_ipv6/ip6_tables.h>
19 #include <linux/netfilter/ipset/ip_set_getport.h>
21 /* We must handle non-linear skbs */
23 get_port(const struct sk_buff
*skb
, int protocol
, unsigned int protooff
,
24 bool src
, __be16
*port
, u8
*proto
)
29 const struct tcphdr
*th
;
31 th
= skb_header_pointer(skb
, protooff
, sizeof(_tcph
), &_tcph
);
33 /* No choice either */
36 *port
= src
? th
->source
: th
->dest
;
41 const sctp_sctphdr_t
*sh
;
43 sh
= skb_header_pointer(skb
, protooff
, sizeof(_sh
), &_sh
);
45 /* No choice either */
48 *port
= src
? sh
->source
: sh
->dest
;
52 case IPPROTO_UDPLITE
: {
54 const struct udphdr
*uh
;
56 uh
= skb_header_pointer(skb
, protooff
, sizeof(_udph
), &_udph
);
58 /* No choice either */
61 *port
= src
? uh
->source
: uh
->dest
;
66 const struct icmphdr
*ic
;
68 ic
= skb_header_pointer(skb
, protooff
, sizeof(_ich
), &_ich
);
72 *port
= (__force __be16
)htons((ic
->type
<< 8) | ic
->code
);
75 case IPPROTO_ICMPV6
: {
77 const struct icmp6hdr
*ic
;
79 ic
= skb_header_pointer(skb
, protooff
, sizeof(_ich
), &_ich
);
83 *port
= (__force __be16
)
84 htons((ic
->icmp6_type
<< 8) | ic
->icmp6_code
);
96 ip_set_get_ip4_port(const struct sk_buff
*skb
, bool src
,
97 __be16
*port
, u8
*proto
)
99 const struct iphdr
*iph
= ip_hdr(skb
);
100 unsigned int protooff
= ip_hdrlen(skb
);
101 int protocol
= iph
->protocol
;
103 /* See comments at tcp_match in ip_tables.c */
104 if (protocol
<= 0 || (ntohs(iph
->frag_off
) & IP_OFFSET
))
107 return get_port(skb
, protocol
, protooff
, src
, port
, proto
);
109 EXPORT_SYMBOL_GPL(ip_set_get_ip4_port
);
111 #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
113 ip_set_get_ip6_port(const struct sk_buff
*skb
, bool src
,
114 __be16
*port
, u8
*proto
)
119 nexthdr
= ipv6_hdr(skb
)->nexthdr
;
120 protoff
= ipv6_skip_exthdr(skb
, sizeof(struct ipv6hdr
), &nexthdr
);
124 return get_port(skb
, nexthdr
, protoff
, src
, port
, proto
);
126 EXPORT_SYMBOL_GPL(ip_set_get_ip6_port
);
130 ip_set_get_ip_port(const struct sk_buff
*skb
, u8 pf
, bool src
, __be16
*port
)
137 ret
= ip_set_get_ip4_port(skb
, src
, port
, &proto
);
140 ret
= ip_set_get_ip6_port(skb
, src
, port
, &proto
);
155 EXPORT_SYMBOL_GPL(ip_set_get_ip_port
);