1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2013 Patrick McHardy <kaber@trash.net>
6 #include <linux/netfilter_ipv6/ip6_tables.h>
7 #include <linux/netfilter/x_tables.h>
8 #include <linux/netfilter/xt_SYNPROXY.h>
10 #include <net/netfilter/nf_synproxy.h>
13 synproxy_tg6(struct sk_buff
*skb
, const struct xt_action_param
*par
)
15 const struct xt_synproxy_info
*info
= par
->targinfo
;
16 struct net
*net
= xt_net(par
);
17 struct synproxy_net
*snet
= synproxy_pernet(net
);
18 struct synproxy_options opts
= {};
19 struct tcphdr
*th
, _th
;
21 if (nf_ip6_checksum(skb
, xt_hooknum(par
), par
->thoff
, IPPROTO_TCP
))
24 th
= skb_header_pointer(skb
, par
->thoff
, sizeof(_th
), &_th
);
28 if (!synproxy_parse_options(skb
, par
->thoff
, th
, &opts
))
31 if (th
->syn
&& !(th
->ack
|| th
->fin
|| th
->rst
)) {
32 /* Initial SYN from client */
33 this_cpu_inc(snet
->stats
->syn_received
);
35 if (th
->ece
&& th
->cwr
)
36 opts
.options
|= XT_SYNPROXY_OPT_ECN
;
38 opts
.options
&= info
->options
;
39 opts
.mss_encode
= opts
.mss_option
;
40 opts
.mss_option
= info
->mss
;
41 if (opts
.options
& XT_SYNPROXY_OPT_TIMESTAMP
)
42 synproxy_init_timestamp_cookie(info
, &opts
);
44 opts
.options
&= ~(XT_SYNPROXY_OPT_WSCALE
|
45 XT_SYNPROXY_OPT_SACK_PERM
|
48 synproxy_send_client_synack_ipv6(net
, skb
, th
, &opts
);
52 } else if (th
->ack
&& !(th
->fin
|| th
->rst
|| th
->syn
)) {
54 if (synproxy_recv_client_ack_ipv6(net
, skb
, th
, &opts
,
66 static int synproxy_tg6_check(const struct xt_tgchk_param
*par
)
68 struct synproxy_net
*snet
= synproxy_pernet(par
->net
);
69 const struct ip6t_entry
*e
= par
->entryinfo
;
72 if (!(e
->ipv6
.flags
& IP6T_F_PROTO
) ||
73 e
->ipv6
.proto
!= IPPROTO_TCP
||
74 e
->ipv6
.invflags
& XT_INV_PROTO
)
77 err
= nf_ct_netns_get(par
->net
, par
->family
);
81 err
= nf_synproxy_ipv6_init(snet
, par
->net
);
83 nf_ct_netns_put(par
->net
, par
->family
);
90 static void synproxy_tg6_destroy(const struct xt_tgdtor_param
*par
)
92 struct synproxy_net
*snet
= synproxy_pernet(par
->net
);
94 nf_synproxy_ipv6_fini(snet
, par
->net
);
95 nf_ct_netns_put(par
->net
, par
->family
);
98 static struct xt_target synproxy_tg6_reg __read_mostly
= {
100 .family
= NFPROTO_IPV6
,
101 .hooks
= (1 << NF_INET_LOCAL_IN
) | (1 << NF_INET_FORWARD
),
102 .target
= synproxy_tg6
,
103 .targetsize
= sizeof(struct xt_synproxy_info
),
104 .checkentry
= synproxy_tg6_check
,
105 .destroy
= synproxy_tg6_destroy
,
109 static int __init
synproxy_tg6_init(void)
111 return xt_register_target(&synproxy_tg6_reg
);
114 static void __exit
synproxy_tg6_exit(void)
116 xt_unregister_target(&synproxy_tg6_reg
);
119 module_init(synproxy_tg6_init
);
120 module_exit(synproxy_tg6_exit
);
122 MODULE_LICENSE("GPL");
123 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
124 MODULE_DESCRIPTION("Intercept IPv6 TCP connections and establish them using syncookies");