/************************************************************************* * (C) 2011 AITNET - Sofia/Bulgaria - * by Michael Pounov * * $Author: misho $ * $Id: daemon2.c,v 1.1 2011/10/04 22:37:46 misho Exp $ * *************************************************************************/ #include "global.h" #include "anshd.h" void * pktTx(sched_task_t *task) { struct tagProc *proc; int wlen; FTRACE(3); /* not found argument, drop data */ if (!(proc = TASK_ARG(task))) return (void*) -1; if ((wlen = pktSend(TASK_FD(task), proc->proc_id, proc->proc_flg, 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; 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), buf, &rlen, ð)) == ANSH_FLG_ERR) goto end; VERB(5) LOG("Received %d bytes", rlen); /* 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) goto end; switch (ret) { case ANSH_FLG_EOF: case ANSH_FLG_CPOUT: break; case ANSH_FLG_WINZ: b = (u_short*) buf; ioChgWinPTY(proc->proc_pty, ntohs(buf[0]), ntohs(buf[1]), ntohs(buf[2]), ntohs(buf[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; 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) return NULL; if (waitpid(proc->proc_pid, &wlen, WNOHANG)) { schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL); ioFreePTY(TASK_FD(task), proc->proc_ttyname); 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; } 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 */ schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL); waitpid(proc->proc_pid, &wlen, 0); ioFreePTY(TASK_FD(task), proc->proc_ttyname); 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]); return NULL; } void * fdRx(sched_task_t *task) { struct tagProc *proc; int rlen; FTRACE(3); /* not found argument, drop data */ if (!(proc = TASK_ARG(task))) return (void*) -1; if (waitpid(proc->proc_pid, &rlen, WNOHANG)) { schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL); ioFreePTY(TASK_FD(task), proc->proc_ttyname); 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; } 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 */ schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL); waitpid(proc->proc_pid, &rlen, 0); VERB(3) LOG("EOF process status %d", rlen); ioFreePTY(TASK_FD(task), proc->proc_ttyname); 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); return NULL; } int spawnLogin(sched_task_t *task, struct tagProc *proc) { 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: execl("/usr/bin/login", "login", NULL); // execl("/bin/echo", "echo", "MUUUUUUUUUUUUUUUUU", NULL); /* never reached */ return -1; default: VERB(3) LOG("Parent know child pid %d - ptyfd=%d", proc->proc_pid, proc->proc_pty); schedRead(TASK_ROOT(task), fdRx, proc, proc->proc_pty); break; } return 0; }