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