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