Annotation of qemu/slirp/misc.c, revision 1.1.1.9

1.1       root        1: /*
                      2:  * Copyright (c) 1995 Danny Gasparovski.
1.1.1.3   root        3:  *
1.1       root        4:  * Please read the file COPYRIGHT for the
                      5:  * terms and conditions of the copyright.
                      6:  */
                      7: 
                      8: #include <slirp.h>
1.1.1.5   root        9: #include <libslirp.h>
1.1       root       10: 
1.1.1.5   root       11: #include "monitor.h"
1.1       root       12: 
1.1.1.5   root       13: #ifdef DEBUG
                     14: int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
1.1       root       15: #endif
                     16: 
                     17: struct quehead {
                     18:        struct quehead *qh_link;
                     19:        struct quehead *qh_rlink;
                     20: };
                     21: 
                     22: inline void
1.1.1.5   root       23: insque(void *a, void *b)
1.1       root       24: {
                     25:        register struct quehead *element = (struct quehead *) a;
                     26:        register struct quehead *head = (struct quehead *) b;
                     27:        element->qh_link = head->qh_link;
                     28:        head->qh_link = (struct quehead *)element;
                     29:        element->qh_rlink = (struct quehead *)head;
                     30:        ((struct quehead *)(element->qh_link))->qh_rlink
                     31:        = (struct quehead *)element;
                     32: }
                     33: 
                     34: inline void
1.1.1.5   root       35: remque(void *a)
1.1       root       36: {
                     37:   register struct quehead *element = (struct quehead *) a;
                     38:   ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
                     39:   ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
                     40:   element->qh_rlink = NULL;
                     41: }
                     42: 
1.1.1.5   root       43: int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec,
                     44:              struct in_addr addr, int port)
1.1       root       45: {
                     46:        struct ex_list *tmp_ptr;
1.1.1.3   root       47: 
1.1       root       48:        /* First, check if the port is "bound" */
                     49:        for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
1.1.1.5   root       50:                if (port == tmp_ptr->ex_fport &&
                     51:                    addr.s_addr == tmp_ptr->ex_addr.s_addr)
                     52:                        return -1;
1.1       root       53:        }
1.1.1.3   root       54: 
1.1       root       55:        tmp_ptr = *ex_ptr;
                     56:        *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
                     57:        (*ex_ptr)->ex_fport = port;
                     58:        (*ex_ptr)->ex_addr = addr;
                     59:        (*ex_ptr)->ex_pty = do_pty;
1.1.1.4   root       60:        (*ex_ptr)->ex_exec = (do_pty == 3) ? exec : strdup(exec);
1.1       root       61:        (*ex_ptr)->ex_next = tmp_ptr;
                     62:        return 0;
                     63: }
                     64: 
                     65: #ifndef HAVE_STRERROR
                     66: 
                     67: /*
                     68:  * For systems with no strerror
                     69:  */
                     70: 
                     71: extern int sys_nerr;
                     72: extern char *sys_errlist[];
                     73: 
                     74: char *
                     75: strerror(error)
                     76:        int error;
                     77: {
                     78:        if (error < sys_nerr)
                     79:           return sys_errlist[error];
                     80:        else
                     81:           return "Unknown error.";
                     82: }
                     83: 
                     84: #endif
                     85: 
                     86: 
                     87: #ifdef _WIN32
                     88: 
                     89: int
1.1.1.3   root       90: fork_exec(struct socket *so, const char *ex, int do_pty)
1.1       root       91: {
                     92:     /* not implemented */
                     93:     return 0;
                     94: }
                     95: 
                     96: #else
                     97: 
                     98: /*
                     99:  * XXX This is ugly
                    100:  * We create and bind a socket, then fork off to another
                    101:  * process, which connects to this socket, after which we
                    102:  * exec the wanted program.  If something (strange) happens,
                    103:  * the accept() call could block us forever.
1.1.1.3   root      104:  *
1.1       root      105:  * do_pty = 0   Fork/exec inetd style
                    106:  * do_pty = 1   Fork/exec using slirp.telnetd
                    107:  * do_ptr = 2   Fork/exec using pty
                    108:  */
                    109: int
1.1.1.3   root      110: fork_exec(struct socket *so, const char *ex, int do_pty)
1.1       root      111: {
                    112:        int s;
                    113:        struct sockaddr_in addr;
1.1.1.4   root      114:        socklen_t addrlen = sizeof(addr);
1.1       root      115:        int opt;
1.1.1.3   root      116:         int master = -1;
1.1.1.4   root      117:        const char *argv[256];
1.1       root      118:        /* don't want to clobber the original */
                    119:        char *bptr;
1.1.1.3   root      120:        const char *curarg;
1.1       root      121:        int c, i, ret;
1.1.1.3   root      122: 
1.1       root      123:        DEBUG_CALL("fork_exec");
                    124:        DEBUG_ARG("so = %lx", (long)so);
                    125:        DEBUG_ARG("ex = %lx", (long)ex);
                    126:        DEBUG_ARG("do_pty = %lx", (long)do_pty);
1.1.1.3   root      127: 
1.1       root      128:        if (do_pty == 2) {
1.1.1.3   root      129:                 return 0;
1.1       root      130:        } else {
                    131:                addr.sin_family = AF_INET;
                    132:                addr.sin_port = 0;
                    133:                addr.sin_addr.s_addr = INADDR_ANY;
1.1.1.3   root      134: 
1.1.1.6   root      135:                if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
1.1       root      136:                    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
                    137:                    listen(s, 1) < 0) {
                    138:                        lprint("Error: inet socket: %s\n", strerror(errno));
                    139:                        closesocket(s);
1.1.1.3   root      140: 
1.1       root      141:                        return 0;
                    142:                }
                    143:        }
1.1.1.3   root      144: 
1.1       root      145:        switch(fork()) {
                    146:         case -1:
                    147:                lprint("Error: fork failed: %s\n", strerror(errno));
                    148:                close(s);
                    149:                if (do_pty == 2)
                    150:                   close(master);
                    151:                return 0;
1.1.1.3   root      152: 
1.1       root      153:         case 0:
                    154:                /* Set the DISPLAY */
                    155:                if (do_pty == 2) {
                    156:                        (void) close(master);
                    157: #ifdef TIOCSCTTY /* XXXXX */
                    158:                        (void) setsid();
                    159:                        ioctl(s, TIOCSCTTY, (char *)NULL);
                    160: #endif
                    161:                } else {
                    162:                        getsockname(s, (struct sockaddr *)&addr, &addrlen);
                    163:                        close(s);
                    164:                        /*
                    165:                         * Connect to the socket
                    166:                         * XXX If any of these fail, we're in trouble!
                    167:                         */
1.1.1.6   root      168:                        s = qemu_socket(AF_INET, SOCK_STREAM, 0);
1.1       root      169:                        addr.sin_addr = loopback_addr;
                    170:                         do {
                    171:                             ret = connect(s, (struct sockaddr *)&addr, addrlen);
                    172:                         } while (ret < 0 && errno == EINTR);
                    173:                }
1.1.1.3   root      174: 
1.1       root      175:                dup2(s, 0);
                    176:                dup2(s, 1);
                    177:                dup2(s, 2);
1.1.1.3   root      178:                for (s = getdtablesize() - 1; s >= 3; s--)
1.1       root      179:                   close(s);
1.1.1.3   root      180: 
1.1       root      181:                i = 0;
1.1.1.7   root      182:                bptr = qemu_strdup(ex); /* No need to free() this */
1.1       root      183:                if (do_pty == 1) {
                    184:                        /* Setup "slirp.telnetd -x" */
                    185:                        argv[i++] = "slirp.telnetd";
                    186:                        argv[i++] = "-x";
                    187:                        argv[i++] = bptr;
                    188:                } else
                    189:                   do {
                    190:                        /* Change the string into argv[] */
                    191:                        curarg = bptr;
                    192:                        while (*bptr != ' ' && *bptr != (char)0)
                    193:                           bptr++;
                    194:                        c = *bptr;
                    195:                        *bptr++ = (char)0;
                    196:                        argv[i++] = strdup(curarg);
                    197:                   } while (c);
1.1.1.3   root      198: 
1.1.1.5   root      199:                 argv[i] = NULL;
1.1.1.4   root      200:                execvp(argv[0], (char **)argv);
1.1.1.3   root      201: 
1.1       root      202:                /* Ooops, failed, let's tell the user why */
1.1.1.8   root      203:         fprintf(stderr, "Error: execvp of %s failed: %s\n",
                    204:                 argv[0], strerror(errno));
1.1       root      205:                close(0); close(1); close(2); /* XXX */
                    206:                exit(1);
1.1.1.3   root      207: 
1.1       root      208:         default:
                    209:                if (do_pty == 2) {
                    210:                        close(s);
                    211:                        so->s = master;
                    212:                } else {
                    213:                        /*
                    214:                         * XXX this could block us...
                    215:                         * XXX Should set a timer here, and if accept() doesn't
                    216:                         * return after X seconds, declare it a failure
                    217:                         * The only reason this will block forever is if socket()
                    218:                         * of connect() fail in the child process
                    219:                         */
                    220:                         do {
                    221:                             so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
                    222:                         } while (so->s < 0 && errno == EINTR);
                    223:                         closesocket(s);
                    224:                        opt = 1;
                    225:                        setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
                    226:                        opt = 1;
                    227:                        setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
                    228:                }
                    229:                fd_nonblock(so->s);
1.1.1.3   root      230: 
1.1       root      231:                /* Append the telnet options now */
1.1.1.5   root      232:                 if (so->so_m != NULL && do_pty == 1)  {
1.1       root      233:                        sbappend(so, so->so_m);
1.1.1.5   root      234:                         so->so_m = NULL;
1.1       root      235:                }
1.1.1.3   root      236: 
1.1       root      237:                return 1;
                    238:        }
                    239: }
                    240: #endif
                    241: 
                    242: #ifndef HAVE_STRDUP
                    243: char *
                    244: strdup(str)
                    245:        const char *str;
                    246: {
                    247:        char *bptr;
1.1.1.3   root      248: 
1.1       root      249:        bptr = (char *)malloc(strlen(str)+1);
                    250:        strcpy(bptr, str);
1.1.1.3   root      251: 
1.1       root      252:        return bptr;
                    253: }
                    254: #endif
                    255: 
1.1.1.5   root      256: #include "monitor.h"
1.1.1.3   root      257: 
                    258: void lprint(const char *format, ...)
                    259: {
                    260:     va_list args;
                    261: 
                    262:     va_start(args, format);
1.1.1.8   root      263:     monitor_vprintf(default_mon, format, args);
1.1.1.3   root      264:     va_end(args);
                    265: }
1.1       root      266: 
                    267: void
1.1.1.5   root      268: u_sleep(int usec)
1.1       root      269: {
                    270:        struct timeval t;
                    271:        fd_set fdset;
1.1.1.3   root      272: 
1.1       root      273:        FD_ZERO(&fdset);
1.1.1.3   root      274: 
1.1       root      275:        t.tv_sec = 0;
                    276:        t.tv_usec = usec * 1000;
1.1.1.3   root      277: 
1.1       root      278:        select(0, &fdset, &fdset, &fdset, &t);
                    279: }
                    280: 
                    281: /*
                    282:  * Set fd blocking and non-blocking
                    283:  */
                    284: 
                    285: void
1.1.1.5   root      286: fd_nonblock(int fd)
1.1       root      287: {
                    288: #ifdef FIONBIO
1.1.1.5   root      289: #ifdef _WIN32
                    290:         unsigned long opt = 1;
                    291: #else
                    292:         int opt = 1;
                    293: #endif
1.1.1.3   root      294: 
1.1       root      295:        ioctlsocket(fd, FIONBIO, &opt);
                    296: #else
                    297:        int opt;
1.1.1.3   root      298: 
1.1       root      299:        opt = fcntl(fd, F_GETFL, 0);
                    300:        opt |= O_NONBLOCK;
                    301:        fcntl(fd, F_SETFL, opt);
                    302: #endif
                    303: }
                    304: 
                    305: void
1.1.1.5   root      306: fd_block(int fd)
1.1       root      307: {
                    308: #ifdef FIONBIO
1.1.1.5   root      309: #ifdef _WIN32
                    310:         unsigned long opt = 0;
                    311: #else
1.1       root      312:        int opt = 0;
1.1.1.5   root      313: #endif
1.1.1.3   root      314: 
1.1       root      315:        ioctlsocket(fd, FIONBIO, &opt);
                    316: #else
                    317:        int opt;
1.1.1.3   root      318: 
1.1       root      319:        opt = fcntl(fd, F_GETFL, 0);
                    320:        opt &= ~O_NONBLOCK;
                    321:        fcntl(fd, F_SETFL, opt);
                    322: #endif
                    323: }
                    324: 
1.1.1.5   root      325: void slirp_connection_info(Slirp *slirp, Monitor *mon)
1.1       root      326: {
1.1.1.5   root      327:     const char * const tcpstates[] = {
                    328:         [TCPS_CLOSED]       = "CLOSED",
                    329:         [TCPS_LISTEN]       = "LISTEN",
                    330:         [TCPS_SYN_SENT]     = "SYN_SENT",
                    331:         [TCPS_SYN_RECEIVED] = "SYN_RCVD",
                    332:         [TCPS_ESTABLISHED]  = "ESTABLISHED",
                    333:         [TCPS_CLOSE_WAIT]   = "CLOSE_WAIT",
                    334:         [TCPS_FIN_WAIT_1]   = "FIN_WAIT_1",
                    335:         [TCPS_CLOSING]      = "CLOSING",
                    336:         [TCPS_LAST_ACK]     = "LAST_ACK",
                    337:         [TCPS_FIN_WAIT_2]   = "FIN_WAIT_2",
                    338:         [TCPS_TIME_WAIT]    = "TIME_WAIT",
                    339:     };
                    340:     struct in_addr dst_addr;
                    341:     struct sockaddr_in src;
                    342:     socklen_t src_len;
                    343:     uint16_t dst_port;
                    344:     struct socket *so;
                    345:     const char *state;
                    346:     char buf[20];
                    347:     int n;
                    348: 
                    349:     monitor_printf(mon, "  Protocol[State]    FD  Source Address  Port   "
                    350:                         "Dest. Address  Port RecvQ SendQ\n");
                    351: 
                    352:     for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
                    353:         if (so->so_state & SS_HOSTFWD) {
                    354:             state = "HOST_FORWARD";
                    355:         } else if (so->so_tcpcb) {
                    356:             state = tcpstates[so->so_tcpcb->t_state];
                    357:         } else {
                    358:             state = "NONE";
1.1       root      359:         }
1.1.1.5   root      360:         if (so->so_state & (SS_HOSTFWD | SS_INCOMING)) {
                    361:             src_len = sizeof(src);
                    362:             getsockname(so->s, (struct sockaddr *)&src, &src_len);
                    363:             dst_addr = so->so_laddr;
                    364:             dst_port = so->so_lport;
                    365:         } else {
                    366:             src.sin_addr = so->so_laddr;
                    367:             src.sin_port = so->so_lport;
                    368:             dst_addr = so->so_faddr;
                    369:             dst_port = so->so_fport;
1.1       root      370:         }
1.1.1.5   root      371:         n = snprintf(buf, sizeof(buf), "  TCP[%s]", state);
                    372:         memset(&buf[n], ' ', 19 - n);
                    373:         buf[19] = 0;
                    374:         monitor_printf(mon, "%s %3d %15s %5d ", buf, so->s,
                    375:                        src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
                    376:                        ntohs(src.sin_port));
                    377:         monitor_printf(mon, "%15s %5d %5d %5d\n",
                    378:                        inet_ntoa(dst_addr), ntohs(dst_port),
                    379:                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
                    380:     }
1.1.1.3   root      381: 
1.1.1.5   root      382:     for (so = slirp->udb.so_next; so != &slirp->udb; so = so->so_next) {
                    383:         if (so->so_state & SS_HOSTFWD) {
                    384:             n = snprintf(buf, sizeof(buf), "  UDP[HOST_FORWARD]");
                    385:             src_len = sizeof(src);
                    386:             getsockname(so->s, (struct sockaddr *)&src, &src_len);
                    387:             dst_addr = so->so_laddr;
                    388:             dst_port = so->so_lport;
                    389:         } else {
                    390:             n = snprintf(buf, sizeof(buf), "  UDP[%d sec]",
                    391:                          (so->so_expire - curtime) / 1000);
                    392:             src.sin_addr = so->so_laddr;
                    393:             src.sin_port = so->so_lport;
                    394:             dst_addr = so->so_faddr;
                    395:             dst_port = so->so_fport;
                    396:         }
                    397:         memset(&buf[n], ' ', 19 - n);
                    398:         buf[19] = 0;
                    399:         monitor_printf(mon, "%s %3d %15s %5d ", buf, so->s,
                    400:                        src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
                    401:                        ntohs(src.sin_port));
                    402:         monitor_printf(mon, "%15s %5d %5d %5d\n",
                    403:                        inet_ntoa(dst_addr), ntohs(dst_port),
                    404:                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
                    405:     }
1.1       root      406: }

unix.superglobalmegacorp.com