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