Annotation of fwsync/driver/fwsync.c, revision 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>