All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 03/11] slirp: Avoid zombie processes after fork_exec
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
                   ` (2 preceding siblings ...)
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 02/11] net: Fix and improved ordered packet delivery Jan Kiszka
@ 2009-05-08 10:34 ` Jan Kiszka
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 06/11] slirp: Reorder initialization Jan Kiszka
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

Slirp uses fork_exec for spawning service processes, and QEMU uses this
for running smbd. As SIGCHLD is not handled, these processes become
zombies on termination. Fix this by installing a proper signal handler,
but also make sure we disable the signal while waiting on forked network
setup/shutdown scripts.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |   60 ++++++++++++++++++++++++++++++++++--------------------------
 vl.c  |   13 +++++++++++--
 2 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/net.c b/net.c
index 671138f..6a5c698 100644
--- a/net.c
+++ b/net.c
@@ -1049,38 +1049,46 @@ static int tap_open(char *ifname, int ifname_size)
 
 static int launch_script(const char *setup_script, const char *ifname, int fd)
 {
+    sigset_t oldmask, mask;
     int pid, status;
     char *args[3];
     char **parg;
 
-        /* try to launch network script */
-        pid = fork();
-        if (pid >= 0) {
-            if (pid == 0) {
-                int open_max = sysconf (_SC_OPEN_MAX), i;
-                for (i = 0; i < open_max; i++)
-                    if (i != STDIN_FILENO &&
-                        i != STDOUT_FILENO &&
-                        i != STDERR_FILENO &&
-                        i != fd)
-                        close(i);
-
-                parg = args;
-                *parg++ = (char *)setup_script;
-                *parg++ = (char *)ifname;
-                *parg++ = NULL;
-                execv(setup_script, args);
-                _exit(1);
-            }
-            while (waitpid(pid, &status, 0) != pid);
-            if (!WIFEXITED(status) ||
-                WEXITSTATUS(status) != 0) {
-                fprintf(stderr, "%s: could not launch network script\n",
-                        setup_script);
-                return -1;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGCHLD);
+    sigprocmask(SIG_BLOCK, &mask, &oldmask);
+
+    /* try to launch network script */
+    pid = fork();
+    if (pid == 0) {
+        int open_max = sysconf(_SC_OPEN_MAX), i;
+
+        for (i = 0; i < open_max; i++) {
+            if (i != STDIN_FILENO &&
+                i != STDOUT_FILENO &&
+                i != STDERR_FILENO &&
+                i != fd) {
+                close(i);
             }
         }
-    return 0;
+        parg = args;
+        *parg++ = (char *)setup_script;
+        *parg++ = (char *)ifname;
+        *parg++ = NULL;
+        execv(setup_script, args);
+        _exit(1);
+    } else if (pid > 0) {
+        while (waitpid(pid, &status, 0) != pid) {
+            /* loop */
+        }
+        sigprocmask(SIG_SETMASK, &oldmask, NULL);
+
+        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+            return 0;
+        }
+    }
+    fprintf(stderr, "%s: could not launch network script\n", setup_script);
+    return -1;
 }
 
 static int net_tap_init(VLANState *vlan, const char *model,
diff --git a/vl.c b/vl.c
index 867111c..81569f0 100644
--- a/vl.c
+++ b/vl.c
@@ -4780,7 +4780,12 @@ static void termsig_handler(int signal)
     qemu_system_shutdown_request();
 }
 
-static void termsig_setup(void)
+static void sigchld_handler(int signal)
+{
+    waitpid(-1, NULL, WNOHANG);
+}
+
+static void sighandler_setup(void)
 {
     struct sigaction act;
 
@@ -4789,6 +4794,10 @@ static void termsig_setup(void)
     sigaction(SIGINT,  &act, NULL);
     sigaction(SIGHUP,  &act, NULL);
     sigaction(SIGTERM, &act, NULL);
+
+    act.sa_handler = sigchld_handler;
+    act.sa_flags = SA_NOCLDSTOP;
+    sigaction(SIGCHLD, &act, NULL);
 }
 
 #endif
@@ -5784,7 +5793,7 @@ int main(int argc, char **argv, char **envp)
 
 #ifndef _WIN32
     /* must be after terminal init, SDL library changes signal handlers */
-    termsig_setup();
+    sighandler_setup();
 #endif
 
     /* Maintain compatibility with multiple stdio monitors */

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
@ 2009-05-08 10:34 ` Jan Kiszka
  2009-05-19  7:57   ` Mark McLoughlin
  2009-05-28 15:04   ` Mark McLoughlin
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 01/11] net: Don't deliver to disabled interfaces in qemu_sendv_packet Jan Kiszka
                   ` (10 subsequent siblings)
  11 siblings, 2 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

OK, last try: ea053add70 broke -net socket, ffad4116b9 tried to fix it
but broke error reporting of invalid parameters. So this patch widely
reverts ffad4116b9 again and intead fixes those callers of check_params
that originally suffered from overwritten buffers by using separate
ones.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c    |   23 ++++++++++++-----------
 sysemu.h |    3 ++-
 vl.c     |   39 ++++++++++++++-------------------------
 3 files changed, 28 insertions(+), 37 deletions(-)

diff --git a/net.c b/net.c
index 6a5c698..cf00c9c 100644
--- a/net.c
+++ b/net.c
@@ -1826,7 +1826,7 @@ int net_client_init(const char *device, const char *p)
         uint8_t *macaddr;
         int idx = nic_get_free_idx();
 
-        if (check_params(nic_params, p) < 0) {
+        if (check_params(buf, sizeof(buf), nic_params, p) < 0) {
             fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                     buf, p);
             return -1;
@@ -1877,7 +1877,7 @@ int net_client_init(const char *device, const char *p)
         static const char * const slirp_params[] = {
             "vlan", "name", "hostname", "restrict", "ip", NULL
         };
-        if (check_params(slirp_params, p) < 0) {
+        if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
             fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                     buf, p);
             return -1;
@@ -1928,7 +1928,7 @@ int net_client_init(const char *device, const char *p)
         };
         char ifname[64];
 
-        if (check_params(tap_params, p) < 0) {
+        if (check_params(buf, sizeof(buf), tap_params, p) < 0) {
             fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                     buf, p);
             return -1;
@@ -1944,12 +1944,12 @@ int net_client_init(const char *device, const char *p)
 #elif defined (_AIX)
 #else
     if (!strcmp(device, "tap")) {
-        char ifname[64];
+        char ifname[64], chkbuf[64];
         char setup_script[1024], down_script[1024];
         int fd;
         vlan->nb_host_devs++;
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
-            if (check_params(fd_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -1962,7 +1962,7 @@ int net_client_init(const char *device, const char *p)
             static const char * const tap_params[] = {
                 "vlan", "name", "ifname", "script", "downscript", NULL
             };
-            if (check_params(tap_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), tap_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -1981,9 +1981,10 @@ int net_client_init(const char *device, const char *p)
     } else
 #endif
     if (!strcmp(device, "socket")) {
+        char chkbuf[64];
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
             int fd;
-            if (check_params(fd_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -1996,7 +1997,7 @@ int net_client_init(const char *device, const char *p)
             static const char * const listen_params[] = {
                 "vlan", "name", "listen", NULL
             };
-            if (check_params(listen_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), listen_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -2006,7 +2007,7 @@ int net_client_init(const char *device, const char *p)
             static const char * const connect_params[] = {
                 "vlan", "name", "connect", NULL
             };
-            if (check_params(connect_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), connect_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -2016,7 +2017,7 @@ int net_client_init(const char *device, const char *p)
             static const char * const mcast_params[] = {
                 "vlan", "name", "mcast", NULL
             };
-            if (check_params(mcast_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), mcast_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -2037,7 +2038,7 @@ int net_client_init(const char *device, const char *p)
         char vde_sock[1024], vde_group[512];
 	int vde_port, vde_mode;
 
-        if (check_params(vde_params, p) < 0) {
+        if (check_params(buf, sizeof(buf), vde_params, p) < 0) {
             fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                     buf, p);
             return -1;
diff --git a/sysemu.h b/sysemu.h
index 9bb9fbc..50438a6 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -257,6 +257,7 @@ const char *get_opt_name(char *buf, int buf_size, const char *p, char delim);
 const char *get_opt_value(char *buf, int buf_size, const char *p);
 int get_param_value(char *buf, int buf_size,
                     const char *tag, const char *str);
-int check_params(const char * const *params, const char *str);
+int check_params(char *buf, int buf_size,
+                 const char * const *params, const char *str);
 
 #endif
diff --git a/vl.c b/vl.c
index 81569f0..fad386b 100644
--- a/vl.c
+++ b/vl.c
@@ -1869,45 +1869,34 @@ int get_param_value(char *buf, int buf_size,
     return 0;
 }
 
-int check_params(const char * const *params, const char *str)
+int check_params(char *buf, int buf_size,
+                 const char * const *params, const char *str)
 {
-    int name_buf_size = 1;
     const char *p;
-    char *name_buf;
-    int i, len;
-    int ret = 0;
-
-    for (i = 0; params[i] != NULL; i++) {
-        len = strlen(params[i]) + 1;
-        if (len > name_buf_size) {
-            name_buf_size = len;
-        }
-    }
-    name_buf = qemu_malloc(name_buf_size);
+    int i;
 
     p = str;
     while (*p != '\0') {
-        p = get_opt_name(name_buf, name_buf_size, p, '=');
+        p = get_opt_name(buf, buf_size, p, '=');
         if (*p != '=') {
-            ret = -1;
-            break;
+            return -1;
         }
         p++;
-        for(i = 0; params[i] != NULL; i++)
-            if (!strcmp(params[i], name_buf))
+        for (i = 0; params[i] != NULL; i++) {
+            if (!strcmp(params[i], buf)) {
                 break;
+            }
+        }
         if (params[i] == NULL) {
-            ret = -1;
-            break;
+            return -1;
         }
         p = get_opt_value(NULL, 0, p);
-        if (*p != ',')
+        if (*p != ',') {
             break;
+        }
         p++;
     }
-
-    qemu_free(name_buf);
-    return ret;
+    return 0;
 }
 
 /***********************************************************/
@@ -2260,7 +2249,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
                                            "cache", "format", "serial", "werror",
                                            NULL };
 
-    if (check_params(params, str) < 0) {
+    if (check_params(buf, sizeof(buf), params, str) < 0) {
          fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
                          buf, str);
          return -1;

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 02/11] net: Fix and improved ordered packet delivery
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users Jan Kiszka
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 01/11] net: Don't deliver to disabled interfaces in qemu_sendv_packet Jan Kiszka
@ 2009-05-08 10:34 ` Jan Kiszka
  2009-05-08 15:24   ` Mark McLoughlin
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 03/11] slirp: Avoid zombie processes after fork_exec Jan Kiszka
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

Fix a race in qemu_send_packet when delivering deferred packets and
add proper deferring also to qemu_sendv_packet.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |   57 ++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 42 insertions(+), 15 deletions(-)

diff --git a/net.c b/net.c
index b93b3a6..671138f 100644
--- a/net.c
+++ b/net.c
@@ -438,8 +438,8 @@ void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size)
         vlan->delivering = 1;
         qemu_deliver_packet(vc, buf, size);
         while ((packet = vlan->send_queue) != NULL) {
-            qemu_deliver_packet(packet->sender, packet->data, packet->size);
             vlan->send_queue = packet->next;
+            qemu_deliver_packet(packet->sender, packet->data, packet->size);
             qemu_free(packet);
         }
         vlan->delivering = 0;
@@ -476,30 +476,57 @@ static ssize_t calc_iov_length(const struct iovec *iov, int iovcnt)
     return offset;
 }
 
-ssize_t qemu_sendv_packet(VLANClientState *vc1, const struct iovec *iov,
+ssize_t qemu_sendv_packet(VLANClientState *sender, const struct iovec *iov,
                           int iovcnt)
 {
-    VLANState *vlan = vc1->vlan;
+    VLANState *vlan = sender->vlan;
     VLANClientState *vc;
+    VLANPacket *packet;
     ssize_t max_len = 0;
+    int i;
 
-    if (vc1->link_down)
+    if (sender->link_down)
         return calc_iov_length(iov, iovcnt);
 
-    for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
-        ssize_t len = 0;
+    if (vlan->delivering) {
+        max_len = calc_iov_length(iov, iovcnt);
 
-        if (vc == vc1)
-            continue;
+        packet = qemu_malloc(sizeof(VLANPacket) + max_len);
+        packet->next = vlan->send_queue;
+        packet->sender = sender;
+        packet->size = 0;
+        for (i = 0; i < iovcnt; i++) {
+            size_t len = iov[i].iov_len;
+
+            memcpy(packet->data + packet->size, iov[i].iov_base, len);
+            packet->size += len;
+        }
+        vlan->send_queue = packet;
+    } else {
+        vlan->delivering = 1;
+
+        for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
+            ssize_t len = 0;
 
-        if (vc->link_down)
-            len = calc_iov_length(iov, iovcnt);
-        else if (vc->fd_readv)
-            len = vc->fd_readv(vc->opaque, iov, iovcnt);
-        else if (vc->fd_read)
-            len = vc_sendv_compat(vc, iov, iovcnt);
+            if (vc == sender) {
+                continue;
+            }
+            if (vc->link_down) {
+                len = calc_iov_length(iov, iovcnt);
+            } else if (vc->fd_readv) {
+                len = vc->fd_readv(vc->opaque, iov, iovcnt);
+            } else if (vc->fd_read) {
+                len = vc_sendv_compat(vc, iov, iovcnt);
+            }
+            max_len = MAX(max_len, len);
+        }
 
-        max_len = MAX(max_len, len);
+        while ((packet = vlan->send_queue) != NULL) {
+            vlan->send_queue = packet->next;
+            qemu_deliver_packet(packet->sender, packet->data, packet->size);
+            qemu_free(packet);
+        }
+        vlan->delivering = 0;
     }
 
     return max_len;

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 01/11] net: Don't deliver to disabled interfaces in qemu_sendv_packet
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users Jan Kiszka
@ 2009-05-08 10:34 ` Jan Kiszka
  2009-05-08 15:20   ` Mark McLoughlin
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 02/11] net: Fix and improved ordered packet delivery Jan Kiszka
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net.c b/net.c
index d556015..b93b3a6 100644
--- a/net.c
+++ b/net.c
@@ -494,7 +494,7 @@ ssize_t qemu_sendv_packet(VLANClientState *vc1, const struct iovec *iov,
 
         if (vc->link_down)
             len = calc_iov_length(iov, iovcnt);
-        if (vc->fd_readv)
+        else if (vc->fd_readv)
             len = vc->fd_readv(vc->opaque, iov, iovcnt);
         else if (vc->fd_read)
             len = vc_sendv_compat(vc, iov, iovcnt);

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements
@ 2009-05-08 10:34 Jan Kiszka
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users Jan Kiszka
                   ` (11 more replies)
  0 siblings, 12 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

This series starts with four networking-related fixes and then focuses
on a grand refactoring of the slirp user space IP stack configuration.

The major contribution is that the virtual IP addresses used by slirp
can now be (almost) freely configured. This enables sophisticated
virtual network setups, specifically with guests that depends on
specific addresses.

Find this series also at git://git.kiszka.org/qemu.git queues/net

Jan Kiszka (11):
      net: Don't deliver to disabled interfaces in qemu_sendv_packet
      net: Fix and improved ordered packet delivery
      slirp: Avoid zombie processes after fork_exec
      net: Real fix for check_params users
      net: Improve parameter error reporting
      slirp: Reorder initialization
      Introduce get_next_param_value
      slirp: Move smb, redir, tftp and bootp parameters and -net channel
      slirp: Rework internal configuration
      slirp: Rework external configuration interface
      slirp: Bind support for host forwarding rules

 hw/pci-hotplug.c  |    7 +-
 net.c             |  710 +++++++++++++++++++++++++++++++++++++++--------------
 net.h             |    5 +-
 qemu-options.hx   |  226 ++++++++++--------
 slirp/bootp.c     |   30 +--
 slirp/ctl.h       |    7 -
 slirp/ip_icmp.c   |   15 +-
 slirp/ip_input.c  |    9 +-
 slirp/libslirp.h  |   20 +-
 slirp/main.h      |   12 +-
 slirp/misc.c      |    9 +-
 slirp/misc.h      |    4 +-
 slirp/slirp.c     |  167 +++++++------
 slirp/slirp.h     |    1 -
 slirp/socket.c    |   23 +-
 slirp/socket.h    |    2 +-
 slirp/tcp_input.c |   16 +-
 slirp/tcp_subr.c  |  133 +++-------
 slirp/tftp.c      |    6 +-
 slirp/udp.c       |   30 ++-
 slirp/udp.h       |    2 +-
 sysemu.h          |    5 +-
 vl.c              |   77 ++++---
 23 files changed, 937 insertions(+), 579 deletions(-)
 delete mode 100644 slirp/ctl.h

--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 07/11] Introduce get_next_param_value
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
                   ` (5 preceding siblings ...)
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 10/11] slirp: Rework external configuration interface Jan Kiszka
@ 2009-05-08 10:34 ` Jan Kiszka
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 05/11] net: Improve parameter error reporting Jan Kiszka
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

In order to parse multiple instances of the same param=value pair,
introduce get_next_param_value which can pass back to string parsing
position after reading a parameter value.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 sysemu.h |    2 ++
 vl.c     |   17 +++++++++++++----
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/sysemu.h b/sysemu.h
index 50438a6..4b0ae99 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -257,6 +257,8 @@ const char *get_opt_name(char *buf, int buf_size, const char *p, char delim);
 const char *get_opt_value(char *buf, int buf_size, const char *p);
 int get_param_value(char *buf, int buf_size,
                     const char *tag, const char *str);
+int get_next_param_value(char *buf, int buf_size,
+                         const char *tag, const char **pstr);
 int check_params(char *buf, int buf_size,
                  const char * const *params, const char *str);
 
diff --git a/vl.c b/vl.c
index 8b641f5..4982486 100644
--- a/vl.c
+++ b/vl.c
@@ -1844,20 +1844,23 @@ const char *get_opt_value(char *buf, int buf_size, const char *p)
     return p;
 }
 
-int get_param_value(char *buf, int buf_size,
-                    const char *tag, const char *str)
+int get_next_param_value(char *buf, int buf_size,
+                         const char *tag, const char **pstr)
 {
     const char *p;
     char option[128];
 
-    p = str;
+    p = *pstr;
     for(;;) {
         p = get_opt_name(option, sizeof(option), p, '=');
         if (*p != '=')
             break;
         p++;
         if (!strcmp(tag, option)) {
-            (void)get_opt_value(buf, buf_size, p);
+            *pstr = get_opt_value(buf, buf_size, p);
+            if (**pstr == ',') {
+                (*pstr)++;
+            }
             return strlen(buf);
         } else {
             p = get_opt_value(NULL, 0, p);
@@ -1869,6 +1872,12 @@ int get_param_value(char *buf, int buf_size,
     return 0;
 }
 
+int get_param_value(char *buf, int buf_size,
+                    const char *tag, const char *str)
+{
+    return get_next_param_value(buf, buf_size, tag, &str);
+}
+
 int check_params(char *buf, int buf_size,
                  const char * const *params, const char *str)
 {

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 08/11] slirp: Move smb, redir, tftp and bootp parameters and -net channel
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
                   ` (7 preceding siblings ...)
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 05/11] net: Improve parameter error reporting Jan Kiszka
@ 2009-05-08 10:34 ` Jan Kiszka
  2009-05-28 15:07   ` Mark McLoughlin
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 09/11] slirp: Rework internal configuration Jan Kiszka
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

So far a couple of slirp-related parameters were expressed via
stand-alone command line options. This it inconsistent and unintuitive.
Moreover, it prevents both dynamically reconfigured (host_net_add/
delete) and multi-instance slirp.

This patch refactors the configuration by turning -smb, -redir, -tftp
and -bootp as well as -net channel into options of "-net user". The old
stand-alone command line options are still processed, but no longer
advertised. This allows smooth migration of management applications to
to the new syntax and also the extension of that syntax later in this
series.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |  157 +++++++++++++++++++++++++++++++----------
 net.h            |    3 +
 qemu-options.hx  |  209 +++++++++++++++++++++++++++++-------------------------
 slirp/bootp.c    |    4 +
 slirp/libslirp.h |    5 +
 slirp/main.h     |    2 +
 slirp/slirp.c    |   10 ++-
 slirp/tftp.c     |    6 +-
 vl.c             |    6 +-
 9 files changed, 254 insertions(+), 148 deletions(-)

diff --git a/net.c b/net.c
index b20a907..b5238e8 100644
--- a/net.c
+++ b/net.c
@@ -551,13 +551,18 @@ static void config_error(Monitor *mon, const char *fmt, ...)
 
 /* slirp network adapter */
 
+#define SLIRP_CFG_REDIR 1
+
 struct slirp_config_str {
     struct slirp_config_str *next;
-    const char *str;
+    int flags;
+    char str[1024];
 };
 
 static int slirp_inited;
-static struct slirp_config_str *slirp_redirs;
+static struct slirp_config_str *slirp_configs;
+const char *legacy_tftp_prefix;
+const char *legacy_bootp_filename;
 #ifndef _WIN32
 static const char *slirp_smb_export;
 #endif
@@ -565,6 +570,7 @@ static VLANClientState *slirp_vc;
 
 static void slirp_smb(const char *exported_dir);
 static void slirp_redirection(Monitor *mon, const char *redir_str);
+static void vmchannel_init(Monitor *mon, const char *config_str);
 
 int slirp_can_output(void)
 {
@@ -603,25 +609,40 @@ static void net_slirp_cleanup(VLANClientState *vc)
     slirp_in_use = 0;
 }
 
-static int net_slirp_init(VLANState *vlan, const char *model, const char *name,
-                          int restricted, const char *ip)
+static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
+                          const char *name, int restricted, const char *ip,
+                          const char *tftp_export, const char *bootfile,
+                          const char *smb_export)
 {
     if (slirp_in_use) {
         /* slirp only supports a single instance so far */
         return -1;
     }
     if (!slirp_inited) {
+        if (!tftp_export) {
+            tftp_export = legacy_tftp_prefix;
+        }
+        if (!bootfile) {
+            bootfile = legacy_bootp_filename;
+        }
         slirp_inited = 1;
-        slirp_init(restricted, ip);
+        slirp_init(restricted, ip, tftp_export, bootfile);
 
-        while (slirp_redirs) {
-            struct slirp_config_str *config = slirp_redirs;
+        while (slirp_configs) {
+            struct slirp_config_str *config = slirp_configs;
 
-            slirp_redirection(NULL, config->str);
-            slirp_redirs = config->next;
+            if (config->flags & SLIRP_CFG_REDIR) {
+                slirp_redirection(mon, config->str);
+            } else {
+                vmchannel_init(mon, config->str);
+            }
+            slirp_configs = config->next;
             qemu_free(config);
         }
 #ifndef _WIN32
+        if (smb_export) {
+            slirp_smb_export = smb_export;
+        }
         if (slirp_smb_export) {
             slirp_smb(slirp_smb_export);
         }
@@ -696,9 +717,10 @@ void net_slirp_redir(Monitor *mon, const char *redir_str)
             monitor_printf(mon, "user mode network stack not in use\n");
         } else {
             config = qemu_malloc(sizeof(*config));
-            config->str = redir_str;
-            config->next = slirp_redirs;
-            slirp_redirs = config;
+            pstrcpy(config->str, sizeof(config->str), redir_str);
+            config->flags = SLIRP_CFG_REDIR;
+            config->next = slirp_configs;
+            slirp_configs = config;
         }
         return;
     }
@@ -827,6 +849,36 @@ static void vmchannel_read(void *opaque, const uint8_t *buf, int size)
     slirp_socket_recv(4, vmc->port, buf, size);
 }
 
+static void vmchannel_init(Monitor *mon, const char *config_str)
+{
+    struct VMChannel *vmc;
+    char *devname;
+    char name[20];
+    int port;
+
+    port = strtol(config_str, &devname, 10);
+    if (port < 1 || port > 65535 || *devname != ':') {
+        config_error(mon, "invalid vmchannel port number\n");
+        return;
+    }
+    devname++;
+
+    vmc = qemu_malloc(sizeof(struct VMChannel));
+    snprintf(name, sizeof(name), "vmchannel%d", port);
+    vmc->hd = qemu_chr_open(name, devname, NULL);
+    if (!vmc->hd) {
+        config_error(mon, "could not open vmchannel device '%s'\n", devname);
+        qemu_free(vmc);
+        return;
+    }
+    vmc->port = port;
+
+    slirp_add_exec(3, vmc->hd, 4, port);
+    qemu_chr_add_handlers(vmc->hd, vmchannel_can_read, vmchannel_read,
+                          NULL, vmc);
+    return;
+}
+
 #endif /* CONFIG_SLIRP */
 
 #if !defined(_WIN32)
@@ -1936,10 +1988,16 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
 #ifdef CONFIG_SLIRP
     if (!strcmp(device, "user")) {
         static const char * const slirp_params[] = {
-            "vlan", "name", "hostname", "restrict", "ip", NULL
+            "vlan", "name", "hostname", "restrict", "ip", "tftp", "bootfile",
+            "smb", "redir", "channel", NULL
         };
+        struct slirp_config_str *config;
+        char *tftp_export = NULL;
+        char *bootfile = NULL;
+        char *smb_export = NULL;
         int restricted = 0;
         char *ip = NULL;
+        const char *q;
 
         if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
             config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
@@ -1955,34 +2013,59 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         if (get_param_value(buf, sizeof(buf), "ip", p)) {
             ip = qemu_strdup(buf);
         }
+        if (get_param_value(buf, sizeof(buf), "tftp", p)) {
+            tftp_export = qemu_strdup(buf);
+        }
+        if (get_param_value(buf, sizeof(buf), "bootfile", p)) {
+            bootfile = qemu_strdup(buf);
+        }
+        if (get_param_value(buf, sizeof(buf), "smb", p)) {
+            smb_export = qemu_strdup(buf);
+        }
+        q = p;
+        while (1) {
+            config = qemu_malloc(sizeof(*config));
+            if (!get_next_param_value(config->str, sizeof(config->str),
+                                      "redir", &q)) {
+                break;
+            }
+            config->flags = SLIRP_CFG_REDIR;
+            config->next = slirp_configs;
+            slirp_configs = config;
+            config = NULL;
+        }
+        q = p;
+        while (1) {
+            config = qemu_malloc(sizeof(*config));
+            if (!get_next_param_value(config->str, sizeof(config->str),
+                                      "channel", &q)) {
+                break;
+            }
+            config->flags = 0;
+            config->next = slirp_configs;
+            slirp_configs = config;
+            config = NULL;
+        }
+        qemu_free(config);
         vlan->nb_host_devs++;
-        ret = net_slirp_init(vlan, device, name, restricted, ip);
+        ret = net_slirp_init(mon, vlan, device, name, restricted, ip,
+                             tftp_export, bootfile, smb_export);
         qemu_free(ip);
+        qemu_free(tftp_export);
+        qemu_free(bootfile);
+        qemu_free(smb_export);
     } else if (!strcmp(device, "channel")) {
-        long port;
-        char name[20], *devname;
-        struct VMChannel *vmc;
-
-        port = strtol(p, &devname, 10);
-        devname++;
-        if (port < 1 || port > 65535) {
-            config_error(mon, "vmchannel wrong port number\n");
-            ret = -1;
-            goto out;
-        }
-        vmc = malloc(sizeof(struct VMChannel));
-        snprintf(name, 20, "vmchannel%ld", port);
-        vmc->hd = qemu_chr_open(name, devname, NULL);
-        if (!vmc->hd) {
-            config_error(mon, "could not open vmchannel device '%s'\n",
-                         devname);
-            ret = -1;
-            goto out;
+        if (!slirp_inited) {
+            struct slirp_config_str *config;
+
+            config = qemu_malloc(sizeof(*config));
+            pstrcpy(config->str, sizeof(config->str), p);
+            config->flags = 0;
+            config->next = slirp_configs;
+            slirp_configs = config;
+        } else {
+            vmchannel_init(mon, p);
         }
-        vmc->port = port;
-        slirp_add_exec(3, vmc->hd, 4, port);
-        qemu_chr_add_handlers(vmc->hd, vmchannel_can_read, vmchannel_read,
-                NULL, vmc);
         ret = 0;
     } else
 #endif
diff --git a/net.h b/net.h
index 4f8f393..980c380 100644
--- a/net.h
+++ b/net.h
@@ -108,6 +108,9 @@ uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
 void net_checksum_calculate(uint8_t *data, int length);
 
 /* from net.c */
+extern const char *legacy_tftp_prefix;
+extern const char *legacy_bootp_filename;
+
 int net_client_init(Monitor *mon, const char *device, const char *p);
 void net_client_uninit(NICInfo *nd);
 int net_client_parse(const char *str);
diff --git a/qemu-options.hx b/qemu-options.hx
index 87af798..e721f60 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -723,13 +723,27 @@ STEXI
 @table @option
 ETEXI
 
+HXCOMM Legacy slirp options (now moved to -net user):
+#ifdef CONFIG_SLIRP
+DEF("tftp", HAS_ARG, QEMU_OPTION_tftp, "")
+DEF("bootp", HAS_ARG, QEMU_OPTION_bootp, "")
+DEF("redir", HAS_ARG, QEMU_OPTION_redir, "")
+#ifndef _WIN32
+DEF("smb", HAS_ARG, QEMU_OPTION_smb, "")
+#endif
+#endif
+
 DEF("net", HAS_ARG, QEMU_OPTION_net, \
     "-net nic[,vlan=n][,macaddr=addr][,model=type][,name=str]\n"
     "                create a new Network Interface Card and connect it to VLAN 'n'\n"
 #ifdef CONFIG_SLIRP
-    "-net user[,vlan=n][,name=str][,hostname=host]\n"
-    "                connect the user mode network stack to VLAN 'n' and send\n"
-    "                hostname 'host' to DHCP clients\n"
+    "-net user[,vlan=n][,name=str][ip=netaddr][,restrict=y|n][,hostname=host]\n"
+    "         [,tftp=dir][,bootfile=f][,redir=rule][,channel=rule]"
+#ifndef _WIN32
+                                                                  "[,smb=dir]\n"
+#endif
+    "                connect the user mode network stack to VLAN 'n', configure its\n"
+    "                DHCP server and enabled optional services\n"
 #endif
 #ifdef _WIN32
     "-net tap[,vlan=n][,name=str],ifname=name\n"
@@ -772,13 +786,102 @@ Valid values for @var{type} are
 Not all devices are supported on all targets.  Use -net nic,model=?
 for a list of available devices for your target.
 
-@item -net user[,vlan=@var{n}][,hostname=@var{name}][,name=@var{name}]
+@item -net user[,@var{option}][,@var{option}][,...]
 Use the user mode network stack which requires no administrator
-privilege to run.  @option{hostname=name} can be used to specify the client
-hostname reported by the builtin DHCP server.
+privilege to run. Valid options are:
+
+@table @code
+@item vlan=@var{n}
+Connect user mode stack to VLAN @var{n} (@var{n} = 0 is the default).
+
+@item name=@var{name}
+Assign symbolic name for use in monitor commands.
+
+@item ip=@var{netaddr}
+Set IP network address the guest will see (default: 10.0.2.x).
+
+@item restrict=y|yes|n|no
+If this options is enabled, the guest will be isolated, i.e. it will not be
+able to contact the host and no guest IP packets will be routed over the host
+to the outside. This option does not affect explicitly set forwarding rule.
+
+@item hostname=@var{name}
+Specifies the client hostname reported by the builtin DHCP server.
+
+@item tftp=@var{dir}
+When using the user mode network stack, activate a built-in TFTP
+server. The files in @var{dir} will be exposed as the root of a TFTP server.
+The TFTP client on the guest must be configured in binary mode (use the command
+@code{bin} of the Unix TFTP client). The host IP address on the guest is
+10.0.2.2 by default.
+
+@item bootfile=@var{file}
+When using the user mode network stack, broadcast @var{file} as the BOOTP
+filename. In conjunction with @option{tftp}, this can be used to network boot
+a guest from a local directory.
+
+Example (using pxelinux):
+@example
+qemu -hda linux.img -boot n -net user,tftp=/path/to/tftp/files,bootfile=/pxelinux.0
+@end example
+
+@item smb=@var{dir}
+When using the user mode network stack, activate a built-in SMB
+server so that Windows OSes can access to the host files in @file{@var{dir}}
+transparently.
+
+In the guest Windows OS, the line:
+@example
+10.0.2.4 smbserver
+@end example
+must be added in the file @file{C:\WINDOWS\LMHOSTS} (for windows 9x/Me)
+or @file{C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS} (Windows NT/2000).
+
+Then @file{@var{dir}} can be accessed in @file{\\smbserver\qemu}.
+
+Note that a SAMBA server must be installed on the host OS in
+@file{/usr/sbin/smbd}. QEMU was tested successfully with smbd versions from
+Red Hat 9, Fedora Core 3 and OpenSUSE 11.x.
+
+@item redir=[tcp|udp]:@var{host-port}:[@var{guest-host}]:@var{guest-port}
+Redirect incoming TCP or UDP connections to the host port @var{host-port} to
+the guest @var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
+is not specified, its value is 10.0.2.15 (default address given by the built-in
+DHCP server). If no connection type is specified, TCP is used. This option can
+be given multiple times.
+
+For example, to redirect host X11 connection from screen 1 to guest
+screen 0, use the following:
+
+@example
+# on the host
+qemu -net user,redir=tcp:6001::6000 [...]
+# this host xterm should open in the guest X11 server
+xterm -display :1
+@end example
+
+To redirect telnet connections from host port 5555 to telnet port on
+the guest, use the following:
+
+@example
+# on the host
+qemu -net user,redir=tcp:5555::23 [...]
+telnet localhost 5555
+@end example
+
+Then when you use on the host @code{telnet localhost 5555}, you
+connect to the guest telnet server.
 
-@item -net channel,@var{port}:@var{dev}
-Forward @option{user} TCP connection to port @var{port} to character device @var{dev}
+@item channel=@var{port}:@var{dev}
+Forward guest TCP connections to port @var{port} on the host to character
+device @var{dev}. This option can be given multiple times.
+
+@end table
+
+Note: Legacy stand-alone options -tftp, -bootp, -smb and -redir are still
+processed and applied to -net user. Mixing them with the new configuration
+syntax gives undefined results. Their use for new applications is discouraged
+as they will be removed from future versions.
 
 @item -net tap[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}][,ifname=@var{name}][,script=@var{file}][,downscript=@var{dfile}]
 Connect the host TAP network interface @var{name} to VLAN @var{n}, use
@@ -884,96 +987,6 @@ libpcap, so it can be analyzed with tools such as tcpdump or Wireshark.
 Indicate that no network devices should be configured. It is used to
 override the default configuration (@option{-net nic -net user}) which
 is activated if no @option{-net} options are provided.
-ETEXI
-
-#ifdef CONFIG_SLIRP
-DEF("tftp", HAS_ARG, QEMU_OPTION_tftp, \
-    "-tftp dir       allow tftp access to files in dir [-net user]\n")
-#endif
-STEXI
-@item -tftp @var{dir}
-When using the user mode network stack, activate a built-in TFTP
-server. The files in @var{dir} will be exposed as the root of a TFTP server.
-The TFTP client on the guest must be configured in binary mode (use the command
-@code{bin} of the Unix TFTP client). The host IP address on the guest is as
-usual 10.0.2.2.
-ETEXI
-
-#ifdef CONFIG_SLIRP
-DEF("bootp", HAS_ARG, QEMU_OPTION_bootp, \
-    "-bootp file     advertise file in BOOTP replies\n")
-#endif
-STEXI
-@item -bootp @var{file}
-When using the user mode network stack, broadcast @var{file} as the BOOTP
-filename.  In conjunction with @option{-tftp}, this can be used to network boot
-a guest from a local directory.
-
-Example (using pxelinux):
-@example
-qemu -hda linux.img -boot n -tftp /path/to/tftp/files -bootp /pxelinux.0
-@end example
-ETEXI
-
-#ifndef _WIN32
-DEF("smb", HAS_ARG, QEMU_OPTION_smb, \
-           "-smb dir        allow SMB access to files in 'dir' [-net user]\n")
-#endif
-STEXI
-@item -smb @var{dir}
-When using the user mode network stack, activate a built-in SMB
-server so that Windows OSes can access to the host files in @file{@var{dir}}
-transparently.
-
-In the guest Windows OS, the line:
-@example
-10.0.2.4 smbserver
-@end example
-must be added in the file @file{C:\WINDOWS\LMHOSTS} (for windows 9x/Me)
-or @file{C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS} (Windows NT/2000).
-
-Then @file{@var{dir}} can be accessed in @file{\\smbserver\qemu}.
-
-Note that a SAMBA server must be installed on the host OS in
-@file{/usr/sbin/smbd}. QEMU was tested successfully with smbd version
-2.2.7a from the Red Hat 9 and version 3.0.10-1.fc3 from Fedora Core 3.
-ETEXI
-
-#ifdef CONFIG_SLIRP
-DEF("redir", HAS_ARG, QEMU_OPTION_redir, \
-    "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n" \
-    "                redirect TCP or UDP connections from host to guest [-net user]\n")
-#endif
-STEXI
-@item -redir [tcp|udp]:@var{host-port}:[@var{guest-host}]:@var{guest-port}
-
-When using the user mode network stack, redirect incoming TCP or UDP
-connections to the host port @var{host-port} to the guest
-@var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
-is not specified, its value is 10.0.2.15 (default address given by the
-built-in DHCP server). If no connection type is specified, TCP is used.
-
-For example, to redirect host X11 connection from screen 1 to guest
-screen 0, use the following:
-
-@example
-# on the host
-qemu -redir tcp:6001::6000 [...]
-# this host xterm should open in the guest X11 server
-xterm -display :1
-@end example
-
-To redirect telnet connections from host port 5555 to telnet port on
-the guest, use the following:
-
-@example
-# on the host
-qemu -redir tcp:5555::23 [...]
-telnet localhost 5555
-@end example
-
-Then when you use on the host @code{telnet localhost 5555}, you
-connect to the guest telnet server.
 
 @end table
 ETEXI
diff --git a/slirp/bootp.c b/slirp/bootp.c
index 8a97660..3f4d079 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -38,7 +38,7 @@ typedef struct {
 
 static BOOTPClient bootp_clients[NB_ADDR];
 
-const char *bootp_filename;
+char bootp_filename[PATH_MAX] = "";
 
 static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
 
@@ -249,7 +249,7 @@ static void bootp_reply(const struct bootp_t *bp)
             *q++ = DHCPACK;
         }
 
-        if (bootp_filename)
+        if (bootp_filename[0] != 0)
             snprintf((char *)rbp->bp_file, sizeof(rbp->bp_file), "%s",
                      bootp_filename);
 
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index c0781c3..c5b1bb9 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -5,7 +5,8 @@
 extern "C" {
 #endif
 
-void slirp_init(int restricted, const char *special_ip);
+void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
+                const char *bootfile);
 
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds);
@@ -23,9 +24,7 @@ int slirp_redir(int is_udp, int host_port,
 int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
                    int guest_port);
 
-extern const char *tftp_prefix;
 extern char slirp_hostname[33];
-extern const char *bootp_filename;
 
 void slirp_stats(void);
 void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
diff --git a/slirp/main.h b/slirp/main.h
index ed51385..537c145 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -46,6 +46,8 @@ extern int tcp_keepintvl;
 extern uint8_t client_ethaddr[6];
 extern const char *slirp_special_ip;
 extern int slirp_restrict;
+extern char tftp_prefix[PATH_MAX];
+extern char bootp_filename[PATH_MAX];
 
 #define PROTO_SLIP 0x1
 #ifdef USE_PPP
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 73b3704..0fe0286 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -171,7 +171,8 @@ static void slirp_cleanup(void)
 static void slirp_state_save(QEMUFile *f, void *opaque);
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
 
-void slirp_init(int restricted, const char *special_ip)
+void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
+                const char *bootfile)
 {
     //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
 
@@ -202,7 +203,12 @@ void slirp_init(int restricted, const char *special_ip)
 
     if (special_ip)
         slirp_special_ip = special_ip;
-
+    if (tftp_path) {
+        pstrcpy(tftp_prefix, sizeof(tftp_prefix), tftp_path);
+    }
+    if (bootfile) {
+        pstrcpy(bootp_filename, sizeof(bootp_filename), bootfile);
+    }
     inet_aton(slirp_special_ip, &special_addr);
     alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
     getouraddr();
diff --git a/slirp/tftp.c b/slirp/tftp.c
index 4ad5504..e525c6b 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -37,7 +37,7 @@ struct tftp_session {
 
 static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
 
-const char *tftp_prefix;
+char tftp_prefix[PATH_MAX] = "";
 
 static void tftp_session_update(struct tftp_session *spt)
 {
@@ -335,7 +335,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
 
   /* only allow exported prefixes */
 
-  if (!tftp_prefix) {
+  if (tftp_prefix[0] == 0) {
       tftp_send_error(spt, 2, "Access violation", tp);
       return;
   }
@@ -370,7 +370,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
 	  int tsize = atoi(value);
 	  struct stat stat_p;
 
-	  if (tsize == 0 && tftp_prefix) {
+	  if (tsize == 0 && tftp_prefix[0] != 0) {
 	      char buffer[1024];
 	      int len;
 
diff --git a/vl.c b/vl.c
index 4982486..16be1a4 100644
--- a/vl.c
+++ b/vl.c
@@ -5150,14 +5150,14 @@ int main(int argc, char **argv, char **envp)
                 break;
 #ifdef CONFIG_SLIRP
             case QEMU_OPTION_tftp:
-		tftp_prefix = optarg;
+                legacy_tftp_prefix = optarg;
                 break;
             case QEMU_OPTION_bootp:
-                bootp_filename = optarg;
+                legacy_bootp_filename = optarg;
                 break;
 #ifndef _WIN32
             case QEMU_OPTION_smb:
-		net_slirp_smb(optarg);
+                net_slirp_smb(optarg);
                 break;
 #endif
             case QEMU_OPTION_redir:

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 06/11] slirp: Reorder initialization
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
                   ` (3 preceding siblings ...)
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 03/11] slirp: Avoid zombie processes after fork_exec Jan Kiszka
@ 2009-05-08 10:34 ` Jan Kiszka
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 10/11] slirp: Rework external configuration interface Jan Kiszka
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

This patch reorders the initialization of slirp itself as well as its
associated features smb and redirection. So far the first reference to
slirp triggered the initialization, independent of the actual -net user
option which may carry additional parameters. Now we save any request to
add a smb export or some redirections until the actual initialization of
the stack. This also allows to move a few parameters that were passed
via global variable into the argument list of net_slirp_init.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |  119 ++++++++++++++++++++++++++++++++++++++++--------------
 slirp/libslirp.h |    2 -
 slirp/slirp.c    |    2 -
 3 files changed, 90 insertions(+), 33 deletions(-)

diff --git a/net.c b/net.c
index 658f884..b20a907 100644
--- a/net.c
+++ b/net.c
@@ -551,11 +551,21 @@ static void config_error(Monitor *mon, const char *fmt, ...)
 
 /* slirp network adapter */
 
+struct slirp_config_str {
+    struct slirp_config_str *next;
+    const char *str;
+};
+
 static int slirp_inited;
-static int slirp_restrict;
-static char *slirp_ip;
+static struct slirp_config_str *slirp_redirs;
+#ifndef _WIN32
+static const char *slirp_smb_export;
+#endif
 static VLANClientState *slirp_vc;
 
+static void slirp_smb(const char *exported_dir);
+static void slirp_redirection(Monitor *mon, const char *redir_str);
+
 int slirp_can_output(void)
 {
     return !slirp_vc || qemu_can_send_packet(slirp_vc);
@@ -593,7 +603,8 @@ static void net_slirp_cleanup(VLANClientState *vc)
     slirp_in_use = 0;
 }
 
-static int net_slirp_init(VLANState *vlan, const char *model, const char *name)
+static int net_slirp_init(VLANState *vlan, const char *model, const char *name,
+                          int restricted, const char *ip)
 {
     if (slirp_in_use) {
         /* slirp only supports a single instance so far */
@@ -601,31 +612,41 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name)
     }
     if (!slirp_inited) {
         slirp_inited = 1;
-        slirp_init(slirp_restrict, slirp_ip);
+        slirp_init(restricted, ip);
+
+        while (slirp_redirs) {
+            struct slirp_config_str *config = slirp_redirs;
+
+            slirp_redirection(NULL, config->str);
+            slirp_redirs = config->next;
+            qemu_free(config);
+        }
+#ifndef _WIN32
+        if (slirp_smb_export) {
+            slirp_smb(slirp_smb_export);
+        }
+#endif
     }
-    slirp_vc = qemu_new_vlan_client(vlan, model, name,
-                                    slirp_receive, NULL, net_slirp_cleanup, NULL);
+
+    slirp_vc = qemu_new_vlan_client(vlan, model, name, slirp_receive,
+                                    NULL, net_slirp_cleanup, NULL);
     slirp_vc->info_str[0] = '\0';
     slirp_in_use = 1;
     return 0;
 }
 
-void net_slirp_redir(Monitor *mon, const char *redir_str)
+static void slirp_redirection(Monitor *mon, const char *redir_str)
 {
-    int is_udp;
-    char buf[256], *r;
-    const char *p;
     struct in_addr guest_addr;
     int host_port, guest_port;
-
-    if (!slirp_inited) {
-        slirp_inited = 1;
-        slirp_init(slirp_restrict, slirp_ip);
-    }
+    const char *p;
+    char buf[256], *r;
+    int is_udp;
 
     p = redir_str;
-    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
+    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
         goto fail_syntax;
+    }
     if (!strcmp(buf, "tcp") || buf[0] == '\0') {
         is_udp = 0;
     } else if (!strcmp(buf, "udp")) {
@@ -634,23 +655,28 @@ void net_slirp_redir(Monitor *mon, const char *redir_str)
         goto fail_syntax;
     }
 
-    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
+    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
         goto fail_syntax;
+    }
     host_port = strtol(buf, &r, 0);
-    if (r == buf)
+    if (r == buf) {
         goto fail_syntax;
+    }
 
-    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
+    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
         goto fail_syntax;
+    }
     if (buf[0] == '\0') {
         pstrcpy(buf, sizeof(buf), "10.0.2.15");
     }
-    if (!inet_aton(buf, &guest_addr))
+    if (!inet_aton(buf, &guest_addr)) {
         goto fail_syntax;
+    }
 
     guest_port = strtol(p, &r, 0);
-    if (r == p)
+    if (r == p) {
         goto fail_syntax;
+    }
 
     if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
         config_error(mon, "could not set up redirection '%s'\n", redir_str);
@@ -661,6 +687,25 @@ void net_slirp_redir(Monitor *mon, const char *redir_str)
     config_error(mon, "invalid redirection format '%s'\n", redir_str);
 }
 
+void net_slirp_redir(Monitor *mon, const char *redir_str)
+{
+    struct slirp_config_str *config;
+
+    if (!slirp_inited) {
+        if (mon) {
+            monitor_printf(mon, "user mode network stack not in use\n");
+        } else {
+            config = qemu_malloc(sizeof(*config));
+            config->str = redir_str;
+            config->next = slirp_redirs;
+            slirp_redirs = config;
+        }
+        return;
+    }
+
+    slirp_redirection(mon, redir_str);
+}
+
 #ifndef _WIN32
 
 static char smb_dir[1024];
@@ -696,18 +741,12 @@ static void smb_exit(void)
     erase_dir(smb_dir);
 }
 
-/* automatic user mode samba server configuration */
-void net_slirp_smb(const char *exported_dir)
+static void slirp_smb(const char *exported_dir)
 {
     char smb_conf[1024];
     char smb_cmdline[1024];
     FILE *f;
 
-    if (!slirp_inited) {
-        slirp_inited = 1;
-        slirp_init(slirp_restrict, slirp_ip);
-    }
-
     /* XXX: better tmp dir construction */
     snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%ld", (long)getpid());
     if (mkdir(smb_dir, 0700) < 0) {
@@ -751,7 +790,21 @@ void net_slirp_smb(const char *exported_dir)
     slirp_add_exec(0, smb_cmdline, 4, 139);
 }
 
+/* automatic user mode samba server configuration */
+void net_slirp_smb(const char *exported_dir)
+{
+    if (slirp_smb_export) {
+        fprintf(stderr, "-smb given twice\n");
+        exit(1);
+    }
+    slirp_smb_export = exported_dir;
+    if (slirp_inited) {
+        slirp_smb(exported_dir);
+    }
+}
+
 #endif /* !defined(_WIN32) */
+
 void do_info_slirp(Monitor *mon)
 {
     slirp_stats();
@@ -1885,6 +1938,9 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         static const char * const slirp_params[] = {
             "vlan", "name", "hostname", "restrict", "ip", NULL
         };
+        int restricted = 0;
+        char *ip = NULL;
+
         if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
             config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
             ret = -1;
@@ -1894,13 +1950,14 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
             pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf);
         }
         if (get_param_value(buf, sizeof(buf), "restrict", p)) {
-            slirp_restrict = (buf[0] == 'y') ? 1 : 0;
+            restricted = (buf[0] == 'y') ? 1 : 0;
         }
         if (get_param_value(buf, sizeof(buf), "ip", p)) {
-            slirp_ip = strdup(buf);
+            ip = qemu_strdup(buf);
         }
         vlan->nb_host_devs++;
-        ret = net_slirp_init(vlan, device, name);
+        ret = net_slirp_init(vlan, device, name, restricted, ip);
+        qemu_free(ip);
     } else if (!strcmp(device, "channel")) {
         long port;
         char name[20], *devname;
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index a1cd70e..c0781c3 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -5,7 +5,7 @@
 extern "C" {
 #endif
 
-void slirp_init(int restricted, char *special_ip);
+void slirp_init(int restricted, const char *special_ip);
 
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds);
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 4ca35b2..73b3704 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -171,7 +171,7 @@ static void slirp_cleanup(void)
 static void slirp_state_save(QEMUFile *f, void *opaque);
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
 
-void slirp_init(int restricted, char *special_ip)
+void slirp_init(int restricted, const char *special_ip)
 {
     //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
 

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 09/11] slirp: Rework internal configuration
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
                   ` (8 preceding siblings ...)
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 08/11] slirp: Move smb, redir, tftp and bootp parameters and -net channel Jan Kiszka
@ 2009-05-08 10:34 ` Jan Kiszka
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 11/11] slirp: Bind support for host forwarding rules Jan Kiszka
  2009-05-08 16:25 ` [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Anthony Liguori
  11 siblings, 0 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

The user mode IP stack is currently only minially configurable /wrt to
its virtual IP addresses. This is unfortunate if some guest has a fixed
idea of which IP addresses to use.

Therefore this patch prepares the stack for fully configurable IP
addresses and masks. The user interface and default addresses are kept
yet, they will be enhanced in the following patch.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/bootp.c     |   26 ++++------
 slirp/ctl.h       |    7 ---
 slirp/ip_icmp.c   |   15 ++----
 slirp/ip_input.c  |    9 ++-
 slirp/main.h      |    9 ++-
 slirp/misc.c      |    9 ++-
 slirp/misc.h      |    4 +
 slirp/slirp.c     |  143 +++++++++++++++++++++++++++++++----------------------
 slirp/slirp.h     |    1 
 slirp/socket.c    |   13 ++---
 slirp/tcp_input.c |   16 +++---
 slirp/tcp_subr.c  |  120 ++++++++++++--------------------------------
 slirp/udp.c       |   23 +++++----
 13 files changed, 176 insertions(+), 219 deletions(-)
 delete mode 100644 slirp/ctl.h

diff --git a/slirp/bootp.c b/slirp/bootp.c
index 3f4d079..8717343 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -27,8 +27,6 @@
 
 #define NB_ADDR 16
 
-#define START_ADDR 15
-
 #define LEASE_TIME (24 * 3600)
 
 typedef struct {
@@ -62,7 +60,7 @@ static BOOTPClient *get_new_addr(struct in_addr *paddr)
  found:
     bc = &bootp_clients[i];
     bc->allocated = 1;
-    paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
+    paddr->s_addr = vdhcp_startaddr.s_addr + htonl(i);
     return bc;
 }
 
@@ -70,12 +68,12 @@ static BOOTPClient *request_addr(const struct in_addr *paddr,
                                  const uint8_t *macaddr)
 {
     uint32_t req_addr = ntohl(paddr->s_addr);
-    uint32_t spec_addr = ntohl(special_addr.s_addr);
+    uint32_t dhcp_addr = ntohl(vdhcp_startaddr.s_addr);
     BOOTPClient *bc;
 
-    if (req_addr >= (spec_addr | START_ADDR) &&
-        req_addr < (spec_addr | (NB_ADDR + START_ADDR))) {
-        bc = &bootp_clients[(req_addr & 0xff) - START_ADDR];
+    if (req_addr >= dhcp_addr &&
+        req_addr < (dhcp_addr + NB_ADDR)) {
+        bc = &bootp_clients[req_addr - dhcp_addr];
         if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) {
             bc->allocated = 1;
             return bc;
@@ -97,7 +95,7 @@ static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr)
  found:
     bc = &bootp_clients[i];
     bc->allocated = 1;
-    paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
+    paddr->s_addr = vdhcp_startaddr.s_addr + htonl(i);
     return bc;
 }
 
@@ -154,7 +152,6 @@ static void bootp_reply(const struct bootp_t *bp)
     struct mbuf *m;
     struct bootp_t *rbp;
     struct sockaddr_in saddr, daddr;
-    struct in_addr dns_addr;
     const struct in_addr *preq_addr;
     int dhcp_msg_type, val;
     uint8_t *q;
@@ -216,7 +213,7 @@ static void bootp_reply(const struct bootp_t *bp)
         }
     }
 
-    saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
+    saddr.sin_addr = vhost_addr;
     saddr.sin_port = htons(BOOTP_SERVER);
 
     daddr.sin_port = htons(BOOTP_CLIENT);
@@ -260,10 +257,8 @@ static void bootp_reply(const struct bootp_t *bp)
 
         *q++ = RFC1533_NETMASK;
         *q++ = 4;
-        *q++ = 0xff;
-        *q++ = 0xff;
-        *q++ = 0xff;
-        *q++ = 0x00;
+        memcpy(q, &vnetwork_mask, 4);
+        q += 4;
 
         if (!slirp_restrict) {
             *q++ = RFC1533_GATEWAY;
@@ -273,8 +268,7 @@ static void bootp_reply(const struct bootp_t *bp)
 
             *q++ = RFC1533_DNS;
             *q++ = 4;
-            dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
-            memcpy(q, &dns_addr, 4);
+            memcpy(q, &vnameserver_addr, 4);
             q += 4;
         }
 
diff --git a/slirp/ctl.h b/slirp/ctl.h
deleted file mode 100644
index 4a8576d..0000000
--- a/slirp/ctl.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#define CTL_CMD		0
-#define CTL_EXEC	1
-#define CTL_ALIAS	2
-#define CTL_DNS		3
-
-#define CTL_SPECIAL	"10.0.2.0"
-#define CTL_LOCAL	"10.0.2.15"
diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 61dcaf8..6e93ee3 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -110,7 +110,7 @@ icmp_input(struct mbuf *m, int hlen)
   case ICMP_ECHO:
     icp->icmp_type = ICMP_ECHOREPLY;
     ip->ip_len += hlen;	             /* since ip_input subtracts this */
-    if (ip->ip_dst.s_addr == alias_addr.s_addr) {
+    if (ip->ip_dst.s_addr == vhost_addr.s_addr) {
       icmp_reflect(m);
     } else {
       struct socket *so;
@@ -134,16 +134,13 @@ icmp_input(struct mbuf *m, int hlen)
 
       /* Send the packet */
       addr.sin_family = AF_INET;
-      if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
+      if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) ==
+          vnetwork_addr.s_addr) {
 	/* It's an alias */
-	switch(ntohl(so->so_faddr.s_addr) & 0xff) {
-	case CTL_DNS:
+	if (so->so_faddr.s_addr == vnameserver_addr.s_addr) {
 	  addr.sin_addr = dns_addr;
-	  break;
-	case CTL_ALIAS:
-	default:
+	} else {
 	  addr.sin_addr = loopback_addr;
-	  break;
 	}
       } else {
 	addr.sin_addr = so->so_faddr;
@@ -302,7 +299,7 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
   ip->ip_ttl = MAXTTL;
   ip->ip_p = IPPROTO_ICMP;
   ip->ip_dst = ip->ip_src;    /* ip adresses */
-  ip->ip_src = alias_addr;
+  ip->ip_src = vhost_addr;
 
   (void ) ip_output((struct socket *)NULL, m);
 
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index c37412e..7a3c88b 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -134,18 +134,19 @@ ip_input(struct mbuf *m)
 	}
 
     if (slirp_restrict) {
-        if (memcmp(&ip->ip_dst.s_addr, &special_addr, 3)) {
+        if ((ip->ip_dst.s_addr & vnetwork_mask.s_addr) ==
+            vnetwork_addr.s_addr) {
             if (ip->ip_dst.s_addr == 0xffffffff && ip->ip_p != IPPROTO_UDP)
                 goto bad;
         } else {
-            int host = ntohl(ip->ip_dst.s_addr) & 0xff;
             struct ex_list *ex_ptr;
 
-            if (host == 0xff)
+            if ((ip->ip_dst.s_addr & ~vnetwork_mask.s_addr) ==
+                ~vnetwork_mask.s_addr)
                 goto bad;
 
             for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
-                if (ex_ptr->ex_addr == host)
+                if (ex_ptr->ex_addr.s_addr == ip->ip_dst.s_addr)
                     break;
 
             if (!ex_ptr)
diff --git a/slirp/main.h b/slirp/main.h
index 537c145..8682d55 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -32,9 +32,11 @@ extern char *slirp_tty;
 extern char *exec_shell;
 extern u_int curtime;
 extern fd_set *global_readfds, *global_writefds, *global_xfds;
-extern struct in_addr ctl_addr;
-extern struct in_addr special_addr;
-extern struct in_addr alias_addr;
+extern struct in_addr vnetwork_addr;
+extern struct in_addr vnetwork_mask;
+extern struct in_addr vhost_addr;
+extern struct in_addr vdhcp_startaddr;
+extern struct in_addr vnameserver_addr;
 extern struct in_addr our_addr;
 extern struct in_addr loopback_addr;
 extern struct in_addr dns_addr;
@@ -44,7 +46,6 @@ extern int towrite_max;
 extern int ppp_exit;
 extern int tcp_keepintvl;
 extern uint8_t client_ethaddr[6];
-extern const char *slirp_special_ip;
 extern int slirp_restrict;
 extern char tftp_prefix[PATH_MAX];
 extern char bootp_filename[PATH_MAX];
diff --git a/slirp/misc.c b/slirp/misc.c
index 0137e75..ff7fbf4 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -112,15 +112,16 @@ remque(void *a)
 /* #endif */
 
 
-int
-add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port)
+int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec,
+             struct in_addr 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;
+		if (port == tmp_ptr->ex_fport &&
+		    addr.s_addr == tmp_ptr->ex_addr.s_addr)
+			return -1;
 	}
 
 	tmp_ptr = *ex_ptr;
diff --git a/slirp/misc.h b/slirp/misc.h
index ab8e3a7..29d5749 100644
--- a/slirp/misc.h
+++ b/slirp/misc.h
@@ -10,7 +10,7 @@
 
 struct ex_list {
 	int ex_pty;			/* Do we want a pty? */
-	int ex_addr;			/* The last byte of the address */
+	struct in_addr ex_addr;		/* Server address */
 	int ex_fport;                   /* Port to telnet to */
 	const char *ex_exec;            /* Command line of what to exec */
 	struct ex_list *ex_next;
@@ -74,7 +74,7 @@ void redir_x _P((u_int32_t, int, int, int));
 void getouraddr _P((void));
 void slirp_insque _P((void *, void *));
 void slirp_remque _P((void *));
-int add_exec _P((struct ex_list **, int, char *, int, int));
+int add_exec _P((struct ex_list **, int, char *, struct in_addr, int));
 int slirp_openpty _P((int *, int *));
 int fork_exec(struct socket *so, const char *ex, int do_pty);
 void snooze_hup _P((int));
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 0fe0286..53f866d 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -33,13 +33,16 @@ struct in_addr dns_addr;
 /* host loopback address */
 struct in_addr loopback_addr;
 
-/* address for slirp virtual addresses */
-struct in_addr special_addr;
-/* virtual address alias for host */
-struct in_addr alias_addr;
-
+/* virtual network configuration */
+struct in_addr vnetwork_addr;
+struct in_addr vnetwork_mask;
+struct in_addr vhost_addr;
+struct in_addr vdhcp_startaddr;
+struct in_addr vnameserver_addr;
+
+/* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
 static const uint8_t special_ethaddr[6] = {
-    0x52, 0x54, 0x00, 0x12, 0x35, 0x00
+    0x52, 0x55, 0x00, 0x00, 0x00, 0x00
 };
 
 /* ARP cache for the guest IP addresses (XXX: allow many entries) */
@@ -48,7 +51,6 @@ static struct in_addr client_ipaddr;
 
 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
 
-const char *slirp_special_ip = CTL_SPECIAL;
 int slirp_restrict;
 static int do_slowtimo;
 int link_up;
@@ -174,14 +176,12 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
 void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
                 const char *bootfile)
 {
-    //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
-
+    struct in_addr special_addr = { .s_addr = htonl(0x0a000200) };
 #ifdef _WIN32
-    {
-        WSADATA Data;
-        WSAStartup(MAKEWORD(2,0), &Data);
-	atexit(slirp_cleanup);
-    }
+    WSADATA Data;
+
+    WSAStartup(MAKEWORD(2,0), &Data);
+    atexit(slirp_cleanup);
 #endif
 
     link_up = 1;
@@ -201,16 +201,20 @@ void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
         fprintf (stderr, "Warning: No DNS servers found\n");
     }
 
-    if (special_ip)
-        slirp_special_ip = special_ip;
+    if (special_ip) {
+        inet_aton(special_ip, &special_addr);
+    }
     if (tftp_path) {
         pstrcpy(tftp_prefix, sizeof(tftp_prefix), tftp_path);
     }
     if (bootfile) {
         pstrcpy(bootp_filename, sizeof(bootp_filename), bootfile);
     }
-    inet_aton(slirp_special_ip, &special_addr);
-    alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
+    vnetwork_addr = special_addr;
+    vnetwork_mask.s_addr = htonl(0xffffff00);
+    vhost_addr.s_addr = special_addr.s_addr | htonl(2);
+    vdhcp_startaddr.s_addr = special_addr.s_addr | htonl(15);
+    vnameserver_addr.s_addr = special_addr.s_addr | htonl(3);
     getouraddr();
     register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
 }
@@ -595,10 +599,10 @@ struct arphdr
 	  *	 Ethernet looks like this : This bit is variable sized however...
 	  */
 	unsigned char		ar_sha[ETH_ALEN];	/* sender hardware address	*/
-	unsigned char		ar_sip[4];		/* sender IP address		*/
+	uint32_t		ar_sip;			/* sender IP address		*/
 	unsigned char		ar_tha[ETH_ALEN];	/* target hardware address	*/
-	unsigned char		ar_tip[4];		/* target IP address		*/
-};
+	uint32_t		ar_tip	;		/* target IP address		*/
+} __attribute__((packed));
 
 static void arp_input(const uint8_t *pkt, int pkt_len)
 {
@@ -613,11 +617,12 @@ static void arp_input(const uint8_t *pkt, int pkt_len)
     ar_op = ntohs(ah->ar_op);
     switch(ar_op) {
     case ARPOP_REQUEST:
-        if (!memcmp(ah->ar_tip, &special_addr, 3)) {
-            if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
+        if ((ah->ar_tip & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) {
+            if (ah->ar_tip == vnameserver_addr.s_addr ||
+                ah->ar_tip == vhost_addr.s_addr)
                 goto arp_ok;
             for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
-                if (ex_ptr->ex_addr == ah->ar_tip[3])
+                if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
                     goto arp_ok;
             }
             return;
@@ -627,8 +632,8 @@ static void arp_input(const uint8_t *pkt, int pkt_len)
 
             /* ARP request for alias/dns mac address */
             memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
-            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
-            reh->h_source[5] = ah->ar_tip[3];
+            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
+            memcpy(&reh->h_source[2], &ah->ar_tip, 4);
             reh->h_proto = htons(ETH_P_ARP);
 
             rah->ar_hrd = htons(1);
@@ -637,16 +642,16 @@ static void arp_input(const uint8_t *pkt, int pkt_len)
             rah->ar_pln = 4;
             rah->ar_op = htons(ARPOP_REPLY);
             memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
-            memcpy(rah->ar_sip, ah->ar_tip, 4);
+            rah->ar_sip = ah->ar_tip;
             memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
-            memcpy(rah->ar_tip, ah->ar_sip, 4);
+            rah->ar_tip = ah->ar_sip;
             slirp_output(arp_reply, sizeof(arp_reply));
         }
         break;
     case ARPOP_REPLY:
         /* reply to request of client mac address ? */
         if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) &&
-            !memcmp(ah->ar_sip, &client_ipaddr.s_addr, 4)) {
+            ah->ar_sip == client_ipaddr.s_addr) {
             memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN);
         }
         break;
@@ -710,8 +715,8 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
            in place of sending the packet and we hope that the sender
            will retry sending its packet. */
         memset(reh->h_dest, 0xff, ETH_ALEN);
-        memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
-        reh->h_source[5] = CTL_ALIAS;
+        memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
+        memcpy(&reh->h_source[2], &vhost_addr, 4);
         reh->h_proto = htons(ETH_P_ARP);
         rah->ar_hrd = htons(1);
         rah->ar_pro = htons(ETH_P_IP);
@@ -719,21 +724,21 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
         rah->ar_pln = 4;
         rah->ar_op = htons(ARPOP_REQUEST);
         /* source hw addr */
-        memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1);
-        rah->ar_sha[5] = CTL_ALIAS;
+        memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
+        memcpy(&rah->ar_sha[2], &vhost_addr, 4);
         /* source IP */
-        memcpy(rah->ar_sip, &alias_addr, 4);
+        rah->ar_sip = vhost_addr.s_addr;
         /* target hw addr (none) */
         memset(rah->ar_tha, 0, ETH_ALEN);
         /* target IP */
-        memcpy(rah->ar_tip, &iph->ip_dst, 4);
+        rah->ar_tip = iph->ip_dst.s_addr;
         client_ipaddr = iph->ip_dst;
         slirp_output(arp_req, sizeof(arp_req));
     } else {
         memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
-        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
+        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
         /* XXX: not correct */
-        eh->h_source[5] = CTL_ALIAS;
+        memcpy(&eh->h_source[2], &vhost_addr, 4);
         eh->h_proto = htons(ETH_P_IP);
         memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
         slirp_output(buf, ip_data_len + ETH_HLEN);
@@ -743,6 +748,9 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
 int slirp_redir(int is_udp, int host_port,
                 struct in_addr guest_addr, int guest_port)
 {
+    if (!guest_addr.s_addr) {
+        guest_addr = vdhcp_startaddr;
+    }
     if (is_udp) {
         if (!udp_listen(htons(host_port), guest_addr.s_addr,
                         htons(guest_port), 0))
@@ -758,8 +766,17 @@ int slirp_redir(int is_udp, int host_port,
 int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
                   int guest_port)
 {
-    return add_exec(&exec_list, do_pty, (char *)args,
-                    addr_low_byte, htons(guest_port));
+    struct in_addr guest_addr = {
+        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
+    };
+
+    if ((guest_addr.s_addr & vnetwork_mask.s_addr) != vnetwork_addr.s_addr ||
+        guest_addr.s_addr == vhost_addr.s_addr ||
+        guest_addr.s_addr == vnameserver_addr.s_addr) {
+        return -1;
+    }
+    return add_exec(&exec_list, do_pty, (char *)args, guest_addr,
+                    htons(guest_port));
 }
 
 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
@@ -772,31 +789,32 @@ ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
 	return send(so->s, buf, len, flags);
 }
 
-static struct socket *slirp_find_ctl_socket(int addr_low_byte, int guest_port)
+static struct socket *
+slirp_find_ctl_socket(struct in_addr guest_addr, int guest_port)
 {
-	struct socket *so;
+    struct socket *so;
 
-	for (so = tcb.so_next; so != &tcb; so = so->so_next) {
-		if ((so->so_faddr.s_addr & htonl(0xffffff00)) ==
-				special_addr.s_addr
-				&& (ntohl(so->so_faddr.s_addr) & 0xff) ==
-				addr_low_byte
-				&& htons(so->so_fport) == guest_port)
-			return so;
-	}
-
-	return NULL;
+    for (so = tcb.so_next; so != &tcb; so = so->so_next) {
+        if (so->so_faddr.s_addr == guest_addr.s_addr &&
+            htons(so->so_fport) == guest_port) {
+            return so;
+        }
+    }
+    return NULL;
 }
 
 size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
 {
+    struct in_addr guest_addr = {
+        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
+    };
 	struct iovec iov[2];
 	struct socket *so;
 
     if (!link_up)
         return 0;
 
-	so = slirp_find_ctl_socket(addr_low_byte, guest_port);
+	so = slirp_find_ctl_socket(guest_addr, guest_port);
 
 	if (!so || so->so_state & SS_NOFDREF)
 		return 0;
@@ -811,8 +829,11 @@ void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
         int size)
 {
     int ret;
-    struct socket *so = slirp_find_ctl_socket(addr_low_byte, guest_port);
-   
+    struct in_addr guest_addr = {
+        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
+    };
+    struct socket *so = slirp_find_ctl_socket(guest_addr, guest_port);
+
     if (!so)
         return;
 
@@ -1026,15 +1047,17 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
         if (ret < 0)
             return ret;
 
-        if ((so->so_faddr.s_addr & htonl(0xffffff00)) != special_addr.s_addr)
+        if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) !=
+            vnetwork_addr.s_addr) {
             return -EINVAL;
-
-        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+        }
+        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
             if (ex_ptr->ex_pty == 3 &&
-                    (ntohl(so->so_faddr.s_addr) & 0xff) == ex_ptr->ex_addr &&
-                    so->so_fport == ex_ptr->ex_fport)
+                so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
+                so->so_fport == ex_ptr->ex_fport) {
                 break;
-
+            }
+        }
         if (!ex_ptr)
             return -EINVAL;
 
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 8309fe0..101d094 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -214,7 +214,6 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
 #include "if.h"
 #include "main.h"
 #include "misc.h"
-#include "ctl.h"
 #ifdef USE_PPP
 #include "ppp/pppd.h"
 #include "ppp/ppp.h"
diff --git a/slirp/socket.c b/slirp/socket.c
index 098132a..56f794d 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -550,16 +550,13 @@ sosendto(struct socket *so, struct mbuf *m)
 	DEBUG_ARG("m = %lx", (long)m);
 
         addr.sin_family = AF_INET;
-	if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
+	if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) ==
+	    vnetwork_addr.s_addr) {
 	  /* It's an alias */
-	  switch(ntohl(so->so_faddr.s_addr) & 0xff) {
-	  case CTL_DNS:
+	  if (so->so_faddr.s_addr == vnameserver_addr.s_addr) {
 	    addr.sin_addr = dns_addr;
-	    break;
-	  case CTL_ALIAS:
-	  default:
+	  } else {
 	    addr.sin_addr = loopback_addr;
-	    break;
 	  }
 	} else
 	  addr.sin_addr = so->so_faddr;
@@ -647,7 +644,7 @@ solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
 	getsockname(s,(struct sockaddr *)&addr,&addrlen);
 	so->so_fport = addr.sin_port;
 	if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
-	   so->so_faddr = alias_addr;
+	   so->so_faddr = vhost_addr;
 	else
 	   so->so_faddr = addr.sin_addr;
 
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index effedfc..ab0840d 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -359,11 +359,12 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	m->m_len  -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
 
     if (slirp_restrict) {
-        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
             if (ex_ptr->ex_fport == ti->ti_dport &&
-                    (ntohl(ti->ti_dst.s_addr) & 0xff) == ex_ptr->ex_addr)
+                ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {
                 break;
-
+            }
+        }
         if (!ex_ptr)
             goto drop;
     }
@@ -639,9 +640,10 @@ findso:
 	   * If this is destined for the control address, then flag to
 	   * tcp_ctl once connected, otherwise connect
 	   */
-	  if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) {
-	    int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff;
-	    if (lastbyte!=CTL_ALIAS && lastbyte!=CTL_DNS) {
+	  if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) ==
+	      vnetwork_addr.s_addr) {
+	    if (so->so_faddr.s_addr != vhost_addr.s_addr &&
+		so->so_faddr.s_addr != vnameserver_addr.s_addr) {
 #if 0
 	      if(lastbyte==CTL_CMD || lastbyte==CTL_EXEC) {
 		/* Command or exec adress */
@@ -652,7 +654,7 @@ findso:
 		/* May be an add exec */
 		for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
 		  if(ex_ptr->ex_fport == so->so_fport &&
-		     lastbyte == ex_ptr->ex_addr) {
+		     so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
 		    so->so_state |= SS_CTL;
 		    break;
 		  }
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 9d020a6..858d1ae 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -384,16 +384,12 @@ int tcp_fconnect(struct socket *so)
     setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
 
     addr.sin_family = AF_INET;
-    if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
+    if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) {
       /* It's an alias */
-      switch(ntohl(so->so_faddr.s_addr) & 0xff) {
-      case CTL_DNS:
+      if (so->so_faddr.s_addr == vnameserver_addr.s_addr) {
 	addr.sin_addr = dns_addr;
-	break;
-      case CTL_ALIAS:
-      default:
+      } else {
 	addr.sin_addr = loopback_addr;
-	break;
       }
     } else
       addr.sin_addr = so->so_faddr;
@@ -478,7 +474,7 @@ tcp_connect(struct socket *inso)
 	so->so_faddr = addr.sin_addr;
 	/* Translate connections from localhost to the real hostname */
 	if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
-	   so->so_faddr = alias_addr;
+	   so->so_faddr = vhost_addr;
 
 	/* Close the accept() socket, set right state */
 	if (inso->so_state & SS_FACCEPTONCE) {
@@ -1228,84 +1224,34 @@ do_prompt:
  * Return 0 if this connections is to be closed, 1 otherwise,
  * return 2 if this is a command-line connection
  */
-int
-tcp_ctl(struct socket *so)
+int tcp_ctl(struct socket *so)
 {
-	struct sbuf *sb = &so->so_snd;
-	int command;
- 	struct ex_list *ex_ptr;
-	int do_pty;
-        //	struct socket *tmpso;
-
-	DEBUG_CALL("tcp_ctl");
-	DEBUG_ARG("so = %lx", (long )so);
-
-#if 0
-	/*
-	 * Check if they're authorised
-	 */
-	if (ctl_addr.s_addr && (ctl_addr.s_addr == -1 || (so->so_laddr.s_addr != ctl_addr.s_addr))) {
-		sb->sb_cc = sprintf(sb->sb_wptr,"Error: Permission denied.\r\n");
-		sb->sb_wptr += sb->sb_cc;
-		return 0;
-	}
-#endif
-	command = (ntohl(so->so_faddr.s_addr) & 0xff);
-
-	switch(command) {
-	default: /* Check for exec's */
-
-		/*
-		 * Check if it's pty_exec
-		 */
-		for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
-			if (ex_ptr->ex_fport == so->so_fport &&
-			    command == ex_ptr->ex_addr) {
-				if (ex_ptr->ex_pty == 3) {
-					so->s = -1;
-					so->extra = (void *)ex_ptr->ex_exec;
-					return 1;
-				}
-				do_pty = ex_ptr->ex_pty;
-				goto do_exec;
-			}
-		}
-
-		/*
-		 * Nothing bound..
-		 */
-		/* tcp_fconnect(so); */
-
-		/* FALLTHROUGH */
-	case CTL_ALIAS:
-          sb->sb_cc = snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data),
-                               "Error: No application configured.\r\n");
-	  sb->sb_wptr += sb->sb_cc;
-	  return(0);
-
-	do_exec:
-		DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));
-		return(fork_exec(so, ex_ptr->ex_exec, do_pty));
-
-#if 0
-	case CTL_CMD:
-	   for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
-	     if (tmpso->so_emu == EMU_CTL &&
-		 !(tmpso->so_tcpcb?
-		   (tmpso->so_tcpcb->t_state & (TCPS_TIME_WAIT|TCPS_LAST_ACK))
-		   :0)) {
-	       /* Ooops, control connection already active */
-	       sb->sb_cc = sprintf(sb->sb_wptr,"Sorry, already connected.\r\n");
-	       sb->sb_wptr += sb->sb_cc;
-	       return 0;
-	     }
-	   }
-	   so->so_emu = EMU_CTL;
-	   ctl_password_ok = 0;
-	   sb->sb_cc = sprintf(sb->sb_wptr, "Slirp command-line ready (type \"help\" for help).\r\nSlirp> ");
-	   sb->sb_wptr += sb->sb_cc;
-	   do_echo=-1;
-	   return(2);
-#endif
-	}
+    struct sbuf *sb = &so->so_snd;
+    struct ex_list *ex_ptr;
+    int do_pty;
+
+    DEBUG_CALL("tcp_ctl");
+    DEBUG_ARG("so = %lx", (long )so);
+
+    if (so->so_faddr.s_addr != vhost_addr.s_addr) {
+        /* Check if it's pty_exec */
+        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+            if (ex_ptr->ex_fport == so->so_fport &&
+                so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
+                if (ex_ptr->ex_pty == 3) {
+                    so->s = -1;
+                    so->extra = (void *)ex_ptr->ex_exec;
+                    return 1;
+                }
+                do_pty = ex_ptr->ex_pty;
+                DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));
+                return fork_exec(so, ex_ptr->ex_exec, do_pty);
+            }
+        }
+    }
+    sb->sb_cc =
+        snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data),
+                 "Error: No application configured.\r\n");
+    sb->sb_wptr += sb->sb_cc;
+    return 0;
 }
diff --git a/slirp/udp.c b/slirp/udp.c
index 11e78cd..dd91671 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -314,12 +314,14 @@ int udp_output(struct socket *so, struct mbuf *m,
     struct sockaddr_in saddr, daddr;
 
     saddr = *addr;
-    if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
-        if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff))
-            saddr.sin_addr.s_addr = alias_addr.s_addr;
-        else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||
-                 (ntohl(so->so_faddr.s_addr) & 0xff) != CTL_ALIAS)
-            saddr.sin_addr.s_addr = so->so_faddr.s_addr;
+    if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) {
+        if ((so->so_faddr.s_addr & ~vnetwork_mask.s_addr) ==
+            ~vnetwork_mask.s_addr) {
+            saddr.sin_addr = vhost_addr;
+        } else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||
+                   so->so_faddr.s_addr != vhost_addr.s_addr) {
+            saddr.sin_addr = so->so_faddr;
+        }
     }
     daddr.sin_addr = so->so_laddr;
     daddr.sin_port = so->so_lport;
@@ -654,11 +656,12 @@ udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags)
 
 	getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
 	so->so_fport = addr.sin_port;
-	if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
-	   so->so_faddr = alias_addr;
-	else
+	if (addr.sin_addr.s_addr == 0 ||
+	    addr.sin_addr.s_addr == loopback_addr.s_addr) {
+	   so->so_faddr = vhost_addr;
+	} else {
 	   so->so_faddr = addr.sin_addr;
-
+	}
 	so->so_lport = lport;
 	so->so_laddr.s_addr = laddr;
 	if (flags != SS_FACCEPTONCE)

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 05/11] net: Improve parameter error reporting
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
                   ` (6 preceding siblings ...)
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 07/11] Introduce get_next_param_value Jan Kiszka
@ 2009-05-08 10:34 ` Jan Kiszka
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 08/11] slirp: Move smb, redir, tftp and bootp parameters and -net channel Jan Kiszka
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

As host network devices can also be instantiated via the monitor, errors
should then be reported to the related monitor instead of stderr. This
requires larger refactoring, so this patch starts small with introducing
a helper to catch both cases and convert net_client_init as well as
net_slirp_redir.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 hw/pci-hotplug.c |    7 ++-
 net.c            |  131 ++++++++++++++++++++++++++++--------------------------
 net.h            |    2 -
 vl.c             |    2 -
 4 files changed, 75 insertions(+), 67 deletions(-)

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 603d74d..8eaaecc 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -33,11 +33,12 @@
 #include "virtio-blk.h"
 
 #if defined(TARGET_I386) || defined(TARGET_X86_64)
-static PCIDevice *qemu_pci_hot_add_nic(PCIBus *pci_bus, const char *opts)
+static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon, PCIBus *pci_bus,
+                                       const char *opts)
 {
     int ret;
 
-    ret = net_client_init("nic", opts);
+    ret = net_client_init(mon, "nic", opts);
     if (ret < 0)
         return NULL;
     return pci_nic_init(pci_bus, &nd_table[ret], -1, "rtl8139");
@@ -151,7 +152,7 @@ void pci_device_hot_add(Monitor *mon, const char *pci_addr, const char *type,
     }
 
     if (strcmp(type, "nic") == 0)
-        dev = qemu_pci_hot_add_nic(pci_bus, opts);
+        dev = qemu_pci_hot_add_nic(mon, pci_bus, opts);
     else if (strcmp(type, "storage") == 0)
         dev = qemu_pci_hot_add_storage(mon, pci_bus, opts);
     else
diff --git a/net.c b/net.c
index cf00c9c..658f884 100644
--- a/net.c
+++ b/net.c
@@ -532,6 +532,21 @@ ssize_t qemu_sendv_packet(VLANClientState *sender, const struct iovec *iov,
     return max_len;
 }
 
+static void config_error(Monitor *mon, const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    if (mon) {
+        monitor_vprintf(mon, fmt, ap);
+    } else {
+        fprintf(stderr, "qemu: ");
+        vfprintf(stderr, fmt, ap);
+        exit(1);
+    }
+    va_end(ap);
+}
+
 #if defined(CONFIG_SLIRP)
 
 /* slirp network adapter */
@@ -599,7 +614,7 @@ void net_slirp_redir(Monitor *mon, const char *redir_str)
 {
     int is_udp;
     char buf[256], *r;
-    const char *p, *errmsg;
+    const char *p;
     struct in_addr guest_addr;
     int host_port, guest_port;
 
@@ -638,20 +653,12 @@ void net_slirp_redir(Monitor *mon, const char *redir_str)
         goto fail_syntax;
 
     if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
-        errmsg = "could not set up redirection\n";
-        goto fail;
+        config_error(mon, "could not set up redirection '%s'\n", redir_str);
     }
     return;
 
  fail_syntax:
-    errmsg = "invalid redirection format\n";
- fail:
-    if (mon) {
-        monitor_printf(mon, "%s", errmsg);
-    } else {
-        fprintf(stderr, "qemu: %s", errmsg);
-        exit(1);
-    }
+    config_error(mon, "invalid redirection format '%s'\n", redir_str);
 }
 
 #ifndef _WIN32
@@ -1699,7 +1706,7 @@ static void net_dump_cleanup(VLANClientState *vc)
     qemu_free(s);
 }
 
-static int net_dump_init(VLANState *vlan, const char *device,
+static int net_dump_init(Monitor *mon, VLANState *vlan, const char *device,
                          const char *name, const char *filename, int len)
 {
     struct pcap_file_hdr hdr;
@@ -1709,7 +1716,7 @@ static int net_dump_init(VLANState *vlan, const char *device,
 
     s->fd = open(filename, O_CREAT | O_WRONLY, 0644);
     if (s->fd < 0) {
-        fprintf(stderr, "-net dump: can't open %s\n", filename);
+        config_error(mon, "-net dump: can't open %s\n", filename);
         return -1;
     }
 
@@ -1724,7 +1731,7 @@ static int net_dump_init(VLANState *vlan, const char *device,
     hdr.linktype = 1;
 
     if (write(s->fd, &hdr, sizeof(hdr)) < sizeof(hdr)) {
-        perror("-net dump write error");
+        config_error(mon, "-net dump write error: %s\n", strerror(errno));
         close(s->fd);
         qemu_free(s);
         return -1;
@@ -1799,7 +1806,7 @@ void qemu_check_nic_model_list(NICInfo *nd, const char * const *models,
     exit(exit_status);
 }
 
-int net_client_init(const char *device, const char *p)
+int net_client_init(Monitor *mon, const char *device, const char *p)
 {
     static const char * const fd_params[] = {
         "vlan", "name", "fd", NULL
@@ -1816,7 +1823,7 @@ int net_client_init(const char *device, const char *p)
     vlan = qemu_find_vlan(vlan_id);
 
     if (get_param_value(buf, sizeof(buf), "name", p)) {
-        name = strdup(buf);
+        name = qemu_strdup(buf);
     }
     if (!strcmp(device, "nic")) {
         static const char * const nic_params[] = {
@@ -1827,12 +1834,12 @@ int net_client_init(const char *device, const char *p)
         int idx = nic_get_free_idx();
 
         if (check_params(buf, sizeof(buf), nic_params, p) < 0) {
-            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                    buf, p);
-            return -1;
+            config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
+            ret = -1;
+            goto out;
         }
         if (idx == -1 || nb_nics >= MAX_NICS) {
-            fprintf(stderr, "Too Many NICs\n");
+            config_error(mon, "Too Many NICs\n");
             ret = -1;
             goto out;
         }
@@ -1847,7 +1854,7 @@ int net_client_init(const char *device, const char *p)
 
         if (get_param_value(buf, sizeof(buf), "macaddr", p)) {
             if (parse_macaddr(macaddr, buf) < 0) {
-                fprintf(stderr, "invalid syntax for ethernet address\n");
+                config_error(mon, "invalid syntax for ethernet address\n");
                 ret = -1;
                 goto out;
             }
@@ -1865,8 +1872,9 @@ int net_client_init(const char *device, const char *p)
     } else
     if (!strcmp(device, "none")) {
         if (*p != '\0') {
-            fprintf(stderr, "qemu: 'none' takes no parameters\n");
-            return -1;
+            config_error(mon, "'none' takes no parameters\n");
+            ret = -1;
+            goto out;
         }
         /* does nothing. It is needed to signal that no network cards
            are wanted */
@@ -1878,9 +1886,9 @@ int net_client_init(const char *device, const char *p)
             "vlan", "name", "hostname", "restrict", "ip", NULL
         };
         if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
-            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                    buf, p);
-            return -1;
+            config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
+            ret = -1;
+            goto out;
         }
         if (get_param_value(buf, sizeof(buf), "hostname", p)) {
             pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf);
@@ -1901,7 +1909,7 @@ int net_client_init(const char *device, const char *p)
         port = strtol(p, &devname, 10);
         devname++;
         if (port < 1 || port > 65535) {
-            fprintf(stderr, "vmchannel wrong port number\n");
+            config_error(mon, "vmchannel wrong port number\n");
             ret = -1;
             goto out;
         }
@@ -1909,8 +1917,8 @@ int net_client_init(const char *device, const char *p)
         snprintf(name, 20, "vmchannel%ld", port);
         vmc->hd = qemu_chr_open(name, devname, NULL);
         if (!vmc->hd) {
-            fprintf(stderr, "qemu: could not open vmchannel device"
-                    "'%s'\n", devname);
+            config_error(mon, "could not open vmchannel device '%s'\n",
+                         devname);
             ret = -1;
             goto out;
         }
@@ -1929,12 +1937,12 @@ int net_client_init(const char *device, const char *p)
         char ifname[64];
 
         if (check_params(buf, sizeof(buf), tap_params, p) < 0) {
-            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                    buf, p);
-            return -1;
+            config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
+            ret = -1;
+            goto out;
         }
         if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
-            fprintf(stderr, "tap: no interface name\n");
+            config_error(mon, "tap: no interface name\n");
             ret = -1;
             goto out;
         }
@@ -1950,9 +1958,9 @@ int net_client_init(const char *device, const char *p)
         vlan->nb_host_devs++;
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
             if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
-                return -1;
+                config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
+                ret = -1;
+                goto out;
             }
             fd = strtol(buf, NULL, 0);
             fcntl(fd, F_SETFL, O_NONBLOCK);
@@ -1963,9 +1971,9 @@ int net_client_init(const char *device, const char *p)
                 "vlan", "name", "ifname", "script", "downscript", NULL
             };
             if (check_params(chkbuf, sizeof(chkbuf), tap_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
-                return -1;
+                config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
+                ret = -1;
+                goto out;
             }
             if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
                 ifname[0] = '\0';
@@ -1985,9 +1993,9 @@ int net_client_init(const char *device, const char *p)
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
             int fd;
             if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
-                return -1;
+                config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
+                ret = -1;
+                goto out;
             }
             fd = strtol(buf, NULL, 0);
             ret = -1;
@@ -1998,9 +2006,9 @@ int net_client_init(const char *device, const char *p)
                 "vlan", "name", "listen", NULL
             };
             if (check_params(chkbuf, sizeof(chkbuf), listen_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
-                return -1;
+                config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
+                ret = -1;
+                goto out;
             }
             ret = net_socket_listen_init(vlan, device, name, buf);
         } else if (get_param_value(buf, sizeof(buf), "connect", p) > 0) {
@@ -2008,9 +2016,9 @@ int net_client_init(const char *device, const char *p)
                 "vlan", "name", "connect", NULL
             };
             if (check_params(chkbuf, sizeof(chkbuf), connect_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
-                return -1;
+                config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
+                ret = -1;
+                goto out;
             }
             ret = net_socket_connect_init(vlan, device, name, buf);
         } else if (get_param_value(buf, sizeof(buf), "mcast", p) > 0) {
@@ -2018,13 +2026,13 @@ int net_client_init(const char *device, const char *p)
                 "vlan", "name", "mcast", NULL
             };
             if (check_params(chkbuf, sizeof(chkbuf), mcast_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
-                return -1;
+                config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
+                ret = -1;
+                goto out;
             }
             ret = net_socket_mcast_init(vlan, device, name, buf);
         } else {
-            fprintf(stderr, "Unknown socket options: %s\n", p);
+            config_error(mon, "Unknown socket options: %s\n", p);
             ret = -1;
             goto out;
         }
@@ -2039,9 +2047,9 @@ int net_client_init(const char *device, const char *p)
 	int vde_port, vde_mode;
 
         if (check_params(buf, sizeof(buf), vde_params, p) < 0) {
-            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                    buf, p);
-            return -1;
+            config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
+            ret = -1;
+            goto out;
         }
         vlan->nb_host_devs++;
         if (get_param_value(vde_sock, sizeof(vde_sock), "sock", p) <= 0) {
@@ -2072,18 +2080,17 @@ int net_client_init(const char *device, const char *p)
         if (!get_param_value(buf, sizeof(buf), "file", p)) {
             snprintf(buf, sizeof(buf), "qemu-vlan%d.pcap", vlan_id);
         }
-        ret = net_dump_init(vlan, device, name, buf, len);
+        ret = net_dump_init(mon, vlan, device, name, buf, len);
     } else {
-        fprintf(stderr, "Unknown network device: %s\n", device);
+        config_error(mon, "Unknown network device: %s\n", device);
         ret = -1;
         goto out;
     }
     if (ret < 0) {
-        fprintf(stderr, "Could not initialize device '%s'\n", device);
+        config_error(mon, "Could not initialize device '%s'\n", device);
     }
 out:
-    if (name)
-        free(name);
+    qemu_free(name);
     return ret;
 }
 
@@ -2121,7 +2128,7 @@ void net_host_device_add(Monitor *mon, const char *device, const char *opts)
         monitor_printf(mon, "invalid host network device %s\n", device);
         return;
     }
-    if (net_client_init(device, opts ? opts : "") < 0) {
+    if (net_client_init(mon, device, opts ? opts : "") < 0) {
         monitor_printf(mon, "adding host network device %s failed\n", device);
     }
 }
@@ -2167,7 +2174,7 @@ int net_client_parse(const char *str)
     if (*p == ',')
         p++;
 
-    return net_client_init(device, p);
+    return net_client_init(NULL, device, p);
 }
 
 void do_info_network(Monitor *mon)
diff --git a/net.h b/net.h
index cdf63a4..4f8f393 100644
--- a/net.h
+++ b/net.h
@@ -108,7 +108,7 @@ uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
 void net_checksum_calculate(uint8_t *data, int length);
 
 /* from net.c */
-int net_client_init(const char *device, const char *p);
+int net_client_init(Monitor *mon, const char *device, const char *p);
 void net_client_uninit(NICInfo *nd);
 int net_client_parse(const char *str);
 void net_slirp_smb(const char *exported_dir);
diff --git a/vl.c b/vl.c
index fad386b..8b641f5 100644
--- a/vl.c
+++ b/vl.c
@@ -2730,7 +2730,7 @@ static int usb_device_add(const char *devname, int is_hotplug)
     } else if (strstart(devname, "net:", &p)) {
         int nic = nb_nics;
 
-        if (net_client_init("nic", p) < 0)
+        if (net_client_init(NULL, "nic", p) < 0)
             return -1;
         nd_table[nic].model = "usb";
         dev = usb_net_init(&nd_table[nic]);

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 10/11] slirp: Rework external configuration interface
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
                   ` (4 preceding siblings ...)
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 06/11] slirp: Reorder initialization Jan Kiszka
@ 2009-05-08 10:34 ` Jan Kiszka
  2009-05-28 15:07   ` Mark McLoughlin
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 07/11] Introduce get_next_param_value Jan Kiszka
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

With the internal IP configuration made more flexible, we can now
enhance the user interface. This patch adds a number of new options to
"-net user": net (address and mask), host, dhcpstart, dns and smbserver.
It also renames "redir" to "hostfwd" and "channel" to "guestfwd" in
order to (hopefully) clarify their meanings. The format of guestfwd is
extended so that the user can define not only the port but also the
virtual server's IP address the forwarding starts from.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |  295 +++++++++++++++++++++++++++++++++++++++++-------------
 qemu-options.hx  |   52 ++++++----
 slirp/libslirp.h |   17 ++-
 slirp/main.h     |    1 
 slirp/slirp.c    |   46 ++++----
 5 files changed, 289 insertions(+), 122 deletions(-)

diff --git a/net.c b/net.c
index b5238e8..dcd4a6e 100644
--- a/net.c
+++ b/net.c
@@ -551,12 +551,14 @@ static void config_error(Monitor *mon, const char *fmt, ...)
 
 /* slirp network adapter */
 
-#define SLIRP_CFG_REDIR 1
+#define SLIRP_CFG_HOSTFWD 1
+#define SLIRP_CFG_LEGACY  2
 
 struct slirp_config_str {
     struct slirp_config_str *next;
     int flags;
     char str[1024];
+    int legacy_format;
 };
 
 static int slirp_inited;
@@ -568,9 +570,10 @@ static const char *slirp_smb_export;
 #endif
 static VLANClientState *slirp_vc;
 
-static void slirp_smb(const char *exported_dir);
-static void slirp_redirection(Monitor *mon, const char *redir_str);
-static void vmchannel_init(Monitor *mon, const char *config_str);
+static void slirp_smb(const char *exported_dir, struct in_addr vserver_addr);
+static void slirp_hostfwd(Monitor *mon, const char *redir_str);
+static void slirp_guestfwd(Monitor *mon, const char *config_str,
+                           int legacy_format);
 
 int slirp_can_output(void)
 {
@@ -610,15 +613,32 @@ static void net_slirp_cleanup(VLANClientState *vc)
 }
 
 static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
-                          const char *name, int restricted, const char *ip,
-                          const char *tftp_export, const char *bootfile,
-                          const char *smb_export)
+                          const char *name, int restricted,
+                          const char *vnetwork, const char *vhost,
+                          const char *vhostname, const char *tftp_export,
+                          const char *bootfile, const char *vdhcp_start,
+                          const char *vnameserver, const char *smb_export,
+                          const char *vsmbserver)
 {
     if (slirp_in_use) {
         /* slirp only supports a single instance so far */
         return -1;
     }
     if (!slirp_inited) {
+        /* default settings according to historic slirp */
+        struct in_addr net  = { .s_addr = htonl(0x0a000000) }; /* 10.0.0.0 */
+        struct in_addr mask = { .s_addr = htonl(0xff000000) }; /* 255.0.0.0 */
+        struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
+        struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
+        struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
+#ifndef _WIN32
+        struct in_addr smbsrv = { .s_addr = 0 };
+#endif
+        char buf[20];
+        uint32_t addr;
+        int shift;
+        char *end;
+
         if (!tftp_export) {
             tftp_export = legacy_tftp_prefix;
         }
@@ -626,15 +646,83 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
             bootfile = legacy_bootp_filename;
         }
         slirp_inited = 1;
-        slirp_init(restricted, ip, tftp_export, bootfile);
+
+        if (vnetwork) {
+            if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
+                if (!inet_aton(vnetwork, &net)) {
+                    return -1;
+                }
+                addr = ntohl(net.s_addr);
+                if (!(addr & 0x80000000)) {
+                    mask.s_addr = htonl(0xff000000); /* class A */
+                } else if ((addr & 0xfff00000) == 0xac100000) {
+                    mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
+                } else if ((addr & 0xc0000000) == 0x80000000) {
+                    mask.s_addr = htonl(0xffff0000); /* class B */
+                } else if ((addr & 0xffff0000) == 0xc0a80000) {
+                    mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
+                } else if ((addr & 0xffff0000) == 0xc6120000) {
+                    mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
+                } else if ((addr & 0xe0000000) == 0xe0000000) {
+                    mask.s_addr = htonl(0xffffff00); /* class C */
+                } else {
+                    mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
+                }
+            } else {
+                if (!inet_aton(buf, &net)) {
+                    return -1;
+                }
+                shift = strtol(vnetwork, &end, 10);
+                if (*end != '\0') {
+                    if (!inet_aton(vnetwork, &mask)) {
+                        return -1;
+                    }
+                } else if (shift < 4 || shift > 32) {
+                    return -1;
+                } else {
+                    mask.s_addr = htonl(0xffffffff << (32 - shift));
+                }
+            }
+            net.s_addr &= mask.s_addr;
+            host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
+            dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
+            dns.s_addr  = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
+        }
+
+        if (vhost && !inet_aton(vhost, &host)) {
+            return -1;
+        }
+        if ((host.s_addr & mask.s_addr) != net.s_addr) {
+            return -1;
+        }
+
+        if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
+            return -1;
+        }
+        if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||
+            dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
+            return -1;
+        }
+
+        if (vnameserver && !inet_aton(vnameserver, &dns)) {
+            return -1;
+        }
+        if ((dns.s_addr & mask.s_addr) != net.s_addr ||
+            dns.s_addr == host.s_addr) {
+            return -1;
+        }
+
+        slirp_init(restricted, net, mask, host, vhostname, tftp_export,
+                   bootfile, dhcp, dns);
 
         while (slirp_configs) {
             struct slirp_config_str *config = slirp_configs;
 
-            if (config->flags & SLIRP_CFG_REDIR) {
-                slirp_redirection(mon, config->str);
+            if (config->flags & SLIRP_CFG_HOSTFWD) {
+                slirp_hostfwd(mon, config->str);
             } else {
-                vmchannel_init(mon, config->str);
+                slirp_guestfwd(mon, config->str,
+                               config->flags & SLIRP_CFG_LEGACY);
             }
             slirp_configs = config->next;
             qemu_free(config);
@@ -643,8 +731,11 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
         if (smb_export) {
             slirp_smb_export = smb_export;
         }
+        if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
+            return -1;
+        }
         if (slirp_smb_export) {
-            slirp_smb(slirp_smb_export);
+            slirp_smb(slirp_smb_export, smbsrv);
         }
 #endif
     }
@@ -656,13 +747,14 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
     return 0;
 }
 
-static void slirp_redirection(Monitor *mon, const char *redir_str)
+static void slirp_hostfwd(Monitor *mon, const char *redir_str)
 {
-    struct in_addr guest_addr;
+    struct in_addr guest_addr = { .s_addr = 0 };
     int host_port, guest_port;
     const char *p;
-    char buf[256], *r;
+    char buf[256];
     int is_udp;
+    char *end;
 
     p = redir_str;
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
@@ -679,33 +771,31 @@ static void slirp_redirection(Monitor *mon, const char *redir_str)
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
         goto fail_syntax;
     }
-    host_port = strtol(buf, &r, 0);
-    if (r == buf) {
+    host_port = strtol(buf, &end, 0);
+    if (*end != '\0' || host_port < 1 || host_port > 65535) {
         goto fail_syntax;
     }
 
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
         goto fail_syntax;
     }
-    if (buf[0] == '\0') {
-        pstrcpy(buf, sizeof(buf), "10.0.2.15");
-    }
-    if (!inet_aton(buf, &guest_addr)) {
+    if (buf[0] != '\0' && !inet_aton(buf, &guest_addr)) {
         goto fail_syntax;
     }
 
-    guest_port = strtol(p, &r, 0);
-    if (r == p) {
+    guest_port = strtol(p, &end, 0);
+    if (*end != '\0' || guest_port < 1 || guest_port > 65535) {
         goto fail_syntax;
     }
 
     if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
-        config_error(mon, "could not set up redirection '%s'\n", redir_str);
+        config_error(mon, "could not set up host forwarding rule '%s'\n",
+                     redir_str);
     }
     return;
 
  fail_syntax:
-    config_error(mon, "invalid redirection format '%s'\n", redir_str);
+    config_error(mon, "invalid host forwarding rule '%s'\n", redir_str);
 }
 
 void net_slirp_redir(Monitor *mon, const char *redir_str)
@@ -718,14 +808,14 @@ void net_slirp_redir(Monitor *mon, const char *redir_str)
         } else {
             config = qemu_malloc(sizeof(*config));
             pstrcpy(config->str, sizeof(config->str), redir_str);
-            config->flags = SLIRP_CFG_REDIR;
+            config->flags = SLIRP_CFG_HOSTFWD;
             config->next = slirp_configs;
             slirp_configs = config;
         }
         return;
     }
 
-    slirp_redirection(mon, redir_str);
+    slirp_hostfwd(mon, redir_str);
 }
 
 #ifndef _WIN32
@@ -763,7 +853,7 @@ static void smb_exit(void)
     erase_dir(smb_dir);
 }
 
-static void slirp_smb(const char *exported_dir)
+static void slirp_smb(const char *exported_dir, struct in_addr vserver_addr)
 {
     char smb_conf[1024];
     char smb_cmdline[1024];
@@ -809,19 +899,24 @@ static void slirp_smb(const char *exported_dir)
     snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
              SMBD_COMMAND, smb_conf);
 
-    slirp_add_exec(0, smb_cmdline, 4, 139);
+    if (slirp_add_exec(0, smb_cmdline, vserver_addr, 139) < 0) {
+        fprintf(stderr, "conflicting/invalid smbserver address\n");
+        exit(1);
+    }
 }
 
 /* automatic user mode samba server configuration */
 void net_slirp_smb(const char *exported_dir)
 {
+    struct in_addr vserver_addr = { .s_addr = 0 };
+
     if (slirp_smb_export) {
         fprintf(stderr, "-smb given twice\n");
         exit(1);
     }
     slirp_smb_export = exported_dir;
     if (slirp_inited) {
-        slirp_smb(exported_dir);
+        slirp_smb(exported_dir, vserver_addr);
     }
 }
 
@@ -832,51 +927,85 @@ void do_info_slirp(Monitor *mon)
     slirp_stats();
 }
 
-struct VMChannel {
+struct GuestFwd {
     CharDriverState *hd;
+    struct in_addr server;
     int port;
 };
 
-static int vmchannel_can_read(void *opaque)
+static int guestfwd_can_read(void *opaque)
 {
-    struct VMChannel *vmc = (struct VMChannel*)opaque;
-    return slirp_socket_can_recv(4, vmc->port);
+    struct GuestFwd *fwd = opaque;
+    return slirp_socket_can_recv(fwd->server, fwd->port);
 }
 
-static void vmchannel_read(void *opaque, const uint8_t *buf, int size)
+static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
 {
-    struct VMChannel *vmc = (struct VMChannel*)opaque;
-    slirp_socket_recv(4, vmc->port, buf, size);
+    struct GuestFwd *fwd = opaque;
+    slirp_socket_recv(fwd->server, fwd->port, buf, size);
 }
 
-static void vmchannel_init(Monitor *mon, const char *config_str)
+static void slirp_guestfwd(Monitor *mon, const char *config_str,
+                           int legacy_format)
 {
-    struct VMChannel *vmc;
-    char *devname;
-    char name[20];
+    struct in_addr server = { .s_addr = 0 };
+    struct GuestFwd *fwd;
+    const char *p;
+    char buf[128];
+    char *end;
     int port;
 
-    port = strtol(config_str, &devname, 10);
-    if (port < 1 || port > 65535 || *devname != ':') {
-        config_error(mon, "invalid vmchannel port number\n");
-        return;
+    p = config_str;
+    if (legacy_format) {
+        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+            goto fail_syntax;
+        }
+    } else {
+        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+            goto fail_syntax;
+        }
+        if (strcmp(buf, "tcp") && buf[0] != '\0') {
+            goto fail_syntax;
+        }
+        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+            goto fail_syntax;
+        }
+        if (buf[0] != '\0' && !inet_aton(buf, &server)) {
+            goto fail_syntax;
+        }
+        if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
+            goto fail_syntax;
+        }
+    }
+    port = strtol(buf, &end, 10);
+    if (*end != '\0' || port < 1 || port > 65535) {
+        goto fail_syntax;
     }
-    devname++;
 
-    vmc = qemu_malloc(sizeof(struct VMChannel));
-    snprintf(name, sizeof(name), "vmchannel%d", port);
-    vmc->hd = qemu_chr_open(name, devname, NULL);
-    if (!vmc->hd) {
-        config_error(mon, "could not open vmchannel device '%s'\n", devname);
-        qemu_free(vmc);
+    fwd = qemu_malloc(sizeof(struct GuestFwd));
+    snprintf(buf, sizeof(buf), "guestfwd.tcp:%d", port);
+    fwd->hd = qemu_chr_open(buf, p, NULL);
+    if (!fwd->hd) {
+        config_error(mon, "could not open guest forwarding device '%s'\n",
+                     buf);
+        qemu_free(fwd);
         return;
     }
-    vmc->port = port;
+    fwd->server = server;
+    fwd->port = port;
 
-    slirp_add_exec(3, vmc->hd, 4, port);
-    qemu_chr_add_handlers(vmc->hd, vmchannel_can_read, vmchannel_read,
-                          NULL, vmc);
+    if (slirp_add_exec(3, fwd->hd, server, port) < 0) {
+        config_error(mon, "conflicting/invalid host:port in guest forwarding "
+                     "rule '%s'\n", config_str);
+        qemu_free(fwd);
+        return;
+    }
+    qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
+                          NULL, fwd);
     return;
+
+ fail_syntax:
+    config_error(mon, "invalid guest forwarding rule '%s'\n", config_str);
 }
 
 #endif /* CONFIG_SLIRP */
@@ -1988,15 +2117,21 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
 #ifdef CONFIG_SLIRP
     if (!strcmp(device, "user")) {
         static const char * const slirp_params[] = {
-            "vlan", "name", "hostname", "restrict", "ip", "tftp", "bootfile",
-            "smb", "redir", "channel", NULL
+            "vlan", "name", "hostname", "restrict", "net", "host",
+            "tftp", "bootfile", "dhcpstart", "dns", "smb", "smbserver",
+            "hostfwd", "guestfwd", NULL
         };
         struct slirp_config_str *config;
+        int restricted = 0;
+        char *vnet = NULL;
+        char *vhost = NULL;
+        char *vhostname = NULL;
         char *tftp_export = NULL;
         char *bootfile = NULL;
+        char *vdhcp_start = NULL;
+        char *vnamesrv = NULL;
         char *smb_export = NULL;
-        int restricted = 0;
-        char *ip = NULL;
+        char *vsmbsrv = NULL;
         const char *q;
 
         if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
@@ -2004,14 +2139,23 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
             ret = -1;
             goto out;
         }
+        if (get_param_value(buf, sizeof(buf), "net", p)) {
+            vnet = qemu_strdup(buf);
+        }
+        if (get_param_value(buf, sizeof(buf), "host", p)) {
+            vhost = qemu_strdup(buf);
+        }
         if (get_param_value(buf, sizeof(buf), "hostname", p)) {
-            pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf);
+            vhostname = qemu_strdup(buf);
         }
         if (get_param_value(buf, sizeof(buf), "restrict", p)) {
             restricted = (buf[0] == 'y') ? 1 : 0;
         }
-        if (get_param_value(buf, sizeof(buf), "ip", p)) {
-            ip = qemu_strdup(buf);
+        if (get_param_value(buf, sizeof(buf), "dhcpstart", p)) {
+            vdhcp_start = qemu_strdup(buf);
+        }
+        if (get_param_value(buf, sizeof(buf), "dns", p)) {
+            vnamesrv = qemu_strdup(buf);
         }
         if (get_param_value(buf, sizeof(buf), "tftp", p)) {
             tftp_export = qemu_strdup(buf);
@@ -2021,15 +2165,18 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         }
         if (get_param_value(buf, sizeof(buf), "smb", p)) {
             smb_export = qemu_strdup(buf);
+            if (get_param_value(buf, sizeof(buf), "smbserver", p)) {
+                vsmbsrv = qemu_strdup(buf);
+            }
         }
         q = p;
         while (1) {
             config = qemu_malloc(sizeof(*config));
             if (!get_next_param_value(config->str, sizeof(config->str),
-                                      "redir", &q)) {
+                                      "hostfwd", &q)) {
                 break;
             }
-            config->flags = SLIRP_CFG_REDIR;
+            config->flags = SLIRP_CFG_HOSTFWD;
             config->next = slirp_configs;
             slirp_configs = config;
             config = NULL;
@@ -2038,7 +2185,7 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         while (1) {
             config = qemu_malloc(sizeof(*config));
             if (!get_next_param_value(config->str, sizeof(config->str),
-                                      "channel", &q)) {
+                                      "guestfwd", &q)) {
                 break;
             }
             config->flags = 0;
@@ -2048,23 +2195,29 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         }
         qemu_free(config);
         vlan->nb_host_devs++;
-        ret = net_slirp_init(mon, vlan, device, name, restricted, ip,
-                             tftp_export, bootfile, smb_export);
-        qemu_free(ip);
+        ret = net_slirp_init(mon, vlan, device, name, restricted, vnet, vhost,
+                             vhostname, tftp_export, bootfile, vdhcp_start,
+                             vnamesrv, smb_export, vsmbsrv);
+        qemu_free(vnet);
+        qemu_free(vhost);
+        qemu_free(vhostname);
         qemu_free(tftp_export);
         qemu_free(bootfile);
+        qemu_free(vdhcp_start);
+        qemu_free(vnamesrv);
         qemu_free(smb_export);
+        qemu_free(vsmbsrv);
     } else if (!strcmp(device, "channel")) {
         if (!slirp_inited) {
             struct slirp_config_str *config;
 
             config = qemu_malloc(sizeof(*config));
             pstrcpy(config->str, sizeof(config->str), p);
-            config->flags = 0;
+            config->flags = SLIRP_CFG_LEGACY;
             config->next = slirp_configs;
             slirp_configs = config;
         } else {
-            vmchannel_init(mon, p);
+            slirp_guestfwd(mon, p, 1);
         }
         ret = 0;
     } else
diff --git a/qemu-options.hx b/qemu-options.hx
index e721f60..971bd9d 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -737,10 +737,11 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, \
     "-net nic[,vlan=n][,macaddr=addr][,model=type][,name=str]\n"
     "                create a new Network Interface Card and connect it to VLAN 'n'\n"
 #ifdef CONFIG_SLIRP
-    "-net user[,vlan=n][,name=str][ip=netaddr][,restrict=y|n][,hostname=host]\n"
-    "         [,tftp=dir][,bootfile=f][,redir=rule][,channel=rule]"
+    "-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=y|n]\n"
+    "         [,hostname=host][,dhcpstart=addr][,dns=addr][,tftp=dir][,bootfile=f]\n"
+    "         [,hostfwd=rule][,guestfwd=rule]"
 #ifndef _WIN32
-                                                                  "[,smb=dir]\n"
+                                             "[,smb=dir[,smbserver=addr]]\n"
 #endif
     "                connect the user mode network stack to VLAN 'n', configure its\n"
     "                DHCP server and enabled optional services\n"
@@ -797,8 +798,14 @@ Connect user mode stack to VLAN @var{n} (@var{n} = 0 is the default).
 @item name=@var{name}
 Assign symbolic name for use in monitor commands.
 
-@item ip=@var{netaddr}
-Set IP network address the guest will see (default: 10.0.2.x).
+@item net=@var{addr}[/@var{mask}]
+Set IP network address the guest will see. Optionally specify the netmask,
+either in the form a.b.c.d or as number of valid top-most bits. Default is
+10.0.2.0/8.
+
+@item host=@var{addr}
+Specify the guest-visible address of the host. Default is the 2nd IP in the
+guest network, i.e. x.x.x.2.
 
 @item restrict=y|yes|n|no
 If this options is enabled, the guest will be isolated, i.e. it will not be
@@ -808,12 +815,20 @@ to the outside. This option does not affect explicitly set forwarding rule.
 @item hostname=@var{name}
 Specifies the client hostname reported by the builtin DHCP server.
 
+@item dhcpstart=@var{addr}
+Specify the first of the 16 IPs the built-in DHCP server can assign. Default
+is the 16th to 31st IP in the guest network, i.e. x.x.x.16 to x.x.x.31.
+
+@item dns=@var{addr}
+Specify the guest-visible address of the virtual nameserver. The address must
+be different from the host address. Default is the 3rd IP in the guest network,
+i.e. x.x.x.3.
+
 @item tftp=@var{dir}
 When using the user mode network stack, activate a built-in TFTP
 server. The files in @var{dir} will be exposed as the root of a TFTP server.
 The TFTP client on the guest must be configured in binary mode (use the command
-@code{bin} of the Unix TFTP client). The host IP address on the guest is
-10.0.2.2 by default.
+@code{bin} of the Unix TFTP client).
 
 @item bootfile=@var{file}
 When using the user mode network stack, broadcast @var{file} as the BOOTP
@@ -825,10 +840,11 @@ Example (using pxelinux):
 qemu -hda linux.img -boot n -net user,tftp=/path/to/tftp/files,bootfile=/pxelinux.0
 @end example
 
-@item smb=@var{dir}
+@item smb=@var{dir}[,smbserver=@var{addr}]
 When using the user mode network stack, activate a built-in SMB
 server so that Windows OSes can access to the host files in @file{@var{dir}}
-transparently.
+transparently. The IP address of the SMB server can be set to @var{addr}. By
+default the 4th IP in the guest network is used, i.e. x.x.x.4.
 
 In the guest Windows OS, the line:
 @example
@@ -843,19 +859,19 @@ Note that a SAMBA server must be installed on the host OS in
 @file{/usr/sbin/smbd}. QEMU was tested successfully with smbd versions from
 Red Hat 9, Fedora Core 3 and OpenSUSE 11.x.
 
-@item redir=[tcp|udp]:@var{host-port}:[@var{guest-host}]:@var{guest-port}
-Redirect incoming TCP or UDP connections to the host port @var{host-port} to
-the guest @var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
-is not specified, its value is 10.0.2.15 (default address given by the built-in
-DHCP server). If no connection type is specified, TCP is used. This option can
-be given multiple times.
+@item hostfwd=[tcp|udp]:@var{hostport}:[@var{guestaddr}]:@var{guestport}
+Redirect incoming TCP or UDP connections to the host port @var{hostport} to
+the guest IP address @var{guestaddr} on guest port @var{guestport}. If
+@var{guestaddr} is not specified, its value is x.x.x.15 (default first address
+given by the built-in DHCP server). If no connection type is specified, TCP is
+used. This option can be given multiple times.
 
 For example, to redirect host X11 connection from screen 1 to guest
 screen 0, use the following:
 
 @example
 # on the host
-qemu -net user,redir=tcp:6001::6000 [...]
+qemu -net user,hostfwd=tcp:6001::6000 [...]
 # this host xterm should open in the guest X11 server
 xterm -display :1
 @end example
@@ -865,14 +881,14 @@ the guest, use the following:
 
 @example
 # on the host
-qemu -net user,redir=tcp:5555::23 [...]
+qemu -net user,hostfwd=tcp:5555::23 [...]
 telnet localhost 5555
 @end example
 
 Then when you use on the host @code{telnet localhost 5555}, you
 connect to the guest telnet server.
 
-@item channel=@var{port}:@var{dev}
+@item guestfwd=[tcp]:@var{server}:@var{port}-@var{dev}
 Forward guest TCP connections to port @var{port} on the host to character
 device @var{dev}. This option can be given multiple times.
 
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index c5b1bb9..4ac8750 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -5,8 +5,11 @@
 extern "C" {
 #endif
 
-void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
-                const char *bootfile);
+void slirp_init(int restricted, struct in_addr vnetwork,
+                struct in_addr vnetmask, struct in_addr vhost,
+                const char *vhostname, const char *tftp_path,
+                const char *bootfile, struct in_addr vdhcp_start,
+                struct in_addr vnameserver);
 
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds);
@@ -21,15 +24,13 @@ void slirp_output(const uint8_t *pkt, int pkt_len);
 
 int slirp_redir(int is_udp, int host_port,
                 struct in_addr guest_addr, int guest_port);
-int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
+int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
                    int guest_port);
 
-extern char slirp_hostname[33];
-
 void slirp_stats(void);
-void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
-		int size);
-size_t slirp_socket_can_recv(int addr_low_byte, int guest_port);
+void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
+                       const uint8_t *buf, int size);
+size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port);
 
 #ifdef __cplusplus
 }
diff --git a/slirp/main.h b/slirp/main.h
index 8682d55..b185235 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -47,6 +47,7 @@ extern int ppp_exit;
 extern int tcp_keepintvl;
 extern uint8_t client_ethaddr[6];
 extern int slirp_restrict;
+extern char slirp_hostname[33];
 extern char tftp_prefix[PATH_MAX];
 extern char bootp_filename[PATH_MAX];
 
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 53f866d..ad2feb4 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -173,10 +173,12 @@ static void slirp_cleanup(void)
 static void slirp_state_save(QEMUFile *f, void *opaque);
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
 
-void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
-                const char *bootfile)
+void slirp_init(int restricted, struct in_addr vnetwork,
+                struct in_addr vnetmask, struct in_addr vhost,
+                const char *vhostname, const char *tftp_path,
+                const char *bootfile, struct in_addr vdhcp_start,
+                struct in_addr vnameserver)
 {
-    struct in_addr special_addr = { .s_addr = htonl(0x0a000200) };
 #ifdef _WIN32
     WSADATA Data;
 
@@ -201,8 +203,11 @@ void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
         fprintf (stderr, "Warning: No DNS servers found\n");
     }
 
-    if (special_ip) {
-        inet_aton(special_ip, &special_addr);
+    vnetwork_addr = vnetwork;
+    vnetwork_mask = vnetmask;
+    vhost_addr = vhost;
+    if (vhostname) {
+        pstrcpy(slirp_hostname, sizeof(slirp_hostname), vhostname);
     }
     if (tftp_path) {
         pstrcpy(tftp_prefix, sizeof(tftp_prefix), tftp_path);
@@ -210,11 +215,8 @@ void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
     if (bootfile) {
         pstrcpy(bootp_filename, sizeof(bootp_filename), bootfile);
     }
-    vnetwork_addr = special_addr;
-    vnetwork_mask.s_addr = htonl(0xffffff00);
-    vhost_addr.s_addr = special_addr.s_addr | htonl(2);
-    vdhcp_startaddr.s_addr = special_addr.s_addr | htonl(15);
-    vnameserver_addr.s_addr = special_addr.s_addr | htonl(3);
+    vdhcp_startaddr = vdhcp_start;
+    vnameserver_addr = vnameserver;
     getouraddr();
     register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
 }
@@ -763,13 +765,13 @@ int slirp_redir(int is_udp, int host_port,
     return 0;
 }
 
-int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
-                  int guest_port)
+int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
+                   int guest_port)
 {
-    struct in_addr guest_addr = {
-        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
-    };
-
+    if (!guest_addr.s_addr) {
+        guest_addr.s_addr =
+            vnetwork_addr.s_addr | (htonl(0x0204) & ~vnetwork_mask.s_addr);
+    }
     if ((guest_addr.s_addr & vnetwork_mask.s_addr) != vnetwork_addr.s_addr ||
         guest_addr.s_addr == vhost_addr.s_addr ||
         guest_addr.s_addr == vnameserver_addr.s_addr) {
@@ -803,11 +805,8 @@ slirp_find_ctl_socket(struct in_addr guest_addr, int guest_port)
     return NULL;
 }
 
-size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
+size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
 {
-    struct in_addr guest_addr = {
-        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
-    };
 	struct iovec iov[2];
 	struct socket *so;
 
@@ -825,13 +824,10 @@ size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
 	return sopreprbuf(so, iov, NULL);
 }
 
-void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
-        int size)
+void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
+                       const uint8_t *buf, int size)
 {
     int ret;
-    struct in_addr guest_addr = {
-        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
-    };
     struct socket *so = slirp_find_ctl_socket(guest_addr, guest_port);
 
     if (!so)

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 11/11] slirp: Bind support for host forwarding rules
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
                   ` (9 preceding siblings ...)
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 09/11] slirp: Rework internal configuration Jan Kiszka
@ 2009-05-08 10:34 ` Jan Kiszka
  2009-05-08 16:25 ` [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Anthony Liguori
  11 siblings, 0 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 10:34 UTC (permalink / raw)
  To: qemu-devel

Extend the hostfwd rule format so that the user can specify on which
host interface qemu should listen for incoming connections. If omitted,
binding will takes place against all interfaces.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |   28 +++++++++++++++++++++-------
 qemu-options.hx  |   11 ++++++-----
 slirp/libslirp.h |    2 +-
 slirp/slirp.c    |    8 ++++----
 slirp/socket.c   |   10 +++++-----
 slirp/socket.h   |    2 +-
 slirp/tcp_subr.c |   13 +++++++------
 slirp/udp.c      |    7 ++++---
 slirp/udp.h      |    2 +-
 9 files changed, 50 insertions(+), 33 deletions(-)

diff --git a/net.c b/net.c
index dcd4a6e..36c5f4b 100644
--- a/net.c
+++ b/net.c
@@ -571,7 +571,8 @@ static const char *slirp_smb_export;
 static VLANClientState *slirp_vc;
 
 static void slirp_smb(const char *exported_dir, struct in_addr vserver_addr);
-static void slirp_hostfwd(Monitor *mon, const char *redir_str);
+static void slirp_hostfwd(Monitor *mon, const char *redir_str,
+                          int legacy_format);
 static void slirp_guestfwd(Monitor *mon, const char *config_str,
                            int legacy_format);
 
@@ -719,7 +720,8 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
             struct slirp_config_str *config = slirp_configs;
 
             if (config->flags & SLIRP_CFG_HOSTFWD) {
-                slirp_hostfwd(mon, config->str);
+                slirp_hostfwd(mon, config->str,
+                              config->flags & SLIRP_CFG_LEGACY);
             } else {
                 slirp_guestfwd(mon, config->str,
                                config->flags & SLIRP_CFG_LEGACY);
@@ -747,8 +749,10 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
     return 0;
 }
 
-static void slirp_hostfwd(Monitor *mon, const char *redir_str)
+static void slirp_hostfwd(Monitor *mon, const char *redir_str,
+                          int legacy_format)
 {
+    struct in_addr host_addr = { .s_addr = INADDR_ANY };
     struct in_addr guest_addr = { .s_addr = 0 };
     int host_port, guest_port;
     const char *p;
@@ -768,7 +772,16 @@ static void slirp_hostfwd(Monitor *mon, const char *redir_str)
         goto fail_syntax;
     }
 
-    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+    if (!legacy_format) {
+        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+            goto fail_syntax;
+        }
+        if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
+            goto fail_syntax;
+        }
+    }
+
+    if (get_str_sep(buf, sizeof(buf), &p, legacy_format ? ':' : '-') < 0) {
         goto fail_syntax;
     }
     host_port = strtol(buf, &end, 0);
@@ -788,7 +801,8 @@ static void slirp_hostfwd(Monitor *mon, const char *redir_str)
         goto fail_syntax;
     }
 
-    if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
+    if (slirp_redir(is_udp, host_addr, host_port,
+                    guest_addr, guest_port) < 0) {
         config_error(mon, "could not set up host forwarding rule '%s'\n",
                      redir_str);
     }
@@ -808,14 +822,14 @@ void net_slirp_redir(Monitor *mon, const char *redir_str)
         } else {
             config = qemu_malloc(sizeof(*config));
             pstrcpy(config->str, sizeof(config->str), redir_str);
-            config->flags = SLIRP_CFG_HOSTFWD;
+            config->flags = SLIRP_CFG_HOSTFWD | SLIRP_CFG_LEGACY;
             config->next = slirp_configs;
             slirp_configs = config;
         }
         return;
     }
 
-    slirp_hostfwd(mon, redir_str);
+    slirp_hostfwd(mon, redir_str, 1);
 }
 
 #ifndef _WIN32
diff --git a/qemu-options.hx b/qemu-options.hx
index 971bd9d..9c57085 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -859,11 +859,12 @@ Note that a SAMBA server must be installed on the host OS in
 @file{/usr/sbin/smbd}. QEMU was tested successfully with smbd versions from
 Red Hat 9, Fedora Core 3 and OpenSUSE 11.x.
 
-@item hostfwd=[tcp|udp]:@var{hostport}:[@var{guestaddr}]:@var{guestport}
+@item hostfwd=[tcp|udp]:[@var{hostaddr}]:@var{hostport}-[@var{guestaddr}]:@var{guestport}
 Redirect incoming TCP or UDP connections to the host port @var{hostport} to
 the guest IP address @var{guestaddr} on guest port @var{guestport}. If
 @var{guestaddr} is not specified, its value is x.x.x.15 (default first address
-given by the built-in DHCP server). If no connection type is specified, TCP is
+given by the built-in DHCP server). By specifying @var{hostaddr}, the rule can
+be bound to a specific host interface. If no connection type is set, TCP is
 used. This option can be given multiple times.
 
 For example, to redirect host X11 connection from screen 1 to guest
@@ -871,7 +872,7 @@ screen 0, use the following:
 
 @example
 # on the host
-qemu -net user,hostfwd=tcp:6001::6000 [...]
+qemu -net user,hostfwd=tcp:127.0.0.1:6001-:6000 [...]
 # this host xterm should open in the guest X11 server
 xterm -display :1
 @end example
@@ -889,8 +890,8 @@ Then when you use on the host @code{telnet localhost 5555}, you
 connect to the guest telnet server.
 
 @item guestfwd=[tcp]:@var{server}:@var{port}-@var{dev}
-Forward guest TCP connections to port @var{port} on the host to character
-device @var{dev}. This option can be given multiple times.
+Forward guest TCP connections to the IP address @var{server} on port @var{port}
+to the character device @var{dev}. This option can be given multiple times.
 
 @end table
 
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 4ac8750..c2eb89d 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -22,7 +22,7 @@ void slirp_input(const uint8_t *pkt, int pkt_len);
 int slirp_can_output(void);
 void slirp_output(const uint8_t *pkt, int pkt_len);
 
-int slirp_redir(int is_udp, int host_port,
+int slirp_redir(int is_udp, struct in_addr host_addr, int host_port,
                 struct in_addr guest_addr, int guest_port);
 int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
                    int guest_port);
diff --git a/slirp/slirp.c b/slirp/slirp.c
index ad2feb4..2117ccd 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -747,19 +747,19 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
     }
 }
 
-int slirp_redir(int is_udp, int host_port,
+int slirp_redir(int is_udp, struct in_addr host_addr, int host_port,
                 struct in_addr guest_addr, int guest_port)
 {
     if (!guest_addr.s_addr) {
         guest_addr = vdhcp_startaddr;
     }
     if (is_udp) {
-        if (!udp_listen(htons(host_port), guest_addr.s_addr,
+        if (!udp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
                         htons(guest_port), 0))
             return -1;
     } else {
-        if (!solisten(htons(host_port), guest_addr.s_addr,
-                      htons(guest_port), 0))
+        if (!tcp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
+                        htons(guest_port), 0))
             return -1;
     }
     return 0;
diff --git a/slirp/socket.c b/slirp/socket.c
index 56f794d..8b3cecd 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -581,17 +581,17 @@ sosendto(struct socket *so, struct mbuf *m)
 }
 
 /*
- * XXX This should really be tcp_listen
+ * Listen for incoming TCP connections
  */
 struct socket *
-solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
+tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags)
 {
 	struct sockaddr_in addr;
 	struct socket *so;
 	int s, opt = 1;
 	socklen_t addrlen = sizeof(addr);
 
-	DEBUG_CALL("solisten");
+	DEBUG_CALL("tcp_listen");
 	DEBUG_ARG("port = %d", port);
 	DEBUG_ARG("laddr = %x", laddr);
 	DEBUG_ARG("lport = %d", lport);
@@ -620,8 +620,8 @@ solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
 	so->so_laddr.s_addr = laddr; /* Ditto */
 
 	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = INADDR_ANY;
-	addr.sin_port = port;
+	addr.sin_addr.s_addr = haddr;
+	addr.sin_port = hport;
 
 	if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
 	    (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
diff --git a/slirp/socket.h b/slirp/socket.h
index f5adaba..ac36aaa 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -82,7 +82,7 @@ int sosendoob _P((struct socket *));
 int sowrite _P((struct socket *));
 void sorecvfrom _P((struct socket *));
 int sosendto _P((struct socket *, struct mbuf *));
-struct socket * solisten _P((u_int, u_int32_t, u_int, int));
+struct socket * tcp_listen _P((u_int32_t, u_int, u_int32_t, u_int, int));
 void soisfconnecting _P((register struct socket *));
 void soisfconnected _P((register struct socket *));
 void soisfdisconnected _P((struct socket *));
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 858d1ae..b60339e 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -970,7 +970,7 @@ do_prompt:
 			laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
 			lport = htons((n5 << 8) | (n6));
 
-			if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(INADDR_ANY, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
 			   return 1;
 
 			n6 = ntohs(so->so_fport);
@@ -1002,7 +1002,7 @@ do_prompt:
 			laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
 			lport = htons((n5 << 8) | (n6));
 
-			if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(INADDR_ANY, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
 			   return 1;
 
 			n6 = ntohs(so->so_fport);
@@ -1042,7 +1042,7 @@ do_prompt:
 			lport += m->m_data[i] - '0';
 		}
 		if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
-		    (so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
+		    (so = tcp_listen(INADDR_ANY, 0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
                     m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, "%d",
                                         ntohs(so->so_fport)) + 1;
 		return 1;
@@ -1057,7 +1057,7 @@ do_prompt:
 
 		/* The %256s is for the broken mIRC */
 		if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
-			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 				return 1;
 
 			m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1066,7 +1066,7 @@ do_prompt:
                                              (unsigned long)ntohl(so->so_faddr.s_addr),
                                              ntohs(so->so_fport), 1);
 		} else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
-			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 				return 1;
 
 			m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1075,7 +1075,7 @@ do_prompt:
                                              (unsigned long)ntohl(so->so_faddr.s_addr),
                                              ntohs(so->so_fport), n1, 1);
 		} else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
-			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 				return 1;
 
 			m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1191,6 +1191,7 @@ do_prompt:
 				/* try to get udp port between 6970 - 7170 */
 				for (p = 6970; p < 7071; p++) {
 					if (udp_listen( htons(p),
+						       INADDR_ANY,
 						       so->so_laddr.s_addr,
 						       htons(lport),
 						       SS_FACCEPTONCE)) {
diff --git a/slirp/udp.c b/slirp/udp.c
index dd91671..66e12d6 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -629,7 +629,8 @@ struct cu_header {
 }
 
 struct socket *
-udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags)
+udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport,
+           int flags)
 {
 	struct sockaddr_in addr;
 	struct socket *so;
@@ -644,8 +645,8 @@ udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags)
 	insque(so,&udb);
 
 	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = INADDR_ANY;
-	addr.sin_port = port;
+	addr.sin_addr.s_addr = haddr;
+	addr.sin_port = hport;
 
 	if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
 		udp_detach(so);
diff --git a/slirp/udp.h b/slirp/udp.h
index 51a07a2..d4c2bea 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -101,7 +101,7 @@ void udp_input _P((register struct mbuf *, int));
 int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
 int udp_attach _P((struct socket *));
 void udp_detach _P((struct socket *));
-struct socket * udp_listen _P((u_int, u_int32_t, u_int, int));
+struct socket * udp_listen _P((u_int32_t, u_int, u_int32_t, u_int, int));
 int udp_output2(struct socket *so, struct mbuf *m,
                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
                 int iptos);

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 01/11] net: Don't deliver to disabled interfaces in qemu_sendv_packet
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 01/11] net: Don't deliver to disabled interfaces in qemu_sendv_packet Jan Kiszka
@ 2009-05-08 15:20   ` Mark McLoughlin
  2009-05-08 22:27     ` [Qemu-devel] "FLOSS bounty" ( FB )for running QEMU on SheevaPlug AGSCalabrese
  0 siblings, 1 reply; 38+ messages in thread
From: Mark McLoughlin @ 2009-05-08 15:20 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

On Fri, 2009-05-08 at 12:34 +0200, Jan Kiszka wrote:
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
> 
>  net.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/net.c b/net.c
> index d556015..b93b3a6 100644
> --- a/net.c
> +++ b/net.c
> @@ -494,7 +494,7 @@ ssize_t qemu_sendv_packet(VLANClientState *vc1, const struct iovec *iov,
>  
>          if (vc->link_down)
>              len = calc_iov_length(iov, iovcnt);
> -        if (vc->fd_readv)
> +        else if (vc->fd_readv)
>              len = vc->fd_readv(vc->opaque, iov, iovcnt);

Acked-by: Mark McLoughlin <markmc@redhat.com>

Cheers,
Mark.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] net: Fix and improved ordered packet delivery
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 02/11] net: Fix and improved ordered packet delivery Jan Kiszka
@ 2009-05-08 15:24   ` Mark McLoughlin
  0 siblings, 0 replies; 38+ messages in thread
From: Mark McLoughlin @ 2009-05-08 15:24 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

On Fri, 2009-05-08 at 12:34 +0200, Jan Kiszka wrote:
> Fix a race in qemu_send_packet when delivering deferred packets and

Not really a race condition, but yeah - delivering a deferred packet can
cause another packet to be queued.

> add proper deferring also to qemu_sendv_packet.

Yep, we need this.

> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>

Acked-by: Mark McLoughlin <markmc@redhat.com>

Cheers,
Mark.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements
  2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
                   ` (10 preceding siblings ...)
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 11/11] slirp: Bind support for host forwarding rules Jan Kiszka
@ 2009-05-08 16:25 ` Anthony Liguori
  2009-05-08 17:01   ` Jan Kiszka
  11 siblings, 1 reply; 38+ messages in thread
From: Anthony Liguori @ 2009-05-08 16:25 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

Jan Kiszka wrote:
> This series starts with four networking-related fixes and then focuses
> on a grand refactoring of the slirp user space IP stack configuration.
>
> The major contribution is that the virtual IP addresses used by slirp
> can now be (almost) freely configured. This enables sophisticated
> virtual network setups, specifically with guests that depends on
> specific addresses.
>
> Find this series also at git://git.kiszka.org/qemu.git queues/net
>
> Jan Kiszka (11):
>       net: Don't deliver to disabled interfaces in qemu_sendv_packet
>       net: Fix and improved ordered packet delivery
>       slirp: Avoid zombie processes after fork_exec
>       net: Real fix for check_params users
>       net: Improve parameter error reporting
>       slirp: Reorder initialization
>       Introduce get_next_param_value
>       slirp: Move smb, redir, tftp and bootp parameters and -net channel
>       slirp: Rework internal configuration
>       slirp: Rework external configuration interface
>       slirp: Bind support for host forwarding rules
>   

With this series applied, I get:

  CC    slirp/cksum.o
In file included from /home/anthony/git/qemu/slirp/slirp.h:216,
                 from /home/anthony/git/qemu/slirp/cksum.c:34:
/home/anthony/git/qemu/slirp/main.h:51: error: ‘PATH_MAX’ undeclared 
here (not in a function)
make: *** [slirp/cksum.o] Error 1

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements
  2009-05-08 16:25 ` [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Anthony Liguori
@ 2009-05-08 17:01   ` Jan Kiszka
  2009-05-09  7:41     ` [Qemu-devel] [PATCH 08/11 v2] slirp: Move smb, redir, tftp and bootp parameters and -net channel Jan Kiszka
  0 siblings, 1 reply; 38+ messages in thread
From: Jan Kiszka @ 2009-05-08 17:01 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel

Anthony Liguori wrote:
> Jan Kiszka wrote:
>> This series starts with four networking-related fixes and then focuses
>> on a grand refactoring of the slirp user space IP stack configuration.
>>
>> The major contribution is that the virtual IP addresses used by slirp
>> can now be (almost) freely configured. This enables sophisticated
>> virtual network setups, specifically with guests that depends on
>> specific addresses.
>>
>> Find this series also at git://git.kiszka.org/qemu.git queues/net
>>
>> Jan Kiszka (11):
>>       net: Don't deliver to disabled interfaces in qemu_sendv_packet
>>       net: Fix and improved ordered packet delivery
>>       slirp: Avoid zombie processes after fork_exec
>>       net: Real fix for check_params users
>>       net: Improve parameter error reporting
>>       slirp: Reorder initialization
>>       Introduce get_next_param_value
>>       slirp: Move smb, redir, tftp and bootp parameters and -net channel
>>       slirp: Rework internal configuration
>>       slirp: Rework external configuration interface
>>       slirp: Bind support for host forwarding rules
>>   
> 
> With this series applied, I get:
> 
>  CC    slirp/cksum.o
> In file included from /home/anthony/git/qemu/slirp/slirp.h:216,
>                 from /home/anthony/git/qemu/slirp/cksum.c:34:
> /home/anthony/git/qemu/slirp/main.h:51: error: ‘PATH_MAX’ undeclared
> here (not in a function)
> make: *** [slirp/cksum.o] Error 1

Hmpf.

As I can't reproduce here: Does this add-on patch make it build?

diff --git a/slirp/main.h b/slirp/main.h
index 537c145..44f649a 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -9,6 +9,8 @@
 #include <sys/select.h>
 #endif
 
+#include <limit.h>
+
 #define TOWRITEMAX 512
 
 extern struct timeval tt;


Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] "FLOSS bounty"  ( FB )for running QEMU on SheevaPlug
  2009-05-08 15:20   ` Mark McLoughlin
@ 2009-05-08 22:27     ` AGSCalabrese
  2009-05-08 22:47       ` Marek Vasut
  2009-05-08 22:58       ` Paul Brook
  0 siblings, 2 replies; 38+ messages in thread
From: AGSCalabrese @ 2009-05-08 22:27 UTC (permalink / raw)
  To: qemu-devel

I want to use QEMU on the SheevaPlug ( which is ARM based ).
     http://www.marvell.com/products/embedded_processors/developer/kirkwood/sheevaplug.jsp
What size "FB" ($$$) will it take to get this done ?
Everything I plan to do on the SheevaPlug will be FLOSS.

Best
Gus S. Calabrese

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] "FLOSS bounty" ( FB )for running QEMU on SheevaPlug
  2009-05-08 22:27     ` [Qemu-devel] "FLOSS bounty" ( FB )for running QEMU on SheevaPlug AGSCalabrese
@ 2009-05-08 22:47       ` Marek Vasut
  2009-05-08 22:58       ` Paul Brook
  1 sibling, 0 replies; 38+ messages in thread
From: Marek Vasut @ 2009-05-08 22:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: AGSCalabrese

On Saturday 09 of May 2009 00:27:37 AGSCalabrese wrote:
> I want to use QEMU on the SheevaPlug ( which is ARM based ).
>     
> http://www.marvell.com/products/embedded_processors/developer/kirkwood/shee
>vaplug.jsp What size "FB" ($$$) will it take to get this done ?
> Everything I plan to do on the SheevaPlug will be FLOSS.

It does run linux so where's the problem ?
>
> Best
> Gus S. Calabrese

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] "FLOSS bounty" ( FB )for running QEMU on SheevaPlug
  2009-05-08 22:27     ` [Qemu-devel] "FLOSS bounty" ( FB )for running QEMU on SheevaPlug AGSCalabrese
  2009-05-08 22:47       ` Marek Vasut
@ 2009-05-08 22:58       ` Paul Brook
  1 sibling, 0 replies; 38+ messages in thread
From: Paul Brook @ 2009-05-08 22:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: AGSCalabrese

On Friday 08 May 2009, AGSCalabrese wrote:
> I want to use QEMU on the SheevaPlug ( which is ARM based ).
>     
> http://www.marvell.com/products/embedded_processors/developer/kirkwood/shee
>vaplug.jsp What size "FB" ($$$) will it take to get this done ?
> Everything I plan to do on the SheevaPlug will be FLOSS.

Should pretty much work already.

Paul

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 08/11 v2] slirp: Move smb, redir, tftp and bootp parameters and -net channel
  2009-05-08 17:01   ` Jan Kiszka
@ 2009-05-09  7:41     ` Jan Kiszka
  0 siblings, 0 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-09  7:41 UTC (permalink / raw)
  Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 25606 bytes --]

Jan Kiszka wrote:
> Anthony Liguori wrote:
>> Jan Kiszka wrote:
>>> This series starts with four networking-related fixes and then focuses
>>> on a grand refactoring of the slirp user space IP stack configuration.
>>>
>>> The major contribution is that the virtual IP addresses used by slirp
>>> can now be (almost) freely configured. This enables sophisticated
>>> virtual network setups, specifically with guests that depends on
>>> specific addresses.
>>>
>>> Find this series also at git://git.kiszka.org/qemu.git queues/net
>>>
>>> Jan Kiszka (11):
>>>       net: Don't deliver to disabled interfaces in qemu_sendv_packet
>>>       net: Fix and improved ordered packet delivery
>>>       slirp: Avoid zombie processes after fork_exec
>>>       net: Real fix for check_params users
>>>       net: Improve parameter error reporting
>>>       slirp: Reorder initialization
>>>       Introduce get_next_param_value
>>>       slirp: Move smb, redir, tftp and bootp parameters and -net channel
>>>       slirp: Rework internal configuration
>>>       slirp: Rework external configuration interface
>>>       slirp: Bind support for host forwarding rules
>>>   
>> With this series applied, I get:
>>
>>  CC    slirp/cksum.o
>> In file included from /home/anthony/git/qemu/slirp/slirp.h:216,
>>                 from /home/anthony/git/qemu/slirp/cksum.c:34:
>> /home/anthony/git/qemu/slirp/main.h:51: error: ‘PATH_MAX’ undeclared
>> here (not in a function)
>> make: *** [slirp/cksum.o] Error 1
> 
> Hmpf.
> 
> As I can't reproduce here: Does this add-on patch make it build?
> 
> diff --git a/slirp/main.h b/slirp/main.h
> index 537c145..44f649a 100644
> --- a/slirp/main.h
> +++ b/slirp/main.h
> @@ -9,6 +9,8 @@
>  #include <sys/select.h>
>  #endif
>  
> +#include <limit.h>
> +

This should have been "limits", of course. Here is an updated patch 8:

--------->

So far a couple of slirp-related parameters were expressed via
stand-alone command line options. This it inconsistent and unintuitive.
Moreover, it prevents both dynamically reconfigured (host_net_add/
delete) and multi-instance slirp.

This patch refactors the configuration by turning -smb, -redir, -tftp
and -bootp as well as -net channel into options of "-net user". The old
stand-alone command line options are still processed, but no longer
advertised. This allows smooth migration of management applications to
to the new syntax and also the extension of that syntax later in this
series.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |  157 +++++++++++++++++++++++++++++++----------
 net.h            |    3 +
 qemu-options.hx  |  209 +++++++++++++++++++++++++++++-------------------------
 slirp/bootp.c    |    4 +
 slirp/libslirp.h |    5 +
 slirp/main.h     |    4 +
 slirp/slirp.c    |   10 ++-
 slirp/tftp.c     |    6 +-
 vl.c             |    6 +-
 9 files changed, 256 insertions(+), 148 deletions(-)

diff --git a/net.c b/net.c
index b20a907..b5238e8 100644
--- a/net.c
+++ b/net.c
@@ -551,13 +551,18 @@ static void config_error(Monitor *mon, const char *fmt, ...)
 
 /* slirp network adapter */
 
+#define SLIRP_CFG_REDIR 1
+
 struct slirp_config_str {
     struct slirp_config_str *next;
-    const char *str;
+    int flags;
+    char str[1024];
 };
 
 static int slirp_inited;
-static struct slirp_config_str *slirp_redirs;
+static struct slirp_config_str *slirp_configs;
+const char *legacy_tftp_prefix;
+const char *legacy_bootp_filename;
 #ifndef _WIN32
 static const char *slirp_smb_export;
 #endif
@@ -565,6 +570,7 @@ static VLANClientState *slirp_vc;
 
 static void slirp_smb(const char *exported_dir);
 static void slirp_redirection(Monitor *mon, const char *redir_str);
+static void vmchannel_init(Monitor *mon, const char *config_str);
 
 int slirp_can_output(void)
 {
@@ -603,25 +609,40 @@ static void net_slirp_cleanup(VLANClientState *vc)
     slirp_in_use = 0;
 }
 
-static int net_slirp_init(VLANState *vlan, const char *model, const char *name,
-                          int restricted, const char *ip)
+static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
+                          const char *name, int restricted, const char *ip,
+                          const char *tftp_export, const char *bootfile,
+                          const char *smb_export)
 {
     if (slirp_in_use) {
         /* slirp only supports a single instance so far */
         return -1;
     }
     if (!slirp_inited) {
+        if (!tftp_export) {
+            tftp_export = legacy_tftp_prefix;
+        }
+        if (!bootfile) {
+            bootfile = legacy_bootp_filename;
+        }
         slirp_inited = 1;
-        slirp_init(restricted, ip);
+        slirp_init(restricted, ip, tftp_export, bootfile);
 
-        while (slirp_redirs) {
-            struct slirp_config_str *config = slirp_redirs;
+        while (slirp_configs) {
+            struct slirp_config_str *config = slirp_configs;
 
-            slirp_redirection(NULL, config->str);
-            slirp_redirs = config->next;
+            if (config->flags & SLIRP_CFG_REDIR) {
+                slirp_redirection(mon, config->str);
+            } else {
+                vmchannel_init(mon, config->str);
+            }
+            slirp_configs = config->next;
             qemu_free(config);
         }
 #ifndef _WIN32
+        if (smb_export) {
+            slirp_smb_export = smb_export;
+        }
         if (slirp_smb_export) {
             slirp_smb(slirp_smb_export);
         }
@@ -696,9 +717,10 @@ void net_slirp_redir(Monitor *mon, const char *redir_str)
             monitor_printf(mon, "user mode network stack not in use\n");
         } else {
             config = qemu_malloc(sizeof(*config));
-            config->str = redir_str;
-            config->next = slirp_redirs;
-            slirp_redirs = config;
+            pstrcpy(config->str, sizeof(config->str), redir_str);
+            config->flags = SLIRP_CFG_REDIR;
+            config->next = slirp_configs;
+            slirp_configs = config;
         }
         return;
     }
@@ -827,6 +849,36 @@ static void vmchannel_read(void *opaque, const uint8_t *buf, int size)
     slirp_socket_recv(4, vmc->port, buf, size);
 }
 
+static void vmchannel_init(Monitor *mon, const char *config_str)
+{
+    struct VMChannel *vmc;
+    char *devname;
+    char name[20];
+    int port;
+
+    port = strtol(config_str, &devname, 10);
+    if (port < 1 || port > 65535 || *devname != ':') {
+        config_error(mon, "invalid vmchannel port number\n");
+        return;
+    }
+    devname++;
+
+    vmc = qemu_malloc(sizeof(struct VMChannel));
+    snprintf(name, sizeof(name), "vmchannel%d", port);
+    vmc->hd = qemu_chr_open(name, devname, NULL);
+    if (!vmc->hd) {
+        config_error(mon, "could not open vmchannel device '%s'\n", devname);
+        qemu_free(vmc);
+        return;
+    }
+    vmc->port = port;
+
+    slirp_add_exec(3, vmc->hd, 4, port);
+    qemu_chr_add_handlers(vmc->hd, vmchannel_can_read, vmchannel_read,
+                          NULL, vmc);
+    return;
+}
+
 #endif /* CONFIG_SLIRP */
 
 #if !defined(_WIN32)
@@ -1936,10 +1988,16 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
 #ifdef CONFIG_SLIRP
     if (!strcmp(device, "user")) {
         static const char * const slirp_params[] = {
-            "vlan", "name", "hostname", "restrict", "ip", NULL
+            "vlan", "name", "hostname", "restrict", "ip", "tftp", "bootfile",
+            "smb", "redir", "channel", NULL
         };
+        struct slirp_config_str *config;
+        char *tftp_export = NULL;
+        char *bootfile = NULL;
+        char *smb_export = NULL;
         int restricted = 0;
         char *ip = NULL;
+        const char *q;
 
         if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
             config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
@@ -1955,34 +2013,59 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         if (get_param_value(buf, sizeof(buf), "ip", p)) {
             ip = qemu_strdup(buf);
         }
+        if (get_param_value(buf, sizeof(buf), "tftp", p)) {
+            tftp_export = qemu_strdup(buf);
+        }
+        if (get_param_value(buf, sizeof(buf), "bootfile", p)) {
+            bootfile = qemu_strdup(buf);
+        }
+        if (get_param_value(buf, sizeof(buf), "smb", p)) {
+            smb_export = qemu_strdup(buf);
+        }
+        q = p;
+        while (1) {
+            config = qemu_malloc(sizeof(*config));
+            if (!get_next_param_value(config->str, sizeof(config->str),
+                                      "redir", &q)) {
+                break;
+            }
+            config->flags = SLIRP_CFG_REDIR;
+            config->next = slirp_configs;
+            slirp_configs = config;
+            config = NULL;
+        }
+        q = p;
+        while (1) {
+            config = qemu_malloc(sizeof(*config));
+            if (!get_next_param_value(config->str, sizeof(config->str),
+                                      "channel", &q)) {
+                break;
+            }
+            config->flags = 0;
+            config->next = slirp_configs;
+            slirp_configs = config;
+            config = NULL;
+        }
+        qemu_free(config);
         vlan->nb_host_devs++;
-        ret = net_slirp_init(vlan, device, name, restricted, ip);
+        ret = net_slirp_init(mon, vlan, device, name, restricted, ip,
+                             tftp_export, bootfile, smb_export);
         qemu_free(ip);
+        qemu_free(tftp_export);
+        qemu_free(bootfile);
+        qemu_free(smb_export);
     } else if (!strcmp(device, "channel")) {
-        long port;
-        char name[20], *devname;
-        struct VMChannel *vmc;
-
-        port = strtol(p, &devname, 10);
-        devname++;
-        if (port < 1 || port > 65535) {
-            config_error(mon, "vmchannel wrong port number\n");
-            ret = -1;
-            goto out;
-        }
-        vmc = malloc(sizeof(struct VMChannel));
-        snprintf(name, 20, "vmchannel%ld", port);
-        vmc->hd = qemu_chr_open(name, devname, NULL);
-        if (!vmc->hd) {
-            config_error(mon, "could not open vmchannel device '%s'\n",
-                         devname);
-            ret = -1;
-            goto out;
+        if (!slirp_inited) {
+            struct slirp_config_str *config;
+
+            config = qemu_malloc(sizeof(*config));
+            pstrcpy(config->str, sizeof(config->str), p);
+            config->flags = 0;
+            config->next = slirp_configs;
+            slirp_configs = config;
+        } else {
+            vmchannel_init(mon, p);
         }
-        vmc->port = port;
-        slirp_add_exec(3, vmc->hd, 4, port);
-        qemu_chr_add_handlers(vmc->hd, vmchannel_can_read, vmchannel_read,
-                NULL, vmc);
         ret = 0;
     } else
 #endif
diff --git a/net.h b/net.h
index 4f8f393..980c380 100644
--- a/net.h
+++ b/net.h
@@ -108,6 +108,9 @@ uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
 void net_checksum_calculate(uint8_t *data, int length);
 
 /* from net.c */
+extern const char *legacy_tftp_prefix;
+extern const char *legacy_bootp_filename;
+
 int net_client_init(Monitor *mon, const char *device, const char *p);
 void net_client_uninit(NICInfo *nd);
 int net_client_parse(const char *str);
diff --git a/qemu-options.hx b/qemu-options.hx
index 87af798..e721f60 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -723,13 +723,27 @@ STEXI
 @table @option
 ETEXI
 
+HXCOMM Legacy slirp options (now moved to -net user):
+#ifdef CONFIG_SLIRP
+DEF("tftp", HAS_ARG, QEMU_OPTION_tftp, "")
+DEF("bootp", HAS_ARG, QEMU_OPTION_bootp, "")
+DEF("redir", HAS_ARG, QEMU_OPTION_redir, "")
+#ifndef _WIN32
+DEF("smb", HAS_ARG, QEMU_OPTION_smb, "")
+#endif
+#endif
+
 DEF("net", HAS_ARG, QEMU_OPTION_net, \
     "-net nic[,vlan=n][,macaddr=addr][,model=type][,name=str]\n"
     "                create a new Network Interface Card and connect it to VLAN 'n'\n"
 #ifdef CONFIG_SLIRP
-    "-net user[,vlan=n][,name=str][,hostname=host]\n"
-    "                connect the user mode network stack to VLAN 'n' and send\n"
-    "                hostname 'host' to DHCP clients\n"
+    "-net user[,vlan=n][,name=str][ip=netaddr][,restrict=y|n][,hostname=host]\n"
+    "         [,tftp=dir][,bootfile=f][,redir=rule][,channel=rule]"
+#ifndef _WIN32
+                                                                  "[,smb=dir]\n"
+#endif
+    "                connect the user mode network stack to VLAN 'n', configure its\n"
+    "                DHCP server and enabled optional services\n"
 #endif
 #ifdef _WIN32
     "-net tap[,vlan=n][,name=str],ifname=name\n"
@@ -772,13 +786,102 @@ Valid values for @var{type} are
 Not all devices are supported on all targets.  Use -net nic,model=?
 for a list of available devices for your target.
 
-@item -net user[,vlan=@var{n}][,hostname=@var{name}][,name=@var{name}]
+@item -net user[,@var{option}][,@var{option}][,...]
 Use the user mode network stack which requires no administrator
-privilege to run.  @option{hostname=name} can be used to specify the client
-hostname reported by the builtin DHCP server.
+privilege to run. Valid options are:
+
+@table @code
+@item vlan=@var{n}
+Connect user mode stack to VLAN @var{n} (@var{n} = 0 is the default).
+
+@item name=@var{name}
+Assign symbolic name for use in monitor commands.
+
+@item ip=@var{netaddr}
+Set IP network address the guest will see (default: 10.0.2.x).
+
+@item restrict=y|yes|n|no
+If this options is enabled, the guest will be isolated, i.e. it will not be
+able to contact the host and no guest IP packets will be routed over the host
+to the outside. This option does not affect explicitly set forwarding rule.
+
+@item hostname=@var{name}
+Specifies the client hostname reported by the builtin DHCP server.
+
+@item tftp=@var{dir}
+When using the user mode network stack, activate a built-in TFTP
+server. The files in @var{dir} will be exposed as the root of a TFTP server.
+The TFTP client on the guest must be configured in binary mode (use the command
+@code{bin} of the Unix TFTP client). The host IP address on the guest is
+10.0.2.2 by default.
+
+@item bootfile=@var{file}
+When using the user mode network stack, broadcast @var{file} as the BOOTP
+filename. In conjunction with @option{tftp}, this can be used to network boot
+a guest from a local directory.
+
+Example (using pxelinux):
+@example
+qemu -hda linux.img -boot n -net user,tftp=/path/to/tftp/files,bootfile=/pxelinux.0
+@end example
+
+@item smb=@var{dir}
+When using the user mode network stack, activate a built-in SMB
+server so that Windows OSes can access to the host files in @file{@var{dir}}
+transparently.
+
+In the guest Windows OS, the line:
+@example
+10.0.2.4 smbserver
+@end example
+must be added in the file @file{C:\WINDOWS\LMHOSTS} (for windows 9x/Me)
+or @file{C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS} (Windows NT/2000).
+
+Then @file{@var{dir}} can be accessed in @file{\\smbserver\qemu}.
+
+Note that a SAMBA server must be installed on the host OS in
+@file{/usr/sbin/smbd}. QEMU was tested successfully with smbd versions from
+Red Hat 9, Fedora Core 3 and OpenSUSE 11.x.
+
+@item redir=[tcp|udp]:@var{host-port}:[@var{guest-host}]:@var{guest-port}
+Redirect incoming TCP or UDP connections to the host port @var{host-port} to
+the guest @var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
+is not specified, its value is 10.0.2.15 (default address given by the built-in
+DHCP server). If no connection type is specified, TCP is used. This option can
+be given multiple times.
+
+For example, to redirect host X11 connection from screen 1 to guest
+screen 0, use the following:
+
+@example
+# on the host
+qemu -net user,redir=tcp:6001::6000 [...]
+# this host xterm should open in the guest X11 server
+xterm -display :1
+@end example
+
+To redirect telnet connections from host port 5555 to telnet port on
+the guest, use the following:
+
+@example
+# on the host
+qemu -net user,redir=tcp:5555::23 [...]
+telnet localhost 5555
+@end example
+
+Then when you use on the host @code{telnet localhost 5555}, you
+connect to the guest telnet server.
 
-@item -net channel,@var{port}:@var{dev}
-Forward @option{user} TCP connection to port @var{port} to character device @var{dev}
+@item channel=@var{port}:@var{dev}
+Forward guest TCP connections to port @var{port} on the host to character
+device @var{dev}. This option can be given multiple times.
+
+@end table
+
+Note: Legacy stand-alone options -tftp, -bootp, -smb and -redir are still
+processed and applied to -net user. Mixing them with the new configuration
+syntax gives undefined results. Their use for new applications is discouraged
+as they will be removed from future versions.
 
 @item -net tap[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}][,ifname=@var{name}][,script=@var{file}][,downscript=@var{dfile}]
 Connect the host TAP network interface @var{name} to VLAN @var{n}, use
@@ -884,96 +987,6 @@ libpcap, so it can be analyzed with tools such as tcpdump or Wireshark.
 Indicate that no network devices should be configured. It is used to
 override the default configuration (@option{-net nic -net user}) which
 is activated if no @option{-net} options are provided.
-ETEXI
-
-#ifdef CONFIG_SLIRP
-DEF("tftp", HAS_ARG, QEMU_OPTION_tftp, \
-    "-tftp dir       allow tftp access to files in dir [-net user]\n")
-#endif
-STEXI
-@item -tftp @var{dir}
-When using the user mode network stack, activate a built-in TFTP
-server. The files in @var{dir} will be exposed as the root of a TFTP server.
-The TFTP client on the guest must be configured in binary mode (use the command
-@code{bin} of the Unix TFTP client). The host IP address on the guest is as
-usual 10.0.2.2.
-ETEXI
-
-#ifdef CONFIG_SLIRP
-DEF("bootp", HAS_ARG, QEMU_OPTION_bootp, \
-    "-bootp file     advertise file in BOOTP replies\n")
-#endif
-STEXI
-@item -bootp @var{file}
-When using the user mode network stack, broadcast @var{file} as the BOOTP
-filename.  In conjunction with @option{-tftp}, this can be used to network boot
-a guest from a local directory.
-
-Example (using pxelinux):
-@example
-qemu -hda linux.img -boot n -tftp /path/to/tftp/files -bootp /pxelinux.0
-@end example
-ETEXI
-
-#ifndef _WIN32
-DEF("smb", HAS_ARG, QEMU_OPTION_smb, \
-           "-smb dir        allow SMB access to files in 'dir' [-net user]\n")
-#endif
-STEXI
-@item -smb @var{dir}
-When using the user mode network stack, activate a built-in SMB
-server so that Windows OSes can access to the host files in @file{@var{dir}}
-transparently.
-
-In the guest Windows OS, the line:
-@example
-10.0.2.4 smbserver
-@end example
-must be added in the file @file{C:\WINDOWS\LMHOSTS} (for windows 9x/Me)
-or @file{C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS} (Windows NT/2000).
-
-Then @file{@var{dir}} can be accessed in @file{\\smbserver\qemu}.
-
-Note that a SAMBA server must be installed on the host OS in
-@file{/usr/sbin/smbd}. QEMU was tested successfully with smbd version
-2.2.7a from the Red Hat 9 and version 3.0.10-1.fc3 from Fedora Core 3.
-ETEXI
-
-#ifdef CONFIG_SLIRP
-DEF("redir", HAS_ARG, QEMU_OPTION_redir, \
-    "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n" \
-    "                redirect TCP or UDP connections from host to guest [-net user]\n")
-#endif
-STEXI
-@item -redir [tcp|udp]:@var{host-port}:[@var{guest-host}]:@var{guest-port}
-
-When using the user mode network stack, redirect incoming TCP or UDP
-connections to the host port @var{host-port} to the guest
-@var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
-is not specified, its value is 10.0.2.15 (default address given by the
-built-in DHCP server). If no connection type is specified, TCP is used.
-
-For example, to redirect host X11 connection from screen 1 to guest
-screen 0, use the following:
-
-@example
-# on the host
-qemu -redir tcp:6001::6000 [...]
-# this host xterm should open in the guest X11 server
-xterm -display :1
-@end example
-
-To redirect telnet connections from host port 5555 to telnet port on
-the guest, use the following:
-
-@example
-# on the host
-qemu -redir tcp:5555::23 [...]
-telnet localhost 5555
-@end example
-
-Then when you use on the host @code{telnet localhost 5555}, you
-connect to the guest telnet server.
 
 @end table
 ETEXI
diff --git a/slirp/bootp.c b/slirp/bootp.c
index 8a97660..3f4d079 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -38,7 +38,7 @@ typedef struct {
 
 static BOOTPClient bootp_clients[NB_ADDR];
 
-const char *bootp_filename;
+char bootp_filename[PATH_MAX] = "";
 
 static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
 
@@ -249,7 +249,7 @@ static void bootp_reply(const struct bootp_t *bp)
             *q++ = DHCPACK;
         }
 
-        if (bootp_filename)
+        if (bootp_filename[0] != 0)
             snprintf((char *)rbp->bp_file, sizeof(rbp->bp_file), "%s",
                      bootp_filename);
 
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index c0781c3..c5b1bb9 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -5,7 +5,8 @@
 extern "C" {
 #endif
 
-void slirp_init(int restricted, const char *special_ip);
+void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
+                const char *bootfile);
 
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds);
@@ -23,9 +24,7 @@ int slirp_redir(int is_udp, int host_port,
 int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
                    int guest_port);
 
-extern const char *tftp_prefix;
 extern char slirp_hostname[33];
-extern const char *bootp_filename;
 
 void slirp_stats(void);
 void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
diff --git a/slirp/main.h b/slirp/main.h
index ed51385..9e84569 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -9,6 +9,8 @@
 #include <sys/select.h>
 #endif
 
+#include <limits.h>
+
 #define TOWRITEMAX 512
 
 extern struct timeval tt;
@@ -46,6 +48,8 @@ extern int tcp_keepintvl;
 extern uint8_t client_ethaddr[6];
 extern const char *slirp_special_ip;
 extern int slirp_restrict;
+extern char tftp_prefix[PATH_MAX];
+extern char bootp_filename[PATH_MAX];
 
 #define PROTO_SLIP 0x1
 #ifdef USE_PPP
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 73b3704..0fe0286 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -171,7 +171,8 @@ static void slirp_cleanup(void)
 static void slirp_state_save(QEMUFile *f, void *opaque);
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
 
-void slirp_init(int restricted, const char *special_ip)
+void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
+                const char *bootfile)
 {
     //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
 
@@ -202,7 +203,12 @@ void slirp_init(int restricted, const char *special_ip)
 
     if (special_ip)
         slirp_special_ip = special_ip;
-
+    if (tftp_path) {
+        pstrcpy(tftp_prefix, sizeof(tftp_prefix), tftp_path);
+    }
+    if (bootfile) {
+        pstrcpy(bootp_filename, sizeof(bootp_filename), bootfile);
+    }
     inet_aton(slirp_special_ip, &special_addr);
     alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
     getouraddr();
diff --git a/slirp/tftp.c b/slirp/tftp.c
index 4ad5504..e525c6b 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -37,7 +37,7 @@ struct tftp_session {
 
 static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
 
-const char *tftp_prefix;
+char tftp_prefix[PATH_MAX] = "";
 
 static void tftp_session_update(struct tftp_session *spt)
 {
@@ -335,7 +335,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
 
   /* only allow exported prefixes */
 
-  if (!tftp_prefix) {
+  if (tftp_prefix[0] == 0) {
       tftp_send_error(spt, 2, "Access violation", tp);
       return;
   }
@@ -370,7 +370,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
 	  int tsize = atoi(value);
 	  struct stat stat_p;
 
-	  if (tsize == 0 && tftp_prefix) {
+	  if (tsize == 0 && tftp_prefix[0] != 0) {
 	      char buffer[1024];
 	      int len;
 
diff --git a/vl.c b/vl.c
index 6ab798d..728e6f2 100644
--- a/vl.c
+++ b/vl.c
@@ -5146,14 +5146,14 @@ int main(int argc, char **argv, char **envp)
                 break;
 #ifdef CONFIG_SLIRP
             case QEMU_OPTION_tftp:
-		tftp_prefix = optarg;
+                legacy_tftp_prefix = optarg;
                 break;
             case QEMU_OPTION_bootp:
-                bootp_filename = optarg;
+                legacy_bootp_filename = optarg;
                 break;
 #ifndef _WIN32
             case QEMU_OPTION_smb:
-		net_slirp_smb(optarg);
+                net_slirp_smb(optarg);
                 break;
 #endif
             case QEMU_OPTION_redir:


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users Jan Kiszka
@ 2009-05-19  7:57   ` Mark McLoughlin
  2009-05-19  9:34     ` Jan Kiszka
  2009-05-28 15:04   ` Mark McLoughlin
  1 sibling, 1 reply; 38+ messages in thread
From: Mark McLoughlin @ 2009-05-19  7:57 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

Hi Jan,

On Fri, 2009-05-08 at 12:34 +0200, Jan Kiszka wrote:
> OK, last try: ea053add70 broke -net socket, ffad4116b9 tried to fix it
> but broke error reporting of invalid parameters. So this patch widely
> reverts ffad4116b9 again and intead fixes those callers of check_params
> that originally suffered from overwritten buffers by using separate
> ones.
> 
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
> 
>  net.c    |   23 ++++++++++++-----------
>  sysemu.h |    3 ++-
>  vl.c     |   39 ++++++++++++++-------------------------
>  3 files changed, 28 insertions(+), 37 deletions(-)
> 
> diff --git a/net.c b/net.c
> index 6a5c698..cf00c9c 100644
> --- a/net.c
> +++ b/net.c
> @@ -1826,7 +1826,7 @@ int net_client_init(const char *device, const char *p)
>          uint8_t *macaddr;
>          int idx = nic_get_free_idx();
>  
> -        if (check_params(nic_params, p) < 0) {
> +        if (check_params(buf, sizeof(buf), nic_params, p) < 0) {
>              fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
>                      buf, p);
>              return -1;

All callers used the scratch buffer to obtain the invalid parameter name
for error messages. Now, e.g. I get:

  $> qemu-system-x86_64 -drive foo=bar
  qemu: unknown parameter '\x10' in 'foo=bar'

Cheers,
Mark.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users
  2009-05-19  7:57   ` Mark McLoughlin
@ 2009-05-19  9:34     ` Jan Kiszka
  2009-05-19  9:57       ` Mark McLoughlin
  0 siblings, 1 reply; 38+ messages in thread
From: Jan Kiszka @ 2009-05-19  9:34 UTC (permalink / raw)
  To: Mark McLoughlin; +Cc: qemu-devel

Mark McLoughlin wrote:
> Hi Jan,
> 
> On Fri, 2009-05-08 at 12:34 +0200, Jan Kiszka wrote:
>> OK, last try: ea053add70 broke -net socket, ffad4116b9 tried to fix it
>> but broke error reporting of invalid parameters. So this patch widely
>> reverts ffad4116b9 again and intead fixes those callers of check_params
>> that originally suffered from overwritten buffers by using separate
>> ones.
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>> ---
>>
>>  net.c    |   23 ++++++++++++-----------
>>  sysemu.h |    3 ++-
>>  vl.c     |   39 ++++++++++++++-------------------------
>>  3 files changed, 28 insertions(+), 37 deletions(-)
>>
>> diff --git a/net.c b/net.c
>> index 6a5c698..cf00c9c 100644
>> --- a/net.c
>> +++ b/net.c
>> @@ -1826,7 +1826,7 @@ int net_client_init(const char *device, const char *p)
>>          uint8_t *macaddr;
>>          int idx = nic_get_free_idx();
>>  
>> -        if (check_params(nic_params, p) < 0) {
>> +        if (check_params(buf, sizeof(buf), nic_params, p) < 0) {
>>              fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
>>                      buf, p);
>>              return -1;
> 
> All callers used the scratch buffer to obtain the invalid parameter name
> for error messages. Now, e.g. I get:
> 
>   $> qemu-system-x86_64 -drive foo=bar
>   qemu: unknown parameter '\x10' in 'foo=bar'
> 

Works for me with that patch applied. Are you sure you ran the right
(==patched) instance of qemu-system-x86_64? :->

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users
  2009-05-19  9:34     ` Jan Kiszka
@ 2009-05-19  9:57       ` Mark McLoughlin
  0 siblings, 0 replies; 38+ messages in thread
From: Mark McLoughlin @ 2009-05-19  9:57 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

On Tue, 2009-05-19 at 11:34 +0200, Jan Kiszka wrote:
> Mark McLoughlin wrote:
> > Hi Jan,
> > 
> > On Fri, 2009-05-08 at 12:34 +0200, Jan Kiszka wrote:
> >> OK, last try: ea053add70 broke -net socket, ffad4116b9 tried to fix it
> >> but broke error reporting of invalid parameters. So this patch widely
> >> reverts ffad4116b9 again and intead fixes those callers of check_params
> >> that originally suffered from overwritten buffers by using separate
> >> ones.
> >>
> >> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> >> ---
> >>
> >>  net.c    |   23 ++++++++++++-----------
> >>  sysemu.h |    3 ++-
> >>  vl.c     |   39 ++++++++++++++-------------------------
> >>  3 files changed, 28 insertions(+), 37 deletions(-)
> >>
> >> diff --git a/net.c b/net.c
> >> index 6a5c698..cf00c9c 100644
> >> --- a/net.c
> >> +++ b/net.c
> >> @@ -1826,7 +1826,7 @@ int net_client_init(const char *device, const char *p)
> >>          uint8_t *macaddr;
> >>          int idx = nic_get_free_idx();
> >>  
> >> -        if (check_params(nic_params, p) < 0) {
> >> +        if (check_params(buf, sizeof(buf), nic_params, p) < 0) {
> >>              fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
> >>                      buf, p);
> >>              return -1;
> > 
> > All callers used the scratch buffer to obtain the invalid parameter name
> > for error messages. Now, e.g. I get:
> > 
> >   $> qemu-system-x86_64 -drive foo=bar
> >   qemu: unknown parameter '\x10' in 'foo=bar'
> > 
> 
> Works for me with that patch applied. Are you sure you ran the right
> (==patched) instance of qemu-system-x86_64? :->

Apologies, I was confused - I thought this patch had already been
applied and was causing the problem that it actually fixes :-)

Cheers,
Mark.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users Jan Kiszka
  2009-05-19  7:57   ` Mark McLoughlin
@ 2009-05-28 15:04   ` Mark McLoughlin
  2009-05-28 15:05     ` [Qemu-devel] [PATCH 1/3] Revert "Fix output of uninitialized strings" Mark McLoughlin
  2009-05-28 15:22     ` [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users Kevin Wolf
  1 sibling, 2 replies; 38+ messages in thread
From: Mark McLoughlin @ 2009-05-28 15:04 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

On Fri, 2009-05-08 at 12:34 +0200, Jan Kiszka wrote:
> OK, last try: ea053add70 broke -net socket, ffad4116b9 tried to fix it
> but broke error reporting of invalid parameters. So this patch widely
> reverts ffad4116b9 again and intead fixes those callers of check_params
> that originally suffered from overwritten buffers by using separate
> ones.
> 
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>

Okay, I think we should revert Kevin's fix from master and replace it
with this one.

> @@ -1944,12 +1944,12 @@ int net_client_init(const char *device, const char *p)
>  #elif defined (_AIX)
>  #else
>      if (!strcmp(device, "tap")) {
> -        char ifname[64];
> +        char ifname[64], chkbuf[64];
>          char setup_script[1024], down_script[1024];
>          int fd;
>          vlan->nb_host_devs++;
>          if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
> -            if (check_params(fd_params, p) < 0) {
> +            if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
>                  fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
>                          buf, p);

Should use chkbuf in the fprintf.

Following up with a patch series.

Cheers,
Mark.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 1/3] Revert "Fix output of uninitialized strings"
  2009-05-28 15:04   ` Mark McLoughlin
@ 2009-05-28 15:05     ` Mark McLoughlin
  2009-05-28 15:06       ` [Qemu-devel] [PATCH 2/3] net: Real fix for check_params users Mark McLoughlin
  2009-05-28 15:22     ` [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users Kevin Wolf
  1 sibling, 1 reply; 38+ messages in thread
From: Mark McLoughlin @ 2009-05-28 15:05 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

This reverts commit 8cf07dcbe7691dbe4f47563058659dba6ef66b05.

This is a sorry saga.

This commit:

  8e4416af45 net: Add parameter checks for VLAN clients

broken '-net socket' and this commit:

  ffad4116b9 net: Fix -net socket parameter checks

fixed the problem but introduced another problem which
this commit:

  8cf07dcbe7 Fix output of uninitialized strings

fixed that final problem, but causing us to lose some
error reporting information in the process.

Meanwhile Jan posted a patch to mostly re-do ffad4116b9
in a way that fixes the original issue, but without
losing the error reporting information. So, let's revert
8cf07dcbe7 and apply Jan's patch.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c |   30 ++++++++++++++++++++----------
 vl.c  |    3 ++-
 2 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/net.c b/net.c
index 97e1ac5..390d6a6 100644
--- a/net.c
+++ b/net.c
@@ -1912,7 +1912,8 @@ int net_client_init(const char *device, const char *p)
         int idx = nic_get_free_idx();
 
         if (check_params(nic_params, p) < 0) {
-            fprintf(stderr, "qemu: invalid parameter in '%s'\n", p);
+            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                    buf, p);
             return -1;
         }
         if (idx == -1 || nb_nics >= MAX_NICS) {
@@ -1962,7 +1963,8 @@ int net_client_init(const char *device, const char *p)
             "vlan", "name", "hostname", "restrict", "ip", NULL
         };
         if (check_params(slirp_params, p) < 0) {
-            fprintf(stderr, "qemu: invalid parameter in '%s'\n", p);
+            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                    buf, p);
             return -1;
         }
         if (get_param_value(buf, sizeof(buf), "hostname", p)) {
@@ -2012,7 +2014,8 @@ int net_client_init(const char *device, const char *p)
         char ifname[64];
 
         if (check_params(tap_params, p) < 0) {
-            fprintf(stderr, "qemu: invalid parameter in '%s'\n", p);
+            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                    buf, p);
             return -1;
         }
         if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
@@ -2032,7 +2035,8 @@ int net_client_init(const char *device, const char *p)
         vlan->nb_host_devs++;
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
             if (check_params(fd_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter in '%s'\n", p);
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
                 return -1;
             }
             fd = strtol(buf, NULL, 0);
@@ -2044,7 +2048,8 @@ int net_client_init(const char *device, const char *p)
                 "vlan", "name", "ifname", "script", "downscript", NULL
             };
             if (check_params(tap_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter in '%s'\n", p);
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
                 return -1;
             }
             if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
@@ -2064,7 +2069,8 @@ int net_client_init(const char *device, const char *p)
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
             int fd;
             if (check_params(fd_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter in '%s'\n", p);
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
                 return -1;
             }
             fd = strtol(buf, NULL, 0);
@@ -2076,7 +2082,8 @@ int net_client_init(const char *device, const char *p)
                 "vlan", "name", "listen", NULL
             };
             if (check_params(listen_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter in '%s'\n", p);
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
                 return -1;
             }
             ret = net_socket_listen_init(vlan, device, name, buf);
@@ -2085,7 +2092,8 @@ int net_client_init(const char *device, const char *p)
                 "vlan", "name", "connect", NULL
             };
             if (check_params(connect_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter in '%s'\n", p);
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
                 return -1;
             }
             ret = net_socket_connect_init(vlan, device, name, buf);
@@ -2094,7 +2102,8 @@ int net_client_init(const char *device, const char *p)
                 "vlan", "name", "mcast", NULL
             };
             if (check_params(mcast_params, p) < 0) {
-                fprintf(stderr, "qemu: invalid parameter in '%s'\n", p);
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
                 return -1;
             }
             ret = net_socket_mcast_init(vlan, device, name, buf);
@@ -2114,7 +2123,8 @@ int net_client_init(const char *device, const char *p)
 	int vde_port, vde_mode;
 
         if (check_params(vde_params, p) < 0) {
-            fprintf(stderr, "qemu: invalid parameter in '%s'\n", p);
+            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                    buf, p);
             return -1;
         }
         vlan->nb_host_devs++;
diff --git a/vl.c b/vl.c
index 012b2a3..975e811 100644
--- a/vl.c
+++ b/vl.c
@@ -2227,7 +2227,8 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
                                            NULL };
 
     if (check_params(params, str) < 0) {
-         fprintf(stderr, "qemu: unknown parameter in '%s'\n", str);
+         fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
+                         buf, str);
          return -1;
     }
 
-- 
1.6.2.2

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 2/3] net: Real fix for check_params users
  2009-05-28 15:05     ` [Qemu-devel] [PATCH 1/3] Revert "Fix output of uninitialized strings" Mark McLoughlin
@ 2009-05-28 15:06       ` Mark McLoughlin
  2009-05-28 15:06         ` [Qemu-devel] [PATCH 3/3] net: fix error reporting for some net parameter checks Mark McLoughlin
  0 siblings, 1 reply; 38+ messages in thread
From: Mark McLoughlin @ 2009-05-28 15:06 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

From: Jan Kiszka <jan.kiszka@siemens.com>

OK, last try: 8e4416af45 broke -net socket, ffad4116b9 tried to fix it
but broke error reporting of invalid parameters. So this patch widely
reverts ffad4116b9 again and intead fixes those callers of check_params
that originally suffered from overwritten buffers by using separate
ones.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c    |   23 ++++++++++++-----------
 sysemu.h |    3 ++-
 vl.c     |   39 ++++++++++++++-------------------------
 3 files changed, 28 insertions(+), 37 deletions(-)

diff --git a/net.c b/net.c
index 390d6a6..723e934 100644
--- a/net.c
+++ b/net.c
@@ -1911,7 +1911,7 @@ int net_client_init(const char *device, const char *p)
         uint8_t *macaddr;
         int idx = nic_get_free_idx();
 
-        if (check_params(nic_params, p) < 0) {
+        if (check_params(buf, sizeof(buf), nic_params, p) < 0) {
             fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                     buf, p);
             return -1;
@@ -1962,7 +1962,7 @@ int net_client_init(const char *device, const char *p)
         static const char * const slirp_params[] = {
             "vlan", "name", "hostname", "restrict", "ip", NULL
         };
-        if (check_params(slirp_params, p) < 0) {
+        if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
             fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                     buf, p);
             return -1;
@@ -2013,7 +2013,7 @@ int net_client_init(const char *device, const char *p)
         };
         char ifname[64];
 
-        if (check_params(tap_params, p) < 0) {
+        if (check_params(buf, sizeof(buf), tap_params, p) < 0) {
             fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                     buf, p);
             return -1;
@@ -2029,12 +2029,12 @@ int net_client_init(const char *device, const char *p)
 #elif defined (_AIX)
 #else
     if (!strcmp(device, "tap")) {
-        char ifname[64];
+        char ifname[64], chkbuf[64];
         char setup_script[1024], down_script[1024];
         int fd;
         vlan->nb_host_devs++;
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
-            if (check_params(fd_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -2047,7 +2047,7 @@ int net_client_init(const char *device, const char *p)
             static const char * const tap_params[] = {
                 "vlan", "name", "ifname", "script", "downscript", NULL
             };
-            if (check_params(tap_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), tap_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -2066,9 +2066,10 @@ int net_client_init(const char *device, const char *p)
     } else
 #endif
     if (!strcmp(device, "socket")) {
+        char chkbuf[64];
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
             int fd;
-            if (check_params(fd_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -2081,7 +2082,7 @@ int net_client_init(const char *device, const char *p)
             static const char * const listen_params[] = {
                 "vlan", "name", "listen", NULL
             };
-            if (check_params(listen_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), listen_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -2091,7 +2092,7 @@ int net_client_init(const char *device, const char *p)
             static const char * const connect_params[] = {
                 "vlan", "name", "connect", NULL
             };
-            if (check_params(connect_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), connect_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -2101,7 +2102,7 @@ int net_client_init(const char *device, const char *p)
             static const char * const mcast_params[] = {
                 "vlan", "name", "mcast", NULL
             };
-            if (check_params(mcast_params, p) < 0) {
+            if (check_params(chkbuf, sizeof(chkbuf), mcast_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                         buf, p);
                 return -1;
@@ -2122,7 +2123,7 @@ int net_client_init(const char *device, const char *p)
         char vde_sock[1024], vde_group[512];
 	int vde_port, vde_mode;
 
-        if (check_params(vde_params, p) < 0) {
+        if (check_params(buf, sizeof(buf), vde_params, p) < 0) {
             fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
                     buf, p);
             return -1;
diff --git a/sysemu.h b/sysemu.h
index 92501ed..b57f6bb 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -267,7 +267,8 @@ void usb_info(Monitor *mon);
 
 int get_param_value(char *buf, int buf_size,
                     const char *tag, const char *str);
-int check_params(const char * const *params, const char *str);
+int check_params(char *buf, int buf_size,
+                 const char * const *params, const char *str);
 
 void register_devices(void);
 
diff --git a/vl.c b/vl.c
index 975e811..4d04d65 100644
--- a/vl.c
+++ b/vl.c
@@ -1835,45 +1835,34 @@ int get_param_value(char *buf, int buf_size,
     return 0;
 }
 
-int check_params(const char * const *params, const char *str)
+int check_params(char *buf, int buf_size,
+                 const char * const *params, const char *str)
 {
-    int name_buf_size = 1;
     const char *p;
-    char *name_buf;
-    int i, len;
-    int ret = 0;
-
-    for (i = 0; params[i] != NULL; i++) {
-        len = strlen(params[i]) + 1;
-        if (len > name_buf_size) {
-            name_buf_size = len;
-        }
-    }
-    name_buf = qemu_malloc(name_buf_size);
+    int i;
 
     p = str;
     while (*p != '\0') {
-        p = get_opt_name(name_buf, name_buf_size, p, '=');
+        p = get_opt_name(buf, buf_size, p, '=');
         if (*p != '=') {
-            ret = -1;
-            break;
+            return -1;
         }
         p++;
-        for(i = 0; params[i] != NULL; i++)
-            if (!strcmp(params[i], name_buf))
+        for (i = 0; params[i] != NULL; i++) {
+            if (!strcmp(params[i], buf)) {
                 break;
+            }
+        }
         if (params[i] == NULL) {
-            ret = -1;
-            break;
+            return -1;
         }
         p = get_opt_value(NULL, 0, p);
-        if (*p != ',')
+        if (*p != ',') {
             break;
+        }
         p++;
     }
-
-    qemu_free(name_buf);
-    return ret;
+    return 0;
 }
 
 /***********************************************************/
@@ -2226,7 +2215,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
                                            "cache", "format", "serial", "werror",
                                            NULL };
 
-    if (check_params(params, str) < 0) {
+    if (check_params(buf, sizeof(buf), params, str) < 0) {
          fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
                          buf, str);
          return -1;
-- 
1.6.2.2

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH 3/3] net: fix error reporting for some net parameter checks
  2009-05-28 15:06       ` [Qemu-devel] [PATCH 2/3] net: Real fix for check_params users Mark McLoughlin
@ 2009-05-28 15:06         ` Mark McLoughlin
  2009-05-28 15:56           ` [Qemu-devel] " Jan Kiszka
  0 siblings, 1 reply; 38+ messages in thread
From: Mark McLoughlin @ 2009-05-28 15:06 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

A small bit of confusion between buffers is causing errors like:

  qemu: invalid parameter '10' in 'script=/etc/qemu-ifup,fd=10'

instead of:

  qemu: invalid parameter 'script' in 'script=/etc/qemu-ifup,fd=10'

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/net.c b/net.c
index 723e934..2594ed7 100644
--- a/net.c
+++ b/net.c
@@ -2036,7 +2036,7 @@ int net_client_init(const char *device, const char *p)
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
             if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
+                        chkbuf, p);
                 return -1;
             }
             fd = strtol(buf, NULL, 0);
@@ -2049,7 +2049,7 @@ int net_client_init(const char *device, const char *p)
             };
             if (check_params(chkbuf, sizeof(chkbuf), tap_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
+                        chkbuf, p);
                 return -1;
             }
             if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
@@ -2071,7 +2071,7 @@ int net_client_init(const char *device, const char *p)
             int fd;
             if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
+                        chkbuf, p);
                 return -1;
             }
             fd = strtol(buf, NULL, 0);
@@ -2084,7 +2084,7 @@ int net_client_init(const char *device, const char *p)
             };
             if (check_params(chkbuf, sizeof(chkbuf), listen_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
+                        chkbuf, p);
                 return -1;
             }
             ret = net_socket_listen_init(vlan, device, name, buf);
@@ -2094,7 +2094,7 @@ int net_client_init(const char *device, const char *p)
             };
             if (check_params(chkbuf, sizeof(chkbuf), connect_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
+                        chkbuf, p);
                 return -1;
             }
             ret = net_socket_connect_init(vlan, device, name, buf);
@@ -2104,7 +2104,7 @@ int net_client_init(const char *device, const char *p)
             };
             if (check_params(chkbuf, sizeof(chkbuf), mcast_params, p) < 0) {
                 fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
-                        buf, p);
+                        chkbuf, p);
                 return -1;
             }
             ret = net_socket_mcast_init(vlan, device, name, buf);
-- 
1.6.2.2

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 08/11] slirp: Move smb, redir, tftp and bootp parameters and -net channel
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 08/11] slirp: Move smb, redir, tftp and bootp parameters and -net channel Jan Kiszka
@ 2009-05-28 15:07   ` Mark McLoughlin
  2009-05-28 15:52     ` Jan Kiszka
  2009-05-29 11:42     ` Paul Brook
  0 siblings, 2 replies; 38+ messages in thread
From: Mark McLoughlin @ 2009-05-28 15:07 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

On Fri, 2009-05-08 at 12:34 +0200, Jan Kiszka wrote:
> So far a couple of slirp-related parameters were expressed via
> stand-alone command line options. This it inconsistent and unintuitive.
> Moreover, it prevents both dynamically reconfigured (host_net_add/
> delete) and multi-instance slirp.
> 
> This patch refactors the configuration by turning -smb, -redir, -tftp
> and -bootp as well as -net channel into options of "-net user". The old
> stand-alone command line options are still processed, but no longer
> advertised. This allows smooth migration of management applications to
> to the new syntax and also the extension of that syntax later in this
> series.
> 
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
...
> diff --git a/slirp/main.h b/slirp/main.h
> index ed51385..537c145 100644
> --- a/slirp/main.h
> +++ b/slirp/main.h
> @@ -46,6 +46,8 @@ extern int tcp_keepintvl;
>  extern uint8_t client_ethaddr[6];
>  extern const char *slirp_special_ip;
>  extern int slirp_restrict;
> +extern char tftp_prefix[PATH_MAX];
> +extern char bootp_filename[PATH_MAX];

This wouldn't build for me without including limits.h here

Cheers,
Mark.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 10/11] slirp: Rework external configuration interface
  2009-05-08 10:34 ` [Qemu-devel] [PATCH 10/11] slirp: Rework external configuration interface Jan Kiszka
@ 2009-05-28 15:07   ` Mark McLoughlin
  2009-05-28 15:55     ` Jan Kiszka
  0 siblings, 1 reply; 38+ messages in thread
From: Mark McLoughlin @ 2009-05-28 15:07 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

On Fri, 2009-05-08 at 12:34 +0200, Jan Kiszka wrote:
> With the internal IP configuration made more flexible, we can now
> enhance the user interface. This patch adds a number of new options to
> "-net user": net (address and mask), host, dhcpstart, dns and smbserver.
> It also renames "redir" to "hostfwd" and "channel" to "guestfwd" in
> order to (hopefully) clarify their meanings. The format of guestfwd is
> extended so that the user can define not only the port but also the
> virtual server's IP address the forwarding starts from.
> 
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>

...

> @@ -1988,15 +2117,21 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
>  #ifdef CONFIG_SLIRP
>      if (!strcmp(device, "user")) {
>          static const char * const slirp_params[] = {
> -            "vlan", "name", "hostname", "restrict", "ip", "tftp", "bootfile",
> -            "smb", "redir", "channel", NULL
> +            "vlan", "name", "hostname", "restrict", "net", "host",
> +            "tftp", "bootfile", "dhcpstart", "dns", "smb", "smbserver",
> +            "hostfwd", "guestfwd", NULL

You're renaming "redir" and "channel" here which isn't a big deal since
you've only introduced them in the previous patch, but it would be
better to use the final names in the original patch.

More importantly, though, you've dropped the "ip" parameter which is in
the 0.10.x releases. We can't just drop existing parameters.

By way of meta-comment, some of these patches are much harder to review
than they need to be, because e.g. you're doing lots of cleanups
together with the real changes, or not breaking changes into smaller
chunks.

Cheers,
Mark.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users
  2009-05-28 15:04   ` Mark McLoughlin
  2009-05-28 15:05     ` [Qemu-devel] [PATCH 1/3] Revert "Fix output of uninitialized strings" Mark McLoughlin
@ 2009-05-28 15:22     ` Kevin Wolf
  1 sibling, 0 replies; 38+ messages in thread
From: Kevin Wolf @ 2009-05-28 15:22 UTC (permalink / raw)
  To: Mark McLoughlin; +Cc: Jan Kiszka, qemu-devel

Mark McLoughlin schrieb:
> On Fri, 2009-05-08 at 12:34 +0200, Jan Kiszka wrote:
>> OK, last try: ea053add70 broke -net socket, ffad4116b9 tried to fix it
>> but broke error reporting of invalid parameters. So this patch widely
>> reverts ffad4116b9 again and intead fixes those callers of check_params
>> that originally suffered from overwritten buffers by using separate
>> ones.
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> 
> Okay, I think we should revert Kevin's fix from master and replace it
> with this one.

Agreed. I wasn't aware of this one.

Kevin

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 08/11] slirp: Move smb, redir, tftp and bootp parameters and -net channel
  2009-05-28 15:07   ` Mark McLoughlin
@ 2009-05-28 15:52     ` Jan Kiszka
  2009-05-29 11:42     ` Paul Brook
  1 sibling, 0 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-28 15:52 UTC (permalink / raw)
  To: Mark McLoughlin; +Cc: qemu-devel

Mark McLoughlin wrote:
> On Fri, 2009-05-08 at 12:34 +0200, Jan Kiszka wrote:
>> So far a couple of slirp-related parameters were expressed via
>> stand-alone command line options. This it inconsistent and unintuitive.
>> Moreover, it prevents both dynamically reconfigured (host_net_add/
>> delete) and multi-instance slirp.
>>
>> This patch refactors the configuration by turning -smb, -redir, -tftp
>> and -bootp as well as -net channel into options of "-net user". The old
>> stand-alone command line options are still processed, but no longer
>> advertised. This allows smooth migration of management applications to
>> to the new syntax and also the extension of that syntax later in this
>> series.
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ....
>> diff --git a/slirp/main.h b/slirp/main.h
>> index ed51385..537c145 100644
>> --- a/slirp/main.h
>> +++ b/slirp/main.h
>> @@ -46,6 +46,8 @@ extern int tcp_keepintvl;
>>  extern uint8_t client_ethaddr[6];
>>  extern const char *slirp_special_ip;
>>  extern int slirp_restrict;
>> +extern char tftp_prefix[PATH_MAX];
>> +extern char bootp_filename[PATH_MAX];
> 
> This wouldn't build for me without including limits.h here

Please use v2 (see
http://permalink.gmane.org/gmane.comp.emulators.qemu/43080).

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 10/11] slirp: Rework external configuration interface
  2009-05-28 15:07   ` Mark McLoughlin
@ 2009-05-28 15:55     ` Jan Kiszka
  2009-05-28 17:23       ` Mark McLoughlin
  0 siblings, 1 reply; 38+ messages in thread
From: Jan Kiszka @ 2009-05-28 15:55 UTC (permalink / raw)
  To: Mark McLoughlin; +Cc: qemu-devel

Mark McLoughlin wrote:
> On Fri, 2009-05-08 at 12:34 +0200, Jan Kiszka wrote:
>> With the internal IP configuration made more flexible, we can now
>> enhance the user interface. This patch adds a number of new options to
>> "-net user": net (address and mask), host, dhcpstart, dns and smbserver.
>> It also renames "redir" to "hostfwd" and "channel" to "guestfwd" in
>> order to (hopefully) clarify their meanings. The format of guestfwd is
>> extended so that the user can define not only the port but also the
>> virtual server's IP address the forwarding starts from.
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> 
> ....
> 
>> @@ -1988,15 +2117,21 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
>>  #ifdef CONFIG_SLIRP
>>      if (!strcmp(device, "user")) {
>>          static const char * const slirp_params[] = {
>> -            "vlan", "name", "hostname", "restrict", "ip", "tftp", "bootfile",
>> -            "smb", "redir", "channel", NULL
>> +            "vlan", "name", "hostname", "restrict", "net", "host",
>> +            "tftp", "bootfile", "dhcpstart", "dns", "smb", "smbserver",
>> +            "hostfwd", "guestfwd", NULL
> 
> You're renaming "redir" and "channel" here which isn't a big deal since
> you've only introduced them in the previous patch, but it would be
> better to use the final names in the original patch.

Well, the purpose of the original patch was only to pull "redir" and
"channel" as-is into the -net parameter list, not to refactor the
interface otherwise.

> 
> More importantly, though, you've dropped the "ip" parameter which is in
> the 0.10.x releases. We can't just drop existing parameters.

OK, I see the problem - though this parameter was probable rarely used
(it was undocumented and suffered from the poor configurability). Will
have a closer look.

> 
> By way of meta-comment, some of these patches are much harder to review
> than they need to be, because e.g. you're doing lots of cleanups
> together with the real changes, or not breaking changes into smaller
> chunks.

There might be a few coding style updates included, when I touch related
lines. Or please give some (or the most annoying) example.

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] Re: [PATCH 3/3] net: fix error reporting for some net parameter checks
  2009-05-28 15:06         ` [Qemu-devel] [PATCH 3/3] net: fix error reporting for some net parameter checks Mark McLoughlin
@ 2009-05-28 15:56           ` Jan Kiszka
  0 siblings, 0 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-28 15:56 UTC (permalink / raw)
  To: Mark McLoughlin; +Cc: qemu-devel

Mark McLoughlin wrote:
> A small bit of confusion between buffers is causing errors like:
> 
>   qemu: invalid parameter '10' in 'script=/etc/qemu-ifup,fd=10'
> 
> instead of:
> 
>   qemu: invalid parameter 'script' in 'script=/etc/qemu-ifup,fd=10'
> 
> Signed-off-by: Mark McLoughlin <markmc@redhat.com>
> ---
>  net.c |   12 ++++++------
>  1 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/net.c b/net.c
> index 723e934..2594ed7 100644
> --- a/net.c
> +++ b/net.c
> @@ -2036,7 +2036,7 @@ int net_client_init(const char *device, const char *p)
>          if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
>              if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
>                  fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
> -                        buf, p);
> +                        chkbuf, p);
>                  return -1;
>              }
>              fd = strtol(buf, NULL, 0);
> @@ -2049,7 +2049,7 @@ int net_client_init(const char *device, const char *p)
>              };
>              if (check_params(chkbuf, sizeof(chkbuf), tap_params, p) < 0) {
>                  fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
> -                        buf, p);
> +                        chkbuf, p);
>                  return -1;
>              }
>              if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
> @@ -2071,7 +2071,7 @@ int net_client_init(const char *device, const char *p)
>              int fd;
>              if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
>                  fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
> -                        buf, p);
> +                        chkbuf, p);
>                  return -1;
>              }
>              fd = strtol(buf, NULL, 0);
> @@ -2084,7 +2084,7 @@ int net_client_init(const char *device, const char *p)
>              };
>              if (check_params(chkbuf, sizeof(chkbuf), listen_params, p) < 0) {
>                  fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
> -                        buf, p);
> +                        chkbuf, p);
>                  return -1;
>              }
>              ret = net_socket_listen_init(vlan, device, name, buf);
> @@ -2094,7 +2094,7 @@ int net_client_init(const char *device, const char *p)
>              };
>              if (check_params(chkbuf, sizeof(chkbuf), connect_params, p) < 0) {
>                  fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
> -                        buf, p);
> +                        chkbuf, p);
>                  return -1;
>              }
>              ret = net_socket_connect_init(vlan, device, name, buf);
> @@ -2104,7 +2104,7 @@ int net_client_init(const char *device, const char *p)
>              };
>              if (check_params(chkbuf, sizeof(chkbuf), mcast_params, p) < 0) {
>                  fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
> -                        buf, p);
> +                        chkbuf, p);
>                  return -1;
>              }
>              ret = net_socket_mcast_init(vlan, device, name, buf);

Ack for all three.

(My dear. I promise to never touch these param checks again.)

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 10/11] slirp: Rework external configuration interface
  2009-05-28 15:55     ` Jan Kiszka
@ 2009-05-28 17:23       ` Mark McLoughlin
  2009-05-28 20:41         ` Jan Kiszka
  0 siblings, 1 reply; 38+ messages in thread
From: Mark McLoughlin @ 2009-05-28 17:23 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel

On Thu, 2009-05-28 at 17:55 +0200, Jan Kiszka wrote:
> > You're renaming "redir" and "channel" here which isn't a big deal since
> > you've only introduced them in the previous patch, but it would be
> > better to use the final names in the original patch.
> 
> Well, the purpose of the original patch was only to pull "redir" and
> "channel" as-is into the -net parameter list, not to refactor the
> interface otherwise.

It's a bisectability thing - we shouldn't introduce parameters in a
patch that we intend to rename in a subsequent patch.

e.g. if a distro cherry-picked this patch, we'd have options in the wild
that aren't available upstream.

> > More importantly, though, you've dropped the "ip" parameter which is
> in
> > the 0.10.x releases. We can't just drop existing parameters.
> 
> OK, I see the problem - though this parameter was probable rarely used
> (it was undocumented and suffered from the poor configurability). Will
> have a closer look.

Great. Probably best to re-send 7-11 with both of these things fixed up.

> > By way of meta-comment, some of these patches are much harder to
> review
> > than they need to be, because e.g. you're doing lots of cleanups
> > together with the real changes, or not breaking changes into smaller
> > chunks.
> 
> There might be a few coding style updates included, when I touch
> related
> lines. Or please give some (or the most annoying) example.

Okay:

  - In "Avoid zombie processes after fork_exec" you needlessly 
    re-arrange the code in launch_script() - it could have very 
    reasonably been an easy to review +6 hunk rather than a -24/+36 
    hunk if you'd split the cleanup out into its own patch

  - "Real fix for check_params users" could have been split into the
    revert followed by the better fix

  - In "Improve parameter error reporting", you replace a strdup() with 
    qemu_strdup(), unrelated to the goal of the patch

  - In "Reorder initialization", you change the formatting of the args 
    to the qemu_new_vlan_client() call - conflicted with my patches

  - In the same patch you've added a whole pile of braces in 
    what was net_slirp_redir() - made re-basing onto Alexander's slirp 
    stuff that bit more involved

  - You could have split up "slirp: Move smb, redir, tftp and bootp
    parameters and -net channel", maybe even made a separate patch for 
    each move

  - It's very hard to understand why each of the changes in "slirp:    
    Rework internal configuration" is needed and it's a big patch - 
    e.g. you completely re-wrote tcp_ctl(). Could that have been done 
    with a cleanup patch with no functional changes followed by the 
    actual functional changes?

  - "slirp: Rework external configuration interface" introduces several 
    new slirp options. Surely should be possible to split up into 
    smaller patches.

Cheers,
Mark.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 10/11] slirp: Rework external configuration interface
  2009-05-28 17:23       ` Mark McLoughlin
@ 2009-05-28 20:41         ` Jan Kiszka
  0 siblings, 0 replies; 38+ messages in thread
From: Jan Kiszka @ 2009-05-28 20:41 UTC (permalink / raw)
  To: Mark McLoughlin; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 3831 bytes --]

Mark McLoughlin wrote:
> On Thu, 2009-05-28 at 17:55 +0200, Jan Kiszka wrote:
>>> You're renaming "redir" and "channel" here which isn't a big deal since
>>> you've only introduced them in the previous patch, but it would be
>>> better to use the final names in the original patch.
>> Well, the purpose of the original patch was only to pull "redir" and
>> "channel" as-is into the -net parameter list, not to refactor the
>> interface otherwise.
> 
> It's a bisectability thing - we shouldn't introduce parameters in a
> patch that we intend to rename in a subsequent patch.

I do not only rename them, I also change their syntax.

> 
> e.g. if a distro cherry-picked this patch, we'd have options in the wild
> that aren't available upstream.

If distros cherry-pick transient public interface changes, I really
can't help - or I would consequently have to merge internal, external
interface rework and the final hostfwd syntax extension into a single
patch. I don't think this is desired either.

> 
>>> More importantly, though, you've dropped the "ip" parameter which is
>> in
>>> the 0.10.x releases. We can't just drop existing parameters.
>> OK, I see the problem - though this parameter was probable rarely used
>> (it was undocumented and suffered from the poor configurability). Will
>> have a closer look.
> 
> Great. Probably best to re-send 7-11 with both of these things fixed up.
> 
>>> By way of meta-comment, some of these patches are much harder to
>> review
>>> than they need to be, because e.g. you're doing lots of cleanups
>>> together with the real changes, or not breaking changes into smaller
>>> chunks.
>> There might be a few coding style updates included, when I touch
>> related
>> lines. Or please give some (or the most annoying) example.
> 
> Okay:
> 
>   - In "Avoid zombie processes after fork_exec" you needlessly 
>     re-arrange the code in launch_script() - it could have very 
>     reasonably been an easy to review +6 hunk rather than a -24/+36 
>     hunk if you'd split the cleanup out into its own patch
> 
>   - "Real fix for check_params users" could have been split into the
>     revert followed by the better fix
> 
>   - In "Improve parameter error reporting", you replace a strdup() with 
>     qemu_strdup(), unrelated to the goal of the patch
> 
>   - In "Reorder initialization", you change the formatting of the args 
>     to the qemu_new_vlan_client() call - conflicted with my patches
> 
>   - In the same patch you've added a whole pile of braces in 
>     what was net_slirp_redir() - made re-basing onto Alexander's slirp 
>     stuff that bit more involved
> 

Agreed (though the last conflict was not only related to that hunk),
some could have just been dropped, others split up without too much effort.

>   - You could have split up "slirp: Move smb, redir, tftp and bootp
>     parameters and -net channel", maybe even made a separate patch for 
>     each move

But that would have been overkill (they share a lot).

> 
>   - It's very hard to understand why each of the changes in "slirp:    
>     Rework internal configuration" is needed and it's a big patch - 
>     e.g. you completely re-wrote tcp_ctl(). Could that have been done 
>     with a cleanup patch with no functional changes followed by the 
>     actual functional changes?

Yes, tcp_ctl could have been sanitized beforehand. But the rest is
related to scope of the patch.

> 
>   - "slirp: Rework external configuration interface" introduces several 
>     new slirp options. Surely should be possible to split up into 
>     smaller patches.

Not impossible, but significant additional effort.

Thanks for the detailed comments! Will try harder to avoid the needless
mixups in the future.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 08/11] slirp: Move smb, redir, tftp and bootp parameters and -net channel
  2009-05-28 15:07   ` Mark McLoughlin
  2009-05-28 15:52     ` Jan Kiszka
@ 2009-05-29 11:42     ` Paul Brook
  2009-05-29 14:19       ` Jan Kiszka
  1 sibling, 1 reply; 38+ messages in thread
From: Paul Brook @ 2009-05-29 11:42 UTC (permalink / raw)
  To: qemu-devel, Mark McLoughlin; +Cc: Jan Kiszka

> > +extern char tftp_prefix[PATH_MAX];
> > +extern char bootp_filename[PATH_MAX];
>
> This wouldn't build for me without including limits.h here

It still won't work. You can't assume PATH_MAX is defined at all.

Paul

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 08/11] slirp: Move smb, redir, tftp and bootp parameters and -net channel
  2009-05-29 11:42     ` Paul Brook
@ 2009-05-29 14:19       ` Jan Kiszka
  2009-05-29 15:36         ` Paul Brook
  0 siblings, 1 reply; 38+ messages in thread
From: Jan Kiszka @ 2009-05-29 14:19 UTC (permalink / raw)
  To: Paul Brook; +Cc: Mark McLoughlin, qemu-devel

Paul Brook wrote:
>>> +extern char tftp_prefix[PATH_MAX];
>>> +extern char bootp_filename[PATH_MAX];
>> This wouldn't build for me without including limits.h here
> 
> It still won't work. You can't assume PATH_MAX is defined at all.
> 

You are right, one cannot always assume its there, but we already do:

block.c:    char tmp_filename[PATH_MAX];
block.c:    char backing_filename[PATH_MAX];
qemu-char.c:    char pty_name[PATH_MAX];
...

So there must be a way to make all platforms happy qemu builds against.
Otherwise I wouldn't have used it in the first place.

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH 08/11] slirp: Move smb, redir, tftp and bootp parameters and -net channel
  2009-05-29 14:19       ` Jan Kiszka
@ 2009-05-29 15:36         ` Paul Brook
  0 siblings, 0 replies; 38+ messages in thread
From: Paul Brook @ 2009-05-29 15:36 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Mark McLoughlin, qemu-devel

> > It still won't work. You can't assume PATH_MAX is defined at all.
>
> You are right, one cannot always assume its there, but we already do:
>
> block.c:    char tmp_filename[PATH_MAX];
> block.c:    char backing_filename[PATH_MAX];
> qemu-char.c:    char pty_name[PATH_MAX];

I consider these to be bugs, with the possible exception of qemu-char.c which 
appears to be part of an OpenBSD workaround.

Paul

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2009-05-29 15:36 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-08 10:34 [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Jan Kiszka
2009-05-08 10:34 ` [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users Jan Kiszka
2009-05-19  7:57   ` Mark McLoughlin
2009-05-19  9:34     ` Jan Kiszka
2009-05-19  9:57       ` Mark McLoughlin
2009-05-28 15:04   ` Mark McLoughlin
2009-05-28 15:05     ` [Qemu-devel] [PATCH 1/3] Revert "Fix output of uninitialized strings" Mark McLoughlin
2009-05-28 15:06       ` [Qemu-devel] [PATCH 2/3] net: Real fix for check_params users Mark McLoughlin
2009-05-28 15:06         ` [Qemu-devel] [PATCH 3/3] net: fix error reporting for some net parameter checks Mark McLoughlin
2009-05-28 15:56           ` [Qemu-devel] " Jan Kiszka
2009-05-28 15:22     ` [Qemu-devel] [PATCH 04/11] net: Real fix for check_params users Kevin Wolf
2009-05-08 10:34 ` [Qemu-devel] [PATCH 01/11] net: Don't deliver to disabled interfaces in qemu_sendv_packet Jan Kiszka
2009-05-08 15:20   ` Mark McLoughlin
2009-05-08 22:27     ` [Qemu-devel] "FLOSS bounty" ( FB )for running QEMU on SheevaPlug AGSCalabrese
2009-05-08 22:47       ` Marek Vasut
2009-05-08 22:58       ` Paul Brook
2009-05-08 10:34 ` [Qemu-devel] [PATCH 02/11] net: Fix and improved ordered packet delivery Jan Kiszka
2009-05-08 15:24   ` Mark McLoughlin
2009-05-08 10:34 ` [Qemu-devel] [PATCH 03/11] slirp: Avoid zombie processes after fork_exec Jan Kiszka
2009-05-08 10:34 ` [Qemu-devel] [PATCH 06/11] slirp: Reorder initialization Jan Kiszka
2009-05-08 10:34 ` [Qemu-devel] [PATCH 10/11] slirp: Rework external configuration interface Jan Kiszka
2009-05-28 15:07   ` Mark McLoughlin
2009-05-28 15:55     ` Jan Kiszka
2009-05-28 17:23       ` Mark McLoughlin
2009-05-28 20:41         ` Jan Kiszka
2009-05-08 10:34 ` [Qemu-devel] [PATCH 07/11] Introduce get_next_param_value Jan Kiszka
2009-05-08 10:34 ` [Qemu-devel] [PATCH 05/11] net: Improve parameter error reporting Jan Kiszka
2009-05-08 10:34 ` [Qemu-devel] [PATCH 08/11] slirp: Move smb, redir, tftp and bootp parameters and -net channel Jan Kiszka
2009-05-28 15:07   ` Mark McLoughlin
2009-05-28 15:52     ` Jan Kiszka
2009-05-29 11:42     ` Paul Brook
2009-05-29 14:19       ` Jan Kiszka
2009-05-29 15:36         ` Paul Brook
2009-05-08 10:34 ` [Qemu-devel] [PATCH 09/11] slirp: Rework internal configuration Jan Kiszka
2009-05-08 10:34 ` [Qemu-devel] [PATCH 11/11] slirp: Bind support for host forwarding rules Jan Kiszka
2009-05-08 16:25 ` [Qemu-devel] [PATCH 00/11] Networking fixes and slirp enhancements Anthony Liguori
2009-05-08 17:01   ` Jan Kiszka
2009-05-09  7:41     ` [Qemu-devel] [PATCH 08/11 v2] slirp: Move smb, redir, tftp and bootp parameters and -net channel Jan Kiszka

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.