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>