File:  [ELWIX - Embedded LightWeight unIX -] / ansh / src / anshd.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Oct 4 22:37:46 2011 UTC (12 years, 8 months ago) by misho
Branches: MAIN
CVS tags: HEAD
Initial revision

/*************************************************************************
 * (C) 2011 AITNET - Sofia/Bulgaria - <office@aitnet.org>
 *  by Michael Pounov <misho@elwix.org>
 *
 * $Author: misho $
 * $Id: anshd.c,v 1.1 2011/10/04 22:37:46 misho Exp $
 *
 *************************************************************************/
#include "global.h"
#include "anshd.h"
#include "proc.h"


intptr_t Kill;
int bpfLEN, Verbose, Crypted = 1;
proc_head_t pH;
int Daemon = 1;

extern char compiled[], compiledby[], compilehost[];

static void
Usage()
{
	printf(	" -= anshd =- ELWIX Layer2 remote management service\n"
		"=== %s === %s@%s ===\n\n"
		" Syntax: anshd [options]\n\n"
		"\t-d <dev>\tBind to host interface, like 'em0' (default is first host interface)\n"
		"\t-i <id>\tService ID (default is 42)\n"
		"\t-U <user>\tRun service with other user\n"
		"\t-C <dir>\tRun service into chroot directory\n"
		"\t-u\t\tSwitch to unencrypted traffic between hosts\n"
		"\t-b\t\tRun into batch mode (default is daemon mode)\n"
		"\t-v\t\tVerbose (more -v, more verbosity ...)\n"
		"\t-h\t\tThis help screen!\n"
		"\n", compiled, compiledby, compilehost);
}

static void
sig(int s)
{
	int state;

	switch (s) {
		case SIGHUP:
			LOG("Got SIGHUP!\n");
			break;
		case SIGTERM:
			LOG("Got SIGTERM!\n");
			Kill++;
			break;
		case SIGPIPE:
			LOG("Got SIGPIPE!\n");
			break;
		case SIGCHLD:
			while (waitpid(-1, &state, WNOHANG) > 0);
			break;
	}
}

int
main(int argc, char **argv)
{
	struct passwd *pass;
	int fd, h = 0, uid = 0, gid = 0;
	long id = ANSH_ID;
	char ch, szUser[STRSIZ] = "root", szChroot[STRSIZ] = "/", szDev[STRSIZ] = { 0 };
	struct sigaction sact;
	sched_root_task_t *root = NULL;
	struct tagProc *proc;

	Get1stEth(szDev, STRSIZ);

	while ((ch = getopt(argc, argv, "hvulbd:U:C:")) != -1)
		switch (ch) {
			case 'U':
				pass = getpwnam(optarg);
				if (!pass) {
					printf("Error:: User %s not found!\n", optarg);
					return 1;
				} else {
					strlcpy(szUser, optarg, sizeof szUser);
					uid = pass->pw_uid;
					gid = pass->pw_gid;
				}
				endpwent();
				break;
			case 'C':
				if (access(optarg, R_OK)) {
					printf("Error:: in chroot %s #%d - %s\n", optarg, errno, strerror(errno));
					return 1;
				} else
					strlcpy(szChroot, optarg, sizeof szChroot);
				break;
			case 'i':
				id = strtol(optarg, NULL, 0);
				break;
			case 'd':
				strlcpy(szDev, optarg, sizeof szDev);
				break;
			case 'u':
				Crypted ^= Crypted;
				break;
			case 'b':
				Daemon ^= Daemon;
				break;
			case 'v':
				Verbose++;
				break;
			case 'h':
			default:
				Usage();
				return 1;
		}
	argc -= optind;
	argv += optind;

	/* catch signals */
	memset(&sact, 0, sizeof sact);
	sigemptyset(&sact.sa_mask);
	sact.sa_handler = sig;
	sigaction(SIGPIPE, &sact, NULL);
	sigaction(SIGCHLD, &sact, NULL);
	sigaction(SIGTERM, &sact, NULL);
	sigaction(SIGHUP, &sact, NULL);

	openlog("anshd", LOG_CONS | LOG_PID, LOG_DAEMON);

	if (Daemon) {
		switch (fork()) {
			case -1:
				ERR("Daemon mode #%d - %s\n", errno, strerror(errno));
				closelog();
				return 1;
			case 0:
				VERB(1) LOG("Welcome to dark ...\n");

				setsid();

				fd = open("/dev/null", O_WRONLY);
				if (fd) {
					dup2(fd, STDIN_FILENO);
					dup2(fd, STDOUT_FILENO);
					dup2(fd, STDERR_FILENO);
					if (fd > 2)
						close(fd);
				}
				break;
			default:
				VERB(1) LOG("Going to shadow land ...\n");
				closelog();
				return 0;
		}
	}

	h = PrepareL2(szDev, &bpfLEN);
	if (h == -1) {
		ERR("Error:: Descriptor not opened ... abort!\n");
		closelog();
		return 2;
	}

	SLIST_INIT(&pH);
	if (!(proc = InitProc(h, NULL, id, bpfLEN))) {
		ERR("Error:: Not enough memory ...\n");
		close(h);
		closelog();
		return 3;
	}

	root = schedBegin();
	if (!root) {
		ERR("Scheduler not init #%d - %s\n", sched_GetErrno(), sched_GetError());
		DestroyProc(id);
		close(h);
		closelog();
		return 4;
	}

	chdir("/");
	chroot(szChroot);

	setgid(gid);
	setuid(uid);

	if (schedRead(root, pktRx, (void*) id, h)) {
		schedRun(root, &Kill);
	} else
		ERR("Failed to add reader task #%d - %s\n", sched_GetErrno(), sched_GetError());

	VERB(1) LOG("Finish process.");
	schedEnd(&root);
	DestroyProc(id);
	close(h);
	closelog();
	return 0;
}

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