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