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