File:  [ELWIX - Embedded LightWeight unIX -] / ansh / src / daemon2.c
Revision 1.1.1.1.2.5: download - view: text, annotated - select for diffs - revision graph
Thu Oct 13 15:24:17 2011 UTC (12 years, 9 months ago) by misho
Branches: ansh1_0
Diff to: branchpoint 1.1.1.1: preferred, unified
fix bpflen

    1: /*************************************************************************
    2:  * (C) 2011 AITNET - Sofia/Bulgaria - <office@aitnet.org>
    3:  *  by Michael Pounov <misho@elwix.org>
    4:  *
    5:  * $Author: misho $
    6:  * $Id: daemon2.c,v 1.1.1.1.2.5 2011/10/13 15:24:17 misho Exp $
    7:  *
    8:  *************************************************************************/
    9: #include "global.h"
   10: #include "anshd.h"
   11: 
   12: 
   13: void *
   14: pktTx(sched_task_t *task)
   15: {
   16: 	struct tagProc *proc;
   17: 	int wlen;
   18: 	u_char *str;
   19: 
   20: 	FTRACE(3);
   21: 
   22: 	/* not found argument, drop data */
   23: 	if (!(proc = TASK_ARG(task)))
   24: 		return (void*) -1;
   25: 
   26: 	if (Crypted) {
   27: 		str = cryptBuffer(proc->proc_buf_[FD2NET], proc->proc_rlen_[FD2NET], Crypted);
   28: 		if (str) {
   29: 			memcpy(proc->proc_buf_[FD2NET], str, proc->proc_rlen_[FD2NET]);
   30: 			free(str);
   31: 		}
   32: 	}
   33: 
   34: 	if ((wlen = pktSend(TASK_FD(task), ++proc->proc_seq, proc->proc_flg, Crypted, 
   35: 					proc->proc_buf_[FD2NET], proc->proc_rlen_[FD2NET], 
   36: 					&proc->proc_ea)) != ANSH_FLG_ERR) {
   37: 		proc->proc_flg = ANSH_FLG_OK;
   38: 		proc->proc_rlen_[FD2NET] = 0;
   39: 	}
   40: 	VERB(5) LOG("Sended %d bytes", wlen);
   41: 
   42: 	return NULL;
   43: }
   44: 
   45: void *
   46: pktRx(sched_task_t *task)
   47: {
   48: 	u_char *buf, *str;
   49: 	struct ether_header eth;
   50: 	int rlen, n = 0;
   51: 	struct tagProc *proc = NULL;
   52: 	char ret;
   53: 	u_short *b;
   54: 	u_int seq;
   55: 
   56: 	FTRACE(3);
   57: 
   58: 	rlen = bpfLEN;
   59: 	if (!(buf = malloc(rlen)))
   60: 		goto end;
   61: 	else
   62: 		memset(buf, 0, rlen);
   63: 
   64: 	if ((ret = pktRecv(TASK_FD(task), &seq, &Crypted, buf, &rlen, &eth)) == ANSH_FLG_ERR)
   65: 		goto end;
   66: 	VERB(5) LOG("Received %d bytes", rlen);
   67: 	if (!(ret & ANSH_FLG_CPOUT))
   68: 		goto end;
   69: 
   70: 	/* packet is ok find active session */
   71: 	SLIST_FOREACH(proc, &pH, proc_next)
   72: 		if (proc->proc_id == ntohs(eth.ether_type)) {
   73: 			n = ANSH_CODE;
   74: 			break;
   75: 		}
   76: 	/* not found in sessions, drop packet */
   77: 	if (n != ANSH_CODE) {
   78: 		proc = NULL;
   79: 		goto end;
   80: 	}
   81: 
   82: 	if (Crypted) {
   83: 		str = cryptBuffer(buf, rlen, Crypted);
   84: 		if (str) {
   85: 			memcpy(buf, str, rlen);
   86: 			free(str);
   87: 		}
   88: 	}
   89: 
   90: 	switch (ret) {
   91: 		case ANSH_FLG_EOF:
   92: 		case ANSH_FLG_CPOUT:
   93: 			if (seq <= proc->proc_seq)
   94: 				goto end;
   95: 			else if (seq > (proc->proc_seq + 1))
   96: 				LOG("LOST PACKET(s) detect: %d; received seq=%d - %d", 
   97: 						seq - proc->proc_seq + 1, seq, proc->proc_seq);
   98: 			proc->proc_seq = seq;
   99: 			break;
  100: 		case ANSH_FLG_WINZ:
  101: 			b = (u_short*) buf;
  102: 			ioChgWinPTY(proc->proc_pty, ntohs(b[0]), ntohs(b[1]), ntohs(b[2]), ntohs(b[3]));
  103: 			/* if not started login, lets start & go! */
  104: 			if (!proc->proc_pid) {
  105: 				memcpy(&proc->proc_ea.octet, &eth.ether_shost, ETHER_ADDR_LEN);
  106: 				spawnLogin(task, proc);
  107: 			}
  108: 		default:
  109: 			goto end;
  110: 	}
  111: 
  112: 	proc->proc_flg = ret;
  113: 	proc->proc_rlen_[NET2FD] = rlen;
  114: 	memset(proc->proc_buf_[NET2FD], 0, proc->proc_blen);
  115: 	memcpy(proc->proc_buf_[NET2FD], buf, proc->proc_rlen_[NET2FD]);
  116: 	schedWrite(TASK_ROOT(task), fdTx, proc, proc->proc_pty);
  117: end:
  118: 	free(buf);
  119: 	schedRead(TASK_ROOT(task), pktRx, NULL, proc ? proc->proc_sock : TASK_FD(task));
  120: 	return NULL;
  121: }
  122: 
  123: void *
  124: fdTx(sched_task_t *task)
  125: {
  126: 	struct tagProc *proc;
  127: 	struct timeval tv = { 0 };
  128: 	int wlen;
  129: 
  130: 	FTRACE(3);
  131: 
  132: 	/* not found argument, drop data */
  133: 	if (!(proc = TASK_ARG(task)))
  134: 		return (void*) -1;
  135: 
  136: 	/* if != ANSH_FLG_CPOUT isnt received from client */
  137: 	if (proc->proc_flg != ANSH_FLG_CPOUT || !proc->proc_pid)
  138: 		return NULL;
  139: 
  140: 	if (waitpid(proc->proc_pid, &wlen, WNOHANG)) {
  141: 		ioFreePTY(TASK_FD(task), proc->proc_ttyname);
  142: 		schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
  143: 
  144: 		proc->proc_pid = 0;
  145: 		proc->proc_seq = 0;
  146: 		proc->proc_flg = ANSH_FLG_EOF;
  147: 		proc->proc_rlen_[FD2NET] = 0;
  148: 
  149: 		schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
  150: 		return NULL;
  151: 	}
  152: 
  153: 	/* if Timeout defined, disarm timer */
  154: 	if (Timeout)
  155: 		schedCancelby(TASK_ROOT(task), &TASK_ROOT(task)->root_timer, CRITERIA_CALL, TOfunc, NULL);
  156: 
  157: 	wlen = write(TASK_FD(task), proc->proc_buf_[NET2FD], proc->proc_rlen_[NET2FD]);
  158: 	switch (wlen) {
  159: 		case -1:
  160: 			ERR("write2tty #%d - %s", errno, strerror(errno));
  161: 			/* exit from shell and release tty */
  162: 			waitpid(proc->proc_pid, &wlen, 0);
  163: 			ioFreePTY(TASK_FD(task), proc->proc_ttyname);
  164: 			schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
  165: 
  166: 			proc->proc_pid = 0;
  167: 			proc->proc_seq = 0;
  168: 			proc->proc_flg = ANSH_FLG_EOF;
  169: 			proc->proc_rlen_[FD2NET] = 0;
  170: 
  171: 			schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
  172: 			return NULL;
  173: 		default:
  174: 			proc->proc_flg = ANSH_FLG_OK;
  175: 			proc->proc_rlen_[NET2FD] = 0;
  176: 	}
  177: 	VERB(3) LOG("Writed %d bytes - %s", wlen, proc->proc_buf_[NET2FD]);
  178: 
  179: 	/* if Timeout defined, go arm timer */
  180: 	if (Timeout) {
  181: 		tv.tv_sec = Timeout;
  182: 		schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
  183: 	}
  184: 	return NULL;
  185: }
  186: 
  187: void *
  188: fdRx(sched_task_t *task)
  189: {
  190: 	struct tagProc *proc;
  191: 	struct timeval tv = { 0 };
  192: 	int rlen;
  193: 
  194: 	FTRACE(3);
  195: 
  196: 	/* not found argument, drop data */
  197: 	if (!(proc = TASK_ARG(task)))
  198: 		return (void*) -1;
  199: 	if (!proc->proc_pid)
  200: 		return NULL;
  201: 
  202: 	if (waitpid(proc->proc_pid, &rlen, WNOHANG)) {
  203: 		ioFreePTY(TASK_FD(task), proc->proc_ttyname);
  204: 		schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
  205: 
  206: 		proc->proc_pid = 0;
  207: 		proc->proc_seq = 0;
  208: 		proc->proc_flg = ANSH_FLG_EOF;
  209: 		proc->proc_rlen_[FD2NET] = 0;
  210: 
  211: 		schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
  212: 		return NULL;
  213: 	}
  214: 
  215: 	/* if Timeout defined, disarm timer */
  216: 	if (Timeout)
  217: 		schedCancelby(TASK_ROOT(task), &TASK_ROOT(task)->root_timer, CRITERIA_CALL, TOfunc, NULL);
  218: 
  219: 	memset(proc->proc_buf_[FD2NET], 0, proc->proc_blen);
  220: 	rlen = read(TASK_FD(task), proc->proc_buf_[FD2NET], 
  221: 			proc->proc_blen - ETHER_HDR_LEN + sizeof(struct ansh_hdr));
  222: 	switch (rlen) {
  223: 		case -1:
  224: 			ERR("readtty #%d - %s", errno, strerror(errno));
  225: 		case 0:
  226: 			/* exit from shell and release tty */
  227: 			waitpid(proc->proc_pid, &rlen, 0);
  228: 			ioFreePTY(TASK_FD(task), proc->proc_ttyname);
  229: 			schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
  230: 			VERB(3) LOG("EOF process status %d", rlen);
  231: 
  232: 			proc->proc_pid = 0;
  233: 			proc->proc_seq = 0;
  234: 			proc->proc_flg = ANSH_FLG_EOF;
  235: 			proc->proc_rlen_[FD2NET] = 0;
  236: 
  237: 			schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
  238: 			return NULL;
  239: 		default:
  240: 			proc->proc_flg = ANSH_FLG_OK;
  241: 			proc->proc_rlen_[FD2NET] = rlen;
  242: 	}
  243: 	VERB(3) LOG("Readed %d bytes - %s", rlen, proc->proc_buf_[FD2NET]);
  244: 
  245: 	schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
  246: 	schedRead(TASK_ROOT(task), fdRx, proc, proc->proc_pty);
  247: 
  248: 	/* if Timeout defined, go arm timer */
  249: 	if (Timeout) {
  250: 		tv.tv_sec = Timeout;
  251: 		schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
  252: 	}
  253: 	return NULL;
  254: }
  255: 
  256: int
  257: spawnLogin(sched_task_t *task, struct tagProc *proc)
  258: {
  259: 	int flg;
  260: 	struct timeval tv = { 0 };
  261: 	char str[STRSIZ] = { 0 };
  262: 
  263: 	FTRACE(3);
  264: 
  265: 	assert(proc);
  266: 
  267: 	switch ((proc->proc_pid = ioForkPTY(&proc->proc_pty, proc->proc_ttyname, 
  268: 					sizeof proc->proc_ttyname, NULL, NULL, NULL))) {
  269: 		case -1:
  270: 			ERR("ioForkPTY() #%d - %s", io_GetErrno(), io_GetError());
  271: 			return -1;
  272: 		case 0:
  273: 			printf("anshd ELWIX remote management system (%s)\n\n", proc->proc_ttyname);
  274: 			strlcpy(str, "-hansh@", sizeof str);
  275: 			ether_ntoa_r(&proc->proc_ea, str + 7);
  276: 
  277: 			execl("/usr/bin/login", "login", str, NULL);
  278: 			/* never reached */
  279: 			return -1;
  280: 		default:
  281: 			flg = fcntl(proc->proc_pty, F_GETFL);
  282: 			fcntl(proc->proc_pty, F_SETFL, flg | O_NONBLOCK);
  283: 
  284: 			VERB(3) LOG("Parent know child pid %d", proc->proc_pid);
  285: 			schedRead(TASK_ROOT(task), fdRx, proc, proc->proc_pty);
  286: 
  287: 			/* if Timeout defined, go arm timer */
  288: 			if (Timeout) {
  289: 				tv.tv_sec = Timeout;
  290: 				schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
  291: 			}
  292: 			break;
  293: 	}
  294: 
  295: 	return 0;
  296: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>