|
1 /* |
|
2 * Copyright (c) 1995 Danny Gasparovski. |
|
3 * |
|
4 * Please read the file COPYRIGHT for the |
|
5 * terms and conditions of the copyright. |
|
6 */ |
|
7 |
|
8 #define WANT_SYS_IOCTL_H |
|
9 #include <slirp.h> |
|
10 |
|
11 u_int curtime, time_fasttimo, last_slowtimo; |
|
12 |
|
13 #if 0 |
|
14 int x_port = -1; |
|
15 int x_display = 0; |
|
16 int x_screen = 0; |
|
17 |
|
18 int |
|
19 show_x(buff, inso) |
|
20 char *buff; |
|
21 struct socket *inso; |
|
22 { |
|
23 if (x_port < 0) { |
|
24 lprint("X Redir: X not being redirected.\r\n"); |
|
25 } else { |
|
26 lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n", |
|
27 inet_ntoa(our_addr), x_port, x_screen); |
|
28 lprint("X Redir: In csh/tcsh/etc. type: setenv DISPLAY %s:%d.%d\r\n", |
|
29 inet_ntoa(our_addr), x_port, x_screen); |
|
30 if (x_display) |
|
31 lprint("X Redir: Redirecting to display %d\r\n", x_display); |
|
32 } |
|
33 |
|
34 return CFG_OK; |
|
35 } |
|
36 |
|
37 |
|
38 /* |
|
39 * XXX Allow more than one X redirection? |
|
40 */ |
|
41 void |
|
42 redir_x(inaddr, start_port, display, screen) |
|
43 u_int32_t inaddr; |
|
44 int start_port; |
|
45 int display; |
|
46 int screen; |
|
47 { |
|
48 int i; |
|
49 |
|
50 if (x_port >= 0) { |
|
51 lprint("X Redir: X already being redirected.\r\n"); |
|
52 show_x(0, 0); |
|
53 } else { |
|
54 for (i = 6001 + (start_port-1); i <= 6100; i++) { |
|
55 if (solisten(htons(i), inaddr, htons(6000 + display), 0)) { |
|
56 /* Success */ |
|
57 x_port = i - 6000; |
|
58 x_display = display; |
|
59 x_screen = screen; |
|
60 show_x(0, 0); |
|
61 return; |
|
62 } |
|
63 } |
|
64 lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n"); |
|
65 } |
|
66 } |
|
67 #endif |
|
68 |
|
69 /* |
|
70 * Get our IP address and put it in our_addr |
|
71 */ |
|
72 void |
|
73 getouraddr() |
|
74 { |
|
75 char buff[256]; |
|
76 struct hostent *he = NULL; |
|
77 |
|
78 if (gethostname(buff,256) == 0) |
|
79 he = gethostbyname(buff); |
|
80 if (he) |
|
81 our_addr = *(struct in_addr *)he->h_addr; |
|
82 if (our_addr.s_addr == 0) |
|
83 our_addr.s_addr = loopback_addr.s_addr; |
|
84 } |
|
85 |
|
86 #if SIZEOF_CHAR_P == 8 |
|
87 |
|
88 struct quehead_32 { |
|
89 u_int32_t qh_link; |
|
90 u_int32_t qh_rlink; |
|
91 }; |
|
92 |
|
93 inline void |
|
94 insque_32(a, b) |
|
95 void *a; |
|
96 void *b; |
|
97 { |
|
98 register struct quehead_32 *element = (struct quehead_32 *) a; |
|
99 register struct quehead_32 *head = (struct quehead_32 *) b; |
|
100 element->qh_link = head->qh_link; |
|
101 head->qh_link = (u_int32_t)element; |
|
102 element->qh_rlink = (u_int32_t)head; |
|
103 ((struct quehead_32 *)(element->qh_link))->qh_rlink |
|
104 = (u_int32_t)element; |
|
105 } |
|
106 |
|
107 inline void |
|
108 remque_32(a) |
|
109 void *a; |
|
110 { |
|
111 register struct quehead_32 *element = (struct quehead_32 *) a; |
|
112 ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink; |
|
113 ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link; |
|
114 element->qh_rlink = 0; |
|
115 } |
|
116 |
|
117 #endif /* SIZEOF_CHAR_P == 8 */ |
|
118 |
|
119 struct quehead { |
|
120 struct quehead *qh_link; |
|
121 struct quehead *qh_rlink; |
|
122 }; |
|
123 |
|
124 inline void |
|
125 insque(a, b) |
|
126 void *a, *b; |
|
127 { |
|
128 register struct quehead *element = (struct quehead *) a; |
|
129 register struct quehead *head = (struct quehead *) b; |
|
130 element->qh_link = head->qh_link; |
|
131 head->qh_link = (struct quehead *)element; |
|
132 element->qh_rlink = (struct quehead *)head; |
|
133 ((struct quehead *)(element->qh_link))->qh_rlink |
|
134 = (struct quehead *)element; |
|
135 } |
|
136 |
|
137 inline void |
|
138 remque(a) |
|
139 void *a; |
|
140 { |
|
141 register struct quehead *element = (struct quehead *) a; |
|
142 ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; |
|
143 ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link; |
|
144 element->qh_rlink = NULL; |
|
145 /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */ |
|
146 } |
|
147 |
|
148 /* #endif */ |
|
149 |
|
150 |
|
151 int |
|
152 add_exec(ex_ptr, do_pty, exec, addr, port) |
|
153 struct ex_list **ex_ptr; |
|
154 int do_pty; |
|
155 char *exec; |
|
156 int addr; |
|
157 int port; |
|
158 { |
|
159 struct ex_list *tmp_ptr; |
|
160 |
|
161 /* First, check if the port is "bound" */ |
|
162 for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) { |
|
163 if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr) |
|
164 return -1; |
|
165 } |
|
166 |
|
167 tmp_ptr = *ex_ptr; |
|
168 *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list)); |
|
169 (*ex_ptr)->ex_fport = port; |
|
170 (*ex_ptr)->ex_addr = addr; |
|
171 (*ex_ptr)->ex_pty = do_pty; |
|
172 (*ex_ptr)->ex_exec = strdup(exec); |
|
173 (*ex_ptr)->ex_next = tmp_ptr; |
|
174 return 0; |
|
175 } |
|
176 |
|
177 #ifndef HAVE_STRERROR |
|
178 |
|
179 /* |
|
180 * For systems with no strerror |
|
181 */ |
|
182 |
|
183 extern int sys_nerr; |
|
184 extern char *sys_errlist[]; |
|
185 |
|
186 char * |
|
187 strerror(error) |
|
188 int error; |
|
189 { |
|
190 if (error < sys_nerr) |
|
191 return sys_errlist[error]; |
|
192 else |
|
193 return "Unknown error."; |
|
194 } |
|
195 |
|
196 #endif |
|
197 |
|
198 |
|
199 #ifdef _WIN32 |
|
200 |
|
201 int |
|
202 fork_exec(struct socket *so, const char *ex, int do_pty) |
|
203 { |
|
204 /* not implemented */ |
|
205 return 0; |
|
206 } |
|
207 |
|
208 #else |
|
209 |
|
210 #ifndef CONFIG_QEMU |
|
211 int |
|
212 slirp_openpty(amaster, aslave) |
|
213 int *amaster, *aslave; |
|
214 { |
|
215 register int master, slave; |
|
216 |
|
217 #ifdef HAVE_GRANTPT |
|
218 char *ptr; |
|
219 |
|
220 if ((master = open("/dev/ptmx", O_RDWR)) < 0 || |
|
221 grantpt(master) < 0 || |
|
222 unlockpt(master) < 0 || |
|
223 (ptr = ptsname(master)) == NULL) { |
|
224 close(master); |
|
225 return -1; |
|
226 } |
|
227 |
|
228 if ((slave = open(ptr, O_RDWR)) < 0 || |
|
229 ioctl(slave, I_PUSH, "ptem") < 0 || |
|
230 ioctl(slave, I_PUSH, "ldterm") < 0 || |
|
231 ioctl(slave, I_PUSH, "ttcompat") < 0) { |
|
232 close(master); |
|
233 close(slave); |
|
234 return -1; |
|
235 } |
|
236 |
|
237 *amaster = master; |
|
238 *aslave = slave; |
|
239 return 0; |
|
240 |
|
241 #else |
|
242 |
|
243 static char line[] = "/dev/ptyXX"; |
|
244 register const char *cp1, *cp2; |
|
245 |
|
246 for (cp1 = "pqrsPQRS"; *cp1; cp1++) { |
|
247 line[8] = *cp1; |
|
248 for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) { |
|
249 line[9] = *cp2; |
|
250 if ((master = open(line, O_RDWR, 0)) == -1) { |
|
251 if (errno == ENOENT) |
|
252 return (-1); /* out of ptys */ |
|
253 } else { |
|
254 line[5] = 't'; |
|
255 /* These will fail */ |
|
256 (void) chown(line, getuid(), 0); |
|
257 (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP); |
|
258 #ifdef HAVE_REVOKE |
|
259 (void) revoke(line); |
|
260 #endif |
|
261 if ((slave = open(line, O_RDWR, 0)) != -1) { |
|
262 *amaster = master; |
|
263 *aslave = slave; |
|
264 return 0; |
|
265 } |
|
266 (void) close(master); |
|
267 line[5] = 'p'; |
|
268 } |
|
269 } |
|
270 } |
|
271 errno = ENOENT; /* out of ptys */ |
|
272 return (-1); |
|
273 #endif |
|
274 } |
|
275 #endif |
|
276 |
|
277 /* |
|
278 * XXX This is ugly |
|
279 * We create and bind a socket, then fork off to another |
|
280 * process, which connects to this socket, after which we |
|
281 * exec the wanted program. If something (strange) happens, |
|
282 * the accept() call could block us forever. |
|
283 * |
|
284 * do_pty = 0 Fork/exec inetd style |
|
285 * do_pty = 1 Fork/exec using slirp.telnetd |
|
286 * do_ptr = 2 Fork/exec using pty |
|
287 */ |
|
288 int |
|
289 fork_exec(struct socket *so, const char *ex, int do_pty) |
|
290 { |
|
291 int s; |
|
292 struct sockaddr_in addr; |
|
293 socklen_t addrlen = sizeof(addr); |
|
294 int opt; |
|
295 int master = -1; |
|
296 const char *argv[256]; |
|
297 #if 0 |
|
298 char buff[256]; |
|
299 #endif |
|
300 /* don't want to clobber the original */ |
|
301 char *bptr; |
|
302 const char *curarg; |
|
303 int c, i, ret; |
|
304 |
|
305 DEBUG_CALL("fork_exec"); |
|
306 DEBUG_ARG("so = %lx", (long)so); |
|
307 DEBUG_ARG("ex = %lx", (long)ex); |
|
308 DEBUG_ARG("do_pty = %lx", (long)do_pty); |
|
309 |
|
310 if (do_pty == 2) { |
|
311 #if 0 |
|
312 if (slirp_openpty(&master, &s) == -1) { |
|
313 lprint("Error: openpty failed: %s\n", strerror(errno)); |
|
314 return 0; |
|
315 } |
|
316 #else |
|
317 return 0; |
|
318 #endif |
|
319 } else { |
|
320 addr.sin_family = AF_INET; |
|
321 addr.sin_port = 0; |
|
322 addr.sin_addr.s_addr = INADDR_ANY; |
|
323 |
|
324 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 || |
|
325 bind(s, (struct sockaddr *)&addr, addrlen) < 0 || |
|
326 listen(s, 1) < 0) { |
|
327 lprint("Error: inet socket: %s\n", strerror(errno)); |
|
328 closesocket(s); |
|
329 |
|
330 return 0; |
|
331 } |
|
332 } |
|
333 |
|
334 switch(fork()) { |
|
335 case -1: |
|
336 lprint("Error: fork failed: %s\n", strerror(errno)); |
|
337 close(s); |
|
338 if (do_pty == 2) |
|
339 close(master); |
|
340 return 0; |
|
341 |
|
342 case 0: |
|
343 /* Set the DISPLAY */ |
|
344 if (do_pty == 2) { |
|
345 (void) close(master); |
|
346 #ifdef TIOCSCTTY /* XXXXX */ |
|
347 (void) setsid(); |
|
348 ioctl(s, TIOCSCTTY, (char *)NULL); |
|
349 #endif |
|
350 } else { |
|
351 getsockname(s, (struct sockaddr *)&addr, &addrlen); |
|
352 close(s); |
|
353 /* |
|
354 * Connect to the socket |
|
355 * XXX If any of these fail, we're in trouble! |
|
356 */ |
|
357 s = socket(AF_INET, SOCK_STREAM, 0); |
|
358 addr.sin_addr = loopback_addr; |
|
359 do { |
|
360 ret = connect(s, (struct sockaddr *)&addr, addrlen); |
|
361 } while (ret < 0 && errno == EINTR); |
|
362 } |
|
363 |
|
364 #if 0 |
|
365 if (x_port >= 0) { |
|
366 #ifdef HAVE_SETENV |
|
367 sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); |
|
368 setenv("DISPLAY", buff, 1); |
|
369 #else |
|
370 sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); |
|
371 putenv(buff); |
|
372 #endif |
|
373 } |
|
374 #endif |
|
375 dup2(s, 0); |
|
376 dup2(s, 1); |
|
377 dup2(s, 2); |
|
378 for (s = getdtablesize() - 1; s >= 3; s--) |
|
379 close(s); |
|
380 |
|
381 i = 0; |
|
382 bptr = strdup(ex); /* No need to free() this */ |
|
383 if (do_pty == 1) { |
|
384 /* Setup "slirp.telnetd -x" */ |
|
385 argv[i++] = "slirp.telnetd"; |
|
386 argv[i++] = "-x"; |
|
387 argv[i++] = bptr; |
|
388 } else |
|
389 do { |
|
390 /* Change the string into argv[] */ |
|
391 curarg = bptr; |
|
392 while (*bptr != ' ' && *bptr != (char)0) |
|
393 bptr++; |
|
394 c = *bptr; |
|
395 *bptr++ = (char)0; |
|
396 argv[i++] = strdup(curarg); |
|
397 } while (c); |
|
398 |
|
399 argv[i] = 0; |
|
400 execvp(argv[0], (char **)argv); |
|
401 |
|
402 /* Ooops, failed, let's tell the user why */ |
|
403 { |
|
404 char buff[256]; |
|
405 |
|
406 snprintf(buff, sizeof(buff), |
|
407 "Error: execvp of %s failed: %s\n", |
|
408 argv[0], strerror(errno)); |
|
409 write(2, buff, strlen(buff)+1); |
|
410 } |
|
411 close(0); close(1); close(2); /* XXX */ |
|
412 exit(1); |
|
413 |
|
414 default: |
|
415 if (do_pty == 2) { |
|
416 close(s); |
|
417 so->s = master; |
|
418 } else { |
|
419 /* |
|
420 * XXX this could block us... |
|
421 * XXX Should set a timer here, and if accept() doesn't |
|
422 * return after X seconds, declare it a failure |
|
423 * The only reason this will block forever is if socket() |
|
424 * of connect() fail in the child process |
|
425 */ |
|
426 do { |
|
427 so->s = accept(s, (struct sockaddr *)&addr, &addrlen); |
|
428 } while (so->s < 0 && errno == EINTR); |
|
429 closesocket(s); |
|
430 opt = 1; |
|
431 setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); |
|
432 opt = 1; |
|
433 setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); |
|
434 } |
|
435 fd_nonblock(so->s); |
|
436 |
|
437 /* Append the telnet options now */ |
|
438 if (so->so_m != 0 && do_pty == 1) { |
|
439 sbappend(so, so->so_m); |
|
440 so->so_m = 0; |
|
441 } |
|
442 |
|
443 return 1; |
|
444 } |
|
445 } |
|
446 #endif |
|
447 |
|
448 #ifndef HAVE_STRDUP |
|
449 char * |
|
450 strdup(str) |
|
451 const char *str; |
|
452 { |
|
453 char *bptr; |
|
454 |
|
455 bptr = (char *)malloc(strlen(str)+1); |
|
456 strcpy(bptr, str); |
|
457 |
|
458 return bptr; |
|
459 } |
|
460 #endif |
|
461 |
|
462 #if 0 |
|
463 void |
|
464 snooze_hup(num) |
|
465 int num; |
|
466 { |
|
467 int s, ret; |
|
468 #ifndef NO_UNIX_SOCKETS |
|
469 struct sockaddr_un sock_un; |
|
470 #endif |
|
471 struct sockaddr_in sock_in; |
|
472 char buff[256]; |
|
473 |
|
474 ret = -1; |
|
475 if (slirp_socket_passwd) { |
|
476 s = socket(AF_INET, SOCK_STREAM, 0); |
|
477 if (s < 0) |
|
478 slirp_exit(1); |
|
479 sock_in.sin_family = AF_INET; |
|
480 sock_in.sin_addr.s_addr = slirp_socket_addr; |
|
481 sock_in.sin_port = htons(slirp_socket_port); |
|
482 if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0) |
|
483 slirp_exit(1); /* just exit...*/ |
|
484 sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit); |
|
485 write(s, buff, strlen(buff)+1); |
|
486 } |
|
487 #ifndef NO_UNIX_SOCKETS |
|
488 else { |
|
489 s = socket(AF_UNIX, SOCK_STREAM, 0); |
|
490 if (s < 0) |
|
491 slirp_exit(1); |
|
492 sock_un.sun_family = AF_UNIX; |
|
493 strcpy(sock_un.sun_path, socket_path); |
|
494 if (connect(s, (struct sockaddr *)&sock_un, |
|
495 sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0) |
|
496 slirp_exit(1); |
|
497 sprintf(buff, "kill none:%d", slirp_socket_unit); |
|
498 write(s, buff, strlen(buff)+1); |
|
499 } |
|
500 #endif |
|
501 slirp_exit(0); |
|
502 } |
|
503 |
|
504 |
|
505 void |
|
506 snooze() |
|
507 { |
|
508 sigset_t s; |
|
509 int i; |
|
510 |
|
511 /* Don't need our data anymore */ |
|
512 /* XXX This makes SunOS barf */ |
|
513 /* brk(0); */ |
|
514 |
|
515 /* Close all fd's */ |
|
516 for (i = 255; i >= 0; i--) |
|
517 close(i); |
|
518 |
|
519 signal(SIGQUIT, slirp_exit); |
|
520 signal(SIGHUP, snooze_hup); |
|
521 sigemptyset(&s); |
|
522 |
|
523 /* Wait for any signal */ |
|
524 sigsuspend(&s); |
|
525 |
|
526 /* Just in case ... */ |
|
527 exit(255); |
|
528 } |
|
529 |
|
530 void |
|
531 relay(s) |
|
532 int s; |
|
533 { |
|
534 char buf[8192]; |
|
535 int n; |
|
536 fd_set readfds; |
|
537 struct ttys *ttyp; |
|
538 |
|
539 /* Don't need our data anymore */ |
|
540 /* XXX This makes SunOS barf */ |
|
541 /* brk(0); */ |
|
542 |
|
543 signal(SIGQUIT, slirp_exit); |
|
544 signal(SIGHUP, slirp_exit); |
|
545 signal(SIGINT, slirp_exit); |
|
546 signal(SIGTERM, slirp_exit); |
|
547 |
|
548 /* Fudge to get term_raw and term_restore to work */ |
|
549 if (NULL == (ttyp = tty_attach (0, slirp_tty))) { |
|
550 lprint ("Error: tty_attach failed in misc.c:relay()\r\n"); |
|
551 slirp_exit (1); |
|
552 } |
|
553 ttyp->fd = 0; |
|
554 ttyp->flags |= TTY_CTTY; |
|
555 term_raw(ttyp); |
|
556 |
|
557 while (1) { |
|
558 FD_ZERO(&readfds); |
|
559 |
|
560 FD_SET(0, &readfds); |
|
561 FD_SET(s, &readfds); |
|
562 |
|
563 n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0); |
|
564 |
|
565 if (n <= 0) |
|
566 slirp_exit(0); |
|
567 |
|
568 if (FD_ISSET(0, &readfds)) { |
|
569 n = read(0, buf, 8192); |
|
570 if (n <= 0) |
|
571 slirp_exit(0); |
|
572 n = writen(s, buf, n); |
|
573 if (n <= 0) |
|
574 slirp_exit(0); |
|
575 } |
|
576 |
|
577 if (FD_ISSET(s, &readfds)) { |
|
578 n = read(s, buf, 8192); |
|
579 if (n <= 0) |
|
580 slirp_exit(0); |
|
581 n = writen(0, buf, n); |
|
582 if (n <= 0) |
|
583 slirp_exit(0); |
|
584 } |
|
585 } |
|
586 |
|
587 /* Just in case.... */ |
|
588 exit(1); |
|
589 } |
|
590 #endif |
|
591 |
|
592 #ifdef CONFIG_QEMU |
|
593 extern void term_vprintf(const char *fmt, va_list ap); |
|
594 |
|
595 void lprint(const char *format, ...) |
|
596 { |
|
597 va_list args; |
|
598 |
|
599 va_start(args, format); |
|
600 term_vprintf(format, args); |
|
601 va_end(args); |
|
602 } |
|
603 #else |
|
604 int (*lprint_print) _P((void *, const char *, va_list)); |
|
605 char *lprint_ptr, *lprint_ptr2, **lprint_arg; |
|
606 |
|
607 void |
|
608 #ifdef __STDC__ |
|
609 lprint(const char *format, ...) |
|
610 #else |
|
611 lprint(va_alist) va_dcl |
|
612 #endif |
|
613 { |
|
614 va_list args; |
|
615 |
|
616 #ifdef __STDC__ |
|
617 va_start(args, format); |
|
618 #else |
|
619 char *format; |
|
620 va_start(args); |
|
621 format = va_arg(args, char *); |
|
622 #endif |
|
623 #if 0 |
|
624 /* If we're printing to an sbuf, make sure there's enough room */ |
|
625 /* XXX +100? */ |
|
626 if (lprint_sb) { |
|
627 if ((lprint_ptr - lprint_sb->sb_wptr) >= |
|
628 (lprint_sb->sb_datalen - (strlen(format) + 100))) { |
|
629 int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data; |
|
630 int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data; |
|
631 int deltap = lprint_ptr - lprint_sb->sb_data; |
|
632 |
|
633 lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data, |
|
634 lprint_sb->sb_datalen + TCP_SNDSPACE); |
|
635 |
|
636 /* Adjust all values */ |
|
637 lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw; |
|
638 lprint_sb->sb_rptr = lprint_sb->sb_data + deltar; |
|
639 lprint_ptr = lprint_sb->sb_data + deltap; |
|
640 |
|
641 lprint_sb->sb_datalen += TCP_SNDSPACE; |
|
642 } |
|
643 } |
|
644 #endif |
|
645 if (lprint_print) |
|
646 lprint_ptr += (*lprint_print)(*lprint_arg, format, args); |
|
647 |
|
648 /* Check if they want output to be logged to file as well */ |
|
649 if (lfd) { |
|
650 /* |
|
651 * Remove \r's |
|
652 * otherwise you'll get ^M all over the file |
|
653 */ |
|
654 int len = strlen(format); |
|
655 char *bptr1, *bptr2; |
|
656 |
|
657 bptr1 = bptr2 = strdup(format); |
|
658 |
|
659 while (len--) { |
|
660 if (*bptr1 == '\r') |
|
661 memcpy(bptr1, bptr1+1, len+1); |
|
662 else |
|
663 bptr1++; |
|
664 } |
|
665 vfprintf(lfd, bptr2, args); |
|
666 free(bptr2); |
|
667 } |
|
668 va_end(args); |
|
669 } |
|
670 |
|
671 void |
|
672 add_emu(buff) |
|
673 char *buff; |
|
674 { |
|
675 u_int lport, fport; |
|
676 u_int8_t tos = 0, emu = 0; |
|
677 char buff1[256], buff2[256], buff4[128]; |
|
678 char *buff3 = buff4; |
|
679 struct emu_t *emup; |
|
680 struct socket *so; |
|
681 |
|
682 if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) { |
|
683 lprint("Error: Bad arguments\r\n"); |
|
684 return; |
|
685 } |
|
686 |
|
687 if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) { |
|
688 lport = 0; |
|
689 if (sscanf(buff1, "%d", &fport) != 1) { |
|
690 lprint("Error: Bad first argument\r\n"); |
|
691 return; |
|
692 } |
|
693 } |
|
694 |
|
695 if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) { |
|
696 buff3 = 0; |
|
697 if (sscanf(buff2, "%256s", buff1) != 1) { |
|
698 lprint("Error: Bad second argument\r\n"); |
|
699 return; |
|
700 } |
|
701 } |
|
702 |
|
703 if (buff3) { |
|
704 if (strcmp(buff3, "lowdelay") == 0) |
|
705 tos = IPTOS_LOWDELAY; |
|
706 else if (strcmp(buff3, "throughput") == 0) |
|
707 tos = IPTOS_THROUGHPUT; |
|
708 else { |
|
709 lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n"); |
|
710 return; |
|
711 } |
|
712 } |
|
713 |
|
714 if (strcmp(buff1, "ftp") == 0) |
|
715 emu = EMU_FTP; |
|
716 else if (strcmp(buff1, "irc") == 0) |
|
717 emu = EMU_IRC; |
|
718 else if (strcmp(buff1, "none") == 0) |
|
719 emu = EMU_NONE; /* ie: no emulation */ |
|
720 else { |
|
721 lprint("Error: Unknown service\r\n"); |
|
722 return; |
|
723 } |
|
724 |
|
725 /* First, check that it isn't already emulated */ |
|
726 for (emup = tcpemu; emup; emup = emup->next) { |
|
727 if (emup->lport == lport && emup->fport == fport) { |
|
728 lprint("Error: port already emulated\r\n"); |
|
729 return; |
|
730 } |
|
731 } |
|
732 |
|
733 /* link it */ |
|
734 emup = (struct emu_t *)malloc(sizeof (struct emu_t)); |
|
735 emup->lport = (u_int16_t)lport; |
|
736 emup->fport = (u_int16_t)fport; |
|
737 emup->tos = tos; |
|
738 emup->emu = emu; |
|
739 emup->next = tcpemu; |
|
740 tcpemu = emup; |
|
741 |
|
742 /* And finally, mark all current sessions, if any, as being emulated */ |
|
743 for (so = tcb.so_next; so != &tcb; so = so->so_next) { |
|
744 if ((lport && lport == ntohs(so->so_lport)) || |
|
745 (fport && fport == ntohs(so->so_fport))) { |
|
746 if (emu) |
|
747 so->so_emu = emu; |
|
748 if (tos) |
|
749 so->so_iptos = tos; |
|
750 } |
|
751 } |
|
752 |
|
753 lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport); |
|
754 } |
|
755 #endif |
|
756 |
|
757 #ifdef BAD_SPRINTF |
|
758 |
|
759 #undef vsprintf |
|
760 #undef sprintf |
|
761 |
|
762 /* |
|
763 * Some BSD-derived systems have a sprintf which returns char * |
|
764 */ |
|
765 |
|
766 int |
|
767 vsprintf_len(string, format, args) |
|
768 char *string; |
|
769 const char *format; |
|
770 va_list args; |
|
771 { |
|
772 vsprintf(string, format, args); |
|
773 return strlen(string); |
|
774 } |
|
775 |
|
776 int |
|
777 #ifdef __STDC__ |
|
778 sprintf_len(char *string, const char *format, ...) |
|
779 #else |
|
780 sprintf_len(va_alist) va_dcl |
|
781 #endif |
|
782 { |
|
783 va_list args; |
|
784 #ifdef __STDC__ |
|
785 va_start(args, format); |
|
786 #else |
|
787 char *string; |
|
788 char *format; |
|
789 va_start(args); |
|
790 string = va_arg(args, char *); |
|
791 format = va_arg(args, char *); |
|
792 #endif |
|
793 vsprintf(string, format, args); |
|
794 return strlen(string); |
|
795 } |
|
796 |
|
797 #endif |
|
798 |
|
799 void |
|
800 u_sleep(usec) |
|
801 int usec; |
|
802 { |
|
803 struct timeval t; |
|
804 fd_set fdset; |
|
805 |
|
806 FD_ZERO(&fdset); |
|
807 |
|
808 t.tv_sec = 0; |
|
809 t.tv_usec = usec * 1000; |
|
810 |
|
811 select(0, &fdset, &fdset, &fdset, &t); |
|
812 } |
|
813 |
|
814 /* |
|
815 * Set fd blocking and non-blocking |
|
816 */ |
|
817 |
|
818 void |
|
819 fd_nonblock(fd) |
|
820 int fd; |
|
821 { |
|
822 #ifdef FIONBIO |
|
823 int opt = 1; |
|
824 |
|
825 ioctlsocket(fd, FIONBIO, &opt); |
|
826 #else |
|
827 int opt; |
|
828 |
|
829 opt = fcntl(fd, F_GETFL, 0); |
|
830 opt |= O_NONBLOCK; |
|
831 fcntl(fd, F_SETFL, opt); |
|
832 #endif |
|
833 } |
|
834 |
|
835 void |
|
836 fd_block(fd) |
|
837 int fd; |
|
838 { |
|
839 #ifdef FIONBIO |
|
840 int opt = 0; |
|
841 |
|
842 ioctlsocket(fd, FIONBIO, &opt); |
|
843 #else |
|
844 int opt; |
|
845 |
|
846 opt = fcntl(fd, F_GETFL, 0); |
|
847 opt &= ~O_NONBLOCK; |
|
848 fcntl(fd, F_SETFL, opt); |
|
849 #endif |
|
850 } |
|
851 |
|
852 |
|
853 #if 0 |
|
854 /* |
|
855 * invoke RSH |
|
856 */ |
|
857 int |
|
858 rsh_exec(so,ns, user, host, args) |
|
859 struct socket *so; |
|
860 struct socket *ns; |
|
861 char *user; |
|
862 char *host; |
|
863 char *args; |
|
864 { |
|
865 int fd[2]; |
|
866 int fd0[2]; |
|
867 int s; |
|
868 char buff[256]; |
|
869 |
|
870 DEBUG_CALL("rsh_exec"); |
|
871 DEBUG_ARG("so = %lx", (long)so); |
|
872 |
|
873 if (pipe(fd)<0) { |
|
874 lprint("Error: pipe failed: %s\n", strerror(errno)); |
|
875 return 0; |
|
876 } |
|
877 /* #ifdef HAVE_SOCKETPAIR */ |
|
878 #if 1 |
|
879 if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) { |
|
880 close(fd[0]); |
|
881 close(fd[1]); |
|
882 lprint("Error: openpty failed: %s\n", strerror(errno)); |
|
883 return 0; |
|
884 } |
|
885 #else |
|
886 if (slirp_openpty(&fd0[0], &fd0[1]) == -1) { |
|
887 close(fd[0]); |
|
888 close(fd[1]); |
|
889 lprint("Error: openpty failed: %s\n", strerror(errno)); |
|
890 return 0; |
|
891 } |
|
892 #endif |
|
893 |
|
894 switch(fork()) { |
|
895 case -1: |
|
896 lprint("Error: fork failed: %s\n", strerror(errno)); |
|
897 close(fd[0]); |
|
898 close(fd[1]); |
|
899 close(fd0[0]); |
|
900 close(fd0[1]); |
|
901 return 0; |
|
902 |
|
903 case 0: |
|
904 close(fd[0]); |
|
905 close(fd0[0]); |
|
906 |
|
907 /* Set the DISPLAY */ |
|
908 if (x_port >= 0) { |
|
909 #ifdef HAVE_SETENV |
|
910 sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); |
|
911 setenv("DISPLAY", buff, 1); |
|
912 #else |
|
913 sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); |
|
914 putenv(buff); |
|
915 #endif |
|
916 } |
|
917 |
|
918 dup2(fd0[1], 0); |
|
919 dup2(fd0[1], 1); |
|
920 dup2(fd[1], 2); |
|
921 for (s = 3; s <= 255; s++) |
|
922 close(s); |
|
923 |
|
924 execlp("rsh","rsh","-l", user, host, args, NULL); |
|
925 |
|
926 /* Ooops, failed, let's tell the user why */ |
|
927 |
|
928 sprintf(buff, "Error: execlp of %s failed: %s\n", |
|
929 "rsh", strerror(errno)); |
|
930 write(2, buff, strlen(buff)+1); |
|
931 close(0); close(1); close(2); /* XXX */ |
|
932 exit(1); |
|
933 |
|
934 default: |
|
935 close(fd[1]); |
|
936 close(fd0[1]); |
|
937 ns->s=fd[0]; |
|
938 so->s=fd0[0]; |
|
939 |
|
940 return 1; |
|
941 } |
|
942 } |
|
943 #endif |