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