File:  [ELWIX - Embedded LightWeight unIX -] / fwsync / driver / fwsync.c
Revision 1.3: download - view: text, annotated - select for diffs - revision graph
Mon Jul 4 13:29:10 2022 UTC (23 months, 2 weeks ago) by misho
Branches: MAIN
CVS tags: HEAD
start handling of fws_proto

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>