Commit | Line | Data |
---|---|---|
09c434b8 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
1da177e4 LT |
2 | /* |
3 | * IPv6 raw table, a port of the IPv4 raw table to IPv6 | |
4 | * | |
5 | * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | |
6 | */ | |
902d6a4c | 7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
1da177e4 LT |
8 | #include <linux/module.h> |
9 | #include <linux/netfilter_ipv6/ip6_tables.h> | |
5a0e3ad6 | 10 | #include <linux/slab.h> |
1da177e4 | 11 | |
6e23ae2a | 12 | #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) |
1da177e4 | 13 | |
b9e69e12 FW |
14 | static int __net_init ip6table_raw_table_init(struct net *net); |
15 | ||
902d6a4c SAK |
16 | static bool raw_before_defrag __read_mostly; |
17 | MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag"); | |
18 | module_param(raw_before_defrag, bool, 0000); | |
19 | ||
b069b37a | 20 | static const struct xt_table packet_raw = { |
1ab1457c YH |
21 | .name = "raw", |
22 | .valid_hooks = RAW_VALID_HOOKS, | |
2e4e6a17 | 23 | .me = THIS_MODULE, |
f88e6a8a | 24 | .af = NFPROTO_IPV6, |
9c138866 | 25 | .priority = NF_IP6_PRI_RAW, |
b9e69e12 | 26 | .table_init = ip6table_raw_table_init, |
1da177e4 LT |
27 | }; |
28 | ||
b069b37a AB |
29 | static const struct xt_table packet_raw_before_defrag = { |
30 | .name = "raw", | |
31 | .valid_hooks = RAW_VALID_HOOKS, | |
32 | .me = THIS_MODULE, | |
33 | .af = NFPROTO_IPV6, | |
34 | .priority = NF_IP6_PRI_RAW_BEFORE_DEFRAG, | |
35 | .table_init = ip6table_raw_table_init, | |
36 | }; | |
37 | ||
1da177e4 LT |
38 | /* The work comes in here from netfilter.c. */ |
39 | static unsigned int | |
06198b34 | 40 | ip6table_raw_hook(void *priv, struct sk_buff *skb, |
238e54c9 | 41 | const struct nf_hook_state *state) |
1da177e4 | 42 | { |
6cb8ff3f | 43 | return ip6t_do_table(skb, state, state->net->ipv6.ip6table_raw); |
1da177e4 LT |
44 | } |
45 | ||
2b95efe7 | 46 | static struct nf_hook_ops *rawtable_ops __read_mostly; |
1da177e4 | 47 | |
b9e69e12 | 48 | static int __net_init ip6table_raw_table_init(struct net *net) |
8280aa61 | 49 | { |
e3eaa991 | 50 | struct ip6t_replace *repl; |
b069b37a | 51 | const struct xt_table *table = &packet_raw; |
a67dd266 | 52 | int ret; |
e3eaa991 | 53 | |
b069b37a AB |
54 | if (raw_before_defrag) |
55 | table = &packet_raw_before_defrag; | |
56 | ||
b9e69e12 FW |
57 | if (net->ipv6.ip6table_raw) |
58 | return 0; | |
59 | ||
b069b37a | 60 | repl = ip6t_alloc_initial_table(table); |
e3eaa991 JE |
61 | if (repl == NULL) |
62 | return -ENOMEM; | |
b069b37a | 63 | ret = ip6t_register_table(net, table, repl, rawtable_ops, |
a67dd266 | 64 | &net->ipv6.ip6table_raw); |
e3eaa991 | 65 | kfree(repl); |
a67dd266 | 66 | return ret; |
8280aa61 AD |
67 | } |
68 | ||
69 | static void __net_exit ip6table_raw_net_exit(struct net *net) | |
70 | { | |
b9e69e12 FW |
71 | if (!net->ipv6.ip6table_raw) |
72 | return; | |
a67dd266 | 73 | ip6t_unregister_table(net, net->ipv6.ip6table_raw, rawtable_ops); |
b9e69e12 | 74 | net->ipv6.ip6table_raw = NULL; |
8280aa61 AD |
75 | } |
76 | ||
77 | static struct pernet_operations ip6table_raw_net_ops = { | |
8280aa61 AD |
78 | .exit = ip6table_raw_net_exit, |
79 | }; | |
80 | ||
65b4b4e8 | 81 | static int __init ip6table_raw_init(void) |
1da177e4 LT |
82 | { |
83 | int ret; | |
b069b37a | 84 | const struct xt_table *table = &packet_raw; |
1da177e4 | 85 | |
902d6a4c | 86 | if (raw_before_defrag) { |
b069b37a | 87 | table = &packet_raw_before_defrag; |
902d6a4c SAK |
88 | |
89 | pr_info("Enabling raw table before defrag\n"); | |
90 | } | |
91 | ||
b9e69e12 | 92 | /* Register hooks */ |
b069b37a | 93 | rawtable_ops = xt_hook_ops_alloc(table, ip6table_raw_hook); |
b9e69e12 FW |
94 | if (IS_ERR(rawtable_ops)) |
95 | return PTR_ERR(rawtable_ops); | |
96 | ||
8280aa61 | 97 | ret = register_pernet_subsys(&ip6table_raw_net_ops); |
b9e69e12 FW |
98 | if (ret < 0) { |
99 | kfree(rawtable_ops); | |
8280aa61 | 100 | return ret; |
2b95efe7 | 101 | } |
1da177e4 | 102 | |
b9e69e12 FW |
103 | ret = ip6table_raw_table_init(&init_net); |
104 | if (ret) { | |
105 | unregister_pernet_subsys(&ip6table_raw_net_ops); | |
106 | kfree(rawtable_ops); | |
107 | } | |
1da177e4 LT |
108 | return ret; |
109 | } | |
110 | ||
65b4b4e8 | 111 | static void __exit ip6table_raw_fini(void) |
1da177e4 | 112 | { |
8280aa61 | 113 | unregister_pernet_subsys(&ip6table_raw_net_ops); |
b9e69e12 | 114 | kfree(rawtable_ops); |
1da177e4 LT |
115 | } |
116 | ||
65b4b4e8 AM |
117 | module_init(ip6table_raw_init); |
118 | module_exit(ip6table_raw_fini); | |
1da177e4 | 119 | MODULE_LICENSE("GPL"); |