qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 11/11] slirp: Bind support for host forwarding rules


From: Jan Kiszka
Subject: [Qemu-devel] [PATCH 11/11] slirp: Bind support for host forwarding rules
Date: Fri, 08 May 2009 12:34:19 +0200
User-agent: StGIT/0.14.2

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 <address@hidden>
---

 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.
 
address@hidden hostfwd=[tcp|udp]:@var{hostport}:address@hidden:@var{guestport}
address@hidden hostfwd=[tcp|udp]:address@hidden:@address@hidden:@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}:@address@hidden
-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);





reply via email to

[Prev in Thread] Current Thread [Next in Thread]