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