File:  [ELWIX - Embedded LightWeight unIX -] / fwsync / driver / fwsync.c
Revision 1.10: download - view: text, annotated - select for diffs - revision graph
Thu Aug 18 12:53:19 2022 UTC (22 months ago) by misho
Branches: MAIN
CVS tags: HEAD
remove debug line

    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: {
   11: 	int e, rcvflg = 0;
   12: 	struct uio uio;
   13: 	struct mbuf *m = NULL;
   14: 	struct fws_proto *pkt;
   15: 
   16: 	DTRACE();
   17: 
   18: 	callout_schedule(&fws_co, hz);
   19: 
   20: 	memset(&uio, 0, sizeof uio);
   21: 	uio.uio_resid = 1000000000;
   22: 	uio.uio_td = curthread;
   23: 
   24: 	if ((fws_cfg.cfg.on & CFG_SYNC_EDGE) && (fws_ctx.config & CTX_EDGE_READY)) {
   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);
   30: 			return;
   31: 		}
   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));
   36: 			m_freem(m);
   37: 			return;
   38: 		}
   39: 
   40: 		switch (pkt->fws_version) {
   41: 			case FWS_PKTVER_STATE:
   42: 				fwsync_add_state(pkt);
   43: 				break;
   44: 			case FWS_PKTVER_ALIAS:
   45: 				fwsync_add_alias(pkt);
   46: 				break;
   47: 			default:
   48: 				printf("FWSync packet was discarded due to wrong version\n");
   49: 				break;
   50: 		}
   51: 
   52: 		m_freem(m);
   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: 
  170: 		if (fws_ctx.config & CTX_EDGE_ONLINE) {
  171: 			callout_drain(&fws_co);
  172: 			ipfw_unregister_state_sync();
  173: 			ipfw_unregister_alias_sync();
  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: 
  184: 		taskqueue_drain(fws_tq, &fws_sndpkt_task);
  185: 
  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: {
  251: 	int *n;
  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: 
  273: 		callout_reset(&fws_co, hz, fwsync_edge_proc, NULL);
  274: 
  275: 		if (!(fws_ctx.config & CTX_EDGE_ONLINE)) {
  276: 			ipfw_register_state_sync(fwsync_state_sync);
  277: 			ipfw_register_alias_sync(fwsync_alias_sync);
  278: 		}
  279: 
  280: 		fws_ctx.config |= CTX_EDGE_ONLINE;
  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: 
  330: 	if ((*n & CFG_SYNC_EDGE) && (fws_ctx.config & CTX_CFG_EDGE)) {
  331: 		fws_cfg.cfg.on &= ~CFG_SYNC_EDGE;
  332: 		fws_ctx.config &= ~CTX_EDGE_ONLINE;
  333: 
  334: 		callout_drain(&fws_co);
  335: 
  336: 		ipfw_unregister_state_sync();
  337: 		ipfw_unregister_alias_sync();
  338: 	}
  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();
  351: 
  352: 		taskqueue_drain(fws_tq, &fws_sndpkt_task);
  353: 	}
  354: 
  355: 	return 0;
  356: }

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