Annotation of fwsync/driver/fwsync.c, revision 1.12.2.1
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) {
1.12 misho 187: if (fws_ctx.config & CTX_EDGE_ONLINE) {
188: ipfw_unregister_state_sync();
189: ipfw_unregister_alias_sync();
190: }
191:
192: callout_drain(&fws_co);
193:
1.1 misho 194: fws_cfg.cfg.on &= ~CFG_SYNC_EDGE;
195: fws_cfg.cfg.edge = 0;
196: fws_cfg.cfg.addrs = 0;
197: memset(fws_cfg.cfg_addr, 0, sizeof fws_cfg.cfg_addr[0]);
198:
1.12 misho 199: soshutdown(fws_ctx.sockz[CFG_SYNC_ADDR_EDGE], SHUT_RD);
200: soclose(fws_ctx.sockz[CFG_SYNC_ADDR_EDGE]);
1.1 misho 201: }
202: if (*n & CFG_SYNC_COLLECTOR) {
203: if (fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE)) {
204: ipfw_unregister_state_hook();
205: ipfw_unregister_alias_hook();
206: }
207:
1.8 misho 208: taskqueue_drain(fws_tq, &fws_sndpkt_task);
209:
1.1 misho 210: fws_cfg.cfg.on &= ~CFG_SYNC_COLLECTOR;
211: fws_cfg.cfg.collector = 0;
212: fws_cfg.cfg.addrs = 0;
213: memset(fws_cfg.cfg_addr + 1, 0, sizeof fws_cfg.cfg_addr[0] * 2);
214:
215: if (fws_ctx.config & CTX_COLLECTOR_2_READY)
216: soclose(fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_2]);
217: if (fws_ctx.config & CTX_COLLECTOR_1_READY)
218: soclose(fws_ctx.sockz[CFG_SYNC_ADDR_COLLECTOR_1]);
219: }
220:
221: fws_ctx.config ^= fws_ctx.config;
222:
1.12.2.1! misho 223: memset(&fws_acct, 0, sizeof fws_acct);
! 224:
1.1 misho 225: return 0;
226: }
227:
228: int
229: fwsync_get_cfg(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
230: {
231: ipfw_obj_header *oh;
232: struct ipfw_sync_cfg *ucfg;
233: size_t sz;
234:
235: DTRACE();
236:
237: sz = sizeof(*oh) + sizeof(*ucfg);
238: /* Check minimum header size */
239: if (sd->valsize < sz)
240: return (EINVAL);
241:
242: oh = (struct _ipfw_obj_header*) ipfw_get_sopt_header(sd, sz);
243:
244: /* Basic length checks for TLVs */
245: if (oh->ntlv.head.length != sizeof(oh->ntlv))
246: return (EINVAL);
247:
248: ucfg = (struct ipfw_sync_cfg*) (oh + 1);
249:
250: /* Check if name is properly terminated */
251: if (strnlen(ucfg->name, sizeof(ucfg->name)) == sizeof(ucfg->name))
252: return (EINVAL);
253:
254: snprintf(ucfg->name, sizeof ucfg->name, "%d", fws_cfg.cfg.on);
255: ucfg->mode = 0;
256: if (fws_cfg.cfg.edge)
257: ucfg->mode |= CFG_SYNC_EDGE;
258: if (fws_cfg.cfg.collector)
259: ucfg->mode |= CFG_SYNC_COLLECTOR;
260: ucfg->addrs = (fws_cfg.cfg.addrs != 1) ? fws_cfg.cfg.addrs : 1;
261: memcpy(ucfg->addr, fws_cfg.cfg_addr, sizeof ucfg->addr);
262:
263: return 0;
264: }
265:
266: int
267: fwsync_list(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
268: {
269: DTRACE();
270:
271: return 0;
272: }
273:
274: int
275: fwsync_start(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
276: {
1.7 misho 277: int *n;
1.1 misho 278: ipfw_obj_header *oh;
279: size_t sz;
280:
281: DTRACE();
282:
283: sz = sizeof(*oh) + sizeof(int);
284: /* Check minimum header size */
285: if (sd->valsize < sz)
286: return (EINVAL);
287:
288: oh = (ipfw_obj_header*) sd->kbuf;
289:
290: /* Basic length checks for TLVs */
291: if (oh->ntlv.head.length != sizeof(oh->ntlv))
292: return (EINVAL);
293:
294: n = (int*) (oh + 1);
295:
296: if ((*n & CFG_SYNC_EDGE) && (fws_ctx.config & CTX_EDGE_READY)) {
297: fws_cfg.cfg.on |= CFG_SYNC_EDGE;
298:
1.7 misho 299: callout_reset(&fws_co, hz, fwsync_edge_proc, NULL);
1.8 misho 300:
1.9 misho 301: if (!(fws_ctx.config & CTX_EDGE_ONLINE)) {
1.8 misho 302: ipfw_register_state_sync(fwsync_state_sync);
1.9 misho 303: ipfw_register_alias_sync(fwsync_alias_sync);
304: }
1.8 misho 305:
306: fws_ctx.config |= CTX_EDGE_ONLINE;
1.1 misho 307: }
308:
309: if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_1_READY)) {
310: fws_cfg.cfg.on |= CFG_SYNC_COLLECTOR;
311:
312: if (!(fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE))) {
313: ipfw_register_state_hook(fwsync_state_handler);
314: ipfw_register_alias_hook(fwsync_alias_handler);
315: }
316:
317: fws_ctx.config |= CTX_COLLECTOR_1_ONLINE;
318: }
319:
320: if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_2_READY)) {
321: fws_cfg.cfg.on |= CFG_SYNC_COLLECTOR;
322:
323: if (!(fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE))) {
324: ipfw_register_state_hook(fwsync_state_handler);
325: ipfw_register_alias_hook(fwsync_alias_handler);
326: }
327:
328: fws_ctx.config |= CTX_COLLECTOR_2_ONLINE;
329: }
330:
331: return 0;
332: }
333:
334: int
335: fwsync_stop(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd)
336: {
337: int *n;
338: ipfw_obj_header *oh;
339: size_t sz;
340:
341: DTRACE();
342:
343: sz = sizeof(*oh) + sizeof(int);
344: /* Check minimum header size */
345: if (sd->valsize < sz)
346: return (EINVAL);
347:
348: oh = (ipfw_obj_header*) sd->kbuf;
349:
350: /* Basic length checks for TLVs */
351: if (oh->ntlv.head.length != sizeof(oh->ntlv))
352: return (EINVAL);
353:
354: n = (int*) (oh + 1);
355:
1.7 misho 356: if ((*n & CFG_SYNC_EDGE) && (fws_ctx.config & CTX_CFG_EDGE)) {
1.1 misho 357: fws_cfg.cfg.on &= ~CFG_SYNC_EDGE;
1.7 misho 358: fws_ctx.config &= ~CTX_EDGE_ONLINE;
359:
360: callout_drain(&fws_co);
1.8 misho 361:
362: ipfw_unregister_state_sync();
1.9 misho 363: ipfw_unregister_alias_sync();
1.7 misho 364: }
1.1 misho 365:
366: if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_2_ONLINE))
367: fws_ctx.config &= ~CTX_COLLECTOR_2_ONLINE;
368: if ((*n & CFG_SYNC_COLLECTOR) && (fws_ctx.config & CTX_COLLECTOR_1_ONLINE))
369: fws_ctx.config &= ~CTX_COLLECTOR_1_ONLINE;
370:
371: if ((*n & CFG_SYNC_COLLECTOR) &&
372: !(fws_ctx.config & (CTX_COLLECTOR_1_ONLINE | CTX_COLLECTOR_2_ONLINE))) {
373: fws_cfg.cfg.on &= ~CFG_SYNC_COLLECTOR;
374:
375: ipfw_unregister_state_hook();
376: ipfw_unregister_alias_hook();
1.8 misho 377:
378: taskqueue_drain(fws_tq, &fws_sndpkt_task);
1.1 misho 379: }
380:
381: return 0;
382: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>