/*************************************************************************
* (C) 2011 AITNET - Sofia/Bulgaria - <office@aitnet.org>
* by Michael Pounov <misho@elwix.org>
*
* $Author: misho $
* $Id: daemon2.c,v 1.1.1.1.2.3 2011/10/13 11:01:37 misho Exp $
*
*************************************************************************/
#include "global.h"
#include "anshd.h"
void *
pktTx(sched_task_t *task)
{
struct tagProc *proc;
int wlen;
u_char *str;
FTRACE(3);
/* not found argument, drop data */
if (!(proc = TASK_ARG(task)))
return (void*) -1;
if (Crypted) {
str = cryptBuffer(proc->proc_buf_[FD2NET], proc->proc_rlen_[FD2NET], Crypted);
if (str) {
memcpy(proc->proc_buf_[FD2NET], str, proc->proc_rlen_[FD2NET]);
free(str);
}
}
if ((wlen = pktSend(TASK_FD(task), proc->proc_flg, Crypted, proc->proc_buf_[FD2NET],
proc->proc_rlen_[FD2NET], &proc->proc_ea)) != ANSH_FLG_ERR) {
proc->proc_flg = ANSH_FLG_OK;
proc->proc_rlen_[FD2NET] = 0;
}
VERB(5) LOG("Sended %d bytes", wlen);
return NULL;
}
void *
pktRx(sched_task_t *task)
{
u_char *buf, *str;
struct ether_header eth;
int rlen, n = 0;
struct tagProc *proc = NULL;
char ret;
u_short *b;
FTRACE(3);
rlen = bpfLEN;
if (!(buf = malloc(rlen)))
goto end;
if ((ret = pktRecv(TASK_FD(task), &Crypted, buf, &rlen, ð)) == ANSH_FLG_ERR)
goto end;
VERB(5) LOG("Received %d bytes", rlen);
if (!(ret & ANSH_FLG_CPOUT))
goto end;
/* packet is ok find active session */
SLIST_FOREACH(proc, &pH, proc_next)
if (proc->proc_id == ntohs(eth.ether_type)) {
n = ANSH_CODE;
break;
}
/* not found in sessions, drop packet */
if (n != ANSH_CODE) {
proc = NULL;
goto end;
}
if (Crypted) {
str = cryptBuffer(buf, rlen, Crypted);
if (str) {
memcpy(buf, str, rlen);
free(str);
}
}
switch (ret) {
case ANSH_FLG_EOF:
case ANSH_FLG_CPOUT:
break;
case ANSH_FLG_WINZ:
b = (u_short*) buf;
ioChgWinPTY(proc->proc_pty, ntohs(b[0]), ntohs(b[1]), ntohs(b[2]), ntohs(b[3]));
/* if not started login, lets start & go! */
if (!proc->proc_pid) {
memcpy(&proc->proc_ea.octet, ð.ether_shost, ETHER_ADDR_LEN);
spawnLogin(task, proc);
}
default:
goto end;
}
proc->proc_flg = ret;
proc->proc_rlen_[NET2FD] = rlen;
memset(proc->proc_buf_[NET2FD], 0, proc->proc_blen);
memcpy(proc->proc_buf_[NET2FD], buf, proc->proc_rlen_[NET2FD]);
schedWrite(TASK_ROOT(task), fdTx, proc, proc->proc_pty);
end:
free(buf);
schedRead(TASK_ROOT(task), pktRx, NULL, proc ? proc->proc_sock : TASK_FD(task));
return NULL;
}
void *
fdTx(sched_task_t *task)
{
struct tagProc *proc;
struct timeval tv = { 0 };
int wlen;
FTRACE(3);
/* not found argument, drop data */
if (!(proc = TASK_ARG(task)))
return (void*) -1;
/* if != ANSH_FLG_CPOUT isnt received from client */
if (proc->proc_flg != ANSH_FLG_CPOUT || !proc->proc_pid)
return NULL;
if (waitpid(proc->proc_pid, &wlen, WNOHANG)) {
ioFreePTY(TASK_FD(task), proc->proc_ttyname);
schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
proc->proc_pid = 0;
proc->proc_flg = ANSH_FLG_EOF;
proc->proc_rlen_[FD2NET] = 0;
schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
return NULL;
}
/* if Timeout defined, disarm timer */
if (Timeout)
schedCancelby(TASK_ROOT(task), &TASK_ROOT(task)->root_timer, CRITERIA_CALL, TOfunc, NULL);
wlen = write(TASK_FD(task), proc->proc_buf_[NET2FD], proc->proc_rlen_[NET2FD]);
switch (wlen) {
case -1:
ERR("write2tty #%d - %s", errno, strerror(errno));
/* exit from shell and release tty */
waitpid(proc->proc_pid, &wlen, 0);
ioFreePTY(TASK_FD(task), proc->proc_ttyname);
schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
proc->proc_pid = 0;
proc->proc_flg = ANSH_FLG_EOF;
proc->proc_rlen_[FD2NET] = 0;
schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
return NULL;
default:
proc->proc_flg = ANSH_FLG_OK;
proc->proc_rlen_[NET2FD] = 0;
}
VERB(3) LOG("Writed %d bytes - %s", wlen, proc->proc_buf_[NET2FD]);
/* if Timeout defined, go arm timer */
if (Timeout) {
tv.tv_sec = Timeout;
schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
}
return NULL;
}
void *
fdRx(sched_task_t *task)
{
struct tagProc *proc;
struct timeval tv = { 0 };
int rlen;
FTRACE(3);
/* not found argument, drop data */
if (!(proc = TASK_ARG(task)))
return (void*) -1;
if (!proc->proc_pid)
return NULL;
if (waitpid(proc->proc_pid, &rlen, WNOHANG)) {
ioFreePTY(TASK_FD(task), proc->proc_ttyname);
schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
proc->proc_pid = 0;
proc->proc_flg = ANSH_FLG_EOF;
proc->proc_rlen_[FD2NET] = 0;
schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
return NULL;
}
/* if Timeout defined, disarm timer */
if (Timeout)
schedCancelby(TASK_ROOT(task), &TASK_ROOT(task)->root_timer, CRITERIA_CALL, TOfunc, NULL);
memset(proc->proc_buf_[FD2NET], 0, proc->proc_blen);
rlen = read(TASK_FD(task), proc->proc_buf_[FD2NET],
proc->proc_blen - ETHER_HDR_LEN + sizeof(struct ansh_hdr));
switch (rlen) {
case -1:
ERR("readtty #%d - %s", errno, strerror(errno));
case 0:
/* exit from shell and release tty */
waitpid(proc->proc_pid, &rlen, 0);
ioFreePTY(TASK_FD(task), proc->proc_ttyname);
schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
VERB(3) LOG("EOF process status %d", rlen);
proc->proc_pid = 0;
proc->proc_flg = ANSH_FLG_EOF;
proc->proc_rlen_[FD2NET] = 0;
schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
return NULL;
default:
proc->proc_flg = ANSH_FLG_OK;
proc->proc_rlen_[FD2NET] = rlen;
}
VERB(3) LOG("Readed %d bytes - %s", rlen, proc->proc_buf_[FD2NET]);
schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
schedRead(TASK_ROOT(task), fdRx, proc, proc->proc_pty);
/* if Timeout defined, go arm timer */
if (Timeout) {
tv.tv_sec = Timeout;
schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
}
return NULL;
}
int
spawnLogin(sched_task_t *task, struct tagProc *proc)
{
int flg;
struct timeval tv = { 0 };
char str[STRSIZ] = { 0 };
FTRACE(3);
assert(proc);
switch ((proc->proc_pid = ioForkPTY(&proc->proc_pty, proc->proc_ttyname,
sizeof proc->proc_ttyname, NULL, NULL, NULL))) {
case -1:
ERR("ioForkPTY() #%d - %s", io_GetErrno(), io_GetError());
return -1;
case 0:
printf("anshd ELWIX remote management system (%s)\n\n", proc->proc_ttyname);
strlcpy(str, "-hansh@", sizeof str);
ether_ntoa_r(&proc->proc_ea, str + 7);
execl("/usr/bin/login", "login", str, NULL);
/* never reached */
return -1;
default:
flg = fcntl(proc->proc_pty, F_GETFL);
fcntl(proc->proc_pty, F_SETFL, flg | O_NONBLOCK);
VERB(3) LOG("Parent know child pid %d", proc->proc_pid);
schedRead(TASK_ROOT(task), fdRx, proc, proc->proc_pty);
/* if Timeout defined, go arm timer */
if (Timeout) {
tv.tv_sec = Timeout;
schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
}
break;
}
return 0;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>