1: /*-
2: * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3: *
4: * Copyright (c) 2022 Michael Pounov <misho@elwix.org>, CloudSigma AG
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25: * SUCH DAMAGE.
26: */
27: #include "fwsync.h"
28:
29:
30: MALLOC_DEFINE(M_FWSYNC, "fwsync_memory", "FWSync - memory");
31:
32: static struct ipfw_sopt_handler soc[] = {
33: { IP_FW_SYNC_XCONFIG, 0, HDIR_SET, fwsync_cfg },
34: { IP_FW_SYNC_DESTROY, 0, HDIR_SET, fwsync_destroy },
35: { IP_FW_SYNC_XGETCONFIG, 0, HDIR_GET, fwsync_get_cfg },
36: { IP_FW_SYNC_LIST, 0, HDIR_GET, fwsync_list },
37: { IP_FW_SYNC_START, 0, HDIR_SET, fwsync_start },
38: { IP_FW_SYNC_STOP, 0, HDIR_SET, fwsync_stop },
39: };
40:
41: static volatile int fwsync_hooked = 0;
42: struct fwsync_context fws_ctx = { 0 };
43: int fwsync_debug = DRV_DEBUG;
44: static struct sysctl_ctx_list fwsync_sysctl_ctx;
45: struct cfg_sync fws_cfg;
46: //static struct sysctl_oid *fws_sysctl_oid, *fws_sysctl_dir;
47:
48: struct task fws_sndpkt_task;
49: struct taskqueue *fws_tq;
50: struct callout fws_co;
51: struct mtx fws_mtx_c, fws_mtx_e, fws_mtx_u, fws_mtx_n;
52: fwsync_sndpkt_t fwsync_sndpkt, fwsync_updpkt, fwsync_natpkt;
53:
54: SYSCTL_NODE(_net_inet_ip, IFT_FWSYNC, fwsync, CTLFLAG_RW, 0, "IPFW Sync - Sync firewall states");
55: SYSCTL_INT(_net_inet_ip_fwsync, OID_AUTO, debug, CTLFLAG_RW, &fwsync_debug, 0, "Debug driver");
56:
57: static int
58: fws_fini(void *arg)
59: {
60: struct fws_sndpkt *p;
61:
62: DTRACE();
63:
64: if (!fwsync_hooked)
65: return EBUSY;
66:
67: if (fws_cfg.cfg.on || fws_ctx.config) {
68: uprintf("Unable to unload ELWIX %s driver, cause you have active configuration.\n"
69: "Before unload driver flush configuration!\n", DRV_NAME);
70: return EBUSY;
71: }
72:
73: IPFW_DEL_SOPT_HANDLER(1, soc);
74:
75: callout_drain(&fws_co);
76:
77: if (fws_tq) {
78: taskqueue_drain_all(fws_tq);
79: taskqueue_free(fws_tq);
80: }
81:
82: mtx_lock(&fws_mtx_n);
83: while (!TAILQ_EMPTY(&fwsync_natpkt)) {
84: p = TAILQ_FIRST(&fwsync_natpkt);
85: TAILQ_REMOVE(&fwsync_natpkt, p, sp_next);
86: free(p, M_FWSYNC);
87: }
88: mtx_unlock(&fws_mtx_n);
89:
90: mtx_lock(&fws_mtx_u);
91: while (!TAILQ_EMPTY(&fwsync_updpkt)) {
92: p = TAILQ_FIRST(&fwsync_updpkt);
93: TAILQ_REMOVE(&fwsync_updpkt, p, sp_next);
94: free(p, M_FWSYNC);
95: }
96: mtx_unlock(&fws_mtx_u);
97:
98: mtx_lock(&fws_mtx_c);
99: while (!TAILQ_EMPTY(&fwsync_sndpkt)) {
100: p = TAILQ_FIRST(&fwsync_sndpkt);
101: TAILQ_REMOVE(&fwsync_sndpkt, p, sp_next);
102: free(p, M_FWSYNC);
103: }
104: mtx_unlock(&fws_mtx_c);
105:
106: mtx_destroy(&fws_mtx_c);
107: mtx_destroy(&fws_mtx_e);
108: mtx_destroy(&fws_mtx_u);
109: mtx_destroy(&fws_mtx_n);
110:
111: fwsync_hooked = 0;
112:
113: /* sysctl context */
114: sysctl_ctx_free(&fwsync_sysctl_ctx);
115:
116: uprintf("Unloaded ELWIX %s driver version %d ...\n", DRV_NAME, DRV_VERSION);
117: return 0;
118: }
119:
120: static int
121: fws_shut(void *arg)
122: {
123: DTRACE();
124:
125: fws_fini(arg);
126:
127: return 0;
128: }
129:
130: static int
131: fws_init(void *arg)
132: {
133: DTRACE();
134:
135: if (fwsync_hooked)
136: return 0;
137:
138: memset(&fws_cfg, 0, sizeof fws_cfg);
139: memset(&fws_ctx, 0, sizeof fws_ctx);
140:
141: TAILQ_INIT(&fwsync_sndpkt);
142: TAILQ_INIT(&fwsync_updpkt);
143: TAILQ_INIT(&fwsync_natpkt);
144:
145: /* mutexes */
146: mtx_init(&fws_mtx_n, "fwsync mtx alias", NULL, MTX_DEF);
147: mtx_init(&fws_mtx_u, "fwsync mtx dynamic", NULL, MTX_DEF);
148: mtx_init(&fws_mtx_e, "fwsync mtx edge", NULL, MTX_DEF);
149: mtx_init(&fws_mtx_c, "fwsync mtx collector", NULL, MTX_DEF);
150:
151: /* taskqueue */
152: fws_tq = taskqueue_create("fwsync_tq", M_NOWAIT, taskqueue_thread_enqueue, &fws_tq);
153: if (!fws_tq) {
154: printf("Failed to allocate fwsync task queue\n");
155: mtx_destroy(&fws_mtx_c);
156: mtx_destroy(&fws_mtx_e);
157: return ENOMEM;
158: } else
159: taskqueue_start_threads(&fws_tq, 1, PI_NET, "fwsync tq");
160:
161: TASK_INIT(&fws_sndpkt_task, 0, fwsync_sndpkt_handler, &fwsync_sndpkt);
162:
163: /* callout */
164:
165: callout_init_mtx(&fws_co, &fws_mtx_e, 0);
166:
167: /* sysctl context */
168: sysctl_ctx_init(&fwsync_sysctl_ctx);
169:
170: IPFW_ADD_SOPT_HANDLER(1, soc);
171:
172: fwsync_hooked = 1;
173: uprintf("Loaded ELWIX %s driver version %d ...\n", DRV_NAME, DRV_VERSION);
174: return 0;
175: }
176: static int
177: fwsync_main(module_t m, int what, void *arg)
178: {
179: int ret = 0;
180:
181: switch (what) {
182: case MOD_LOAD:
183: ret = fws_init(arg);
184: break;
185: case MOD_UNLOAD:
186: ret = fws_fini(arg);
187: break;
188: case MOD_SHUTDOWN:
189: ret = fws_shut(arg);
190: break;
191: case MOD_QUIESCE:
192: /* don't unload driver if there have configured driver */
193: if (fws_cfg.cfg.on || fws_ctx.config)
194: ret = EBUSY;
195: break;
196: default:
197: ret = EINVAL;
198: break;
199: }
200:
201: return ret;
202: }
203:
204: static moduledata_t fwsync_mod = {
205: "ipfw_sync",
206: fwsync_main,
207: NULL
208: };
209:
210: DECLARE_MODULE(ipfw_sync, fwsync_mod, SI_SUB_PROTO_FIREWALL, SI_ORDER_ANY);
211: MODULE_DEPEND(ipfw_sync, libalias, 1, 1, 1);
212: MODULE_DEPEND(ipfw_sync, ipfw, 3, 3, 3);
213: MODULE_VERSION(ipfw_sync, DRV_VERSION);
214:
215: SYSINIT(fws_init, SI_SUB_PROTO_FIREWALL, (SI_ORDER_ANY - 128), fws_init, NULL);
216: SYSUNINIT(fws_fini, SI_SUB_PROTO_FIREWALL, (SI_ORDER_ANY - 128), fws_fini, NULL);
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>