12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 #include <linux/module.h>
15 #include <linux/netfilter/x_tables.h>
16 #include <linux/netfilter_ipv4/ip_tables.h>
25 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
26 #define XT_SOCKET_HAVE_IPV6 1
27 #include <linux/netfilter_ipv6/ip6_tables.h>
33 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
34 #define XT_SOCKET_HAVE_CONNTRACK 1
39 xt_socket_put_sk(
struct sock *
sk)
48 extract_icmp4_fields(
const struct sk_buff *
skb,
55 unsigned int outside_hdrlen = ip_hdrlen(skb);
56 struct iphdr *inside_iph, _inside_iph;
60 icmph = skb_header_pointer(skb, outside_hdrlen,
61 sizeof(_icmph), &_icmph);
65 switch (icmph->
type) {
76 inside_iph = skb_header_pointer(skb, outside_hdrlen +
78 sizeof(_inside_iph), &_inside_iph);
79 if (inside_iph ==
NULL)
86 ports = skb_header_pointer(skb, outside_hdrlen +
88 (inside_iph->ihl << 2),
89 sizeof(_ports), &_ports);
96 *laddr = inside_iph->
saddr;
98 *raddr = inside_iph->
daddr;
108 const struct iphdr *iph = ip_hdr(skb);
114 #ifdef XT_SOCKET_HAVE_CONNTRACK
120 hp = skb_header_pointer(skb, ip_hdrlen(skb),
121 sizeof(_hdr), &_hdr);
132 if (extract_icmp4_fields(skb, &protocol, &
saddr, &
daddr,
139 #ifdef XT_SOCKET_HAVE_CONNTRACK
143 ct = nf_ct_get(skb, &ctinfo);
144 if (ct && !nf_ct_is_untracked(ct) &&
158 sk = nf_tproxy_get_sock_v4(dev_net(skb->
dev), protocol,
162 bool transparent =
true;
166 inet_sk(sk)->inet_rcv_saddr == 0);
172 inet_sk(sk)->transparent) ||
174 inet_twsk(sk)->tw_transparent));
176 xt_socket_put_sk(sk);
178 if (wildcard || !transparent)
182 pr_debug(
"proto %hhu %pI4:%hu -> %pI4:%hu (orig %pI4:%hu) sock %p\n",
193 return socket_match(skb, par,
NULL);
199 return socket_match(skb, par, par->
matchinfo);
202 #ifdef XT_SOCKET_HAVE_IPV6
205 extract_icmp6_fields(
const struct sk_buff *skb,
206 unsigned int outside_hdrlen,
213 struct ipv6hdr *inside_iph, _inside_iph;
220 icmph = skb_header_pointer(skb, outside_hdrlen,
221 sizeof(_icmph), &_icmph);
228 inside_iph = skb_header_pointer(skb, outside_hdrlen +
sizeof(_icmph),
sizeof(_inside_iph), &_inside_iph);
229 if (inside_iph ==
NULL)
231 inside_nexthdr = inside_iph->
nexthdr;
233 inside_hdrlen =
ipv6_skip_exthdr(skb, outside_hdrlen +
sizeof(_icmph) +
sizeof(_inside_iph),
234 &inside_nexthdr, &inside_fragoff);
235 if (inside_hdrlen < 0)
242 ports = skb_header_pointer(skb, inside_hdrlen,
243 sizeof(_ports), &_ports);
249 *protocol = inside_nexthdr;
250 *laddr = &inside_iph->
saddr;
252 *raddr = &inside_iph->
daddr;
261 struct ipv6hdr *iph = ipv6_hdr(skb);
271 pr_debug(
"unable to find transport header in IPv6 packet, dropping\n");
276 hp = skb_header_pointer(skb, thoff,
277 sizeof(_hdr), &_hdr);
287 if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr,
294 sk = nf_tproxy_get_sock_v6(dev_net(skb->
dev), tproto,
298 bool transparent =
true;
302 ipv6_addr_any(&inet6_sk(sk)->rcv_saddr));
308 inet_sk(sk)->transparent) ||
310 inet_twsk(sk)->tw_transparent));
312 xt_socket_put_sk(sk);
314 if (wildcard || !transparent)
318 pr_debug(
"proto %hhd %pI6:%hu -> %pI6:%hu "
319 "(orig %pI6:%hu) sock %p\n",
320 tproto, saddr,
ntohs(sport),
333 .match = socket_mt4_v0,
342 .match = socket_mt4_v1,
348 #ifdef XT_SOCKET_HAVE_IPV6
353 .match = socket_mt6_v1,
362 static int __init socket_mt_init(
void)
365 #ifdef XT_SOCKET_HAVE_IPV6
372 static void __exit socket_mt_exit(
void)