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