File:  [ELWIX - Embedded LightWeight unIX -] / fwsync / driver / fwsync.c
Revision 1.5: download - view: text, annotated - select for diffs - revision graph
Mon Jul 11 15:59:42 2022 UTC (22 months, 3 weeks ago) by misho
Branches: MAIN
CVS tags: HEAD
Activate debug on module
Adds NAT alias handling
fix memory leak and empty send list

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

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