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