VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/misc.c@ 9144

Last change on this file since 9144 was 1824, checked in by vboxsync, 18 years ago

Disable NAT UDP broadcast resend to local address. Removed the inline declarations and the useless _MSC_VER checks. And eliminated a few compiler warnings.

  • Property svn:eol-style set to native
File size: 14.3 KB
Line 
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
12#if 0
13int x_port = -1;
14int x_display = 0;
15int x_screen = 0;
16
17int
18show_x(buff, inso)
19 char *buff;
20 struct socket *inso;
21{
22 if (x_port < 0) {
23 lprint("X Redir: X not being redirected.\r\n");
24 } else {
25 lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n",
26 inet_ntoa(our_addr), x_port, x_screen);
27 lprint("X Redir: In csh/tcsh/etc. type: setenv DISPLAY %s:%d.%d\r\n",
28 inet_ntoa(our_addr), x_port, x_screen);
29 if (x_display)
30 lprint("X Redir: Redirecting to display %d\r\n", x_display);
31 }
32
33 return CFG_OK;
34}
35
36
37/*
38 * XXX Allow more than one X redirection?
39 */
40void
41redir_x(inaddr, start_port, display, screen)
42 u_int32_t inaddr;
43 int start_port;
44 int display;
45 int screen;
46{
47 int i;
48
49 if (x_port >= 0) {
50 lprint("X Redir: X already being redirected.\r\n");
51 show_x(0, 0);
52 } else {
53 for (i = 6001 + (start_port-1); i <= 6100; i++) {
54 if (solisten(htons(i), inaddr, htons(6000 + display), 0)) {
55 /* Success */
56 x_port = i - 6000;
57 x_display = display;
58 x_screen = screen;
59 show_x(0, 0);
60 return;
61 }
62 }
63 lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n");
64 }
65}
66#endif
67
68#ifndef HAVE_INET_ATON
69int
70inet_aton(cp, ia)
71 const char *cp;
72 struct in_addr *ia;
73{
74 u_int32_t addr = inet_addr(cp);
75 if (addr == 0xffffffff)
76 return 0;
77 ia->s_addr = addr;
78 return 1;
79}
80#endif
81
82/*
83 * Get our IP address and put it in our_addr
84 */
85void
86getouraddr(PNATState pData)
87{
88 char buff[256];
89 struct hostent *he = NULL;
90
91 if (gethostname(buff,256) == 0)
92 he = gethostbyname(buff);
93 if (he)
94 our_addr = *(struct in_addr *)he->h_addr;
95 if (our_addr.s_addr == 0)
96 our_addr.s_addr = loopback_addr.s_addr;
97}
98
99#if SIZEOF_CHAR_P == 8
100
101struct quehead_32 {
102 u_int32_t qh_link;
103 u_int32_t qh_rlink;
104};
105
106void
107insque_32(PNATState pData, void *a, void *b)
108{
109 register struct quehead_32 *element = (struct quehead_32 *) a;
110 register struct quehead_32 *head = (struct quehead_32 *) b;
111 struct quehead_32 *link = u32_to_ptr(pData, head->qh_link, struct quehead_32 *);
112
113 element->qh_link = head->qh_link;
114 element->qh_rlink = ptr_to_u32(pData, head);
115 Assert(link->qh_rlink == element->qh_rlink);
116 link->qh_rlink = head->qh_link = ptr_to_u32(pData, element);
117}
118
119void
120remque_32(PNATState pData, void *a)
121{
122 register struct quehead_32 *element = (struct quehead_32 *) a;
123 struct quehead_32 *link = u32_to_ptr(pData, element->qh_link, struct quehead_32 *);
124 struct quehead_32 *rlink = u32_to_ptr(pData, element->qh_rlink, struct quehead_32 *);
125
126 u32ptr_done(pData, link->qh_rlink, element);
127 link->qh_rlink = element->qh_rlink;
128 rlink->qh_link = element->qh_link;
129 element->qh_rlink = 0;
130}
131
132#endif /* SIZEOF_CHAR_P == 8 */
133
134struct quehead {
135 struct quehead *qh_link;
136 struct quehead *qh_rlink;
137};
138
139void
140insque(PNATState pData, void *a, void *b)
141{
142 register struct quehead *element = (struct quehead *) a;
143 register struct quehead *head = (struct quehead *) b;
144 element->qh_link = head->qh_link;
145 head->qh_link = (struct quehead *)element;
146 element->qh_rlink = (struct quehead *)head;
147 ((struct quehead *)(element->qh_link))->qh_rlink
148 = (struct quehead *)element;
149}
150
151void
152remque(PNATState pData, void *a)
153{
154 register struct quehead *element = (struct quehead *) a;
155 ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
156 ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
157 element->qh_rlink = NULL;
158 /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */
159}
160
161/* #endif */
162
163
164int
165add_exec(ex_ptr, do_pty, exec, addr, port)
166 struct ex_list **ex_ptr;
167 int do_pty;
168 char *exec;
169 int addr;
170 int port;
171{
172 struct ex_list *tmp_ptr;
173
174 /* First, check if the port is "bound" */
175 for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
176 if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
177 return -1;
178 }
179
180 tmp_ptr = *ex_ptr;
181 *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
182 (*ex_ptr)->ex_fport = port;
183 (*ex_ptr)->ex_addr = addr;
184 (*ex_ptr)->ex_pty = do_pty;
185 (*ex_ptr)->ex_exec = strdup(exec);
186 (*ex_ptr)->ex_next = tmp_ptr;
187 return 0;
188}
189
190#ifndef HAVE_STRERROR
191
192/*
193 * For systems with no strerror
194 */
195
196extern int sys_nerr;
197extern char *sys_errlist[];
198
199char *
200strerror(error)
201 int error;
202{
203 if (error < sys_nerr)
204 return sys_errlist[error];
205 else
206 return "Unknown error.";
207}
208
209#endif
210
211
212#ifdef _WIN32
213
214int
215fork_exec(PNATState pData, struct socket *so, char *ex, int do_pty)
216{
217 /* not implemented */
218 return 0;
219}
220
221#else
222
223/*
224 * XXX This is ugly
225 * We create and bind a socket, then fork off to another
226 * process, which connects to this socket, after which we
227 * exec the wanted program. If something (strange) happens,
228 * the accept() call could block us forever.
229 *
230 * do_pty = 0 Fork/exec inetd style
231 * do_pty = 1 Fork/exec using slirp.telnetd
232 * do_ptr = 2 Fork/exec using pty
233 */
234int
235fork_exec(PNATState pData, struct socket *so, char *ex, int do_pty)
236{
237 int s;
238 struct sockaddr_in addr;
239 socklen_t addrlen = sizeof(addr);
240 int opt;
241 int master;
242 char *argv[256];
243#if 0
244 char buff[256];
245#endif
246 /* don't want to clobber the original */
247 char *bptr;
248 char *curarg;
249 int c, i, ret;
250
251 DEBUG_CALL("fork_exec");
252 DEBUG_ARG("so = %lx", (long)so);
253 DEBUG_ARG("ex = %lx", (long)ex);
254 DEBUG_ARG("do_pty = %lx", (long)do_pty);
255
256 if (do_pty == 2) {
257 AssertRelease(do_pty != 2);
258 /* shut up gcc */
259 s = 0;
260 master = 0;
261 } else {
262 addr.sin_family = AF_INET;
263 addr.sin_port = 0;
264 addr.sin_addr.s_addr = INADDR_ANY;
265
266 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
267 bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
268 listen(s, 1) < 0) {
269 lprint("Error: inet socket: %s\n", strerror(errno));
270 closesocket(s);
271
272 return 0;
273 }
274 }
275
276 switch(fork()) {
277 case -1:
278 lprint("Error: fork failed: %s\n", strerror(errno));
279 close(s);
280 if (do_pty == 2)
281 close(master);
282 return 0;
283
284 case 0:
285 /* Set the DISPLAY */
286 if (do_pty == 2) {
287 (void) close(master);
288#ifdef TIOCSCTTY /* XXXXX */
289 (void) setsid();
290 ioctl(s, TIOCSCTTY, (char *)NULL);
291#endif
292 } else {
293 getsockname(s, (struct sockaddr *)&addr, &addrlen);
294 close(s);
295 /*
296 * Connect to the socket
297 * XXX If any of these fail, we're in trouble!
298 */
299 s = socket(AF_INET, SOCK_STREAM, 0);
300 addr.sin_addr = loopback_addr;
301 do {
302 ret = connect(s, (struct sockaddr *)&addr, addrlen);
303 } while (ret < 0 && errno == EINTR);
304 }
305
306#if 0
307 if (x_port >= 0) {
308#ifdef HAVE_SETENV
309 sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
310 setenv("DISPLAY", buff, 1);
311#else
312 sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
313 putenv(buff);
314#endif
315 }
316#endif
317 dup2(s, 0);
318 dup2(s, 1);
319 dup2(s, 2);
320 for (s = 3; s <= 255; s++)
321 close(s);
322
323 i = 0;
324 bptr = strdup(ex); /* No need to free() this */
325 if (do_pty == 1) {
326 /* Setup "slirp.telnetd -x" */
327 argv[i++] = "slirp.telnetd";
328 argv[i++] = "-x";
329 argv[i++] = bptr;
330 } else
331 do {
332 /* Change the string into argv[] */
333 curarg = bptr;
334 while (*bptr != ' ' && *bptr != (char)0)
335 bptr++;
336 c = *bptr;
337 *bptr++ = (char)0;
338 argv[i++] = strdup(curarg);
339 } while (c);
340
341 argv[i] = 0;
342 execvp(argv[0], argv);
343
344 /* Ooops, failed, let's tell the user why */
345 {
346 char buff[256];
347
348 sprintf(buff, "Error: execvp of %s failed: %s\n",
349 argv[0], strerror(errno));
350 write(2, buff, strlen(buff)+1);
351 }
352 close(0); close(1); close(2); /* XXX */
353 exit(1);
354
355 default:
356 if (do_pty == 2) {
357 close(s);
358 so->s = master;
359 } else {
360 /*
361 * XXX this could block us...
362 * XXX Should set a timer here, and if accept() doesn't
363 * return after X seconds, declare it a failure
364 * The only reason this will block forever is if socket()
365 * of connect() fail in the child process
366 */
367 do {
368 so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
369 } while (so->s < 0 && errno == EINTR);
370 closesocket(s);
371 opt = 1;
372 setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
373 opt = 1;
374 setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
375 }
376 fd_nonblock(so->s);
377
378 /* Append the telnet options now */
379 if (so->so_m != 0 && do_pty == 1) {
380 sbappend(pData, so, so->so_m);
381 so->so_m = 0;
382 }
383
384 return 1;
385 }
386}
387#endif
388
389#ifndef HAVE_STRDUP
390char *
391strdup(str)
392 const char *str;
393{
394 char *bptr;
395
396 bptr = (char *)malloc(strlen(str)+1);
397 strcpy(bptr, str);
398
399 return bptr;
400}
401#endif
402
403#if 0
404void
405snooze_hup(num)
406 int num;
407{
408 int s, ret;
409#ifndef NO_UNIX_SOCKETS
410 struct sockaddr_un sock_un;
411#endif
412 struct sockaddr_in sock_in;
413 char buff[256];
414
415 ret = -1;
416 if (slirp_socket_passwd) {
417 s = socket(AF_INET, SOCK_STREAM, 0);
418 if (s < 0)
419 slirp_exit(1);
420 sock_in.sin_family = AF_INET;
421 sock_in.sin_addr.s_addr = slirp_socket_addr;
422 sock_in.sin_port = htons(slirp_socket_port);
423 if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
424 slirp_exit(1); /* just exit...*/
425 sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
426 write(s, buff, strlen(buff)+1);
427 }
428#ifndef NO_UNIX_SOCKETS
429 else {
430 s = socket(AF_UNIX, SOCK_STREAM, 0);
431 if (s < 0)
432 slirp_exit(1);
433 sock_un.sun_family = AF_UNIX;
434 strcpy(sock_un.sun_path, socket_path);
435 if (connect(s, (struct sockaddr *)&sock_un,
436 sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
437 slirp_exit(1);
438 sprintf(buff, "kill none:%d", slirp_socket_unit);
439 write(s, buff, strlen(buff)+1);
440 }
441#endif
442 slirp_exit(0);
443}
444
445
446void
447snooze()
448{
449 sigset_t s;
450 int i;
451
452 /* Don't need our data anymore */
453 /* XXX This makes SunOS barf */
454/* brk(0); */
455
456 /* Close all fd's */
457 for (i = 255; i >= 0; i--)
458 close(i);
459
460 signal(SIGQUIT, slirp_exit);
461 signal(SIGHUP, snooze_hup);
462 sigemptyset(&s);
463
464 /* Wait for any signal */
465 sigsuspend(&s);
466
467 /* Just in case ... */
468 exit(255);
469}
470
471void
472relay(s)
473 int s;
474{
475 char buf[8192];
476 int n;
477 fd_set readfds;
478 struct ttys *ttyp;
479
480 /* Don't need our data anymore */
481 /* XXX This makes SunOS barf */
482/* brk(0); */
483
484 signal(SIGQUIT, slirp_exit);
485 signal(SIGHUP, slirp_exit);
486 signal(SIGINT, slirp_exit);
487 signal(SIGTERM, slirp_exit);
488
489 /* Fudge to get term_raw and term_restore to work */
490 if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
491 lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
492 slirp_exit (1);
493 }
494 ttyp->fd = 0;
495 ttyp->flags |= TTY_CTTY;
496 term_raw(ttyp);
497
498 while (1) {
499 FD_ZERO(&readfds);
500
501 FD_SET(0, &readfds);
502 FD_SET(s, &readfds);
503
504 n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
505
506 if (n <= 0)
507 slirp_exit(0);
508
509 if (FD_ISSET(0, &readfds)) {
510 n = read(0, buf, 8192);
511 if (n <= 0)
512 slirp_exit(0);
513 n = writen(s, buf, n);
514 if (n <= 0)
515 slirp_exit(0);
516 }
517
518 if (FD_ISSET(s, &readfds)) {
519 n = read(s, buf, 8192);
520 if (n <= 0)
521 slirp_exit(0);
522 n = writen(0, buf, n);
523 if (n <= 0)
524 slirp_exit(0);
525 }
526 }
527
528 /* Just in case.... */
529 exit(1);
530}
531#endif
532
533#ifdef BAD_SPRINTF
534
535#undef vsprintf
536#undef sprintf
537
538/*
539 * Some BSD-derived systems have a sprintf which returns char *
540 */
541
542int
543vsprintf_len(string, format, args)
544 char *string;
545 const char *format;
546 va_list args;
547{
548 vsprintf(string, format, args);
549 return strlen(string);
550}
551
552int
553#ifdef __STDC__
554sprintf_len(char *string, const char *format, ...)
555#else
556sprintf_len(va_alist) va_dcl
557#endif
558{
559 va_list args;
560#ifdef __STDC__
561 va_start(args, format);
562#else
563 char *string;
564 char *format;
565 va_start(args);
566 string = va_arg(args, char *);
567 format = va_arg(args, char *);
568#endif
569 vsprintf(string, format, args);
570 return strlen(string);
571}
572
573#endif
574
575void
576u_sleep(usec)
577 int usec;
578{
579 struct timeval t;
580 fd_set fdset;
581
582 FD_ZERO(&fdset);
583
584 t.tv_sec = 0;
585 t.tv_usec = usec * 1000;
586
587 select(0, &fdset, &fdset, &fdset, &t);
588}
589
590/*
591 * Set fd blocking and non-blocking
592 */
593
594void
595fd_nonblock(fd)
596 int fd;
597{
598#ifdef FIONBIO
599 int opt = 1;
600
601 ioctlsocket(fd, FIONBIO, &opt);
602#else
603 int opt;
604
605 opt = fcntl(fd, F_GETFL, 0);
606 opt |= O_NONBLOCK;
607 fcntl(fd, F_SETFL, opt);
608#endif
609}
610
611void
612fd_block(fd)
613 int fd;
614{
615#ifdef FIONBIO
616 int opt = 0;
617
618 ioctlsocket(fd, FIONBIO, &opt);
619#else
620 int opt;
621
622 opt = fcntl(fd, F_GETFL, 0);
623 opt &= ~O_NONBLOCK;
624 fcntl(fd, F_SETFL, opt);
625#endif
626}
627
628
629#if 0
630/*
631 * invoke RSH
632 */
633int
634rsh_exec(so,ns, user, host, args)
635 struct socket *so;
636 struct socket *ns;
637 char *user;
638 char *host;
639 char *args;
640{
641 int fd[2];
642 int fd0[2];
643 int s;
644 char buff[256];
645
646 DEBUG_CALL("rsh_exec");
647 DEBUG_ARG("so = %lx", (long)so);
648
649 if (pipe(fd)<0) {
650 lprint("Error: pipe failed: %s\n", strerror(errno));
651 return 0;
652 }
653/* #ifdef HAVE_SOCKETPAIR */
654#if 1
655 if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
656 close(fd[0]);
657 close(fd[1]);
658 lprint("Error: openpty failed: %s\n", strerror(errno));
659 return 0;
660 }
661#else
662 if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
663 close(fd[0]);
664 close(fd[1]);
665 lprint("Error: openpty failed: %s\n", strerror(errno));
666 return 0;
667 }
668#endif
669
670 switch(fork()) {
671 case -1:
672 lprint("Error: fork failed: %s\n", strerror(errno));
673 close(fd[0]);
674 close(fd[1]);
675 close(fd0[0]);
676 close(fd0[1]);
677 return 0;
678
679 case 0:
680 close(fd[0]);
681 close(fd0[0]);
682
683 /* Set the DISPLAY */
684 if (x_port >= 0) {
685#ifdef HAVE_SETENV
686 sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
687 setenv("DISPLAY", buff, 1);
688#else
689 sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
690 putenv(buff);
691#endif
692 }
693
694 dup2(fd0[1], 0);
695 dup2(fd0[1], 1);
696 dup2(fd[1], 2);
697 for (s = 3; s <= 255; s++)
698 close(s);
699
700 execlp("rsh","rsh","-l", user, host, args, NULL);
701
702 /* Ooops, failed, let's tell the user why */
703
704 sprintf(buff, "Error: execlp of %s failed: %s\n",
705 "rsh", strerror(errno));
706 write(2, buff, strlen(buff)+1);
707 close(0); close(1); close(2); /* XXX */
708 exit(1);
709
710 default:
711 close(fd[1]);
712 close(fd0[1]);
713 ns->s=fd[0];
714 so->s=fd0[0];
715
716 return 1;
717 }
718}
719#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette