Fix elf loader range checking
[qemu] / slirp / misc.c
index 26f8eb5..0137e75 100644 (file)
@@ -1,15 +1,13 @@
 /*
  * Copyright (c) 1995 Danny Gasparovski.
- * 
+ *
  * Please read the file COPYRIGHT for the
  * terms and conditions of the copyright.
  */
 
-#define WANT_SYS_IOCTL_H
 #include <slirp.h>
 
-u_int curtime, time_fasttimo, last_slowtimo, detach_time;
-u_int detach_wait = 600000;    /* 10 minutes */
+u_int curtime, time_fasttimo, last_slowtimo;
 
 #if 0
 int x_port = -1;
@@ -31,7 +29,7 @@ show_x(buff, inso)
                if (x_display)
                   lprint("X Redir: Redirecting to display %d\r\n", x_display);
        }
-       
+
        return CFG_OK;
 }
 
@@ -47,7 +45,7 @@ redir_x(inaddr, start_port, display, screen)
        int screen;
 {
        int i;
-       
+
        if (x_port >= 0) {
                lprint("X Redir: X already being redirected.\r\n");
                show_x(0, 0);
@@ -67,79 +65,30 @@ redir_x(inaddr, start_port, display, screen)
 }
 #endif
 
-#ifndef HAVE_INET_ATON
-int
-inet_aton(cp, ia)
-       const char *cp;
-       struct in_addr *ia;
-{
-       u_int32_t addr = inet_addr(cp);
-       if (addr == 0xffffffff)
-               return 0;
-       ia->s_addr = addr;
-       return 1;
-}
-#endif
-
 /*
  * Get our IP address and put it in our_addr
  */
 void
-getouraddr()
+getouraddr(void)
 {
        char buff[256];
-       struct hostent *he;
-       
-       if (gethostname(buff,256) < 0)
-          return;
-       
-       if ((he = gethostbyname(buff)) == NULL)
-          return;
-       
-       our_addr = *(struct in_addr *)he->h_addr;
+       struct hostent *he = NULL;
+
+       if (gethostname(buff,256) == 0)
+            he = gethostbyname(buff);
+        if (he)
+            our_addr = *(struct in_addr *)he->h_addr;
+        if (our_addr.s_addr == 0)
+            our_addr.s_addr = loopback_addr.s_addr;
 }
 
-#if SIZEOF_CHAR_P == 8
-
-struct quehead_32 {
-       u_int32_t qh_link;
-       u_int32_t qh_rlink;
-};
-
-inline void
-insque_32(a, b)
-       void *a;
-       void *b;
-{
-       register struct quehead_32 *element = (struct quehead_32 *) a;
-       register struct quehead_32 *head = (struct quehead_32 *) b;
-       element->qh_link = head->qh_link;
-       head->qh_link = (u_int32_t)element;
-       element->qh_rlink = (u_int32_t)head;
-       ((struct quehead_32 *)(element->qh_link))->qh_rlink
-       = (u_int32_t)element;
-}
-
-inline void
-remque_32(a)
-       void *a;
-{
-       register struct quehead_32 *element = (struct quehead_32 *) a;
-       ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
-       ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link;
-       element->qh_rlink = 0;
-}
-
-#endif /* SIZEOF_CHAR_P == 8 */
-
 struct quehead {
        struct quehead *qh_link;
        struct quehead *qh_rlink;
 };
 
 inline void
-insque(a, b)
-       void *a, *b;
+insque(void *a, void *b)
 {
        register struct quehead *element = (struct quehead *) a;
        register struct quehead *head = (struct quehead *) b;
@@ -151,8 +100,7 @@ insque(a, b)
 }
 
 inline void
-remque(a)
-     void *a;
+remque(void *a)
 {
   register struct quehead *element = (struct quehead *) a;
   ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
@@ -165,27 +113,22 @@ remque(a)
 
 
 int
-add_exec(ex_ptr, do_pty, exec, addr, port)
-       struct ex_list **ex_ptr;
-       int do_pty;
-       char *exec;
-       int addr;
-       int port;
+add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port)
 {
        struct ex_list *tmp_ptr;
-       
+
        /* First, check if the port is "bound" */
        for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
                if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
                   return -1;
        }
-       
+
        tmp_ptr = *ex_ptr;
        *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
        (*ex_ptr)->ex_fport = port;
        (*ex_ptr)->ex_addr = addr;
        (*ex_ptr)->ex_pty = do_pty;
-       (*ex_ptr)->ex_exec = strdup(exec);
+       (*ex_ptr)->ex_exec = (do_pty == 3) ? exec : strdup(exec);
        (*ex_ptr)->ex_next = tmp_ptr;
        return 0;
 }
@@ -215,10 +158,7 @@ strerror(error)
 #ifdef _WIN32
 
 int
-fork_exec(so, ex, do_pty)
-       struct socket *so;
-       char *ex;
-       int do_pty;
+fork_exec(struct socket *so, const char *ex, int do_pty)
 {
     /* not implemented */
     return 0;
@@ -226,15 +166,16 @@ fork_exec(so, ex, do_pty)
 
 #else
 
+#ifndef CONFIG_QEMU
 int
-openpty(amaster, aslave)
-       int *amaster, *aslave;
+slirp_openpty(amaster, aslave)
+     int *amaster, *aslave;
 {
        register int master, slave;
 
 #ifdef HAVE_GRANTPT
        char *ptr;
-       
+
        if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
            grantpt(master) < 0 ||
            unlockpt(master) < 0 ||
@@ -242,7 +183,7 @@ openpty(amaster, aslave)
                close(master);
                return -1;
        }
-       
+
        if ((slave = open(ptr, O_RDWR)) < 0 ||
            ioctl(slave, I_PUSH, "ptem") < 0 ||
            ioctl(slave, I_PUSH, "ldterm") < 0 ||
@@ -251,16 +192,16 @@ openpty(amaster, aslave)
                close(slave);
                return -1;
        }
-       
+
        *amaster = master;
        *aslave = slave;
        return 0;
-       
+
 #else
-       
+
        static char line[] = "/dev/ptyXX";
        register const char *cp1, *cp2;
-       
+
        for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
                line[8] = *cp1;
                for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
@@ -290,6 +231,7 @@ openpty(amaster, aslave)
        return (-1);
 #endif
 }
+#endif
 
 /*
  * XXX This is ugly
@@ -297,56 +239,57 @@ openpty(amaster, aslave)
  * process, which connects to this socket, after which we
  * exec the wanted program.  If something (strange) happens,
  * the accept() call could block us forever.
- * 
+ *
  * do_pty = 0   Fork/exec inetd style
  * do_pty = 1   Fork/exec using slirp.telnetd
  * do_ptr = 2   Fork/exec using pty
  */
 int
-fork_exec(so, ex, do_pty)
-       struct socket *so;
-       char *ex;
-       int do_pty;
+fork_exec(struct socket *so, const char *ex, int do_pty)
 {
        int s;
        struct sockaddr_in addr;
-       int addrlen = sizeof(addr);
+       socklen_t addrlen = sizeof(addr);
        int opt;
-        int master;
-       char *argv[256];
+        int master = -1;
+       const char *argv[256];
 #if 0
        char buff[256];
 #endif
        /* don't want to clobber the original */
        char *bptr;
-       char *curarg;
-       int c, i;
-       
+       const char *curarg;
+       int c, i, ret;
+
        DEBUG_CALL("fork_exec");
        DEBUG_ARG("so = %lx", (long)so);
        DEBUG_ARG("ex = %lx", (long)ex);
        DEBUG_ARG("do_pty = %lx", (long)do_pty);
-       
+
        if (do_pty == 2) {
-               if (openpty(&master, &s) == -1) {
+#if 0
+               if (slirp_openpty(&master, &s) == -1) {
                        lprint("Error: openpty failed: %s\n", strerror(errno));
                        return 0;
                }
+#else
+                return 0;
+#endif
        } else {
                addr.sin_family = AF_INET;
                addr.sin_port = 0;
                addr.sin_addr.s_addr = INADDR_ANY;
-               
+
                if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
                    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
                    listen(s, 1) < 0) {
                        lprint("Error: inet socket: %s\n", strerror(errno));
                        closesocket(s);
-                       
+
                        return 0;
                }
        }
-       
+
        switch(fork()) {
         case -1:
                lprint("Error: fork failed: %s\n", strerror(errno));
@@ -354,7 +297,7 @@ fork_exec(so, ex, do_pty)
                if (do_pty == 2)
                   close(master);
                return 0;
-               
+
         case 0:
                /* Set the DISPLAY */
                if (do_pty == 2) {
@@ -372,9 +315,11 @@ fork_exec(so, ex, do_pty)
                         */
                        s = socket(AF_INET, SOCK_STREAM, 0);
                        addr.sin_addr = loopback_addr;
-                       connect(s, (struct sockaddr *)&addr, addrlen);
+                        do {
+                            ret = connect(s, (struct sockaddr *)&addr, addrlen);
+                        } while (ret < 0 && errno == EINTR);
                }
-               
+
 #if 0
                if (x_port >= 0) {
 #ifdef HAVE_SETENV
@@ -385,13 +330,13 @@ fork_exec(so, ex, do_pty)
                        putenv(buff);
 #endif
                }
-#endif 
+#endif
                dup2(s, 0);
                dup2(s, 1);
                dup2(s, 2);
-               for (s = 3; s <= 255; s++)
+               for (s = getdtablesize() - 1; s >= 3; s--)
                   close(s);
-               
+
                i = 0;
                bptr = strdup(ex); /* No need to free() this */
                if (do_pty == 1) {
@@ -409,21 +354,22 @@ fork_exec(so, ex, do_pty)
                        *bptr++ = (char)0;
                        argv[i++] = strdup(curarg);
                   } while (c);
-               
-               argv[i] = 0;
-               execvp(argv[0], argv);
-               
+
+                argv[i] = NULL;
+               execvp(argv[0], (char **)argv);
+
                /* Ooops, failed, let's tell the user why */
                  {
                          char buff[256];
-                         
-                         sprintf(buff, "Error: execvp of %s failed: %s\n", 
-                                 argv[0], strerror(errno));
+
+                         snprintf(buff, sizeof(buff),
+                                   "Error: execvp of %s failed: %s\n",
+                                   argv[0], strerror(errno));
                          write(2, buff, strlen(buff)+1);
                  }
                close(0); close(1); close(2); /* XXX */
                exit(1);
-               
+
         default:
                if (do_pty == 2) {
                        close(s);
@@ -436,21 +382,23 @@ fork_exec(so, ex, do_pty)
                         * The only reason this will block forever is if socket()
                         * of connect() fail in the child process
                         */
-                       so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
-                       closesocket(s);
+                        do {
+                            so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
+                        } while (so->s < 0 && errno == EINTR);
+                        closesocket(s);
                        opt = 1;
                        setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
                        opt = 1;
                        setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
                }
                fd_nonblock(so->s);
-               
+
                /* Append the telnet options now */
-               if (so->so_m != 0 && do_pty == 1)  {
+                if (so->so_m != NULL && do_pty == 1)  {
                        sbappend(so, so->so_m);
-                       so->so_m = 0;
+                        so->so_m = NULL;
                }
-               
+
                return 1;
        }
 }
@@ -462,10 +410,10 @@ strdup(str)
        const char *str;
 {
        char *bptr;
-       
+
        bptr = (char *)malloc(strlen(str)+1);
        strcpy(bptr, str);
-       
+
        return bptr;
 }
 #endif
@@ -481,7 +429,7 @@ snooze_hup(num)
 #endif
        struct sockaddr_in sock_in;
        char buff[256];
-       
+
        ret = -1;
        if (slirp_socket_passwd) {
                s = socket(AF_INET, SOCK_STREAM, 0);
@@ -511,29 +459,29 @@ snooze_hup(num)
 #endif
        slirp_exit(0);
 }
-       
-       
+
+
 void
 snooze()
 {
        sigset_t s;
        int i;
-       
+
        /* Don't need our data anymore */
        /* XXX This makes SunOS barf */
 /*     brk(0); */
-       
+
        /* Close all fd's */
        for (i = 255; i >= 0; i--)
           close(i);
-       
+
        signal(SIGQUIT, slirp_exit);
        signal(SIGHUP, snooze_hup);
        sigemptyset(&s);
-       
+
        /* Wait for any signal */
        sigsuspend(&s);
-       
+
        /* Just in case ... */
        exit(255);
 }
@@ -546,16 +494,16 @@ relay(s)
        int n;
        fd_set readfds;
        struct ttys *ttyp;
-       
+
        /* Don't need our data anymore */
        /* XXX This makes SunOS barf */
 /*     brk(0); */
-       
+
        signal(SIGQUIT, slirp_exit);
        signal(SIGHUP, slirp_exit);
         signal(SIGINT, slirp_exit);
        signal(SIGTERM, slirp_exit);
-       
+
        /* Fudge to get term_raw and term_restore to work */
        if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
          lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
@@ -564,18 +512,18 @@ relay(s)
        ttyp->fd = 0;
        ttyp->flags |= TTY_CTTY;
        term_raw(ttyp);
-       
+
        while (1) {
                FD_ZERO(&readfds);
-               
+
                FD_SET(0, &readfds);
                FD_SET(s, &readfds);
-               
+
                n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
-               
+
                if (n <= 0)
                   slirp_exit(0);
-               
+
                if (FD_ISSET(0, &readfds)) {
                        n = read(0, buf, 8192);
                        if (n <= 0)
@@ -584,7 +532,7 @@ relay(s)
                        if (n <= 0)
                           slirp_exit(0);
                }
-               
+
                if (FD_ISSET(s, &readfds)) {
                        n = read(s, buf, 8192);
                        if (n <= 0)
@@ -594,12 +542,24 @@ relay(s)
                           slirp_exit(0);
                }
        }
-       
+
        /* Just in case.... */
        exit(1);
 }
 #endif
 
+#ifdef CONFIG_QEMU
+#include "monitor.h"
+
+void lprint(const char *format, ...)
+{
+    va_list args;
+
+    va_start(args, format);
+    monitor_vprintf(cur_mon, format, args);
+    va_end(args);
+}
+#else
 int (*lprint_print) _P((void *, const char *, va_list));
 char *lprint_ptr, *lprint_ptr2, **lprint_arg;
 
@@ -611,7 +571,7 @@ lprint(va_alist) va_dcl
 #endif
 {
        va_list args;
-        
+
 #ifdef __STDC__
         va_start(args, format);
 #else
@@ -628,33 +588,33 @@ lprint(va_alist) va_dcl
                        int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
                        int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
                        int deltap = lprint_ptr -         lprint_sb->sb_data;
-                                               
+
                        lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
                                                             lprint_sb->sb_datalen + TCP_SNDSPACE);
-                       
+
                        /* Adjust all values */
                        lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
                        lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
                        lprint_ptr =         lprint_sb->sb_data + deltap;
-                       
+
                        lprint_sb->sb_datalen += TCP_SNDSPACE;
                }
        }
-#endif 
+#endif
        if (lprint_print)
           lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
-       
+
        /* Check if they want output to be logged to file as well */
        if (lfd) {
-               /* 
+               /*
                 * Remove \r's
                 * otherwise you'll get ^M all over the file
                 */
                int len = strlen(format);
                char *bptr1, *bptr2;
-               
+
                bptr1 = bptr2 = strdup(format);
-               
+
                while (len--) {
                        if (*bptr1 == '\r')
                           memcpy(bptr1, bptr1+1, len+1);
@@ -677,12 +637,12 @@ add_emu(buff)
        char *buff3 = buff4;
        struct emu_t *emup;
        struct socket *so;
-       
+
        if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
                lprint("Error: Bad arguments\r\n");
                return;
        }
-       
+
        if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
                lport = 0;
                if (sscanf(buff1, "%d", &fport) != 1) {
@@ -690,7 +650,7 @@ add_emu(buff)
                        return;
                }
        }
-       
+
        if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
                buff3 = 0;
                if (sscanf(buff2, "%256s", buff1) != 1) {
@@ -698,7 +658,7 @@ add_emu(buff)
                        return;
                }
        }
-       
+
        if (buff3) {
                if (strcmp(buff3, "lowdelay") == 0)
                   tos = IPTOS_LOWDELAY;
@@ -709,7 +669,7 @@ add_emu(buff)
                        return;
                }
        }
-       
+
        if (strcmp(buff1, "ftp") == 0)
           emu = EMU_FTP;
        else if (strcmp(buff1, "irc") == 0)
@@ -720,7 +680,7 @@ add_emu(buff)
                lprint("Error: Unknown service\r\n");
                return;
        }
-       
+
        /* First, check that it isn't already emulated */
        for (emup = tcpemu; emup; emup = emup->next) {
                if (emup->lport == lport && emup->fport == fport) {
@@ -728,7 +688,7 @@ add_emu(buff)
                        return;
                }
        }
-       
+
        /* link it */
        emup = (struct emu_t *)malloc(sizeof (struct emu_t));
        emup->lport = (u_int16_t)lport;
@@ -737,7 +697,7 @@ add_emu(buff)
        emup->emu = emu;
        emup->next = tcpemu;
        tcpemu = emup;
-       
+
        /* And finally, mark all current sessions, if any, as being emulated */
        for (so = tcb.so_next; so != &tcb; so = so->so_next) {
                if ((lport && lport == ntohs(so->so_lport)) ||
@@ -748,9 +708,10 @@ add_emu(buff)
                           so->so_iptos = tos;
                }
        }
-       
+
        lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
 }
+#endif
 
 #ifdef BAD_SPRINTF
 
@@ -795,17 +756,16 @@ sprintf_len(va_alist) va_dcl
 #endif
 
 void
-u_sleep(usec)
-       int usec;
+u_sleep(int usec)
 {
        struct timeval t;
        fd_set fdset;
-       
+
        FD_ZERO(&fdset);
-       
+
        t.tv_sec = 0;
        t.tv_usec = usec * 1000;
-       
+
        select(0, &fdset, &fdset, &fdset, &t);
 }
 
@@ -814,16 +774,19 @@ u_sleep(usec)
  */
 
 void
-fd_nonblock(fd)
-       int fd;
+fd_nonblock(int fd)
 {
 #ifdef FIONBIO
-       int opt = 1;
-       
+#ifdef _WIN32
+        long opt = 1;
+#else
+        int opt = 1;
+#endif
+
        ioctlsocket(fd, FIONBIO, &opt);
 #else
        int opt;
-       
+
        opt = fcntl(fd, F_GETFL, 0);
        opt |= O_NONBLOCK;
        fcntl(fd, F_SETFL, opt);
@@ -831,16 +794,15 @@ fd_nonblock(fd)
 }
 
 void
-fd_block(fd)
-       int fd;
+fd_block(int fd)
 {
 #ifdef FIONBIO
        int opt = 0;
-       
+
        ioctlsocket(fd, FIONBIO, &opt);
 #else
        int opt;
-       
+
        opt = fcntl(fd, F_GETFL, 0);
        opt &= ~O_NONBLOCK;
        fcntl(fd, F_SETFL, opt);
@@ -864,10 +826,10 @@ rsh_exec(so,ns, user, host, args)
        int fd0[2];
        int s;
        char buff[256];
-       
+
        DEBUG_CALL("rsh_exec");
        DEBUG_ARG("so = %lx", (long)so);
-       
+
        if (pipe(fd)<0) {
           lprint("Error: pipe failed: %s\n", strerror(errno));
           return 0;
@@ -881,14 +843,14 @@ rsh_exec(so,ns, user, host, args)
           return 0;
         }
 #else
-        if (openpty(&fd0[0], &fd0[1]) == -1) {
+        if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
           close(fd[0]);
           close(fd[1]);
           lprint("Error: openpty failed: %s\n", strerror(errno));
           return 0;
         }
 #endif
-       
+
        switch(fork()) {
         case -1:
            lprint("Error: fork failed: %s\n", strerror(errno));
@@ -897,11 +859,11 @@ rsh_exec(so,ns, user, host, args)
            close(fd0[0]);
            close(fd0[1]);
            return 0;
-           
+
         case 0:
            close(fd[0]);
            close(fd0[0]);
-           
+
                /* Set the DISPLAY */
            if (x_port >= 0) {
 #ifdef HAVE_SETENV
@@ -912,29 +874,29 @@ rsh_exec(so,ns, user, host, args)
              putenv(buff);
 #endif
            }
-           
+
            dup2(fd0[1], 0);
            dup2(fd0[1], 1);
            dup2(fd[1], 2);
            for (s = 3; s <= 255; s++)
              close(s);
-           
+
            execlp("rsh","rsh","-l", user, host, args, NULL);
-           
+
            /* Ooops, failed, let's tell the user why */
-           
-           sprintf(buff, "Error: execlp of %s failed: %s\n", 
+
+           sprintf(buff, "Error: execlp of %s failed: %s\n",
                    "rsh", strerror(errno));
            write(2, buff, strlen(buff)+1);
            close(0); close(1); close(2); /* XXX */
            exit(1);
-           
+
         default:
           close(fd[1]);
           close(fd0[1]);
           ns->s=fd[0];
           so->s=fd0[0];
-          
+
           return 1;
        }
 }