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