|
@@ -430,20 +430,57 @@ static unsigned int ipv6_synproxy_hook(void *priv,
|
|
return NF_ACCEPT;
|
|
return NF_ACCEPT;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static struct nf_hook_ops ipv6_synproxy_ops[] __read_mostly = {
|
|
|
|
+ {
|
|
|
|
+ .hook = ipv6_synproxy_hook,
|
|
|
|
+ .pf = NFPROTO_IPV6,
|
|
|
|
+ .hooknum = NF_INET_LOCAL_IN,
|
|
|
|
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM - 1,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ .hook = ipv6_synproxy_hook,
|
|
|
|
+ .pf = NFPROTO_IPV6,
|
|
|
|
+ .hooknum = NF_INET_POST_ROUTING,
|
|
|
|
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM - 1,
|
|
|
|
+ },
|
|
|
|
+};
|
|
|
|
+
|
|
static int synproxy_tg6_check(const struct xt_tgchk_param *par)
|
|
static int synproxy_tg6_check(const struct xt_tgchk_param *par)
|
|
{
|
|
{
|
|
|
|
+ struct synproxy_net *snet = synproxy_pernet(par->net);
|
|
const struct ip6t_entry *e = par->entryinfo;
|
|
const struct ip6t_entry *e = par->entryinfo;
|
|
|
|
+ int err;
|
|
|
|
|
|
if (!(e->ipv6.flags & IP6T_F_PROTO) ||
|
|
if (!(e->ipv6.flags & IP6T_F_PROTO) ||
|
|
e->ipv6.proto != IPPROTO_TCP ||
|
|
e->ipv6.proto != IPPROTO_TCP ||
|
|
e->ipv6.invflags & XT_INV_PROTO)
|
|
e->ipv6.invflags & XT_INV_PROTO)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- return nf_ct_netns_get(par->net, par->family);
|
|
|
|
|
|
+ err = nf_ct_netns_get(par->net, par->family);
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+
|
|
|
|
+ if (snet->hook_ref6 == 0) {
|
|
|
|
+ err = nf_register_net_hooks(par->net, ipv6_synproxy_ops,
|
|
|
|
+ ARRAY_SIZE(ipv6_synproxy_ops));
|
|
|
|
+ if (err) {
|
|
|
|
+ nf_ct_netns_put(par->net, par->family);
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ snet->hook_ref6++;
|
|
|
|
+ return err;
|
|
}
|
|
}
|
|
|
|
|
|
static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par)
|
|
static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par)
|
|
{
|
|
{
|
|
|
|
+ struct synproxy_net *snet = synproxy_pernet(par->net);
|
|
|
|
+
|
|
|
|
+ snet->hook_ref6--;
|
|
|
|
+ if (snet->hook_ref6 == 0)
|
|
|
|
+ nf_unregister_net_hooks(par->net, ipv6_synproxy_ops,
|
|
|
|
+ ARRAY_SIZE(ipv6_synproxy_ops));
|
|
nf_ct_netns_put(par->net, par->family);
|
|
nf_ct_netns_put(par->net, par->family);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -458,46 +495,14 @@ static struct xt_target synproxy_tg6_reg __read_mostly = {
|
|
.me = THIS_MODULE,
|
|
.me = THIS_MODULE,
|
|
};
|
|
};
|
|
|
|
|
|
-static struct nf_hook_ops ipv6_synproxy_ops[] __read_mostly = {
|
|
|
|
- {
|
|
|
|
- .hook = ipv6_synproxy_hook,
|
|
|
|
- .pf = NFPROTO_IPV6,
|
|
|
|
- .hooknum = NF_INET_LOCAL_IN,
|
|
|
|
- .priority = NF_IP_PRI_CONNTRACK_CONFIRM - 1,
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- .hook = ipv6_synproxy_hook,
|
|
|
|
- .pf = NFPROTO_IPV6,
|
|
|
|
- .hooknum = NF_INET_POST_ROUTING,
|
|
|
|
- .priority = NF_IP_PRI_CONNTRACK_CONFIRM - 1,
|
|
|
|
- },
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
static int __init synproxy_tg6_init(void)
|
|
static int __init synproxy_tg6_init(void)
|
|
{
|
|
{
|
|
- int err;
|
|
|
|
-
|
|
|
|
- err = nf_register_hooks(ipv6_synproxy_ops,
|
|
|
|
- ARRAY_SIZE(ipv6_synproxy_ops));
|
|
|
|
- if (err < 0)
|
|
|
|
- goto err1;
|
|
|
|
-
|
|
|
|
- err = xt_register_target(&synproxy_tg6_reg);
|
|
|
|
- if (err < 0)
|
|
|
|
- goto err2;
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
-err2:
|
|
|
|
- nf_unregister_hooks(ipv6_synproxy_ops, ARRAY_SIZE(ipv6_synproxy_ops));
|
|
|
|
-err1:
|
|
|
|
- return err;
|
|
|
|
|
|
+ return xt_register_target(&synproxy_tg6_reg);
|
|
}
|
|
}
|
|
|
|
|
|
static void __exit synproxy_tg6_exit(void)
|
|
static void __exit synproxy_tg6_exit(void)
|
|
{
|
|
{
|
|
xt_unregister_target(&synproxy_tg6_reg);
|
|
xt_unregister_target(&synproxy_tg6_reg);
|
|
- nf_unregister_hooks(ipv6_synproxy_ops, ARRAY_SIZE(ipv6_synproxy_ops));
|
|
|
|
}
|
|
}
|
|
|
|
|
|
module_init(synproxy_tg6_init);
|
|
module_init(synproxy_tg6_init);
|