Annotation of ansh/src/daemon3.c, revision 1.1.1.1.2.7

1.1       misho       1: /*************************************************************************
                      2:  * (C) 2011 AITNET - Sofia/Bulgaria - <office@aitnet.org>
                      3:  *  by Michael Pounov <misho@elwix.org>
                      4:  *
                      5:  * $Author: misho $
1.1.1.1.2.7! misho       6:  * $Id: daemon3.c,v 1.1.1.1.2.6 2011/10/13 16:08:52 misho Exp $
1.1       misho       7:  *
1.1.1.1.2.6  misho       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: */
1.1       misho      46: #include "global.h"
                     47: #include "anshd.h"
                     48: 
                     49: 
                     50: void *
                     51: icmpTx(sched_task_t *task)
                     52: {
                     53:        struct tagProc *proc;
                     54:        int wlen;
1.1.1.1.2.1  misho      55:        u_char *str;
1.1       misho      56: 
                     57:        FTRACE(3);
                     58: 
                     59:        /* not found argument, drop data */
                     60:        if (!(proc = TASK_ARG(task)))
                     61:                return (void*) -1;
                     62: 
1.1.1.1.2.1  misho      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: 
1.1.1.1.2.4  misho      71:        if ((wlen = icmpSend(TASK_FD(task), ++proc->proc_seq, proc->proc_id, proc->proc_flg, Crypted, 
                     72:                                        proc->proc_buf_[FD2NET], proc->proc_rlen_[FD2NET], &proc->proc_cli, 
                     73:                                        sizeof proc->proc_cli)) != ANSH_FLG_ERR) {
1.1       misho      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: icmpRx(sched_task_t *task)
                     84: {
1.1.1.1.2.1  misho      85:        u_char *buf, *str;
1.1       misho      86:        struct sockaddr sa;
                     87:        int rlen, n = 0, salen = sizeof sa;
                     88:        struct tagProc *proc = NULL;
                     89:        char ret;
                     90:        u_short id, *b;
1.1.1.1.2.4  misho      91:        u_int seq;
1.1       misho      92: 
                     93:        FTRACE(3);
                     94: 
                     95:        rlen = bpfLEN;
                     96:        if (!(buf = malloc(rlen)))
                     97:                goto end;
1.1.1.1.2.5  misho      98:        else
                     99:                memset(buf, 0, rlen);
1.1       misho     100: 
1.1.1.1.2.4  misho     101:        if ((ret = icmpRecv(TASK_FD(task), &seq, &id, &Crypted, buf, &rlen, &sa, 
                    102:                                        (socklen_t *) &salen)) == ANSH_FLG_ERR)
1.1       misho     103:                goto end;
1.1.1.1.2.4  misho     104:        VERB(5) LOG("Received %d bytes %d", rlen, seq);
1.1       misho     105:        if (!(ret & ANSH_FLG_CPOUT))
                    106:                goto end;
                    107: 
                    108:        /* packet is ok find active session */
                    109:        SLIST_FOREACH(proc, &pH, proc_next)
                    110:                if (proc->proc_id == id) {
                    111:                        n = ANSH_CODE;
                    112:                        break;
                    113:                }
                    114:        /* not found in sessions, drop packet */
                    115:        if (n != ANSH_CODE) {
                    116:                proc = NULL;
                    117:                goto end;
                    118:        }
                    119: 
1.1.1.1.2.1  misho     120:        if (Crypted) {
                    121:                str = cryptBuffer(buf, rlen, Crypted);
                    122:                if (str) {
                    123:                        memcpy(buf, str, rlen);
                    124:                        free(str);
                    125:                }
                    126:        }
                    127: 
1.1       misho     128:        switch (ret) {
                    129:                case ANSH_FLG_EOF:
                    130:                case ANSH_FLG_CPOUT:
1.1.1.1.2.4  misho     131:                        if (seq <= proc->proc_seq)
                    132:                                goto end;
                    133:                        else if (seq > (proc->proc_seq + 1))
                    134:                                LOG("LOST PACKET(s) detect: %d; received seq=%d - %d", 
                    135:                                                seq - proc->proc_seq + 1, seq, proc->proc_seq);
                    136:                        proc->proc_seq = seq;
1.1       misho     137:                        break;
                    138:                case ANSH_FLG_WINZ:
                    139:                        b = (u_short*) buf;
                    140:                        ioChgWinPTY(proc->proc_pty, ntohs(b[0]), ntohs(b[1]), ntohs(b[2]), ntohs(b[3]));
                    141:                        /* if not started login, lets start & go! */
                    142:                        if (!proc->proc_pid) {
                    143:                                memcpy(&proc->proc_cli, &sa, sizeof sa);
                    144:                                spawnLogin(task, proc);
                    145:                        }
                    146:                default:
                    147:                        goto end;
                    148:        }
                    149: 
                    150:        proc->proc_flg = ret;
                    151:        proc->proc_rlen_[NET2FD] = rlen;
                    152:        memset(proc->proc_buf_[NET2FD], 0, proc->proc_blen);
                    153:        memcpy(proc->proc_buf_[NET2FD], buf, proc->proc_rlen_[NET2FD]);
                    154:        schedWrite(TASK_ROOT(task), fdTx, proc, proc->proc_pty);
                    155: end:
                    156:        free(buf);
                    157:        schedRead(TASK_ROOT(task), icmpRx, NULL, proc ? proc->proc_sock : TASK_FD(task));
                    158:        return NULL;
                    159: }
                    160: 
                    161: void *
                    162: fdTx(sched_task_t *task)
                    163: {
                    164:        struct tagProc *proc;
                    165:        struct timeval tv = { 0 };
                    166:        int wlen;
                    167: 
                    168:        FTRACE(3);
                    169: 
                    170:        /* not found argument, drop data */
                    171:        if (!(proc = TASK_ARG(task)))
                    172:                return (void*) -1;
                    173: 
                    174:        /* if != ANSH_FLG_CPOUT isnt received from client */
                    175:        if (proc->proc_flg != ANSH_FLG_CPOUT || !proc->proc_pid)
                    176:                return NULL;
                    177: 
1.1.1.1.2.7! misho     178:        /*
1.1       misho     179:        if (waitpid(proc->proc_pid, &wlen, WNOHANG)) {
                    180:                ioFreePTY(TASK_FD(task), proc->proc_ttyname);
                    181:                schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
                    182: 
                    183:                proc->proc_pid = 0;
1.1.1.1.2.4  misho     184:                proc->proc_seq = 0;
1.1       misho     185:                proc->proc_flg = ANSH_FLG_EOF;
                    186:                proc->proc_rlen_[FD2NET] = 0;
                    187: 
                    188:                schedWrite(TASK_ROOT(task), icmpTx, proc, proc->proc_sock);
                    189:                return NULL;
                    190:        }
1.1.1.1.2.7! misho     191:        */
1.1       misho     192: 
                    193:        /* if Timeout defined, disarm timer */
                    194:        if (Timeout)
                    195:                schedCancelby(TASK_ROOT(task), &TASK_ROOT(task)->root_timer, CRITERIA_CALL, TOfunc, NULL);
                    196: 
                    197:        wlen = write(TASK_FD(task), proc->proc_buf_[NET2FD], proc->proc_rlen_[NET2FD]);
                    198:        switch (wlen) {
                    199:                case -1:
                    200:                        ERR("write2tty #%d - %s", errno, strerror(errno));
                    201:                        /* exit from shell and release tty */
1.1.1.1.2.7! misho     202:                        /*
1.1       misho     203:                        waitpid(proc->proc_pid, &wlen, 0);
                    204:                        ioFreePTY(TASK_FD(task), proc->proc_ttyname);
                    205:                        schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
                    206: 
                    207:                        proc->proc_pid = 0;
1.1.1.1.2.4  misho     208:                        proc->proc_seq = 0;
1.1       misho     209:                        proc->proc_flg = ANSH_FLG_EOF;
                    210:                        proc->proc_rlen_[FD2NET] = 0;
                    211: 
                    212:                        schedWrite(TASK_ROOT(task), icmpTx, proc, proc->proc_sock);
1.1.1.1.2.7! misho     213:                        */
1.1       misho     214:                        return NULL;
                    215:                default:
                    216:                        proc->proc_flg = ANSH_FLG_OK;
                    217:                        proc->proc_rlen_[NET2FD] = 0;
                    218:        }
                    219:        VERB(3) LOG("Writed %d bytes - %s", wlen, proc->proc_buf_[NET2FD]);
                    220: 
                    221:        /* if Timeout defined, go arm timer */
                    222:        if (Timeout) {
                    223:                tv.tv_sec = Timeout;
                    224:                schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
                    225:        }
                    226:        return NULL;
                    227: }
                    228: 
                    229: void *
                    230: fdRx(sched_task_t *task)
                    231: {
                    232:        struct tagProc *proc;
                    233:        struct timeval tv = { 0 };
                    234:        int rlen;
                    235: 
                    236:        FTRACE(3);
                    237: 
                    238:        /* not found argument, drop data */
                    239:        if (!(proc = TASK_ARG(task)))
                    240:                return (void*) -1;
                    241:        if (!proc->proc_pid)
                    242:                return NULL;
                    243: 
1.1.1.1.2.7! misho     244:        /*
1.1       misho     245:        if (waitpid(proc->proc_pid, &rlen, WNOHANG)) {
                    246:                ioFreePTY(TASK_FD(task), proc->proc_ttyname);
                    247:                schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
                    248: 
                    249:                proc->proc_pid = 0;
1.1.1.1.2.4  misho     250:                proc->proc_seq = 0;
1.1       misho     251:                proc->proc_flg = ANSH_FLG_EOF;
                    252:                proc->proc_rlen_[FD2NET] = 0;
                    253: 
                    254:                schedWrite(TASK_ROOT(task), icmpTx, proc, proc->proc_sock);
                    255:                return NULL;
                    256:        }
1.1.1.1.2.7! misho     257:        */
1.1       misho     258: 
                    259:        /* if Timeout defined, disarm timer */
                    260:        if (Timeout)
                    261:                schedCancelby(TASK_ROOT(task), &TASK_ROOT(task)->root_timer, CRITERIA_CALL, TOfunc, NULL);
                    262: 
                    263:        memset(proc->proc_buf_[FD2NET], 0, proc->proc_blen);
1.1.1.1.2.3  misho     264:        rlen = read(TASK_FD(task), proc->proc_buf_[FD2NET], 
                    265:                        proc->proc_blen - sizeof(struct icmp) + sizeof(struct ansh_hdr));
1.1       misho     266:        switch (rlen) {
                    267:                case -1:
                    268:                        ERR("readtty #%d - %s", errno, strerror(errno));
                    269:                case 0:
                    270:                        /* exit from shell and release tty */
1.1.1.1.2.7! misho     271:                        /*
1.1       misho     272:                        waitpid(proc->proc_pid, &rlen, 0);
                    273:                        ioFreePTY(TASK_FD(task), proc->proc_ttyname);
                    274:                        schedCancelby(TASK_ROOT(task), NULL, CRITERIA_FD, (void*) TASK_FD(task), NULL);
                    275:                        VERB(3) LOG("EOF process status %d", rlen);
                    276: 
                    277:                        proc->proc_pid = 0;
1.1.1.1.2.4  misho     278:                        proc->proc_seq = 0;
1.1       misho     279:                        proc->proc_flg = ANSH_FLG_EOF;
                    280:                        proc->proc_rlen_[FD2NET] = 0;
                    281: 
                    282:                        schedWrite(TASK_ROOT(task), icmpTx, proc, proc->proc_sock);
1.1.1.1.2.7! misho     283:                        */
1.1       misho     284:                        return NULL;
                    285:                default:
                    286:                        proc->proc_flg = ANSH_FLG_OK;
                    287:                        proc->proc_rlen_[FD2NET] = rlen;
                    288:        }
                    289:        VERB(3) LOG("Readed %d bytes - %s", rlen, proc->proc_buf_[FD2NET]);
                    290: 
                    291:        schedWrite(TASK_ROOT(task), icmpTx, proc, proc->proc_sock);
                    292:        schedRead(TASK_ROOT(task), fdRx, proc, proc->proc_pty);
                    293: 
                    294:        /* if Timeout defined, go arm timer */
                    295:        if (Timeout) {
                    296:                tv.tv_sec = Timeout;
                    297:                schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
                    298:        }
                    299:        return NULL;
                    300: }
                    301: 
                    302: int
                    303: spawnLogin(sched_task_t *task, struct tagProc *proc)
                    304: {
                    305:        int flg;
                    306:        struct timeval tv = { 0 };
                    307:        char str[STRSIZ] = { 0 };
                    308:        struct sockaddr_in *sin;
                    309:        struct sockaddr_in6 *sin6;
                    310: 
                    311:        FTRACE(3);
                    312: 
                    313:        assert(proc);
                    314: 
                    315:        switch ((proc->proc_pid = ioForkPTY(&proc->proc_pty, proc->proc_ttyname, 
                    316:                                        sizeof proc->proc_ttyname, NULL, NULL, NULL))) {
                    317:                case -1:
                    318:                        ERR("ioForkPTY() #%d - %s", io_GetErrno(), io_GetError());
                    319:                        return -1;
                    320:                case 0:
                    321:                        printf("ansh3d ELWIX remote management system over ICMP (%s)\n\n", 
                    322:                                        proc->proc_ttyname);
                    323:                        strlcpy(str, "-hansh3@", sizeof str);
                    324:                        if (proc->proc_cli.sa_family == AF_INET) {
                    325:                                sin = (struct sockaddr_in*) &proc->proc_cli;
                    326:                                inet_ntop(AF_INET, &sin->sin_addr, str + 8, INET_ADDRSTRLEN);
1.1.1.1.2.2  misho     327:                        } else if (proc->proc_cli.sa_family == AF_INET6) {
1.1       misho     328:                                sin6 = (struct sockaddr_in6*) &proc->proc_cli;
                    329:                                inet_ntop(AF_INET6, &sin6->sin6_addr, str + 8, INET6_ADDRSTRLEN);
                    330:                        }
                    331:                        execl("/usr/bin/login", "login", str, NULL);
                    332:                        /* never reached */
                    333:                        return -1;
                    334:                default:
                    335:                        flg = fcntl(proc->proc_pty, F_GETFL);
                    336:                        fcntl(proc->proc_pty, F_SETFL, flg | O_NONBLOCK);
                    337: 
                    338:                        VERB(3) LOG("Parent know child pid %d", proc->proc_pid);
                    339:                        schedRead(TASK_ROOT(task), fdRx, proc, proc->proc_pty);
                    340: 
                    341:                        /* if Timeout defined, go arm timer */
                    342:                        if (Timeout) {
                    343:                                tv.tv_sec = Timeout;
                    344:                                schedTimer(TASK_ROOT(task), TOfunc, proc, tv);
                    345:                        }
                    346:                        break;
                    347:        }
                    348: 
                    349:        return 0;
                    350: }

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