/*************************************************************************
* (C) 2011 AITNET - Sofia/Bulgaria - <office@aitnet.org>
* by Michael Pounov <misho@elwix.org>
*
* $Author: misho $
* $Id: anshd.c,v 1.1.1.1.2.1 2011/10/07 13:41:26 misho Exp $
*
*************************************************************************/
#include "global.h"
#include "anshd.h"
#include "proc.h"
intptr_t Kill;
int bpfLEN, Verbose;
u_int 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>