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