ipfw3nat: check_nat func
[dragonfly.git] / sys / net / ipfw3_nat / ip_fw3_nat.c
blob4345f50c5b5a5fa7fd1eea5d20060440f6dd5798
1 /*
2 * Copyright (c) 2014 - 2018 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Bill Yuan <bycn82@dragonflybsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/mbuf.h>
39 #include <sys/socketvar.h>
40 #include <sys/sysctl.h>
41 #include <sys/systimer.h>
42 #include <sys/thread2.h>
43 #include <sys/in_cksum.h>
44 #include <sys/systm.h>
45 #include <sys/proc.h>
46 #include <sys/socket.h>
47 #include <sys/syslog.h>
48 #include <sys/ucred.h>
49 #include <sys/lock.h>
50 #include <sys/mplock2.h>
52 #include <net/ethernet.h>
53 #include <net/netmsg2.h>
54 #include <net/netisr2.h>
55 #include <net/route.h>
56 #include <net/if.h>
58 #include <netinet/in.h>
59 #include <netinet/ip.h>
60 #include <netinet/ip_icmp.h>
61 #include <netinet/tcp.h>
62 #include <netinet/tcp_timer.h>
63 #include <netinet/tcp_var.h>
64 #include <netinet/tcpip.h>
65 #include <netinet/udp.h>
66 #include <netinet/udp_var.h>
67 #include <netinet/in_systm.h>
68 #include <netinet/in_var.h>
69 #include <netinet/in_pcb.h>
70 #include <netinet/ip_var.h>
71 #include <netinet/ip_divert.h>
73 #include <net/ipfw3/ip_fw.h>
74 #include "ip_fw3_nat.h"
76 struct ip_fw3_nat_context *ip_fw3_nat_ctx[MAXCPU];
77 static struct callout ip_fw3_nat_cleanup_callout;
78 extern struct ipfw_context *ipfw_ctx[MAXCPU];
79 extern ip_fw_ctl_t *ipfw_ctl_nat_ptr;
80 static int fw3_nat_cleanup_interval = 1;
82 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw3_nat, CTLFLAG_RW, 0, "ipfw3 NAT");
83 SYSCTL_INT(_net_inet_ip_fw3_nat, OID_AUTO, cleanup_interval, CTLFLAG_RW,
84 &fw3_nat_cleanup_interval, 0, "default life time");
86 RB_PROTOTYPE(state_tree, nat_state, entries, nat_state_cmp);
87 RB_GENERATE(state_tree, nat_state, entries, nat_state_cmp);
89 void
90 check_nat(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
91 struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
93 if ((*args)->eh != NULL) {
94 *cmd_ctl = IP_FW_CTL_NO;
95 *cmd_val = IP_FW_NOT_MATCH;
96 return;
99 struct ip_fw3_nat_context *nat_ctx;
100 struct cfg_nat *nat;
101 int nat_id;
103 nat_ctx = ip_fw3_nat_ctx[mycpuid];
104 (*args)->rule = *f;
105 nat = ((ipfw_insn_nat *)cmd)->nat;
106 if (nat == NULL) {
107 nat_id = cmd->arg1;
108 nat = nat_ctx->nats[nat_id - 1];
109 if (nat == NULL) {
110 *cmd_val = IP_FW_DENY;
111 *cmd_ctl = IP_FW_CTL_DONE;
112 return;
114 ((ipfw_insn_nat *)cmd)->nat = nat;
116 *cmd_val = ip_fw3_nat(*args, nat, (*args)->m);
117 *cmd_ctl = IP_FW_CTL_NAT;
121 ip_fw3_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
123 /* TODO */
124 return IP_FW_NAT;
128 nat_state_cmp(struct nat_state *s1, struct nat_state *s2)
130 if (s1->saddr > s2->saddr)
131 return 1;
132 if (s1->saddr < s2->saddr)
133 return -1;
135 if (s1->daddr > s2->daddr)
136 return 1;
137 if (s1->daddr < s2->daddr)
138 return -1;
140 if (s1->sport > s2->sport)
141 return 1;
142 if (s1->sport < s2->sport)
143 return -1;
145 if (s1->dport > s2->dport)
146 return 1;
147 if (s1->dport < s2->dport)
148 return -1;
150 return 0;
154 ip_fw3_ctl_nat_get_cfg(struct sockopt *sopt)
156 /* TODO */
157 return 0;
161 ip_fw3_ctl_nat_get_record(struct sockopt *sopt)
163 /* TODO */
164 return 0;
168 * Init the RB trees only when the NAT is configured.
170 void
171 nat_add_dispatch(netmsg_t nat_add_msg)
173 struct ip_fw3_nat_context *nat_ctx;
174 struct netmsg_nat_add *msg;
175 struct ioc_nat *ioc;
176 struct cfg_nat *nat;
178 msg = (struct netmsg_nat_add *)nat_add_msg;
179 ioc = &msg->ioc_nat;
180 nat_ctx = ip_fw3_nat_ctx[mycpuid];
182 if (nat_ctx->nats[ioc->id - 1] == NULL) {
183 nat = kmalloc(LEN_CFG_NAT, M_IP_FW3_NAT, M_WAITOK | M_ZERO);
184 RB_INIT(&nat->tree_tcp_in);
185 RB_INIT(&nat->tree_tcp_out);
186 RB_INIT(&nat->tree_udp_in);
187 RB_INIT(&nat->tree_udp_out);
188 RB_INIT(&nat->tree_icmp_in);
189 RB_INIT(&nat->tree_icmp_out);
190 nat->id = ioc->id;
191 memcpy(&nat->ip, &ioc->ip, LEN_IN_ADDR);
192 nat_ctx->nats[ioc->id - 1] = nat;
194 netisr_forwardmsg_all(&msg->base, mycpuid + 1);
198 ip_fw3_ctl_nat_add(struct sockopt *sopt)
200 struct netmsg_nat_add nat_add_msg, *msg;
201 struct ioc_nat *ioc;
203 msg = &nat_add_msg;
204 ioc = (struct ioc_nat *)(sopt->sopt_val);
205 sooptcopyin(sopt, &msg->ioc_nat, sopt->sopt_valsize,
206 sizeof(struct ioc_nat));
207 netmsg_init(&msg->base, NULL, &curthread->td_msgport, 0,
208 nat_add_dispatch);
209 netisr_domsg(&msg->base, 0);
210 return 0;
213 void
214 nat_del_dispatch(netmsg_t nat_del_msg)
216 /* TODO */
220 ip_fw3_ctl_nat_del(struct sockopt *sopt)
222 struct netmsg_nat_del nat_del_msg;
223 struct netmsg_nat_del *msg;
225 /* TODO */
226 msg = &nat_del_msg;
227 netmsg_init(&msg->base, NULL, &curthread->td_msgport,
228 0, nat_del_dispatch);
230 netisr_domsg(&msg->base, 0);
231 return 0;
235 ip_fw3_ctl_nat_flush(struct sockopt *sopt)
237 /* TODO */
238 return 0;
242 ip_fw3_ctl_nat_sockopt(struct sockopt *sopt)
244 int error = 0;
245 switch (sopt->sopt_name) {
246 case IP_FW_NAT_ADD:
247 error = ip_fw3_ctl_nat_add(sopt);
248 break;
249 case IP_FW_NAT_DEL:
250 error = ip_fw3_ctl_nat_del(sopt);
251 break;
252 case IP_FW_NAT_FLUSH:
253 error = ip_fw3_ctl_nat_flush(sopt);
254 break;
255 case IP_FW_NAT_GET:
256 error = ip_fw3_ctl_nat_get_cfg(sopt);
257 break;
258 case IP_FW_NAT_GET_RECORD:
259 error = ip_fw3_ctl_nat_get_record(sopt);
260 break;
261 default:
262 kprintf("ipfw3 nat invalid socket option %d\n",
263 sopt->sopt_name);
265 return error;
268 void
269 nat_init_ctx_dispatch(netmsg_t msg)
271 struct ip_fw3_nat_context *tmp;
272 tmp = kmalloc(sizeof(struct ip_fw3_nat_context),
273 M_IP_FW3_NAT, M_WAITOK | M_ZERO);
274 ip_fw3_nat_ctx[mycpuid] = tmp;
275 netisr_forwardmsg_all(&msg->base, mycpuid + 1);
278 static void
279 ipfw3_nat_cleanup_func_dispatch(netmsg_t nmsg)
281 /* TODO */
282 netisr_forwardmsg_all(&nmsg->base, mycpuid + 1);
285 static void
286 ipfw3_nat_cleanup_func(void *dummy __unused)
288 struct netmsg_base msg;
289 netmsg_init(&msg, NULL, &curthread->td_msgport, 0,
290 ipfw3_nat_cleanup_func_dispatch);
291 netisr_domsg(&msg, 0);
293 callout_reset(&ip_fw3_nat_cleanup_callout,
294 fw3_nat_cleanup_interval * hz,
295 ipfw3_nat_cleanup_func,
296 NULL);
299 static int
300 ip_fw3_nat_init(void)
302 struct netmsg_base msg;
303 register_ipfw_module(MODULE_NAT_ID, MODULE_NAT_NAME);
304 register_ipfw_filter_funcs(MODULE_NAT_ID, O_NAT_NAT,
305 (filter_func)check_nat);
306 ipfw_ctl_nat_ptr = ip_fw3_ctl_nat_sockopt;
307 netmsg_init(&msg, NULL, &curthread->td_msgport,
308 0, nat_init_ctx_dispatch);
309 netisr_domsg(&msg, 0);
311 callout_init_mp(&ip_fw3_nat_cleanup_callout);
312 callout_reset(&ip_fw3_nat_cleanup_callout,
313 fw3_nat_cleanup_interval * hz,
314 ipfw3_nat_cleanup_func,
315 NULL);
316 return 0;
319 static int
320 ip_fw3_nat_fini(void)
322 /* TODO */
323 callout_stop(&ip_fw3_nat_cleanup_callout);
324 return unregister_ipfw_module(MODULE_NAT_ID);
327 static int
328 ip_fw3_nat_modevent(module_t mod, int type, void *data)
330 switch (type) {
331 case MOD_LOAD:
332 return ip_fw3_nat_init();
333 case MOD_UNLOAD:
334 return ip_fw3_nat_fini();
335 default:
336 break;
338 return 0;
341 moduledata_t ip_fw3_nat_mod = {
342 "ipfw3_nat",
343 ip_fw3_nat_modevent,
344 NULL
347 DECLARE_MODULE(ipfw3_nat, ip_fw3_nat_mod,
348 SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
349 MODULE_DEPEND(ipfw3_nat, ipfw3_basic, 1, 1, 1);
350 MODULE_VERSION(ipfw3_nat, 1);