File:  [ELWIX - Embedded LightWeight unIX -] / ansh / src / daemon2.c
Revision 1.1.1.1.2.6: download - view: text, annotated - select for diffs - revision graph
Thu Oct 13 16:08:52 2011 UTC (12 years, 9 months ago) by misho
Branches: ansh1_0
Diff to: branchpoint 1.1.1.1: preferred, unified
added BSD license

    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.6 2011/10/13 16:08:52 misho Exp $
    7:  *
    8:  *************************************************************************
    9: The ELWIX and AITNET software is distributed under the following
   10: terms:
   11: 
   12: All of the documentation and software included in the ELWIX and AITNET
   13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   14: 
   15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
   16: 	by Michael Pounov <misho@elwix.org>.  All rights reserved.
   17: 
   18: Redistribution and use in source and binary forms, with or without
   19: modification, are permitted provided that the following conditions
   20: are met:
   21: 1. Redistributions of source code must retain the above copyright
   22:    notice, this list of conditions and the following disclaimer.
   23: 2. Redistributions in binary form must reproduce the above copyright
   24:    notice, this list of conditions and the following disclaimer in the
   25:    documentation and/or other materials provided with the distribution.
   26: 3. All advertising materials mentioning features or use of this software
   27:    must display the following acknowledgement:
   28: This product includes software developed by Michael Pounov <misho@elwix.org>
   29: ELWIX - Embedded LightWeight unIX and its contributors.
   30: 4. Neither the name of AITNET nor the names of its contributors
   31:    may be used to endorse or promote products derived from this software
   32:    without specific prior written permission.
   33: 
   34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
   35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44: SUCH DAMAGE.
   45: */
   46: #include "global.h"
   47: #include "anshd.h"
   48: 
   49: 
   50: void *
   51: pktTx(sched_task_t *task)
   52: {
   53: 	struct tagProc *proc;
   54: 	int wlen;
   55: 	u_char *str;
   56: 
   57: 	FTRACE(3);
   58: 
   59: 	/* not found argument, drop data */
   60: 	if (!(proc = TASK_ARG(task)))
   61: 		return (void*) -1;
   62: 
   63: 	if (Crypted) {
   64: 		str = cryptBuffer(proc->proc_buf_[FD2NET], proc->proc_rlen_[FD2NET], Crypted);
   65: 		if (str) {
   66: 			memcpy(proc->proc_buf_[FD2NET], str, proc->proc_rlen_[FD2NET]);
   67: 			free(str);
   68: 		}
   69: 	}
   70: 
   71: 	if ((wlen = pktSend(TASK_FD(task), ++proc->proc_seq, proc->proc_flg, Crypted, 
   72: 					proc->proc_buf_[FD2NET], proc->proc_rlen_[FD2NET], 
   73: 					&proc->proc_ea)) != ANSH_FLG_ERR) {
   74: 		proc->proc_flg = ANSH_FLG_OK;
   75: 		proc->proc_rlen_[FD2NET] = 0;
   76: 	}
   77: 	VERB(5) LOG("Sended %d bytes", wlen);
   78: 
   79: 	return NULL;
   80: }
   81: 
   82: void *
   83: pktRx(sched_task_t *task)
   84: {
   85: 	u_char *buf, *str;
   86: 	struct ether_header eth;
   87: 	int rlen, n = 0;
   88: 	struct tagProc *proc = NULL;
   89: 	char ret;
   90: 	u_short *b;
   91: 	u_int seq;
   92: 
   93: 	FTRACE(3);
   94: 
   95: 	rlen = bpfLEN;
   96: 	if (!(buf = malloc(rlen)))
   97: 		goto end;
   98: 	else
   99: 		memset(buf, 0, rlen);
  100: 
  101: 	if ((ret = pktRecv(TASK_FD(task), &seq, &Crypted, buf, &rlen, &eth)) == ANSH_FLG_ERR)
  102: 		goto end;
  103: 	VERB(5) LOG("Received %d bytes", rlen);
  104: 	if (!(ret & ANSH_FLG_CPOUT))
  105: 		goto end;
  106: 
  107: 	/* packet is ok find active session */
  108: 	SLIST_FOREACH(proc, &pH, proc_next)
  109: 		if (proc->proc_id == ntohs(eth.ether_type)) {
  110: 			n = ANSH_CODE;
  111: 			break;
  112: 		}
  113: 	/* not found in sessions, drop packet */
  114: 	if (n != ANSH_CODE) {
  115: 		proc = NULL;
  116: 		goto end;
  117: 	}
  118: 
  119: 	if (Crypted) {
  120: 		str = cryptBuffer(buf, rlen, Crypted);
  121: 		if (str) {
  122: 			memcpy(buf, str, rlen);
  123: 			free(str);
  124: 		}
  125: 	}
  126: 
  127: 	switch (ret) {
  128: 		case ANSH_FLG_EOF:
  129: 		case ANSH_FLG_CPOUT:
  130: 			if (seq <= proc->proc_seq)
  131: 				goto end;
  132: 			else if (seq > (proc->proc_seq + 1))
  133: 				LOG("LOST PACKET(s) detect: %d; received seq=%d - %d", 
  134: 						seq - proc->proc_seq + 1, seq, proc->proc_seq);
  135: 			proc->proc_seq = seq;
  136: 			break;
  137: 		case ANSH_FLG_WINZ:
  138: 			b = (u_short*) buf;
  139: 			ioChgWinPTY(proc->proc_pty, ntohs(b[0]), ntohs(b[1]), ntohs(b[2]), ntohs(b[3]));
  140: 			/* if not started login, lets start & go! */
  141: 			if (!proc->proc_pid) {
  142: 				memcpy(&proc->proc_ea.octet, &eth.ether_shost, ETHER_ADDR_LEN);
  143: 				spawnLogin(task, proc);
  144: 			}
  145: 		default:
  146: 			goto end;
  147: 	}
  148: 
  149: 	proc->proc_flg = ret;
  150: 	proc->proc_rlen_[NET2FD] = rlen;
  151: 	memset(proc->proc_buf_[NET2FD], 0, proc->proc_blen);
  152: 	memcpy(proc->proc_buf_[NET2FD], buf, proc->proc_rlen_[NET2FD]);
  153: 	schedWrite(TASK_ROOT(task), fdTx, proc, proc->proc_pty);
  154: end:
  155: 	free(buf);
  156: 	schedRead(TASK_ROOT(task), pktRx, NULL, proc ? proc->proc_sock : TASK_FD(task));
  157: 	return NULL;
  158: }
  159: 
  160: void *
  161: fdTx(sched_task_t *task)
  162: {
  163: 	struct tagProc *proc;
  164: 	struct timeval tv = { 0 };
  165: 	int wlen;
  166: 
  167: 	FTRACE(3);
  168: 
  169: 	/* not found argument, drop data */
  170: 	if (!(proc = TASK_ARG(task)))
  171: 		return (void*) -1;
  172: 
  173: 	/* if != ANSH_FLG_CPOUT isnt received from client */
  174: 	if (proc->proc_flg != ANSH_FLG_CPOUT || !proc->proc_pid)
  175: 		return NULL;
  176: 
  177: 	if (waitpid(proc->proc_pid, &wlen, WNOHANG)) {
  178: 		ioFreePTY(TASK_FD(task), proc->proc_ttyname);
  179: 		schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
  180: 
  181: 		proc->proc_pid = 0;
  182: 		proc->proc_seq = 0;
  183: 		proc->proc_flg = ANSH_FLG_EOF;
  184: 		proc->proc_rlen_[FD2NET] = 0;
  185: 
  186: 		schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
  187: 		return NULL;
  188: 	}
  189: 
  190: 	/* if Timeout defined, disarm timer */
  191: 	if (Timeout)
  192: 		schedCancelby(TASK_ROOT(task), &TASK_ROOT(task)->root_timer, CRITERIA_CALL, TOfunc, NULL);
  193: 
  194: 	wlen = write(TASK_FD(task), proc->proc_buf_[NET2FD], proc->proc_rlen_[NET2FD]);
  195: 	switch (wlen) {
  196: 		case -1:
  197: 			ERR("write2tty #%d - %s", errno, strerror(errno));
  198: 			/* exit from shell and release tty */
  199: 			waitpid(proc->proc_pid, &wlen, 0);
  200: 			ioFreePTY(TASK_FD(task), proc->proc_ttyname);
  201: 			schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
  202: 
  203: 			proc->proc_pid = 0;
  204: 			proc->proc_seq = 0;
  205: 			proc->proc_flg = ANSH_FLG_EOF;
  206: 			proc->proc_rlen_[FD2NET] = 0;
  207: 
  208: 			schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
  209: 			return NULL;
  210: 		default:
  211: 			proc->proc_flg = ANSH_FLG_OK;
  212: 			proc->proc_rlen_[NET2FD] = 0;
  213: 	}
  214: 	VERB(3) LOG("Writed %d bytes - %s", wlen, proc->proc_buf_[NET2FD]);
  215: 
  216: 	/* if Timeout defined, go arm timer */
  217: 	if (Timeout) {
  218: 		tv.tv_sec = Timeout;
  219: 		schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
  220: 	}
  221: 	return NULL;
  222: }
  223: 
  224: void *
  225: fdRx(sched_task_t *task)
  226: {
  227: 	struct tagProc *proc;
  228: 	struct timeval tv = { 0 };
  229: 	int rlen;
  230: 
  231: 	FTRACE(3);
  232: 
  233: 	/* not found argument, drop data */
  234: 	if (!(proc = TASK_ARG(task)))
  235: 		return (void*) -1;
  236: 	if (!proc->proc_pid)
  237: 		return NULL;
  238: 
  239: 	if (waitpid(proc->proc_pid, &rlen, WNOHANG)) {
  240: 		ioFreePTY(TASK_FD(task), proc->proc_ttyname);
  241: 		schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
  242: 
  243: 		proc->proc_pid = 0;
  244: 		proc->proc_seq = 0;
  245: 		proc->proc_flg = ANSH_FLG_EOF;
  246: 		proc->proc_rlen_[FD2NET] = 0;
  247: 
  248: 		schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
  249: 		return NULL;
  250: 	}
  251: 
  252: 	/* if Timeout defined, disarm timer */
  253: 	if (Timeout)
  254: 		schedCancelby(TASK_ROOT(task), &TASK_ROOT(task)->root_timer, CRITERIA_CALL, TOfunc, NULL);
  255: 
  256: 	memset(proc->proc_buf_[FD2NET], 0, proc->proc_blen);
  257: 	rlen = read(TASK_FD(task), proc->proc_buf_[FD2NET], 
  258: 			proc->proc_blen - ETHER_HDR_LEN + sizeof(struct ansh_hdr));
  259: 	switch (rlen) {
  260: 		case -1:
  261: 			ERR("readtty #%d - %s", errno, strerror(errno));
  262: 		case 0:
  263: 			/* exit from shell and release tty */
  264: 			waitpid(proc->proc_pid, &rlen, 0);
  265: 			ioFreePTY(TASK_FD(task), proc->proc_ttyname);
  266: 			schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
  267: 			VERB(3) LOG("EOF process status %d", rlen);
  268: 
  269: 			proc->proc_pid = 0;
  270: 			proc->proc_seq = 0;
  271: 			proc->proc_flg = ANSH_FLG_EOF;
  272: 			proc->proc_rlen_[FD2NET] = 0;
  273: 
  274: 			schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
  275: 			return NULL;
  276: 		default:
  277: 			proc->proc_flg = ANSH_FLG_OK;
  278: 			proc->proc_rlen_[FD2NET] = rlen;
  279: 	}
  280: 	VERB(3) LOG("Readed %d bytes - %s", rlen, proc->proc_buf_[FD2NET]);
  281: 
  282: 	schedCallOnce(TASK_ROOT(task), pktTx, proc, proc->proc_sock);
  283: 	schedRead(TASK_ROOT(task), fdRx, proc, proc->proc_pty);
  284: 
  285: 	/* if Timeout defined, go arm timer */
  286: 	if (Timeout) {
  287: 		tv.tv_sec = Timeout;
  288: 		schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
  289: 	}
  290: 	return NULL;
  291: }
  292: 
  293: int
  294: spawnLogin(sched_task_t *task, struct tagProc *proc)
  295: {
  296: 	int flg;
  297: 	struct timeval tv = { 0 };
  298: 	char str[STRSIZ] = { 0 };
  299: 
  300: 	FTRACE(3);
  301: 
  302: 	assert(proc);
  303: 
  304: 	switch ((proc->proc_pid = ioForkPTY(&proc->proc_pty, proc->proc_ttyname, 
  305: 					sizeof proc->proc_ttyname, NULL, NULL, NULL))) {
  306: 		case -1:
  307: 			ERR("ioForkPTY() #%d - %s", io_GetErrno(), io_GetError());
  308: 			return -1;
  309: 		case 0:
  310: 			printf("anshd ELWIX remote management system (%s)\n\n", proc->proc_ttyname);
  311: 			strlcpy(str, "-hansh@", sizeof str);
  312: 			ether_ntoa_r(&proc->proc_ea, str + 7);
  313: 
  314: 			execl("/usr/bin/login", "login", str, NULL);
  315: 			/* never reached */
  316: 			return -1;
  317: 		default:
  318: 			flg = fcntl(proc->proc_pty, F_GETFL);
  319: 			fcntl(proc->proc_pty, F_SETFL, flg | O_NONBLOCK);
  320: 
  321: 			VERB(3) LOG("Parent know child pid %d", proc->proc_pid);
  322: 			schedRead(TASK_ROOT(task), fdRx, proc, proc->proc_pty);
  323: 
  324: 			/* if Timeout defined, go arm timer */
  325: 			if (Timeout) {
  326: 				tv.tv_sec = Timeout;
  327: 				schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
  328: 			}
  329: 			break;
  330: 	}
  331: 
  332: 	return 0;
  333: }

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