Annotation of fwsync/driver/fwsync.c, revision 1.11
1.11 ! misho 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: */
1.1 misho 27: #include "fwsync.h"
28:
29:
30: static void
31: fwsync_edge_proc(void *arg)
32: {
1.3 misho 33: int e, rcvflg = 0;
1.1 misho 34: struct uio uio;
35: struct mbuf *m = NULL;
1.3 misho 36: struct fws_proto *pkt;
1.1 misho 37:
38: DTRACE();
39:
1.7 misho 40: callout_schedule(&fws_co, hz);
41:
1.1 misho 42: memset(&uio, 0, sizeof uio);
43: uio.uio_resid = 1000000000;
44: uio.uio_td = curthread;
45:
1.7 misho 46: if ((fws_cfg.cfg.on & CFG_SYNC_EDGE) && (fws_ctx.config & CTX_EDGE_READY)) {
1.1 misho 47: rcvflg = MSG_DONTWAIT;
48: e = soreceive(fws_ctx.sockz[CFG_SYNC_ADDR_EDGE], NULL, &uio, &m, NULL, &rcvflg);
49: if (e) {
50: if (e != EAGAIN)
51: printf("error in edge handler #%d\n", e);
1.7 misho 52: return;
1.1 misho 53: }
1.3 misho 54: pkt = mtod(m, struct fws_proto*);
55: if (m_length(m, NULL) != sizeof(struct fws_proto)) {
56: printf("FWSync packet length=%d isn't match expected %lu\n",
57: m_length(m, NULL), sizeof(struct fws_proto));
1.8 misho 58: m_freem(m);
1.7 misho 59: return;
1.3 misho 60: }
1.1 misho 61:
1.4 misho 62: switch (pkt->fws_version) {
63: case FWS_PKTVER_STATE:
64: fwsync_add_state(pkt);
65: break;
1.5 misho 66: case FWS_PKTVER_ALIAS:
67: fwsync_add_alias(pkt);
1.4 misho 68: break;
69: default:
70: printf("FWSync packet was discarded due to wrong version\n");
1.8 misho 71: break;
1.4 misho 72: }
1.8 misho 73:
74: m_freem(m);
1.1 misho 75: }
76: }
77:
78: int
79: fwsync_cfg(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
80: {
81: ipfw_obj_header *oh;
82: struct ipfw_sync_cfg *ucfg;
83: size_t sz;
84: int e;
85:
86: DTRACE();
87:
88: sz = sizeof(*oh) + sizeof(*ucfg);
89: /* Check minimum header size */
90: if (sd->valsize < sz)
91: return (EINVAL);
92:
93: oh = (ipfw_obj_header*) sd->kbuf;
94:
95: /* Basic length checks for TLVs */
96: if (oh->ntlv.head.length != sizeof(oh->ntlv))
97: return (EINVAL);
98:
99: ucfg = (struct ipfw_sync_cfg*) (oh + 1);
100:
101: /* Check if name is properly terminated */
102: if (strnlen(ucfg->name, sizeof(ucfg->name)) == sizeof(ucfg->name))
103: return (EINVAL);
104:
105: if (ucfg->mode == CFG_SYNC_EDGE && !fws_cfg.cfg.edge && !(fws_ctx.config & CTX_CFG_EDGE) &&
106: !strcmp(ucfg->name, "edge") && ucfg->addrs == 1) {
107: fws_cfg.cfg.edge = 1;
108: memcpy(&fws_cfg.cfg_addr[CFG_SYNC_ADDR_EDGE], &ucfg->addr[CFG_SYNC_ADDR_EDGE],
109: sizeof fws_cfg.cfg_addr[CFG_SYNC_ADDR_EDGE]);
110: fws_ctx.config |= CTX_CFG_EDGE;
111:
112: e = socreate((fws_cfg.cfg_addr[CFG_SYNC_ADDR_EDGE].addr.sa_family == AF_INET) ? AF_INET : AF_INET6,
113: &fws_ctx.sockz[CFG_SYNC_ADDR_EDGE], SOCK_DGRAM, IPPROTO_UDP, curthread->td_ucred, curthread);
114: if (e) {
115: printf("fwsync edge socreate failed #%d\n", e);
116: return e;
117: }
118:
119: e = sobind(fws_ctx.sockz[CFG_SYNC_ADDR_EDGE], &fws_cfg.cfg_addr[CFG_SYNC_ADDR_EDGE].addr, curthread);
120: if (e) {
121: if (e != EADDRINUSE)
122: printf("fwsync edge sobind failed #%d\n", e);
123: else
124: printf("fwsync edge address in use!\n");
125: return e;
126: } else
127: fws_ctx.config |= CTX_EDGE_READY;
128: } else if (ucfg->mode == CFG_SYNC_COLLECTOR && !(fws_ctx.config & CTX_CFG_COLLECTOR_1) &&
129: !strcmp(ucfg->name, "collector") && ucfg->addrs > 0 && ucfg->addrs < 3) {
130: fws_cfg.cfg.collector = 1;
131: fws_cfg.cfg.addrs = ucfg->addrs;
132: memcpy(&fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_1], &ucfg->addr[CFG_SYNC_ADDR_COLLECTOR_1],
133: sizeof fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_1]);
134:
135: fws_ctx.config |= CTX_CFG_COLLECTOR_1;
136:
137: e = socreate((fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_1].addr.sa_family == AF_INET) ? AF_INET : AF_INET6,
138: &fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_1], SOCK_DGRAM, IPPROTO_UDP, curthread->td_ucred, curthread);
139: if (e) {
140: printf("fwsync collector %d socreate failed #%d\n", e, CFG_SYNC_ADDR_COLLECTOR_1);
141: return e;
142: } else
143: fws_ctx.config |= CTX_COLLECTOR_1_READY;
144:
145: if (fws_cfg.cfg.addrs > 1) {
146: memcpy(&fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_2], &ucfg->addr[CFG_SYNC_ADDR_COLLECTOR_2],
147: sizeof fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_2]);
148:
149: fws_ctx.config |= CTX_CFG_COLLECTOR_2;
150:
151: e = socreate((fws_cfg.cfg_addr[CFG_SYNC_ADDR_COLLECTOR_2].addr.sa_family == AF_INET) ? AF_INET : AF_INET6,
152: &fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_2], SOCK_DGRAM, IPPROTO_UDP, curthread->td_ucred, curthread);
153: if (e) {
154: printf("fwsync collector %d socreate failed #%d\n", e, CFG_SYNC_ADDR_COLLECTOR_2);
155: return e;
156: } else
157: fws_ctx.config |= CTX_COLLECTOR_2_READY;
158: }
159: } else
160: return (EINVAL);
161:
162: return 0;
163: }
164:
165: int
166: fwsync_destroy(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
167: {
168: int *n;
169: ipfw_obj_header *oh;
170: size_t sz;
171:
172: DTRACE();
173:
174: sz = sizeof(*oh) + sizeof(int);
175: /* Check minimum header size */
176: if (sd->valsize < sz)
177: return (EINVAL);
178:
179: oh = (ipfw_obj_header*) sd->kbuf;
180:
181: /* Basic length checks for TLVs */
182: if (oh->ntlv.head.length != sizeof(oh->ntlv))
183: return (EINVAL);
184:
185: n = (int*) (oh + 1);
186: if (*n & CFG_SYNC_EDGE) {
187: fws_cfg.cfg.on &= ~CFG_SYNC_EDGE;
188: fws_cfg.cfg.edge = 0;
189: fws_cfg.cfg.addrs = 0;
190: memset(fws_cfg.cfg_addr, 0, sizeof fws_cfg.cfg_addr[0]);
191:
1.7 misho 192: if (fws_ctx.config & CTX_EDGE_ONLINE) {
193: callout_drain(&fws_co);
1.8 misho 194: ipfw_unregister_state_sync();
1.9 misho 195: ipfw_unregister_alias_sync();
1.1 misho 196: soshutdown(fws_ctx.sockz[CFG_SYNC_ADDR_EDGE], SHUT_RD);
197: soclose(fws_ctx.sockz[CFG_SYNC_ADDR_EDGE]);
198: }
199: }
200: if (*n & CFG_SYNC_COLLECTOR) {
201: if (fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE)) {
202: ipfw_unregister_state_hook();
203: ipfw_unregister_alias_hook();
204: }
205:
1.8 misho 206: taskqueue_drain(fws_tq, &fws_sndpkt_task);
207:
1.1 misho 208: fws_cfg.cfg.on &= ~CFG_SYNC_COLLECTOR;
209: fws_cfg.cfg.collector = 0;
210: fws_cfg.cfg.addrs = 0;
211: memset(fws_cfg.cfg_addr + 1, 0, sizeof fws_cfg.cfg_addr[0] * 2);
212:
213: if (fws_ctx.config & CTX_COLLECTOR_2_READY)
214: soclose(fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_2]);
215: if (fws_ctx.config & CTX_COLLECTOR_1_READY)
216: soclose(fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_1]);
217: }
218:
219: fws_ctx.config ^= fws_ctx.config;
220:
221: return 0;
222: }
223:
224: int
225: fwsync_get_cfg(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
226: {
227: ipfw_obj_header *oh;
228: struct ipfw_sync_cfg *ucfg;
229: size_t sz;
230:
231: DTRACE();
232:
233: sz = sizeof(*oh) + sizeof(*ucfg);
234: /* Check minimum header size */
235: if (sd->valsize < sz)
236: return (EINVAL);
237:
238: oh = (struct _ipfw_obj_header*) ipfw_get_sopt_header(sd, sz);
239:
240: /* Basic length checks for TLVs */
241: if (oh->ntlv.head.length != sizeof(oh->ntlv))
242: return (EINVAL);
243:
244: ucfg = (struct ipfw_sync_cfg*) (oh + 1);
245:
246: /* Check if name is properly terminated */
247: if (strnlen(ucfg->name, sizeof(ucfg->name)) == sizeof(ucfg->name))
248: return (EINVAL);
249:
250: snprintf(ucfg->name, sizeof ucfg->name, "%d", fws_cfg.cfg.on);
251: ucfg->mode = 0;
252: if (fws_cfg.cfg.edge)
253: ucfg->mode |= CFG_SYNC_EDGE;
254: if (fws_cfg.cfg.collector)
255: ucfg->mode |= CFG_SYNC_COLLECTOR;
256: ucfg->addrs = (fws_cfg.cfg.addrs != 1) ? fws_cfg.cfg.addrs : 1;
257: memcpy(ucfg->addr, fws_cfg.cfg_addr, sizeof ucfg->addr);
258:
259: return 0;
260: }
261:
262: int
263: fwsync_list(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
264: {
265: DTRACE();
266:
267: return 0;
268: }
269:
270: int
271: fwsync_start(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
272: {
1.7 misho 273: int *n;
1.1 misho 274: ipfw_obj_header *oh;
275: size_t sz;
276:
277: DTRACE();
278:
279: sz = sizeof(*oh) + sizeof(int);
280: /* Check minimum header size */
281: if (sd->valsize < sz)
282: return (EINVAL);
283:
284: oh = (ipfw_obj_header*) sd->kbuf;
285:
286: /* Basic length checks for TLVs */
287: if (oh->ntlv.head.length != sizeof(oh->ntlv))
288: return (EINVAL);
289:
290: n = (int*) (oh + 1);
291:
292: if ((*n & CFG_SYNC_EDGE) && (fws_ctx.config & CTX_EDGE_READY)) {
293: fws_cfg.cfg.on |= CFG_SYNC_EDGE;
294:
1.7 misho 295: callout_reset(&fws_co, hz, fwsync_edge_proc, NULL);
1.8 misho 296:
1.9 misho 297: if (!(fws_ctx.config & CTX_EDGE_ONLINE)) {
1.8 misho 298: ipfw_register_state_sync(fwsync_state_sync);
1.9 misho 299: ipfw_register_alias_sync(fwsync_alias_sync);
300: }
1.8 misho 301:
302: fws_ctx.config |= CTX_EDGE_ONLINE;
1.1 misho 303: }
304:
305: if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_1_READY)) {
306: fws_cfg.cfg.on |= CFG_SYNC_COLLECTOR;
307:
308: if (!(fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE))) {
309: ipfw_register_state_hook(fwsync_state_handler);
310: ipfw_register_alias_hook(fwsync_alias_handler);
311: }
312:
313: fws_ctx.config |= CTX_COLLECTOR_1_ONLINE;
314: }
315:
316: if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_2_READY)) {
317: fws_cfg.cfg.on |= CFG_SYNC_COLLECTOR;
318:
319: if (!(fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE))) {
320: ipfw_register_state_hook(fwsync_state_handler);
321: ipfw_register_alias_hook(fwsync_alias_handler);
322: }
323:
324: fws_ctx.config |= CTX_COLLECTOR_2_ONLINE;
325: }
326:
327: return 0;
328: }
329:
330: int
331: fwsync_stop(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
332: {
333: int *n;
334: ipfw_obj_header *oh;
335: size_t sz;
336:
337: DTRACE();
338:
339: sz = sizeof(*oh) + sizeof(int);
340: /* Check minimum header size */
341: if (sd->valsize < sz)
342: return (EINVAL);
343:
344: oh = (ipfw_obj_header*) sd->kbuf;
345:
346: /* Basic length checks for TLVs */
347: if (oh->ntlv.head.length != sizeof(oh->ntlv))
348: return (EINVAL);
349:
350: n = (int*) (oh + 1);
351:
1.7 misho 352: if ((*n & CFG_SYNC_EDGE) && (fws_ctx.config & CTX_CFG_EDGE)) {
1.1 misho 353: fws_cfg.cfg.on &= ~CFG_SYNC_EDGE;
1.7 misho 354: fws_ctx.config &= ~CTX_EDGE_ONLINE;
355:
356: callout_drain(&fws_co);
1.8 misho 357:
358: ipfw_unregister_state_sync();
1.9 misho 359: ipfw_unregister_alias_sync();
1.7 misho 360: }
1.1 misho 361:
362: if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_2_ONLINE))
363: fws_ctx.config &= ~CTX_COLLECTOR_2_ONLINE;
364: if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_1_ONLINE))
365: fws_ctx.config &= ~CTX_COLLECTOR_1_ONLINE;
366:
367: if ((*n & CFG_SYNC_COLLECTOR) &&
368: !(fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE))) {
369: fws_cfg.cfg.on &= ~CFG_SYNC_COLLECTOR;
370:
371: ipfw_unregister_state_hook();
372: ipfw_unregister_alias_hook();
1.8 misho 373:
374: taskqueue_drain(fws_tq, &fws_sndpkt_task);
1.1 misho 375: }
376:
377: return 0;
378: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>