]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - net/netfilter/ipset/ip_set_getport.c
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>
20 #include <linux/export.h>
22 /* We must handle non-linear skbs */
24 get_port(const struct sk_buff
*skb
, int protocol
, unsigned int protooff
,
25 bool src
, __be16
*port
, u8
*proto
)
30 const struct tcphdr
*th
;
32 th
= skb_header_pointer(skb
, protooff
, sizeof(_tcph
), &_tcph
);
34 /* No choice either */
37 *port
= src
? th
->source
: th
->dest
;
42 const sctp_sctphdr_t
*sh
;
44 sh
= skb_header_pointer(skb
, protooff
, sizeof(_sh
), &_sh
);
46 /* No choice either */
49 *port
= src
? sh
->source
: sh
->dest
;
53 case IPPROTO_UDPLITE
: {
55 const struct udphdr
*uh
;
57 uh
= skb_header_pointer(skb
, protooff
, sizeof(_udph
), &_udph
);
59 /* No choice either */
62 *port
= src
? uh
->source
: uh
->dest
;
67 const struct icmphdr
*ic
;
69 ic
= skb_header_pointer(skb
, protooff
, sizeof(_ich
), &_ich
);
73 *port
= (__force __be16
)htons((ic
->type
<< 8) | ic
->code
);
76 case IPPROTO_ICMPV6
: {
78 const struct icmp6hdr
*ic
;
80 ic
= skb_header_pointer(skb
, protooff
, sizeof(_ich
), &_ich
);
84 *port
= (__force __be16
)
85 htons((ic
->icmp6_type
<< 8) | ic
->icmp6_code
);
97 ip_set_get_ip4_port(const struct sk_buff
*skb
, bool src
,
98 __be16
*port
, u8
*proto
)
100 const struct iphdr
*iph
= ip_hdr(skb
);
101 unsigned int protooff
= skb_network_offset(skb
) + ip_hdrlen(skb
);
102 int protocol
= iph
->protocol
;
104 /* See comments at tcp_match in ip_tables.c */
108 if (ntohs(iph
->frag_off
) & IP_OFFSET
)
113 case IPPROTO_UDPLITE
:
115 /* Port info not available for fragment offset > 0 */
118 /* Other protocols doesn't have ports,
119 * so we can match fragments.
125 return get_port(skb
, protocol
, protooff
, src
, port
, proto
);
127 EXPORT_SYMBOL_GPL(ip_set_get_ip4_port
);
129 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
131 ip_set_get_ip6_port(const struct sk_buff
*skb
, bool src
,
132 __be16
*port
, u8
*proto
)
138 nexthdr
= ipv6_hdr(skb
)->nexthdr
;
139 protoff
= ipv6_skip_exthdr(skb
,
140 skb_network_offset(skb
) +
141 sizeof(struct ipv6hdr
), &nexthdr
,
143 if (protoff
< 0 || (frag_off
& htons(~0x7)) != 0)
146 return get_port(skb
, nexthdr
, protoff
, src
, port
, proto
);
148 EXPORT_SYMBOL_GPL(ip_set_get_ip6_port
);
152 ip_set_get_ip_port(const struct sk_buff
*skb
, u8 pf
, bool src
, __be16
*port
)
159 ret
= ip_set_get_ip4_port(skb
, src
, port
, &proto
);
162 ret
= ip_set_get_ip6_port(skb
, src
, port
, &proto
);
177 EXPORT_SYMBOL_GPL(ip_set_get_ip_port
);