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: struct fws_acct fws_acct;
54:
55: SYSCTL_NODE(_net_inet_ip, IFT_FWSYNC, fwsync, CTLFLAG_RW, 0, "IPFW Sync - Sync firewall states");
56: SYSCTL_INT(_net_inet_ip_fwsync, OID_AUTO, debug, CTLFLAG_RW, &fwsync_debug, 0, "Debug driver");
57: SYSCTL_NODE(_net_inet_ip_fwsync, IFT_FWSYNC_ACCT, acct, CTLFLAG_RD, 0, "IPFW Sync - Handled states");
58: SYSCTL_ULONG(_net_inet_ip_fwsync_acct, OID_AUTO, collector_states, CTLFLAG_RD, &fws_acct.states[0], 0, "Sent states to network");
59: SYSCTL_ULONG(_net_inet_ip_fwsync_acct, OID_AUTO, edge_states, CTLFLAG_RD, &fws_acct.states[1], 0, "Received states from network");
60: SYSCTL_ULONG(_net_inet_ip_fwsync_acct, OID_AUTO, collector_aliases, CTLFLAG_RD, &fws_acct.aliases[0], 0, "Sent aliases to network");
61: SYSCTL_ULONG(_net_inet_ip_fwsync_acct, OID_AUTO, edge_aliases, CTLFLAG_RD, &fws_acct.aliases[1], 0, "Received aliases from network");
62:
63: static int
64: fws_fini(void *arg)
65: {
66: struct fws_sndpkt *p;
67:
68: DTRACE();
69:
70: if (!fwsync_hooked)
71: return EBUSY;
72:
73: if (fws_cfg.cfg.on || fws_ctx.config) {
74: uprintf("Unable to unload ELWIX %s driver, cause you have active configuration.\n"
75: "Before unload driver flush configuration!\n", DRV_NAME);
76: return EBUSY;
77: }
78:
79: IPFW_DEL_SOPT_HANDLER(1, soc);
80:
81: callout_drain(&fws_co);
82:
83: if (fws_tq) {
84: taskqueue_drain_all(fws_tq);
85: taskqueue_free(fws_tq);
86: }
87:
88: mtx_lock(&fws_mtx_n);
89: while (!TAILQ_EMPTY(&fwsync_natpkt)) {
90: p = TAILQ_FIRST(&fwsync_natpkt);
91: TAILQ_REMOVE(&fwsync_natpkt, p, sp_next);
92: free(p, M_FWSYNC);
93: }
94: mtx_unlock(&fws_mtx_n);
95:
96: mtx_lock(&fws_mtx_u);
97: while (!TAILQ_EMPTY(&fwsync_updpkt)) {
98: p = TAILQ_FIRST(&fwsync_updpkt);
99: TAILQ_REMOVE(&fwsync_updpkt, p, sp_next);
100: free(p, M_FWSYNC);
101: }
102: mtx_unlock(&fws_mtx_u);
103:
104: mtx_lock(&fws_mtx_c);
105: while (!TAILQ_EMPTY(&fwsync_sndpkt)) {
106: p = TAILQ_FIRST(&fwsync_sndpkt);
107: TAILQ_REMOVE(&fwsync_sndpkt, p, sp_next);
108: free(p, M_FWSYNC);
109: }
110: mtx_unlock(&fws_mtx_c);
111:
112: mtx_destroy(&fws_mtx_c);
113: mtx_destroy(&fws_mtx_e);
114: mtx_destroy(&fws_mtx_u);
115: mtx_destroy(&fws_mtx_n);
116:
117: fwsync_hooked = 0;
118:
119: /* sysctl context */
120: sysctl_ctx_free(&fwsync_sysctl_ctx);
121:
122: uprintf("Unloaded ELWIX %s driver version %d ...\n", DRV_NAME, DRV_VERSION);
123: return 0;
124: }
125:
126: static int
127: fws_shut(void *arg)
128: {
129: DTRACE();
130:
131: fws_fini(arg);
132:
133: return 0;
134: }
135:
136: static int
137: fws_init(void *arg)
138: {
139: DTRACE();
140:
141: if (fwsync_hooked)
142: return 0;
143:
144: memset(&fws_cfg, 0, sizeof fws_cfg);
145: memset(&fws_ctx, 0, sizeof fws_ctx);
146: memset(&fws_acct, 0, sizeof fws_acct);
147:
148: TAILQ_INIT(&fwsync_sndpkt);
149: TAILQ_INIT(&fwsync_updpkt);
150: TAILQ_INIT(&fwsync_natpkt);
151:
152: /* mutexes */
153: mtx_init(&fws_mtx_n, "fwsync mtx alias", NULL, MTX_DEF);
154: mtx_init(&fws_mtx_u, "fwsync mtx dynamic", NULL, MTX_DEF);
155: mtx_init(&fws_mtx_e, "fwsync mtx edge", NULL, MTX_DEF);
156: mtx_init(&fws_mtx_c, "fwsync mtx collector", NULL, MTX_DEF);
157:
158: /* taskqueue */
159: fws_tq = taskqueue_create("fwsync_tq", M_NOWAIT, taskqueue_thread_enqueue, &fws_tq);
160: if (!fws_tq) {
161: printf("Failed to allocate fwsync task queue\n");
162: mtx_destroy(&fws_mtx_c);
163: mtx_destroy(&fws_mtx_e);
164: return ENOMEM;
165: } else
166: taskqueue_start_threads(&fws_tq, 1, PI_NET, "fwsync tq");
167:
168: TASK_INIT(&fws_sndpkt_task, 0, fwsync_sndpkt_handler, &fwsync_sndpkt);
169:
170: /* callout */
171:
172: callout_init_mtx(&fws_co, &fws_mtx_e, 0);
173:
174: /* sysctl context */
175: sysctl_ctx_init(&fwsync_sysctl_ctx);
176:
177: IPFW_ADD_SOPT_HANDLER(1, soc);
178:
179: fwsync_hooked = 1;
180: uprintf("Loaded ELWIX %s driver version %d ...\n", DRV_NAME, DRV_VERSION);
181: return 0;
182: }
183: static int
184: fwsync_main(module_t m, int what, void *arg)
185: {
186: int ret = 0;
187:
188: switch (what) {
189: case MOD_LOAD:
190: ret = fws_init(arg);
191: break;
192: case MOD_UNLOAD:
193: ret = fws_fini(arg);
194: break;
195: case MOD_SHUTDOWN:
196: ret = fws_shut(arg);
197: break;
198: case MOD_QUIESCE:
199: /* don't unload driver if there have configured driver */
200: if (fws_cfg.cfg.on || fws_ctx.config)
201: ret = EBUSY;
202: break;
203: default:
204: ret = EINVAL;
205: break;
206: }
207:
208: return ret;
209: }
210:
211: static moduledata_t fwsync_mod = {
212: "ipfw_sync",
213: fwsync_main,
214: NULL
215: };
216:
217: DECLARE_MODULE(ipfw_sync, fwsync_mod, SI_SUB_PROTO_FIREWALL, SI_ORDER_ANY);
218: MODULE_DEPEND(ipfw_sync, libalias, 1, 1, 1);
219: MODULE_DEPEND(ipfw_sync, ipfw, 3, 3, 3);
220: MODULE_VERSION(ipfw_sync, DRV_VERSION);
221:
222: SYSINIT(fws_init, SI_SUB_PROTO_FIREWALL, (SI_ORDER_ANY - 128), fws_init, NULL);
223: SYSUNINIT(fws_fini, SI_SUB_PROTO_FIREWALL, (SI_ORDER_ANY - 128), fws_fini, NULL);
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>