/************************************************************************* * (C) 2011 AITNET - Sofia/Bulgaria - * by Michael Pounov * * $Author: misho $ * $Id: daemon2.c,v 1.1.1.1.2.1 2011/10/10 09:11:48 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_id, 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; schedWrite(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; schedWrite(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; schedWrite(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); 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; schedWrite(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]); schedWrite(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; }