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