1: /*************************************************************************
2: * (C) 2022 CloudSigma AG - Sofia/Bulgaria
3: * by Michael Pounov <misho@elwix.org>
4: **************************************************************************/
5: #include "fwsync.h"
6:
7:
8: MALLOC_DEFINE(M_FWSYNC, "fwsync_memory", "FWSync - memory");
9:
10: static struct ipfw_sopt_handler soc[] = {
11: { IP_FW_SYNC_XCONFIG, 0, HDIR_SET, fwsync_cfg },
12: { IP_FW_SYNC_DESTROY, 0, HDIR_SET, fwsync_destroy },
13: { IP_FW_SYNC_XGETCONFIG, 0, HDIR_GET, fwsync_get_cfg },
14: { IP_FW_SYNC_LIST, 0, HDIR_GET, fwsync_list },
15: { IP_FW_SYNC_START, 0, HDIR_SET, fwsync_start },
16: { IP_FW_SYNC_STOP, 0, HDIR_SET, fwsync_stop },
17: };
18:
19: static volatile int fwsync_hooked = 0;
20: struct fwsync_context fws_ctx = { 0 };
21: int fwsync_debug = DRV_DEBUG;
22: static struct sysctl_ctx_list fwsync_sysctl_ctx;
23: struct cfg_sync fws_cfg;
24: //static struct sysctl_oid *fws_sysctl_oid, *fws_sysctl_dir;
25:
26: struct task fws_sndpkt_task;
27: struct taskqueue *fws_tq;
28: struct mtx fws_mtx_c, fws_mtx_e;
29: fwsync_sndpkt_t fwsync_sndpkt;
30:
31: SYSCTL_NODE(_net_inet_ip, IFT_FWSYNC, fwsync, CTLFLAG_RW, 0, "IPFW Sync - Sync firewall states");
32: SYSCTL_INT(_net_inet_ip_fwsync, OID_AUTO, debug, CTLFLAG_RW, &fwsync_debug, 0, "Debug driver");
33:
34: static int
35: fws_fini(void *arg)
36: {
37: struct fws_sndpkt *p;
38:
39: DTRACE();
40:
41: if (!fwsync_hooked)
42: return EBUSY;
43:
44: if (fws_cfg.cfg.on || fws_ctx.config) {
45: uprintf("Unable to unload ELWIX %s driver, cause you have active configuration.\n"
46: "Before unload driver flush configuration!\n", DRV_NAME);
47: return EBUSY;
48: }
49:
50: IPFW_DEL_SOPT_HANDLER(1, soc);
51:
52: if (fws_tq)
53: taskqueue_free(fws_tq);
54:
55: mtx_lock(&fws_mtx_c);
56: while (!TAILQ_EMPTY(&fwsync_sndpkt)) {
57: p = TAILQ_FIRST(&fwsync_sndpkt);
58: TAILQ_REMOVE(&fwsync_sndpkt, p, sp_next);
59: free(p, M_FWSYNC);
60: }
61: mtx_unlock(&fws_mtx_c);
62:
63: mtx_destroy(&fws_mtx_c);
64: mtx_destroy(&fws_mtx_e);
65:
66: fwsync_hooked = 0;
67:
68: /* sysctl context */
69: sysctl_ctx_free(&fwsync_sysctl_ctx);
70:
71: uprintf("Unloaded ELWIX %s driver version %d ...\n", DRV_NAME, DRV_VERSION);
72: return 0;
73: }
74:
75: static int
76: fws_shut(void *arg)
77: {
78: DTRACE();
79:
80: fws_fini(arg);
81:
82: return 0;
83: }
84:
85: static int
86: fws_init(void *arg)
87: {
88: DTRACE();
89:
90: if (fwsync_hooked)
91: return 0;
92:
93: memset(&fws_cfg, 0, sizeof fws_cfg);
94: memset(&fws_ctx, 0, sizeof fws_ctx);
95:
96: TAILQ_INIT(&fwsync_sndpkt);
97:
98: /* mutexes */
99: mtx_init(&fws_mtx_e, "fwsync mtx edge", NULL, MTX_DEF);
100: mtx_init(&fws_mtx_c, "fwsync mtx collector", NULL, MTX_DEF);
101:
102: /* taskqueue */
103: TASK_INIT(&fws_sndpkt_task, 0, fwsync_sndpkt_handler, &fwsync_sndpkt);
104:
105: fws_tq = taskqueue_create("fwsync_tq", M_NOWAIT, taskqueue_thread_enqueue, &fws_tq);
106: if (!fws_tq) {
107: printf("Failed to allocate fwsync task queue\n");
108: mtx_destroy(&fws_mtx_c);
109: mtx_destroy(&fws_mtx_e);
110: return ENOMEM;
111: } else
112: taskqueue_start_threads(&fws_tq, 1, PI_NET, "fwsync tq");
113:
114: /* sysctl context */
115: sysctl_ctx_init(&fwsync_sysctl_ctx);
116:
117: IPFW_ADD_SOPT_HANDLER(1, soc);
118:
119: fwsync_hooked = 1;
120: uprintf("Loaded ELWIX %s driver version %d ...\n", DRV_NAME, DRV_VERSION);
121: return 0;
122: }
123: static int
124: fwsync_main(module_t m, int what, void *arg)
125: {
126: int ret = 0;
127:
128: switch (what) {
129: case MOD_LOAD:
130: ret = fws_init(arg);
131: break;
132: case MOD_UNLOAD:
133: ret = fws_fini(arg);
134: break;
135: case MOD_SHUTDOWN:
136: ret = fws_shut(arg);
137: break;
138: case MOD_QUIESCE:
139: /* don't unload driver if there have configured driver */
140: if (fws_cfg.cfg.on || fws_ctx.config)
141: ret = EBUSY;
142: break;
143: default:
144: ret = EINVAL;
145: break;
146: }
147:
148: return ret;
149: }
150:
151: static moduledata_t fwsync_mod = {
152: "ipfw_sync",
153: fwsync_main,
154: NULL
155: };
156:
157: DECLARE_MODULE(ipfw_sync, fwsync_mod, SI_SUB_PROTO_FIREWALL, SI_ORDER_ANY);
158: MODULE_DEPEND(ipfw_sync, libalias, 1, 1, 1);
159: MODULE_DEPEND(ipfw_sync, ipfw, 3, 3, 3);
160: MODULE_VERSION(ipfw_sync, DRV_VERSION);
161:
162: SYSINIT(fws_init, SI_SUB_PROTO_FIREWALL, (SI_ORDER_ANY - 128), fws_init, NULL);
163: SYSUNINIT(fws_fini, SI_SUB_PROTO_FIREWALL, (SI_ORDER_ANY - 128), fws_fini, NULL);
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>