qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH RFC 0/4] slirp: support hostfwd for ipv6 addresses
@ 2018-10-26  0:03 Maxim Samoylov
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 1/4] slirp: add helper for tcp6 socket creation Maxim Samoylov
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Maxim Samoylov @ 2018-10-26  0:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: max7255

The following patch implements ipv6 host port forwarding support
for qemu slirp net subsystem.

The slirp itself supports ipv6 communication, but
hostfwd currently does not allow listening on and forwarding
ports for ipv6 addresses.

This should be useful, when host works in v6-capable environment
and guests should be accessible there.

Turns out the only thing should be done is to properly parse 
ipv6 addresses and pass them down to listening socket create logic.

The proposed option ipv6-hostfwd syntax is the same as for the hostfwd option,
but one should enclose their ipv6 addresses into square brackets, e.g.:

ipv6-hostfwd=tcp::7255-[fec0::5054:ff:fe12:3456]:80

The guest ipv6 address intended to be specified explicitly,
because there is no dhcpv6 server in slirp.


Maxim Samoylov (4):
  slirp: add helper for tcp6 socket creation
  slirp: add helper for udp6 socket creation
  slirp: add helpers for ipv6 hostfwd manipulation
  net/slirp: add ipv6-hostfwd option for user netdev type

 hmp-commands.hx     |  31 ++++++++
 include/net/slirp.h |   2 +
 net/slirp.c         | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 qapi/net.json       |   3 +-
 slirp/libslirp.h    |   6 ++
 slirp/slirp.c       |  43 +++++++++++
 slirp/socket.c      |  73 ++++++++++++++++++
 slirp/socket.h      |   2 +
 slirp/udp.c         |  48 ++++++++++++
 slirp/udp.h         |   2 +
 10 files changed, 423 insertions(+), 1 deletion(-)

-- 
2.7.4

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

* [Qemu-devel] [PATCH RFC 1/4] slirp: add helper for tcp6 socket creation
  2018-10-26  0:03 [Qemu-devel] [PATCH RFC 0/4] slirp: support hostfwd for ipv6 addresses Maxim Samoylov
@ 2018-10-26  0:03 ` Maxim Samoylov
  2018-10-27 11:11   ` Samuel Thibault
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 2/4] slirp: add helper for udp6 " Maxim Samoylov
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 15+ messages in thread
From: Maxim Samoylov @ 2018-10-26  0:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: max7255

Signed-off-by: Maxim Samoylov <max7255@yandex-team.ru>
---
 slirp/socket.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 slirp/socket.h |  2 ++
 2 files changed, 75 insertions(+)

diff --git a/slirp/socket.c b/slirp/socket.c
index 322383a..e16e6c1 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -776,6 +776,79 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 	return so;
 }
 
+struct socket *
+tcp6_listen(Slirp *slirp, struct in6_addr haddr, u_int hport,
+            struct in6_addr laddr, u_int lport, int flags)
+{
+    struct sockaddr_in6 addr;
+    struct socket *so;
+    int s, opt = 1;
+    socklen_t addrlen = sizeof(addr);
+    memset(&addr, 0, addrlen);
+
+    /* The same flow as in tcp_listen above */
+
+    so = socreate(slirp);
+    if (!so) {
+        return NULL;
+    }
+
+    so->so_tcpcb = tcp_newtcpcb(so);
+    if (so->so_tcpcb == NULL) {
+        free(so);
+        return NULL;
+    }
+
+    insque(so, &slirp->tcb);
+
+    if (flags & SS_FACCEPTONCE) {
+        so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT * 2;
+    }
+
+    so->so_state &= SS_PERSISTENT_MASK;
+    so->so_state |= (SS_FACCEPTCONN | flags);
+    so->so_lfamily = AF_INET6;
+    so->so_lport6 = lport; /* Kept in network format */
+    so->so_laddr6 = laddr;
+
+    addr.sin6_family = AF_INET6;
+    addr.sin6_addr = haddr;
+    addr.sin6_port = hport;
+
+    s = qemu_socket(AF_INET6, SOCK_STREAM, 0);
+    if ((s < 0) ||
+        (socket_set_fast_reuse(s) < 0) ||
+        (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) ||
+        (listen(s, 1) < 0)) {
+        int tmperrno = errno; /* Don't clobber the real reason we failed */
+            if (s >= 0) {
+                closesocket(s);
+            }
+        sofree(so);
+        /* Restore the real errno */
+#ifdef _WIN32
+        WSASetLastError(tmperrno);
+#else
+        errno = tmperrno;
+#endif
+        return NULL;
+    }
+    qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
+
+    getsockname(s, (struct sockaddr *)&addr, &addrlen);
+    so->fhost.sin6 = addr;
+
+    if (!memcmp(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)) ||
+        !memcmp(&addr.sin6_addr, &in6addr_loopback,
+                sizeof(in6addr_loopback))) {
+
+        memcpy(&so->so_faddr6, &slirp->vhost_addr6, sizeof(slirp->vhost_addr6));
+    }
+
+    so->s = s;
+    return so;
+}
+
 /*
  * Various session state calls
  * XXX Should be #define's
diff --git a/slirp/socket.h b/slirp/socket.h
index 2f224bc..b200bb6 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -144,6 +144,8 @@ void sorecvfrom(struct socket *);
 int sosendto(struct socket *, struct mbuf *);
 struct socket * tcp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,
                                int);
+struct socket *tcp6_listen(Slirp *, struct in6_addr, u_int,
+                           struct in6_addr, u_int, int);
 void soisfconnecting(register struct socket *);
 void soisfconnected(register struct socket *);
 void sofwdrain(struct socket *);
-- 
2.7.4

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

* [Qemu-devel] [PATCH RFC 2/4] slirp: add helper for udp6 socket creation
  2018-10-26  0:03 [Qemu-devel] [PATCH RFC 0/4] slirp: support hostfwd for ipv6 addresses Maxim Samoylov
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 1/4] slirp: add helper for tcp6 socket creation Maxim Samoylov
@ 2018-10-26  0:03 ` Maxim Samoylov
  2018-10-27 11:13   ` Samuel Thibault
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 3/4] slirp: add helpers for ipv6 hostfwd manipulation Maxim Samoylov
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 4/4] net/slirp: add ipv6-hostfwd option for user netdev type Maxim Samoylov
  3 siblings, 1 reply; 15+ messages in thread
From: Maxim Samoylov @ 2018-10-26  0:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: max7255

Signed-off-by: Maxim Samoylov <max7255@yandex-team.ru>
---
 slirp/udp.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 slirp/udp.h |  2 ++
 2 files changed, 50 insertions(+)

diff --git a/slirp/udp.c b/slirp/udp.c
index e5bf065..ab24935 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -366,3 +366,51 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 
 	return so;
 }
+
+struct socket *
+udp6_listen(Slirp *slirp, struct in6_addr haddr, u_int hport,
+            struct in6_addr laddr, u_int lport, int flags)
+{
+    struct sockaddr_in6 addr;
+    struct socket *so;
+    socklen_t addrlen = sizeof(addr);
+
+    memset(&addr, 0, sizeof(addr));
+
+    so = socreate(slirp);
+    if (!so) {
+        return NULL;
+    }
+    so->s = qemu_socket(AF_INET6, SOCK_DGRAM, 0);
+        if (so->s < 0) {
+            sofree(so);
+            return NULL;
+        }
+    so->so_expire = curtime + SO_EXPIRE;
+    insque(so, &slirp->udb);
+
+    addr.sin6_family = AF_INET6;
+    addr.sin6_addr = haddr;
+    addr.sin6_port = hport;
+
+    if (bind(so->s, (struct sockaddr *)&addr, addrlen) < 0) {
+        udp_detach(so);
+        return NULL;
+    }
+    socket_set_fast_reuse(so->s);
+
+    getsockname(so->s, (struct sockaddr *)&addr, &addrlen);
+    so->fhost.sin6 = addr;
+    sotranslate_accept(so);
+    so->so_lfamily = AF_INET6;
+    so->so_lport = lport;
+    so->so_laddr6 = laddr;
+    if (flags != SS_FACCEPTONCE) {
+        so->so_expire = 0;
+    }
+
+    so->so_state &= SS_PERSISTENT_MASK;
+    so->so_state |= SS_ISFCONNECTED | flags;
+
+    return so;
+}
diff --git a/slirp/udp.h b/slirp/udp.h
index be657cf..862c6e8 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -80,6 +80,8 @@ int udp_attach(struct socket *, unsigned short af);
 void udp_detach(struct socket *);
 struct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,
                            int);
+struct socket *udp6_listen(Slirp *slirp, struct in6_addr, u_int,
+                            struct in6_addr, u_int, int);
 int udp_output(struct socket *so, struct mbuf *m,
                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
                 int iptos);
-- 
2.7.4

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

* [Qemu-devel] [PATCH RFC 3/4] slirp: add helpers for ipv6 hostfwd manipulation
  2018-10-26  0:03 [Qemu-devel] [PATCH RFC 0/4] slirp: support hostfwd for ipv6 addresses Maxim Samoylov
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 1/4] slirp: add helper for tcp6 socket creation Maxim Samoylov
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 2/4] slirp: add helper for udp6 " Maxim Samoylov
@ 2018-10-26  0:03 ` Maxim Samoylov
  2018-10-27 11:23   ` Samuel Thibault
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 4/4] net/slirp: add ipv6-hostfwd option for user netdev type Maxim Samoylov
  3 siblings, 1 reply; 15+ messages in thread
From: Maxim Samoylov @ 2018-10-26  0:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: max7255

Signed-off-by: Maxim Samoylov <max7255@yandex-team.ru>
---
 slirp/libslirp.h |  6 ++++++
 slirp/slirp.c    | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 42e42e9..3710650 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -34,6 +34,12 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp,
                       struct in_addr guest_addr, int guest_port);
 int slirp_remove_hostfwd(Slirp *slirp, int is_udp,
                          struct in_addr host_addr, int host_port);
+int slirp_add_ipv6_hostfwd(Slirp *slirp, int is_udp,
+                           struct in6_addr host_addr, int host_port,
+                           struct in6_addr guest_addr, int guest_port);
+int slirp_remove_ipv6_hostfwd(Slirp *slirp, int is_udp,
+                              struct in6_addr host_addr, int host_port);
+
 int slirp_add_exec(Slirp *slirp, 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 51de41f..143ddea 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -1065,6 +1065,49 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
     return 0;
 }
 
+int slirp_remove_ipv6_hostfwd(Slirp *slirp, int is_udp,
+                              struct in6_addr host_addr, int host_port)
+{
+    struct socket *so;
+    struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
+    struct sockaddr_in6 addr;
+    int port = htons(host_port);
+    socklen_t addr_len;
+
+    for (so = head->so_next; so != head; so = so->so_next) {
+        addr_len = sizeof(addr);
+        if ((so->so_state & SS_HOSTFWD) &&
+            getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
+            addr_len == sizeof(host_addr) &&
+            !memcmp(&host_addr, &addr, addr_len) &&
+            addr.sin6_port == port) {
+
+            close(so->s);
+            sofree(so);
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+int slirp_add_ipv6_hostfwd(Slirp *slirp, int is_udp,
+                          struct in6_addr host_addr, int host_port,
+                          struct in6_addr guest_addr, int guest_port)
+{
+    if (is_udp) {
+        if (!udp6_listen(slirp, host_addr, htons(host_port),
+                         guest_addr, htons(guest_port), SS_HOSTFWD))
+            return -1;
+    } else {
+        if (!tcp6_listen(slirp, host_addr, htons(host_port),
+                         guest_addr, htons(guest_port), SS_HOSTFWD))
+            return -1;
+    }
+
+    return 0;
+}
+
 int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
                    struct in_addr *guest_addr, int guest_port)
 {
-- 
2.7.4

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

* [Qemu-devel] [PATCH RFC 4/4] net/slirp: add ipv6-hostfwd option for user netdev type
  2018-10-26  0:03 [Qemu-devel] [PATCH RFC 0/4] slirp: support hostfwd for ipv6 addresses Maxim Samoylov
                   ` (2 preceding siblings ...)
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 3/4] slirp: add helpers for ipv6 hostfwd manipulation Maxim Samoylov
@ 2018-10-26  0:03 ` Maxim Samoylov
  2018-10-26  6:14   ` Thomas Huth
                     ` (2 more replies)
  3 siblings, 3 replies; 15+ messages in thread
From: Maxim Samoylov @ 2018-10-26  0:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: max7255

This allows forwarding TCP6 and UDP6 connections down to
netdev=user connected guests.

Signed-off-by: Maxim Samoylov <max7255@yandex-team.ru>
---
 hmp-commands.hx     |  31 ++++++++
 include/net/slirp.h |   2 +
 net/slirp.c         | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 qapi/net.json       |   3 +-
 4 files changed, 249 insertions(+), 1 deletion(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index db0c681..b0e1a08 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1448,6 +1448,37 @@ STEXI
 Remove host-to-guest TCP or UDP redirection.
 ETEXI
 
+#ifdef CONFIG_SLIRP
+    {
+        .name       = "ipv6_hostfwd_add",
+        .args_type  = "arg1:s,arg2:s?,arg3:s?",
+        .params     = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr6]:hostport-guestaddr6:guestport",
+        .help       = "redirect TCP6 or UDP6 connections from host to guest (requires -net user)",
+        .cmd        = hmp_ipv6_hostfwd_add,
+    },
+#endif
+STEXI
+@item hostfwd_add
+@findex hostfwd_add
+Redirect TCP6 or UDP6 connections from host to guest (requires -net user).
+ETEXI
+
+#ifdef CONFIG_SLIRP
+    {
+        .name       = "ipv6_hostfwd_remove",
+        .args_type  = "arg1:s,arg2:s?,arg3:s?",
+        .params     = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr6]:hostport",
+        .help       = "remove host-to-guest TCP6 or UDP6 redirection",
+        .cmd        = hmp_ipv6_hostfwd_remove,
+    },
+
+#endif
+STEXI
+@item hostfwd_remove
+@findex hostfwd_remove
+Remove host-to-guest TCP6 or UDP6 redirection.
+ETEXI
+
     {
         .name       = "balloon",
         .args_type  = "value:M",
diff --git a/include/net/slirp.h b/include/net/slirp.h
index bad3e1e..4796a5c 100644
--- a/include/net/slirp.h
+++ b/include/net/slirp.h
@@ -29,6 +29,8 @@
 
 void hmp_hostfwd_add(Monitor *mon, const QDict *qdict);
 void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict);
+void hmp_ipv6_hostfwd_add(Monitor *mon, const QDict *qdict);
+void hmp_ipv6_hostfwd_remove(Monitor *mon, const QDict *qdict);
 
 void hmp_info_usernet(Monitor *mon, const QDict *qdict);
 
diff --git a/net/slirp.c b/net/slirp.c
index f6dc039..abe112b 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -67,6 +67,7 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
 /* slirp network adapter */
 
 #define SLIRP_CFG_HOSTFWD 1
+#define SLIRP_CFG_IPV6_HOSTFWD 2
 
 struct slirp_config_str {
     struct slirp_config_str *next;
@@ -89,6 +90,8 @@ static QTAILQ_HEAD(slirp_stacks, SlirpState) slirp_stacks =
     QTAILQ_HEAD_INITIALIZER(slirp_stacks);
 
 static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp);
+static int slirp_ipv6_hostfwd(SlirpState *s, const char *redir_str,
+                              Error **errp);
 static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp);
 
 #ifndef _WIN32
@@ -386,6 +389,10 @@ static int net_slirp_init(NetClientState *peer, const char *model,
             if (slirp_hostfwd(s, config->str, errp) < 0) {
                 goto error;
             }
+        } else if (config->flags & SLIRP_CFG_IPV6_HOSTFWD) {
+            if (slirp_ipv6_hostfwd(s, config->str, errp) < 0) {
+                goto error;
+            }
         } else {
             if (slirp_guestfwd(s, config->str, errp) < 0) {
                 goto error;
@@ -504,6 +511,73 @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "invalid format\n");
 }
 
+void hmp_ipv6_hostfwd_remove(Monitor *mon, const QDict *qdict)
+{
+    struct in6_addr host_addr = in6addr_any;
+    int host_port;
+    char buf[256];
+    const char *src_str, *p;
+    SlirpState *s;
+    int is_udp = 0;
+    int err;
+    const char *arg1 = qdict_get_str(qdict, "arg1");
+    const char *arg2 = qdict_get_try_str(qdict, "arg2");
+    const char *arg3 = qdict_get_try_str(qdict, "arg3");
+
+    if (arg2) {
+        s = slirp_lookup(mon, arg1, arg2);
+        src_str = arg3;
+    } else {
+        s = slirp_lookup(mon, NULL, NULL);
+        src_str = arg1;
+    }
+    if (!s) {
+        return;
+    }
+
+    p = src_str;
+    if (!p || 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")) {
+        is_udp = 1;
+    } else {
+        goto fail_syntax;
+    }
+
+    if (*(p++) != '[') {
+        goto fail_syntax;
+    }
+
+    if (get_str_sep(buf, sizeof(buf), &p, ']') < 0) {
+        goto fail_syntax;
+    }
+
+    if (!inet_pton(AF_INET6, buf, &host_addr)) {
+        goto fail_syntax;
+    }
+
+    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+        goto fail_syntax;
+    }
+
+    if (qemu_strtoi(p, NULL, 10, &host_port) < 0) {
+        goto fail_syntax;
+    }
+
+    err = slirp_remove_ipv6_hostfwd(s->slirp, is_udp, host_addr, host_port);
+
+    monitor_printf(mon, "host forwarding rule for %s %s\n", src_str,
+                   err ? "not found" : "removed");
+    return;
+
+ fail_syntax:
+    monitor_printf(mon, "invalid format\n");
+}
+
 static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
 {
     struct in_addr host_addr = { .s_addr = INADDR_ANY };
@@ -577,6 +651,119 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
     return -1;
 }
 
+static int slirp_ipv6_hostfwd(SlirpState *s, const char *redir_str,
+                              Error **errp)
+{
+    struct in6_addr host_addr = in6addr_any;
+    struct in6_addr guest_addr;
+    int host_port, guest_port;
+    const char *p;
+    char buf[256];
+    int is_udp;
+    const char *end;
+    const char *fail_reason = "Unknown reason";
+
+    memset(&guest_addr, 0, sizeof(guest_addr));
+
+    p = redir_str;
+    if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+        fail_reason = "No : separators";
+        goto fail_syntax;
+    }
+    if (!strcmp(buf, "tcp") || buf[0] == '\0') {
+        is_udp = 0;
+    } else if (!strcmp(buf, "udp")) {
+        is_udp = 1;
+    } else {
+        fail_reason = "Bad protocol name";
+        goto fail_syntax;
+    }
+
+    if (*(p++) != '[') {
+        fail_reason = "IPv6 address must be enclosed in square brackets";
+        goto fail_syntax;
+    }
+
+    if (get_str_sep(buf, sizeof(buf), &p, ']') < 0) {
+        fail_reason = "IPv6 address must be enclosed in square brackets";
+        goto fail_syntax;
+    }
+
+    if (!inet_pton(AF_INET6, buf, &host_addr)) {
+        fail_reason = "Bad host address";
+        goto fail_syntax;
+    }
+
+    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0 ||
+        buf[0] != '\0') {
+        fail_reason = "Bad ipv6 address and port separator";
+        goto fail_syntax;
+    }
+
+    if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
+        fail_reason = "Bad host port separator";
+        goto fail_syntax;
+    }
+
+    if (qemu_strtoi(buf, &end, 0, &host_port)) {
+        fail_reason = "Bad host port";
+        goto fail_syntax;
+    }
+
+    if (*end != '\0' || host_port < 0 || host_port > 65535) {
+        fail_reason = "Host port out of range";
+        goto fail_syntax;
+    }
+
+    if (*p == '\0') {
+        fail_reason = "Missing guest ipv6 address";
+        goto fail_syntax;
+    }
+
+    if (*(p++) != '[') {
+        fail_reason = "IPv6 address must be enclosed in square brackets";
+        goto fail_syntax;
+    }
+
+    if (get_str_sep(buf, sizeof(buf), &p,  ']') < 0) {
+        fail_reason = "IPv6 address must be enclosed in square brackets";
+        goto fail_syntax;
+    }
+
+    if (!inet_pton(AF_INET6, buf, &guest_addr)) {
+        fail_reason = "Bad guest address";
+        goto fail_syntax;
+    }
+
+    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0 || buf[0] != '\0') {
+        fail_reason = "Bad ipv6 address and port separator";
+        goto fail_syntax;
+    }
+
+    if (qemu_strtoi(p, &end, 0, &guest_port) < 0) {
+        fail_reason = "Bad guest port";
+        goto fail_syntax;
+    }
+
+    if (*end != '\0' || guest_port < 1 || guest_port > 65535) {
+        fail_reason = "Guest port number out of range";
+        goto fail_syntax;
+    }
+
+    if (slirp_add_ipv6_hostfwd(s->slirp, is_udp, host_addr, host_port,
+                               guest_addr, guest_port) < 0) {
+        error_report("could not set up host forwarding rule '%s'",
+                     redir_str);
+        return -1;
+    }
+    return 0;
+
+ fail_syntax:
+    error_setg(errp, "Invalid host forwarding rule '%s' (%s)", redir_str,
+               fail_reason);
+    return -1;
+}
+
 void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
 {
     const char *redir_str;
@@ -604,6 +791,32 @@ void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
 
 }
 
+void hmp_ipv6_hostfwd_add(Monitor *mon, const QDict *qdict)
+{
+    const char *redir_str;
+    SlirpState *s;
+    const char *arg1 = qdict_get_str(qdict, "arg1");
+    const char *arg2 = qdict_get_try_str(qdict, "arg2");
+    const char *arg3 = qdict_get_try_str(qdict, "arg3");
+
+    if (arg2) {
+        s = slirp_lookup(mon, arg1, arg2);
+        redir_str = arg3;
+    } else if (arg2) {
+        s = slirp_lookup(mon, NULL, arg1);
+        redir_str = arg2;
+    } else {
+        s = slirp_lookup(mon, NULL, NULL);
+        redir_str = arg1;
+    }
+    if (s) {
+        Error *err = NULL;
+        if (slirp_ipv6_hostfwd(s, redir_str, &err) < 0) {
+            error_report_err(err);
+        }
+    }
+}
+
 #ifndef _WIN32
 
 /* automatic user mode samba server configuration */
@@ -906,6 +1119,7 @@ int net_init_slirp(const Netdev *netdev, const char *name,
     /* all optional fields are initialized to "all bits zero" */
 
     net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD);
+    net_init_slirp_configs(user->ipv6_hostfwd, SLIRP_CFG_IPV6_HOSTFWD);
     net_init_slirp_configs(user->guestfwd, 0);
 
     ret = net_slirp_init(peer, "user", name, user->q_restrict,
diff --git a/qapi/net.json b/qapi/net.json
index 8f99fd9..4f67caf 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -201,7 +201,8 @@
     '*smbserver': 'str',
     '*hostfwd':   ['String'],
     '*guestfwd':  ['String'],
-    '*tftp-server-name': 'str' } }
+    '*tftp-server-name': 'str',
+    '*ipv6-hostfwd': ['String']} }
 
 ##
 # @NetdevTapOptions:
-- 
2.7.4

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

* Re: [Qemu-devel] [PATCH RFC 4/4] net/slirp: add ipv6-hostfwd option for user netdev type
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 4/4] net/slirp: add ipv6-hostfwd option for user netdev type Maxim Samoylov
@ 2018-10-26  6:14   ` Thomas Huth
  2018-10-30 14:00     ` Maxim Samoylov
  2018-10-27 11:38   ` Samuel Thibault
  2018-11-05 23:05   ` Eric Blake
  2 siblings, 1 reply; 15+ messages in thread
From: Thomas Huth @ 2018-10-26  6:14 UTC (permalink / raw)
  To: Maxim Samoylov, qemu-devel; +Cc: Samuel Thibault

On 2018-10-26 01:03, Maxim Samoylov wrote:
> This allows forwarding TCP6 and UDP6 connections down to
> netdev=user connected guests.
> 
> Signed-off-by: Maxim Samoylov <max7255@yandex-team.ru>
> ---
>  hmp-commands.hx     |  31 ++++++++
>  include/net/slirp.h |   2 +
>  net/slirp.c         | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  qapi/net.json       |   3 +-
>  4 files changed, 249 insertions(+), 1 deletion(-)
> 
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index db0c681..b0e1a08 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1448,6 +1448,37 @@ STEXI
>  Remove host-to-guest TCP or UDP redirection.
>  ETEXI
>  
> +#ifdef CONFIG_SLIRP
> +    {
> +        .name       = "ipv6_hostfwd_add",
> +        .args_type  = "arg1:s,arg2:s?,arg3:s?",
> +        .params     = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr6]:hostport-guestaddr6:guestport",
> +        .help       = "redirect TCP6 or UDP6 connections from host to guest (requires -net user)",
> +        .cmd        = hmp_ipv6_hostfwd_add,
> +    },
> +#endif
> +STEXI
> +@item hostfwd_add
> +@findex hostfwd_add
> +Redirect TCP6 or UDP6 connections from host to guest (requires -net user).
> +ETEXI
> +
> +#ifdef CONFIG_SLIRP
> +    {
> +        .name       = "ipv6_hostfwd_remove",
> +        .args_type  = "arg1:s,arg2:s?,arg3:s?",
> +        .params     = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr6]:hostport",
> +        .help       = "remove host-to-guest TCP6 or UDP6 redirection",
> +        .cmd        = hmp_ipv6_hostfwd_remove,
> +    },

 Hi,

could you please remove the "[hub_id name]" touple here? I recently sent
a patch to deprecate it for the IPv4 version, too:

https://lists.gnu.org/archive/html/qemu-devel/2018-09/msg03198.html

Also I think it would make sense if you mention in the help text that
IPv6 addresses have to be given with square brackets?

 Thanks,
  Thomas

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

* Re: [Qemu-devel] [PATCH RFC 1/4] slirp: add helper for tcp6 socket creation
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 1/4] slirp: add helper for tcp6 socket creation Maxim Samoylov
@ 2018-10-27 11:11   ` Samuel Thibault
  2018-10-27 11:13     ` Samuel Thibault
  2018-10-30 13:58     ` Maxim Samoylov
  0 siblings, 2 replies; 15+ messages in thread
From: Samuel Thibault @ 2018-10-27 11:11 UTC (permalink / raw)
  To: Maxim Samoylov; +Cc: qemu-devel

Hello,

Thanks for working on this!

There is a lot of overlap with tcp_listen. It'd be much better to
refactor it this way:

struct socket *
tcpx_listen(Slirp *slirp, struct sockaddr *addr, socklen_t *addrlen, int flags)
{
	... The current content of tcp_listen, with all heading and
	trailing addr manipulations removed...
	
	... so->so_lfamily = addr->sa_family;...
	... s = qemu_socket(addr->sa_family, SOCK_STREAM, 0);...
        ... (bind(s, addr, *addrlen) < 0) ||...
	... getsockname(s, addr, addrlen);
}

struct socket *
tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
           u_int lport, int flags)
{
	struct sockaddr_in addr;
	struct socket *so;
	socklen_t addrsize = sizeof(addr);

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = haddr;
	addr.sin_port = hport;

	so = tcpx_listen(slirp, (struct sockaddr *) &addr, &addrsize, flags);

	so->so_lport = lport; /* Kept in network format */
	so->so_laddr.s_addr = laddr; /* Ditto */

	so->so_ffamily = AF_INET;
	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 = slirp->vhost_addr;
	else
	   so->so_faddr = addr.sin_addr;
}

The v6 version then boils down to

struct socket *
tcp6_listen(Slirp *slirp, struct in6_addr haddr, u_int hport, struct
	    in6_addr laddr, u_int lport, int flags)
{
	struct sockaddr_in6 addr;
	struct socket *so;
	socklen_t addrsize = sizeof(addr);

	addr.sin6_family = AF_INET6;
	addr.sin6_addr = haddr;
	addr.sin6_port = hport;

	so = tcpx_listen(slirp, (struct sockaddr *) &addr, &addrsize, flags);

	so->so_lport6 = lport; /* Kept in network format */
	so->so_laddr6 = laddr; /* Ditto */

	so->fhost.sin6 = addr;
	    
	if (!memcmp(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)) ||
	    !memcmp(&addr.sin6_addr, &in6addr_loopback,
	            sizeof(in6addr_loopback))) {
	
	    memcpy(&so->so_faddr6, &slirp->vhost_addr6, sizeof(slirp->vhost_addr6));
	}
}

modulo all typos etc. I may have done.

Maxim Samoylov, le ven. 26 oct. 2018 03:03:40 +0300, a ecrit:
> +    qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));

Is there a reason why you set SO_OOBINLINE, but not TCP_NODELAY? That's
the kind of discrepancy we don't want to let unseen, thus the reason for
a shared implementation :)

Samuel

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

* Re: [Qemu-devel] [PATCH RFC 1/4] slirp: add helper for tcp6 socket creation
  2018-10-27 11:11   ` Samuel Thibault
@ 2018-10-27 11:13     ` Samuel Thibault
  2018-10-30 13:58     ` Maxim Samoylov
  1 sibling, 0 replies; 15+ messages in thread
From: Samuel Thibault @ 2018-10-27 11:13 UTC (permalink / raw)
  To: Maxim Samoylov, h; +Cc: qemu-devel

Samuel Thibault, le sam. 27 oct. 2018 13:11:41 +0200, a ecrit:
> struct socket *
> tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
>            u_int lport, int flags)
> {
> 	struct sockaddr_in addr;
> 	struct socket *so;
> 	socklen_t addrsize = sizeof(addr);

Also  memset(&addr, 0, sizeof(addr);

> 	addr.sin_family = AF_INET;
> 	addr.sin_addr.s_addr = haddr;
> 	addr.sin_port = hport;

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

* Re: [Qemu-devel] [PATCH RFC 2/4] slirp: add helper for udp6 socket creation
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 2/4] slirp: add helper for udp6 " Maxim Samoylov
@ 2018-10-27 11:13   ` Samuel Thibault
  0 siblings, 0 replies; 15+ messages in thread
From: Samuel Thibault @ 2018-10-27 11:13 UTC (permalink / raw)
  To: Maxim Samoylov; +Cc: qemu-devel

Ditto :)

Samuel

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

* Re: [Qemu-devel] [PATCH RFC 3/4] slirp: add helpers for ipv6 hostfwd manipulation
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 3/4] slirp: add helpers for ipv6 hostfwd manipulation Maxim Samoylov
@ 2018-10-27 11:23   ` Samuel Thibault
  0 siblings, 0 replies; 15+ messages in thread
From: Samuel Thibault @ 2018-10-27 11:23 UTC (permalink / raw)
  To: Maxim Samoylov; +Cc: qemu-devel

Hello,

Maxim Samoylov, le ven. 26 oct. 2018 03:03:42 +0300, a ecrit:
> +int slirp_remove_ipv6_hostfwd(Slirp *slirp, int is_udp,
> +                              struct in6_addr host_addr, int host_port)

Similarly, we'd rather share the code than duplicate it :)

Better put the existing slirp_remove_hostfwd code into a

slirp_remove_x_hostfwd(Slirp *slirp, int is_udp, struct sockaddr *addr)

by replacing the explicit ipv4 comparison with a call to a helper
which compares two struct sockaddr (starting with the so_family field,
then testing fields depending the family, and you can put it in
slirp/socket.h)

and then slirp_remove_hostfwd can be rewritten as putting its
parameters into a sockaddr_in and colling slirp_remove_x_hostfwd, and
slirp_remove_ipv6_hostfwd implemented similarly for ipv6.

> +int slirp_add_ipv6_hostfwd(Slirp *slirp, int is_udp,
> +                          struct in6_addr host_addr, int host_port,
> +                          struct in6_addr guest_addr, int guest_port)
> +{
> +    if (is_udp) {
> +        if (!udp6_listen(slirp, host_addr, htons(host_port),
> +                         guest_addr, htons(guest_port), SS_HOSTFWD))
> +            return -1;
> +    } else {
> +        if (!tcp6_listen(slirp, host_addr, htons(host_port),
> +                         guest_addr, htons(guest_port), SS_HOSTFWD))
> +            return -1;
> +    }
> +
> +    return 0;
> +}

That one can remains so :)

Samuel

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

* Re: [Qemu-devel] [PATCH RFC 4/4] net/slirp: add ipv6-hostfwd option for user netdev type
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 4/4] net/slirp: add ipv6-hostfwd option for user netdev type Maxim Samoylov
  2018-10-26  6:14   ` Thomas Huth
@ 2018-10-27 11:38   ` Samuel Thibault
  2018-11-05 23:05   ` Eric Blake
  2 siblings, 0 replies; 15+ messages in thread
From: Samuel Thibault @ 2018-10-27 11:38 UTC (permalink / raw)
  To: Maxim Samoylov; +Cc: qemu-devel

Maxim Samoylov, le ven. 26 oct. 2018 03:03:43 +0300, a ecrit:
> +void hmp_ipv6_hostfwd_remove(Monitor *mon, const QDict *qdict)
> +{

Similarly, a lot can be shared, by introducing 

const char *hmp_hostfwd_lookup(Monitor *mon, const QDict *qdict, int is_v6)

which will contain all the lookup and tcp/udp parsing part, and
just return the src_str (is_v6 to avoid testing only arg1).
hmp_hostfwd_remove and hmp_ipv6_hostfwd_remove can then just start by
calling it and get src_str that it can then use to parse the IPs.

> +    struct in6_addr host_addr = in6addr_any;
> +    if (*(p++) != '[') {
> +        goto fail_syntax;
> +    }

As mentioned, better explicit this in the helper message.

> +static int slirp_ipv6_hostfwd(SlirpState *s, const char *redir_str,
> +                              Error **errp)

For this one I wouldn't bother factorizing, though.

Samuel

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

* Re: [Qemu-devel] [PATCH RFC 1/4] slirp: add helper for tcp6 socket creation
  2018-10-27 11:11   ` Samuel Thibault
  2018-10-27 11:13     ` Samuel Thibault
@ 2018-10-30 13:58     ` Maxim Samoylov
  2018-10-30 16:00       ` Samuel Thibault
  1 sibling, 1 reply; 15+ messages in thread
From: Maxim Samoylov @ 2018-10-30 13:58 UTC (permalink / raw)
  To: Samuel Thibault; +Cc: qemu-devel



On 27.10.2018 14:11, Samuel Thibault wrote:
> Hello,
> 
> Thanks for working on this!
> 

Hi!

I preferred to make this RFC simple and straightforward
with dumb code duplication because I wasn't sure if the feature is
useful for upstream at all :)

I will then unify v4 and v6 implementations as you suggested
(for other patches in the series too) and post the re-spin.

> There is a lot of overlap with tcp_listen. It'd be much better to
> refactor it this way:
> 
> struct socket *
> tcpx_listen(Slirp *slirp, struct sockaddr *addr, socklen_t *addrlen, int flags)
> {
> 	... The current content of tcp_listen, with all heading and
> 	trailing addr manipulations removed...
> 	
> 	... so->so_lfamily = addr->sa_family;...
> 	... s = qemu_socket(addr->sa_family, SOCK_STREAM, 0);...
>          ... (bind(s, addr, *addrlen) < 0) ||...
> 	... getsockname(s, addr, addrlen);
> }
> 
> struct socket *
> tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
>             u_int lport, int flags)
> {
> 	struct sockaddr_in addr;
> 	struct socket *so;
> 	socklen_t addrsize = sizeof(addr);
> 
> 	addr.sin_family = AF_INET;
> 	addr.sin_addr.s_addr = haddr;
> 	addr.sin_port = hport;
> 
> 	so = tcpx_listen(slirp, (struct sockaddr *) &addr, &addrsize, flags);
> 
> 	so->so_lport = lport; /* Kept in network format */
> 	so->so_laddr.s_addr = laddr; /* Ditto */
> 
> 	so->so_ffamily = AF_INET;
> 	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 = slirp->vhost_addr;
> 	else
> 	   so->so_faddr = addr.sin_addr;
> }
> 
> The v6 version then boils down to
> 
> struct socket *
> tcp6_listen(Slirp *slirp, struct in6_addr haddr, u_int hport, struct
> 	    in6_addr laddr, u_int lport, int flags)
> {
> 	struct sockaddr_in6 addr;
> 	struct socket *so;
> 	socklen_t addrsize = sizeof(addr);
> 
> 	addr.sin6_family = AF_INET6;
> 	addr.sin6_addr = haddr;
> 	addr.sin6_port = hport;
> 
> 	so = tcpx_listen(slirp, (struct sockaddr *) &addr, &addrsize, flags);
> 
> 	so->so_lport6 = lport; /* Kept in network format */
> 	so->so_laddr6 = laddr; /* Ditto */
> 
> 	so->fhost.sin6 = addr;
> 	
> 	if (!memcmp(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)) ||
> 	    !memcmp(&addr.sin6_addr, &in6addr_loopback,
> 	            sizeof(in6addr_loopback))) {
> 	
> 	    memcpy(&so->so_faddr6, &slirp->vhost_addr6, sizeof(slirp->vhost_addr6));
> 	}
> }
> 
> modulo all typos etc. I may have done.
> 
> Maxim Samoylov, le ven. 26 oct. 2018 03:03:40 +0300, a ecrit:
>> +    qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
> 
> Is there a reason why you set SO_OOBINLINE, but not TCP_NODELAY? That's
> the kind of discrepancy we don't want to let unseen, thus the reason for
> a shared implementation :)

Actually my code was initially based on the last year master state, so I
missed your changes on TCP_NODELAY while rebasing, will fix.

> 
> Samuel
>

---
Maxim Samoylov, max7255@yandex-team.ru

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

* Re: [Qemu-devel] [PATCH RFC 4/4] net/slirp: add ipv6-hostfwd option for user netdev type
  2018-10-26  6:14   ` Thomas Huth
@ 2018-10-30 14:00     ` Maxim Samoylov
  0 siblings, 0 replies; 15+ messages in thread
From: Maxim Samoylov @ 2018-10-30 14:00 UTC (permalink / raw)
  To: Thomas Huth, qemu-devel; +Cc: Samuel Thibault



On 26.10.2018 09:14, Thomas Huth wrote:
> On 2018-10-26 01:03, Maxim Samoylov wrote:
>> This allows forwarding TCP6 and UDP6 connections down to
>> netdev=user connected guests.
>>
>> Signed-off-by: Maxim Samoylov <max7255@yandex-team.ru>
>> ---
>>   hmp-commands.hx     |  31 ++++++++
>>   include/net/slirp.h |   2 +
>>   net/slirp.c         | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   qapi/net.json       |   3 +-
>>   4 files changed, 249 insertions(+), 1 deletion(-)
>>
>> diff --git a/hmp-commands.hx b/hmp-commands.hx
>> index db0c681..b0e1a08 100644
>> --- a/hmp-commands.hx
>> +++ b/hmp-commands.hx
>> @@ -1448,6 +1448,37 @@ STEXI
>>   Remove host-to-guest TCP or UDP redirection.
>>   ETEXI
>>   
>> +#ifdef CONFIG_SLIRP
>> +    {
>> +        .name       = "ipv6_hostfwd_add",
>> +        .args_type  = "arg1:s,arg2:s?,arg3:s?",
>> +        .params     = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr6]:hostport-guestaddr6:guestport",
>> +        .help       = "redirect TCP6 or UDP6 connections from host to guest (requires -net user)",
>> +        .cmd        = hmp_ipv6_hostfwd_add,
>> +    },
>> +#endif
>> +STEXI
>> +@item hostfwd_add
>> +@findex hostfwd_add
>> +Redirect TCP6 or UDP6 connections from host to guest (requires -net user).
>> +ETEXI
>> +
>> +#ifdef CONFIG_SLIRP
>> +    {
>> +        .name       = "ipv6_hostfwd_remove",
>> +        .args_type  = "arg1:s,arg2:s?,arg3:s?",
>> +        .params     = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr6]:hostport",
>> +        .help       = "remove host-to-guest TCP6 or UDP6 redirection",
>> +        .cmd        = hmp_ipv6_hostfwd_remove,
>> +    },
> 
>   Hi,
> 
> could you please remove the "[hub_id name]" touple here? I recently sent
> a patch to deprecate it for the IPv4 version, too:
> 
> https://lists.gnu.org/archive/html/qemu-devel/2018-09/msg03198.html
> 

Ok

> Also I think it would make sense if you mention in the help text that
> IPv6 addresses have to be given with square brackets?
> 
>   Thanks,
>    Thomas
>

Sure, missed that thing.

---
Maxim Samoylov, max7255@yandex-team.ru

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

* Re: [Qemu-devel] [PATCH RFC 1/4] slirp: add helper for tcp6 socket creation
  2018-10-30 13:58     ` Maxim Samoylov
@ 2018-10-30 16:00       ` Samuel Thibault
  0 siblings, 0 replies; 15+ messages in thread
From: Samuel Thibault @ 2018-10-30 16:00 UTC (permalink / raw)
  To: Maxim Samoylov; +Cc: qemu-devel

Maxim Samoylov, le mar. 30 oct. 2018 16:58:17 +0300, a ecrit:
> On 27.10.2018 14:11, Samuel Thibault wrote:
> > Is there a reason why you set SO_OOBINLINE, but not TCP_NODELAY? That's
> > the kind of discrepancy we don't want to let unseen, thus the reason for
> > a shared implementation :)
> 
> Actually my code was initially based on the last year master state, so I
> missed your changes on TCP_NODELAY while rebasing

Which shows why it's useful to share the code :)

Samuel

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

* Re: [Qemu-devel] [PATCH RFC 4/4] net/slirp: add ipv6-hostfwd option for user netdev type
  2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 4/4] net/slirp: add ipv6-hostfwd option for user netdev type Maxim Samoylov
  2018-10-26  6:14   ` Thomas Huth
  2018-10-27 11:38   ` Samuel Thibault
@ 2018-11-05 23:05   ` Eric Blake
  2 siblings, 0 replies; 15+ messages in thread
From: Eric Blake @ 2018-11-05 23:05 UTC (permalink / raw)
  To: Maxim Samoylov, qemu-devel

On 10/25/18 7:03 PM, Maxim Samoylov wrote:
> This allows forwarding TCP6 and UDP6 connections down to
> netdev=user connected guests.
> 
> Signed-off-by: Maxim Samoylov <max7255@yandex-team.ru>
> ---
>   hmp-commands.hx     |  31 ++++++++
>   include/net/slirp.h |   2 +
>   net/slirp.c         | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>   qapi/net.json       |   3 +-
>   4 files changed, 249 insertions(+), 1 deletion(-)

> +++ b/qapi/net.json
> @@ -201,7 +201,8 @@
>       '*smbserver': 'str',
>       '*hostfwd':   ['String'],
>       '*guestfwd':  ['String'],
> -    '*tftp-server-name': 'str' } }
> +    '*tftp-server-name': 'str',
> +    '*ipv6-hostfwd': ['String']} }

Missing documentation of the new member.  Don't forget a '(since 3.1)' 
comment (if this is still appropriate for the current release; which may 
be doubtful since we are in soft freeze, in which case it will be 3.2 or 
4.0, depending on what the next release is numbered).

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org

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

end of thread, other threads:[~2018-11-05 23:12 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-26  0:03 [Qemu-devel] [PATCH RFC 0/4] slirp: support hostfwd for ipv6 addresses Maxim Samoylov
2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 1/4] slirp: add helper for tcp6 socket creation Maxim Samoylov
2018-10-27 11:11   ` Samuel Thibault
2018-10-27 11:13     ` Samuel Thibault
2018-10-30 13:58     ` Maxim Samoylov
2018-10-30 16:00       ` Samuel Thibault
2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 2/4] slirp: add helper for udp6 " Maxim Samoylov
2018-10-27 11:13   ` Samuel Thibault
2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 3/4] slirp: add helpers for ipv6 hostfwd manipulation Maxim Samoylov
2018-10-27 11:23   ` Samuel Thibault
2018-10-26  0:03 ` [Qemu-devel] [PATCH RFC 4/4] net/slirp: add ipv6-hostfwd option for user netdev type Maxim Samoylov
2018-10-26  6:14   ` Thomas Huth
2018-10-30 14:00     ` Maxim Samoylov
2018-10-27 11:38   ` Samuel Thibault
2018-11-05 23:05   ` Eric Blake

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).