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

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.4   root      116:        const char *argv[256];
1.1       root      117:        /* don't want to clobber the original */
                    118:        char *bptr;
1.1.1.3   root      119:        const char *curarg;
1.1       root      120:        int c, i, ret;
1.1.1.10  root      121:        pid_t pid;
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.1.10  root      145:        pid = fork();
                    146:        switch(pid) {
1.1       root      147:         case -1:
                    148:                lprint("Error: fork failed: %s\n", strerror(errno));
                    149:                close(s);
                    150:                return 0;
1.1.1.3   root      151: 
1.1       root      152:         case 0:
1.1.1.10  root      153:                 setsid();
                    154: 
1.1       root      155:                /* Set the DISPLAY */
1.1.1.12! root      156:                 getsockname(s, (struct sockaddr *)&addr, &addrlen);
        !           157:                 close(s);
        !           158:                 /*
        !           159:                  * Connect to the socket
        !           160:                  * XXX If any of these fail, we're in trouble!
        !           161:                  */
        !           162:                 s = qemu_socket(AF_INET, SOCK_STREAM, 0);
        !           163:                 addr.sin_addr = loopback_addr;
        !           164:                 do {
        !           165:                     ret = connect(s, (struct sockaddr *)&addr, addrlen);
        !           166:                 } while (ret < 0 && errno == EINTR);
1.1.1.3   root      167: 
1.1       root      168:                dup2(s, 0);
                    169:                dup2(s, 1);
                    170:                dup2(s, 2);
1.1.1.3   root      171:                for (s = getdtablesize() - 1; s >= 3; s--)
1.1       root      172:                   close(s);
1.1.1.3   root      173: 
1.1       root      174:                i = 0;
1.1.1.11  root      175:                bptr = g_strdup(ex); /* No need to free() this */
1.1       root      176:                if (do_pty == 1) {
                    177:                        /* Setup "slirp.telnetd -x" */
                    178:                        argv[i++] = "slirp.telnetd";
                    179:                        argv[i++] = "-x";
                    180:                        argv[i++] = bptr;
                    181:                } else
                    182:                   do {
                    183:                        /* Change the string into argv[] */
                    184:                        curarg = bptr;
                    185:                        while (*bptr != ' ' && *bptr != (char)0)
                    186:                           bptr++;
                    187:                        c = *bptr;
                    188:                        *bptr++ = (char)0;
                    189:                        argv[i++] = strdup(curarg);
                    190:                   } while (c);
1.1.1.3   root      191: 
1.1.1.5   root      192:                 argv[i] = NULL;
1.1.1.4   root      193:                execvp(argv[0], (char **)argv);
1.1.1.3   root      194: 
1.1       root      195:                /* Ooops, failed, let's tell the user why */
1.1.1.8   root      196:         fprintf(stderr, "Error: execvp of %s failed: %s\n",
                    197:                 argv[0], strerror(errno));
1.1       root      198:                close(0); close(1); close(2); /* XXX */
                    199:                exit(1);
1.1.1.3   root      200: 
1.1       root      201:         default:
1.1.1.10  root      202:                qemu_add_child_watch(pid);
1.1.1.12! root      203:                 /*
        !           204:                  * XXX this could block us...
        !           205:                  * XXX Should set a timer here, and if accept() doesn't
        !           206:                  * return after X seconds, declare it a failure
        !           207:                  * The only reason this will block forever is if socket()
        !           208:                  * of connect() fail in the child process
        !           209:                  */
        !           210:                 do {
        !           211:                     so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
        !           212:                 } while (so->s < 0 && errno == EINTR);
        !           213:                 closesocket(s);
        !           214:                 opt = 1;
        !           215:                 setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
        !           216:                 opt = 1;
        !           217:                 setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
        !           218:                socket_set_nonblock(so->s);
1.1.1.3   root      219: 
1.1       root      220:                /* Append the telnet options now */
1.1.1.5   root      221:                 if (so->so_m != NULL && do_pty == 1)  {
1.1       root      222:                        sbappend(so, so->so_m);
1.1.1.5   root      223:                         so->so_m = NULL;
1.1       root      224:                }
1.1.1.3   root      225: 
1.1       root      226:                return 1;
                    227:        }
                    228: }
                    229: #endif
                    230: 
                    231: #ifndef HAVE_STRDUP
                    232: char *
                    233: strdup(str)
                    234:        const char *str;
                    235: {
                    236:        char *bptr;
1.1.1.3   root      237: 
1.1       root      238:        bptr = (char *)malloc(strlen(str)+1);
                    239:        strcpy(bptr, str);
1.1.1.3   root      240: 
1.1       root      241:        return bptr;
                    242: }
                    243: #endif
                    244: 
1.1.1.5   root      245: #include "monitor.h"
1.1.1.3   root      246: 
                    247: void lprint(const char *format, ...)
                    248: {
                    249:     va_list args;
                    250: 
                    251:     va_start(args, format);
1.1.1.8   root      252:     monitor_vprintf(default_mon, format, args);
1.1.1.3   root      253:     va_end(args);
                    254: }
1.1       root      255: 
                    256: void
1.1.1.5   root      257: u_sleep(int usec)
1.1       root      258: {
                    259:        struct timeval t;
                    260:        fd_set fdset;
1.1.1.3   root      261: 
1.1       root      262:        FD_ZERO(&fdset);
1.1.1.3   root      263: 
1.1       root      264:        t.tv_sec = 0;
                    265:        t.tv_usec = usec * 1000;
1.1.1.3   root      266: 
1.1       root      267:        select(0, &fdset, &fdset, &fdset, &t);
                    268: }
                    269: 
1.1.1.5   root      270: void slirp_connection_info(Slirp *slirp, Monitor *mon)
1.1       root      271: {
1.1.1.5   root      272:     const char * const tcpstates[] = {
                    273:         [TCPS_CLOSED]       = "CLOSED",
                    274:         [TCPS_LISTEN]       = "LISTEN",
                    275:         [TCPS_SYN_SENT]     = "SYN_SENT",
                    276:         [TCPS_SYN_RECEIVED] = "SYN_RCVD",
                    277:         [TCPS_ESTABLISHED]  = "ESTABLISHED",
                    278:         [TCPS_CLOSE_WAIT]   = "CLOSE_WAIT",
                    279:         [TCPS_FIN_WAIT_1]   = "FIN_WAIT_1",
                    280:         [TCPS_CLOSING]      = "CLOSING",
                    281:         [TCPS_LAST_ACK]     = "LAST_ACK",
                    282:         [TCPS_FIN_WAIT_2]   = "FIN_WAIT_2",
                    283:         [TCPS_TIME_WAIT]    = "TIME_WAIT",
                    284:     };
                    285:     struct in_addr dst_addr;
                    286:     struct sockaddr_in src;
                    287:     socklen_t src_len;
                    288:     uint16_t dst_port;
                    289:     struct socket *so;
                    290:     const char *state;
                    291:     char buf[20];
                    292: 
                    293:     monitor_printf(mon, "  Protocol[State]    FD  Source Address  Port   "
                    294:                         "Dest. Address  Port RecvQ SendQ\n");
                    295: 
                    296:     for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
                    297:         if (so->so_state & SS_HOSTFWD) {
                    298:             state = "HOST_FORWARD";
                    299:         } else if (so->so_tcpcb) {
                    300:             state = tcpstates[so->so_tcpcb->t_state];
                    301:         } else {
                    302:             state = "NONE";
1.1       root      303:         }
1.1.1.5   root      304:         if (so->so_state & (SS_HOSTFWD | SS_INCOMING)) {
                    305:             src_len = sizeof(src);
                    306:             getsockname(so->s, (struct sockaddr *)&src, &src_len);
                    307:             dst_addr = so->so_laddr;
                    308:             dst_port = so->so_lport;
                    309:         } else {
                    310:             src.sin_addr = so->so_laddr;
                    311:             src.sin_port = so->so_lport;
                    312:             dst_addr = so->so_faddr;
                    313:             dst_port = so->so_fport;
1.1       root      314:         }
1.1.1.12! root      315:         snprintf(buf, sizeof(buf), "  TCP[%s]", state);
        !           316:         monitor_printf(mon, "%-19s %3d %15s %5d ", buf, so->s,
1.1.1.5   root      317:                        src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
                    318:                        ntohs(src.sin_port));
                    319:         monitor_printf(mon, "%15s %5d %5d %5d\n",
                    320:                        inet_ntoa(dst_addr), ntohs(dst_port),
                    321:                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
                    322:     }
1.1.1.3   root      323: 
1.1.1.5   root      324:     for (so = slirp->udb.so_next; so != &slirp->udb; so = so->so_next) {
                    325:         if (so->so_state & SS_HOSTFWD) {
1.1.1.12! root      326:             snprintf(buf, sizeof(buf), "  UDP[HOST_FORWARD]");
1.1.1.5   root      327:             src_len = sizeof(src);
                    328:             getsockname(so->s, (struct sockaddr *)&src, &src_len);
                    329:             dst_addr = so->so_laddr;
                    330:             dst_port = so->so_lport;
                    331:         } else {
1.1.1.12! root      332:             snprintf(buf, sizeof(buf), "  UDP[%d sec]",
1.1.1.5   root      333:                          (so->so_expire - curtime) / 1000);
                    334:             src.sin_addr = so->so_laddr;
                    335:             src.sin_port = so->so_lport;
                    336:             dst_addr = so->so_faddr;
                    337:             dst_port = so->so_fport;
                    338:         }
1.1.1.12! root      339:         monitor_printf(mon, "%-19s %3d %15s %5d ", buf, so->s,
1.1.1.5   root      340:                        src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
                    341:                        ntohs(src.sin_port));
                    342:         monitor_printf(mon, "%15s %5d %5d %5d\n",
                    343:                        inet_ntoa(dst_addr), ntohs(dst_port),
                    344:                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
                    345:     }
1.1.1.10  root      346: 
                    347:     for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so->so_next) {
1.1.1.12! root      348:         snprintf(buf, sizeof(buf), "  ICMP[%d sec]",
1.1.1.10  root      349:                      (so->so_expire - curtime) / 1000);
                    350:         src.sin_addr = so->so_laddr;
                    351:         dst_addr = so->so_faddr;
1.1.1.12! root      352:         monitor_printf(mon, "%-19s %3d %15s  -    ", buf, so->s,
1.1.1.10  root      353:                        src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*");
                    354:         monitor_printf(mon, "%15s  -    %5d %5d\n", inet_ntoa(dst_addr),
                    355:                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
                    356:     }
1.1       root      357: }

unix.superglobalmegacorp.com