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