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