File:  [ELWIX - Embedded LightWeight unIX -] / fwsync / driver / fwsync_mod.c
Revision 1.3: download - view: text, annotated - select for diffs - revision graph
Mon Jul 11 12:58:58 2022 UTC (22 months, 1 week ago) by misho
Branches: MAIN
CVS tags: HEAD
unified send packet routine

/*************************************************************************
* (C) 2022 CloudSigma AG - Sofia/Bulgaria
*  by Michael Pounov <misho@elwix.org>
**************************************************************************/
#include "fwsync.h"


MALLOC_DEFINE(M_FWSYNC, "fwsync_memory", "FWSync - memory");

static struct ipfw_sopt_handler	soc[] = {
	{ IP_FW_SYNC_XCONFIG,	0,	HDIR_SET,	fwsync_cfg },
	{ IP_FW_SYNC_DESTROY,	0,	HDIR_SET,	fwsync_destroy },
	{ IP_FW_SYNC_XGETCONFIG,	0,	HDIR_GET,	fwsync_get_cfg },
	{ IP_FW_SYNC_LIST,	0,	HDIR_GET,	fwsync_list },
	{ IP_FW_SYNC_START,	0,	HDIR_SET,	fwsync_start },
	{ IP_FW_SYNC_STOP,	0,	HDIR_SET,	fwsync_stop },
};

static volatile int fwsync_hooked = 0;
struct fwsync_context fws_ctx = { 0 };
int fwsync_debug = DRV_DEBUG;
static struct sysctl_ctx_list fwsync_sysctl_ctx;
struct cfg_sync fws_cfg;
//static struct sysctl_oid *fws_sysctl_oid, *fws_sysctl_dir;

struct task fws_sndpkt_task;
struct taskqueue *fws_tq;
struct mtx fws_mtx_c, fws_mtx_e;
fwsync_sndpkt_t fwsync_sndpkt; 

SYSCTL_NODE(_net_inet_ip, IFT_FWSYNC, fwsync, CTLFLAG_RW, 0, "IPFW Sync - Sync firewall states");
SYSCTL_INT(_net_inet_ip_fwsync, OID_AUTO, debug, CTLFLAG_RW, &fwsync_debug, 0, "Debug driver");

static int
fws_fini(void *arg)
{
	struct fws_sndpkt *p;

	DTRACE();

	if (!fwsync_hooked)
		return EBUSY;

	if (fws_cfg.cfg.on || fws_ctx.config) {
		uprintf("Unable to unload ELWIX %s driver, cause you have active configuration.\n"
				"Before unload driver flush configuration!\n", DRV_NAME);
		return EBUSY;
	}

	IPFW_DEL_SOPT_HANDLER(1, soc);

	if (fws_tq)
		taskqueue_free(fws_tq);

	mtx_lock(&fws_mtx_c);
	while (!TAILQ_EMPTY(&fwsync_sndpkt)) {
		p = TAILQ_FIRST(&fwsync_sndpkt);
		TAILQ_REMOVE(&fwsync_sndpkt, p, sp_next);
		free(p, M_FWSYNC);
	}
	mtx_unlock(&fws_mtx_c);

	mtx_destroy(&fws_mtx_c);
	mtx_destroy(&fws_mtx_e);

	fwsync_hooked = 0;

	/* sysctl context */
	sysctl_ctx_free(&fwsync_sysctl_ctx);

	uprintf("Unloaded ELWIX %s driver version %d ...\n", DRV_NAME, DRV_VERSION);
	return 0;
}

static int
fws_shut(void *arg)
{
	DTRACE();

	fws_fini(arg);

	return 0;
}

static int
fws_init(void *arg)
{
	DTRACE();

	if (fwsync_hooked)
		return 0;

	memset(&fws_cfg, 0, sizeof fws_cfg);
	memset(&fws_ctx, 0, sizeof fws_ctx);

	TAILQ_INIT(&fwsync_sndpkt);

	/* mutexes */
	mtx_init(&fws_mtx_e, "fwsync mtx edge", NULL, MTX_DEF);
	mtx_init(&fws_mtx_c, "fwsync mtx collector", NULL, MTX_DEF);

	/* taskqueue */
	TASK_INIT(&fws_sndpkt_task, 0, fwsync_sndpkt_handler, &fwsync_sndpkt);

	fws_tq = taskqueue_create("fwsync_tq", M_NOWAIT, taskqueue_thread_enqueue, &fws_tq);
	if (!fws_tq) {
		printf("Failed to allocate fwsync task queue\n");
		mtx_destroy(&fws_mtx_c);
		mtx_destroy(&fws_mtx_e);
		return ENOMEM;
	} else
		taskqueue_start_threads(&fws_tq, 1, PI_NET, "fwsync tq");

	/* sysctl context */
	sysctl_ctx_init(&fwsync_sysctl_ctx);

	IPFW_ADD_SOPT_HANDLER(1, soc);

	fwsync_hooked = 1;
	uprintf("Loaded ELWIX %s driver version %d ...\n", DRV_NAME, DRV_VERSION);
	return 0;
}
static int
fwsync_main(module_t m, int what, void *arg)
{
	int ret = 0;

	switch (what) {
		case MOD_LOAD:
			ret = fws_init(arg);
			break;
		case MOD_UNLOAD:
			ret = fws_fini(arg);
			break;
		case MOD_SHUTDOWN:
			ret = fws_shut(arg);
			break;
		case MOD_QUIESCE:
			/* don't unload driver if there have configured driver */
			if (fws_cfg.cfg.on || fws_ctx.config)
				ret = EBUSY;
			break;
		default:
			ret = EINVAL;
			break;
	}

	return ret;
}

static moduledata_t fwsync_mod = {
	"ipfw_sync",
	fwsync_main,
	NULL
};

DECLARE_MODULE(ipfw_sync, fwsync_mod, SI_SUB_PROTO_FIREWALL, SI_ORDER_ANY);
MODULE_DEPEND(ipfw_sync, ipfw, 3, 3, 3);
MODULE_VERSION(ipfw_sync, DRV_VERSION);

SYSINIT(fws_init, SI_SUB_PROTO_FIREWALL, (SI_ORDER_ANY - 128), fws_init, NULL);
SYSUNINIT(fws_fini, SI_SUB_PROTO_FIREWALL, (SI_ORDER_ANY - 128), fws_fini, NULL);

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