/*************************************************************************
* (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.3 2011/10/10 13:56:30 misho Exp $
*
*************************************************************************/
#include "global.h"
#include "anshd.h"
#include "proc.h"
intptr_t Kill;
int Verbose;
u_int Crypted = 1;
proc_head_t pH;
int bpfLEN, Timeout, 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-U <user>\tRun service with other user\n"
"\t-C <dir>\tRun service into chroot directory\n"
"\t-t <timeout>\tTimeout of login if no activity (default is 0 sec)\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:
VERB(1) LOG("Got SIGHUP!\n");
break;
case SIGTERM:
Kill++;
VERB(1) LOG("Got SIGTERM!\n");
break;
case SIGPIPE:
VERB(1) LOG("Got SIGPIPE!\n");
break;
case SIGCHLD:
VERB(1) LOG("Got SIGCHLD!\n");
while (waitpid(-1, &state, WNOHANG) > 0);
break;
}
}
static void *
hook_error(void *root, void *arg)
{
/* sched_root_task_t *r = root; */
if (!root)
return (void*) -1;
if (arg == (void*) EINTR)
return (void*) -1;
return NULL;
}
int
main(int argc, char **argv)
{
struct passwd *pass;
int fd, h = 0, uid = 0, gid = 0;
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, "hvubt:d: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 't':
Timeout = abs(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;
}
}
if (ioCreatePIDFile(PIDFILE_ANSHD, 42)) {
ERR("Error:: already started anshd service ...\n");
closelog();
return 1;
}
h = PrepareL2(szDev, &bpfLEN);
if (h == -1) {
ERR("Error:: Descriptor not opened ... abort!\n");
unlink(PIDFILE_ANSHD);
closelog();
return 2;
}
SLIST_INIT(&pH);
if (!(proc = InitProc(h, NULL, ANSH_ID, bpfLEN))) {
ERR("Error:: Not enough memory ...\n");
close(h);
unlink(PIDFILE_ANSHD);
closelog();
return 3;
}
root = schedBegin();
if (!root) {
ERR("Scheduler not init #%d - %s\n", sched_GetErrno(), sched_GetError());
DestroyProc(ANSH_ID);
close(h);
unlink(PIDFILE_ANSHD);
closelog();
return 4;
} else
root->root_hooks.hook_root.error = hook_error;
chdir("/");
chroot(szChroot);
setgid(gid);
setuid(uid);
if (schedRead(root, pktRx, (void*) ANSH_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(ANSH_ID);
close(h);
unlink(PIDFILE_ANSHD);
closelog();
return 0;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>