All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/17] Net patches
@ 2016-02-02  2:36 Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 01/17] net/slirp: Tell the users when they are using deprecated options Jason Wang
                   ` (17 more replies)
  0 siblings, 18 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Jason Wang

The following changes since commit 0430891ce162b986c6e02a7729a942ecd2a32ca4:

  hw: Clean up includes (2016-01-29 15:07:25 +0000)

are available in the git repository at:

  https://github.com/jasowang/qemu.git tags/net-pull-request

for you to fetch changes up to e8a7a1a574ed6728422959c8aa79ca584cdd1d4d:

  net/filter: Fix the output information for command 'info network' (2016-02-02 10:21:28 +0800)

----------------------------------------------------------------

Major changes for net:

- preparation for ipv6 support in slirp
- fix tx infinite loops of e1000
- fix cadence_gem buffer overflow
- rx netfilter were gone in reverse for future complex netfilter setups

----------------------------------------------------------------
Guillaume Subiron (9):
      slirp: goto bad in udp_input if sosendto fails
      slirp: Generalizing and neutralizing ARP code
      slirp: Adding address family switch for produced frames
      slirp: Make Socket structure IPv6 compatible
      slirp: Factorizing address translation
      slirp: Factorizing and cleaning solookup()
      slirp: Add sockaddr_equal, make solookup family-agnostic
      slirp: Make udp_attach IPv6 compatible
      slirp: Adding family argument to tcp_fconnect()

Laszlo Ersek (1):
      e1000: eliminate infinite loops on out-of-bounds transfer start

Li Zhijian (1):
      net: always walk through filters in reverse if traffic is egress

Michael S. Tsirkin (1):
      cadence_gem: fix buffer overflow

Prasad J Pandit (1):
      net: cadence_gem: check packet size in gem_recieve

Thomas Huth (2):
      net/slirp: Tell the users when they are using deprecated options
      qemu-doc: Do not promote deprecated -smb and -redir options

Vincenzo Maffione (1):
      net: netmap: use nm_open() to open netmap ports

zhanghailiang (1):
      net/filter: Fix the output information for command 'info network'

 hw/net/cadence_gem.c |  12 ++++
 hw/net/e1000.c       |   6 +-
 include/net/filter.h |   1 -
 include/net/net.h    |   2 +-
 net/filter.c         |  43 +++++++-------
 net/net.c            |  52 ++++++++++++++---
 net/netmap.c         |  97 +++++++++++--------------------
 net/slirp.c          |   3 +
 os-posix.c           |   3 +
 qemu-doc.texi        |   9 +--
 slirp/bootp.c        |   2 +-
 slirp/ip_icmp.c      |  23 +++-----
 slirp/mbuf.c         |   2 +-
 slirp/mbuf.h         |   2 +-
 slirp/slirp.c        | 116 +++++++++++++++++++++++++++++--------
 slirp/slirp.h        |   2 +-
 slirp/socket.c       | 158 ++++++++++++++++++++++++++++++++++++++-------------
 slirp/socket.h       |  49 ++++++++++++++--
 slirp/tcp_input.c    |  30 +++++-----
 slirp/tcp_subr.c     |  40 ++++---------
 slirp/tftp.c         |   6 +-
 slirp/udp.c          |  74 +++++++-----------------
 slirp/udp.h          |   5 +-
 vl.c                 |   6 ++
 24 files changed, 445 insertions(+), 298 deletions(-)

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

* [Qemu-devel] [PULL 01/17] net/slirp: Tell the users when they are using deprecated options
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 02/17] qemu-doc: Do not promote deprecated -smb and -redir options Jason Wang
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Thomas Huth, Jason Wang

From: Thomas Huth <thuth@redhat.com>

We don't want to support the legacy -tftp, -bootp, -smb and
-net channel options forever. So let's start telling the users
that they are deprecated and what option should be used instead.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 net/slirp.c | 3 +++
 os-posix.c  | 3 +++
 vl.c        | 6 ++++++
 3 files changed, 12 insertions(+)

diff --git a/net/slirp.c b/net/slirp.c
index f505570..eac4fc2 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -784,6 +784,9 @@ int net_slirp_parse_legacy(QemuOptsList *opts_list, const char *optarg, int *ret
         return 0;
     }
 
+    error_report("The '-net channel' option is deprecated. "
+                 "Please use '-netdev user,guestfwd=...' instead.");
+
     /* handle legacy -net channel,port:chr */
     optarg += strlen("channel,");
 
diff --git a/os-posix.c b/os-posix.c
index e4da406..87e2a16 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -40,6 +40,7 @@
 #include "net/slirp.h"
 #include "qemu-options.h"
 #include "qemu/rcu.h"
+#include "qemu/error-report.h"
 
 #ifdef CONFIG_LINUX
 #include <sys/prctl.h>
@@ -139,6 +140,8 @@ void os_parse_cmd_args(int index, const char *optarg)
     switch (index) {
 #ifdef CONFIG_SLIRP
     case QEMU_OPTION_smb:
+        error_report("The -smb option is deprecated. "
+                     "Please use '-netdev user,smb=...' instead.");
         if (net_slirp_smb(optarg) < 0)
             exit(1);
         break;
diff --git a/vl.c b/vl.c
index f043009..a12eabe 100644
--- a/vl.c
+++ b/vl.c
@@ -3308,12 +3308,18 @@ int main(int argc, char **argv, char **envp)
 #endif
 #ifdef CONFIG_SLIRP
             case QEMU_OPTION_tftp:
+                error_report("The -tftp option is deprecated. "
+                             "Please use '-netdev user,tftp=...' instead.");
                 legacy_tftp_prefix = optarg;
                 break;
             case QEMU_OPTION_bootp:
+                error_report("The -bootp option is deprecated. "
+                             "Please use '-netdev user,bootfile=...' instead.");
                 legacy_bootp_filename = optarg;
                 break;
             case QEMU_OPTION_redir:
+                error_report("The -redir option is deprecated. "
+                             "Please use '-netdev user,hostfwd=...' instead.");
                 if (net_slirp_redir(optarg) < 0)
                     exit(1);
                 break;
-- 
2.5.0

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

* [Qemu-devel] [PULL 02/17] qemu-doc: Do not promote deprecated -smb and -redir options
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 01/17] net/slirp: Tell the users when they are using deprecated options Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 03/17] net: cadence_gem: check packet size in gem_recieve Jason Wang
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Thomas Huth, Jason Wang

From: Thomas Huth <thuth@redhat.com>

Since -smb and -redir are deprecated options, we should not
use them as examples in the documentation anymore.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 qemu-doc.texi | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/qemu-doc.texi b/qemu-doc.texi
index ca4d9de..212aba3 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -1237,9 +1237,9 @@ echo 100 100 > /proc/sys/net/ipv4/ping_group_range
 When using the built-in TFTP server, the router is also the TFTP
 server.
 
-When using the @option{-redir} option, TCP or UDP connections can be
-redirected from the host to the guest. It allows for example to
-redirect X11, telnet or SSH connections.
+When using the @option{'-netdev user,hostfwd=...'} option, TCP or UDP
+connections can be redirected from the host to the guest. It allows for
+example to redirect X11, telnet or SSH connections.
 
 @subsection Connecting VLANs between QEMU instances
 
@@ -1889,7 +1889,8 @@ correctly instructs QEMU to shutdown at the appropriate moment.
 
 @subsubsection Share a directory between Unix and Windows
 
-See @ref{sec_invocation} about the help of the option @option{-smb}.
+See @ref{sec_invocation} about the help of the option
+@option{'-netdev user,smb=...'}.
 
 @subsubsection Windows XP security problem
 
-- 
2.5.0

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

* [Qemu-devel] [PULL 03/17] net: cadence_gem: check packet size in gem_recieve
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 01/17] net/slirp: Tell the users when they are using deprecated options Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 02/17] qemu-doc: Do not promote deprecated -smb and -redir options Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 04/17] cadence_gem: fix buffer overflow Jason Wang
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Jason Wang, Prasad J Pandit

From: Prasad J Pandit <pjp@fedoraproject.org>

While receiving packets in 'gem_receive' routine, if Frame Check
Sequence(FCS) is enabled, it copies the packet into a local
buffer without checking its size. Add check to validate packet
length against the buffer size to avoid buffer overflow.

Reported-by: Ling Liu <liuling-it@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 hw/net/cadence_gem.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index f9e4091..e513d9d 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -678,6 +678,10 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
     } else {
         unsigned crc_val;
 
+        if (size > sizeof(rxbuf) - sizeof(crc_val)) {
+            size = sizeof(rxbuf) - sizeof(crc_val);
+        }
+        bytes_to_copy = size;
         /* The application wants the FCS field, which QEMU does not provide.
          * We must try and calculate one.
          */
-- 
2.5.0

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

* [Qemu-devel] [PULL 04/17] cadence_gem: fix buffer overflow
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (2 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 03/17] net: cadence_gem: check packet size in gem_recieve Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 05/17] slirp: goto bad in udp_input if sosendto fails Jason Wang
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Jason Wang, Michael S. Tsirkin

From: "Michael S. Tsirkin" <mst@redhat.com>

gem_transmit copies a packet from guest into an tx_packet[2048]
array on stack, with size limited by descriptor length set by guest.  If
guest is malicious and specifies a descriptor length that is too large,
and should packet size exceed array size, this results in a buffer
overflow.

Reported-by: 刘令 <liuling-it@360.cn>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 hw/net/cadence_gem.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index e513d9d..0346f3e 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -867,6 +867,14 @@ static void gem_transmit(CadenceGEMState *s)
             break;
         }
 
+        if (tx_desc_get_length(desc) > sizeof(tx_packet) - (p - tx_packet)) {
+            DB_PRINT("TX descriptor @ 0x%x too large: size 0x%x space 0x%x\n",
+                     (unsigned)packet_desc_addr,
+                     (unsigned)tx_desc_get_length(desc),
+                     sizeof(tx_packet) - (p - tx_packet));
+            break;
+        }
+
         /* Gather this fragment of the packet from "dma memory" to our contig.
          * buffer.
          */
-- 
2.5.0

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

* [Qemu-devel] [PULL 05/17] slirp: goto bad in udp_input if sosendto fails
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (3 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 04/17] cadence_gem: fix buffer overflow Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 06/17] slirp: Generalizing and neutralizing ARP code Jason Wang
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Samuel Thibault, Jason Wang, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

Before this patch, if sosendto fails, udp_input is executed as if the
packet was sent, recording the packet for icmp errors, which does not
makes sense since the packet was not actually sent, errors would be
related to a previous packet.

This patch adds a goto bad to cut the execution of this function.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 slirp/udp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/slirp/udp.c b/slirp/udp.c
index fee13b4..ce63414 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -218,6 +218,7 @@ udp_input(register struct mbuf *m, int iphlen)
 	  *ip=save_ip;
 	  DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
 	  icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
+	  goto bad;
 	}
 
 	m_free(so->so_m);   /* used for ICMP if error on sorecvfrom */
-- 
2.5.0

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

* [Qemu-devel] [PULL 06/17] slirp: Generalizing and neutralizing ARP code
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (4 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 05/17] slirp: goto bad in udp_input if sosendto fails Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 07/17] slirp: Adding address family switch for produced frames Jason Wang
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Samuel Thibault, Jason Wang, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

Basically, this patch replaces "arp" by "resolution" every time "arp"
means "mac resolution" and not specifically ARP.

This prepares for IPv6 support.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 slirp/mbuf.c  | 2 +-
 slirp/mbuf.h  | 2 +-
 slirp/slirp.c | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/slirp/mbuf.c b/slirp/mbuf.c
index 795fc29..bc942b6 100644
--- a/slirp/mbuf.c
+++ b/slirp/mbuf.c
@@ -91,7 +91,7 @@ m_get(Slirp *slirp)
 	m->m_len = 0;
         m->m_nextpkt = NULL;
         m->m_prevpkt = NULL;
-        m->arp_requested = false;
+        m->resolution_requested = false;
         m->expiration_date = (uint64_t)-1;
 end_error:
 	DEBUG_ARG("m = %p", m);
diff --git a/slirp/mbuf.h b/slirp/mbuf.h
index b144f1c..38fedf4 100644
--- a/slirp/mbuf.h
+++ b/slirp/mbuf.h
@@ -79,7 +79,7 @@ struct mbuf {
 	int	m_len;			/* Amount of data in this mbuf */
 
 	Slirp *slirp;
-	bool	arp_requested;
+	bool	resolution_requested;
 	uint64_t expiration_date;
 	/* start of dynamic buffer area, must be last element */
 	union {
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 35f819a..1d5d172 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -786,7 +786,7 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
         struct ethhdr *reh = (struct ethhdr *)arp_req;
         struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
 
-        if (!ifm->arp_requested) {
+        if (!ifm->resolution_requested) {
             /* If the client addr is not known, send an ARP request */
             memset(reh->h_dest, 0xff, ETH_ALEN);
             memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
@@ -812,7 +812,7 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
             rah->ar_tip = iph->ip_dst.s_addr;
             slirp->client_ipaddr = iph->ip_dst;
             slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
-            ifm->arp_requested = true;
+            ifm->resolution_requested = true;
 
             /* Expire request and drop outgoing packet after 1 second */
             ifm->expiration_date = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 1000000000ULL;
-- 
2.5.0

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

* [Qemu-devel] [PULL 07/17] slirp: Adding address family switch for produced frames
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (5 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 06/17] slirp: Generalizing and neutralizing ARP code Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 08/17] slirp: Make Socket structure IPv6 compatible Jason Wang
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Samuel Thibault, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

In if_encap, a switch is added to prepare for the IPv6 case. Some code
is factorized.

This prepares for IPv6 support.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 slirp/slirp.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 48 insertions(+), 13 deletions(-)

diff --git a/slirp/slirp.c b/slirp/slirp.c
index 1d5d172..f8dc505 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -762,20 +762,15 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
     }
 }
 
-/* Output the IP packet to the ethernet device. Returns 0 if the packet must be
- * re-queued.
+/* Prepare the IPv4 packet to be sent to the ethernet device. Returns 1 if no
+ * packet should be sent, 0 if the packet must be re-queued, 2 if the packet
+ * is ready to go.
  */
-int if_encap(Slirp *slirp, struct mbuf *ifm)
+static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
+        uint8_t ethaddr[ETH_ALEN])
 {
-    uint8_t buf[1600];
-    struct ethhdr *eh = (struct ethhdr *)buf;
-    uint8_t ethaddr[ETH_ALEN];
     const struct ip *iph = (const struct ip *)ifm->m_data;
 
-    if (ifm->m_len + ETH_HLEN > sizeof(buf)) {
-        return 1;
-    }
-
     if (iph->ip_dst.s_addr == 0) {
         /* 0.0.0.0 can not be a destination address, something went wrong,
          * avoid making it worse */
@@ -819,15 +814,55 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
         }
         return 0;
     } else {
-        memcpy(eh->h_dest, ethaddr, ETH_ALEN);
         memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
         /* XXX: not correct */
         memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
         eh->h_proto = htons(ETH_P_IP);
-        memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
-        slirp_output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
+
+        /* Send this */
+        return 2;
+    }
+}
+
+/* Output the IP packet to the ethernet device. Returns 0 if the packet must be
+ * re-queued.
+ */
+int if_encap(Slirp *slirp, struct mbuf *ifm)
+{
+    uint8_t buf[1600];
+    struct ethhdr *eh = (struct ethhdr *)buf;
+    uint8_t ethaddr[ETH_ALEN];
+    const struct ip *iph = (const struct ip *)ifm->m_data;
+    int ret;
+
+    if (ifm->m_len + ETH_HLEN > sizeof(buf)) {
         return 1;
     }
+
+    switch (iph->ip_v) {
+    case IPVERSION:
+        ret = if_encap4(slirp, ifm, eh, ethaddr);
+        if (ret < 2) {
+            return ret;
+        }
+        break;
+
+    default:
+        /* Do not assert while we don't manage IP6VERSION */
+        /* assert(0); */
+        break;
+    }
+
+    memcpy(eh->h_dest, ethaddr, ETH_ALEN);
+    DEBUG_ARGS((dfd, " src = %02x:%02x:%02x:%02x:%02x:%02x\n",
+                eh->h_source[0], eh->h_source[1], eh->h_source[2],
+                eh->h_source[3], eh->h_source[4], eh->h_source[5]));
+    DEBUG_ARGS((dfd, " dst = %02x:%02x:%02x:%02x:%02x:%02x\n",
+                eh->h_dest[0], eh->h_dest[1], eh->h_dest[2],
+                eh->h_dest[3], eh->h_dest[4], eh->h_dest[5]));
+    memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
+    slirp_output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
+    return 1;
 }
 
 /* Drop host forwarding rule, return 0 if found. */
-- 
2.5.0

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

* [Qemu-devel] [PULL 08/17] slirp: Make Socket structure IPv6 compatible
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (6 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 07/17] slirp: Adding address family switch for produced frames Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 09/17] slirp: Factorizing address translation Jason Wang
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Samuel Thibault, Jason Wang, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

This patch replaces foreign and local address/port couples in Socket
structure by 2 sockaddr_storage which can be casted in sockaddr_in.
Direct access to address and port is still possible thanks to some
\#define, so retrocompatibility of the existing code is assured.

The ss_family field of sockaddr_storage is declared after each socket
creation.

The whole structure is also saved/restored when a Qemu session is
saved/restored.

This prepares for IPv6 support.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 slirp/ip_icmp.c   |  2 ++
 slirp/slirp.c     | 51 ++++++++++++++++++++++++++++++++++++++++++---------
 slirp/socket.c    | 14 +++++++++++---
 slirp/socket.h    | 19 +++++++++++++++----
 slirp/tcp_input.c |  2 ++
 slirp/tcp_subr.c  |  2 ++
 slirp/udp.c       |  4 ++++
 7 files changed, 78 insertions(+), 16 deletions(-)

diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 23b9f0f..58b7ceb 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -170,8 +170,10 @@ icmp_input(struct mbuf *m, int hlen)
 	goto end_error;
       }
       so->so_m = m;
+      so->so_ffamily = AF_INET;
       so->so_faddr = ip->ip_dst;
       so->so_fport = htons(7);
+      so->so_lfamily = AF_INET;
       so->so_laddr = ip->ip_src;
       so->so_lport = htons(9);
       so->so_iptos = ip->ip_tos;
diff --git a/slirp/slirp.c b/slirp/slirp.c
index f8dc505..b900775 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -23,6 +23,7 @@
  */
 #include "qemu-common.h"
 #include "qemu/timer.h"
+#include "qemu/error-report.h"
 #include "sysemu/char.h"
 #include "slirp.h"
 #include "hw/hw.h"
@@ -234,7 +235,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
 
     slirp->opaque = opaque;
 
-    register_savevm(NULL, "slirp", 0, 3,
+    register_savevm(NULL, "slirp", 0, 4,
                     slirp_state_save, slirp_state_load, slirp);
 
     QTAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
@@ -1046,10 +1047,26 @@ static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
 static void slirp_socket_save(QEMUFile *f, struct socket *so)
 {
     qemu_put_be32(f, so->so_urgc);
-    qemu_put_be32(f, so->so_faddr.s_addr);
-    qemu_put_be32(f, so->so_laddr.s_addr);
-    qemu_put_be16(f, so->so_fport);
-    qemu_put_be16(f, so->so_lport);
+    qemu_put_be16(f, so->so_ffamily);
+    switch (so->so_ffamily) {
+    case AF_INET:
+        qemu_put_be32(f, so->so_faddr.s_addr);
+        qemu_put_be16(f, so->so_fport);
+        break;
+    default:
+        error_report(
+                "so_ffamily unknown, unable to save so_faddr and so_fport\n");
+    }
+    qemu_put_be16(f, so->so_lfamily);
+    switch (so->so_lfamily) {
+    case AF_INET:
+        qemu_put_be32(f, so->so_laddr.s_addr);
+        qemu_put_be16(f, so->so_lport);
+        break;
+    default:
+        error_report(
+                "so_ffamily unknown, unable to save so_laddr and so_lport\n");
+    }
     qemu_put_byte(f, so->so_iptos);
     qemu_put_byte(f, so->so_emu);
     qemu_put_byte(f, so->so_type);
@@ -1169,10 +1186,26 @@ static int slirp_socket_load(QEMUFile *f, struct socket *so)
         return -ENOMEM;
 
     so->so_urgc = qemu_get_be32(f);
-    so->so_faddr.s_addr = qemu_get_be32(f);
-    so->so_laddr.s_addr = qemu_get_be32(f);
-    so->so_fport = qemu_get_be16(f);
-    so->so_lport = qemu_get_be16(f);
+    so->so_ffamily = qemu_get_be16(f);
+    switch (so->so_ffamily) {
+    case AF_INET:
+        so->so_faddr.s_addr = qemu_get_be32(f);
+        so->so_fport = qemu_get_be16(f);
+        break;
+    default:
+        error_report(
+                "so_ffamily unknown, unable to restore so_faddr and so_lport\n");
+    }
+    so->so_lfamily = qemu_get_be16(f);
+    switch (so->so_lfamily) {
+    case AF_INET:
+        so->so_laddr.s_addr = qemu_get_be32(f);
+        so->so_lport = qemu_get_be16(f);
+        break;
+    default:
+        error_report(
+                "so_ffamily unknown, unable to restore so_laddr and so_lport\n");
+    }
     so->so_iptos = qemu_get_byte(f);
     so->so_emu = qemu_get_byte(f);
     so->so_type = qemu_get_byte(f);
diff --git a/slirp/socket.c b/slirp/socket.c
index 1673e3a..bf603c9 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -437,8 +437,8 @@ sowrite(struct socket *so)
 void
 sorecvfrom(struct socket *so)
 {
-	struct sockaddr_in addr;
-	socklen_t addrlen = sizeof(struct sockaddr_in);
+	struct sockaddr_storage addr;
+	socklen_t addrlen = sizeof(struct sockaddr_storage);
 
 	DEBUG_CALL("sorecvfrom");
 	DEBUG_ARG("so = %p", so);
@@ -527,7 +527,13 @@ sorecvfrom(struct socket *so)
 	     * If this packet was destined for CTL_ADDR,
 	     * make it look like that's where it came from, done by udp_output
 	     */
-	    udp_output(so, m, &addr);
+	    switch (so->so_ffamily) {
+	    case AF_INET:
+	        udp_output(so, m, (struct sockaddr_in *) &addr);
+	        break;
+	    default:
+	        break;
+	    }
 	  } /* rx error */
 	} /* if ping packet */
 }
@@ -619,6 +625,7 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 
 	so->so_state &= SS_PERSISTENT_MASK;
 	so->so_state |= (SS_FACCEPTCONN | flags);
+	so->so_lfamily = AF_INET;
 	so->so_lport = lport; /* Kept in network format */
 	so->so_laddr.s_addr = laddr; /* Ditto */
 
@@ -645,6 +652,7 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 	qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
 
 	getsockname(s,(struct sockaddr *)&addr,&addrlen);
+	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;
diff --git a/slirp/socket.h b/slirp/socket.h
index 57e0407..e854903 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -31,10 +31,21 @@ struct socket {
   struct tcpiphdr *so_ti;	   /* Pointer to the original ti within
 				    * so_mconn, for non-blocking connections */
   int so_urgc;
-  struct in_addr so_faddr;	   /* foreign host table entry */
-  struct in_addr so_laddr;	   /* local host table entry */
-  uint16_t so_fport;		   /* foreign port */
-  uint16_t so_lport;		   /* local port */
+  union {   /* foreign host */
+      struct sockaddr_storage ss;
+      struct sockaddr_in sin;
+  } fhost;
+#define so_faddr fhost.sin.sin_addr
+#define so_fport fhost.sin.sin_port
+#define so_ffamily fhost.ss.ss_family
+
+  union {   /* local host */
+      struct sockaddr_storage ss;
+      struct sockaddr_in sin;
+  } lhost;
+#define so_laddr lhost.sin.sin_addr
+#define so_lport lhost.sin.sin_port
+#define so_lfamily lhost.ss.ss_family
 
   uint8_t	so_iptos;	/* Type of service */
   uint8_t	so_emu;		/* Is the socket emulated? */
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 6b096ec..4c3191d 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -374,8 +374,10 @@ findso:
 	  sbreserve(&so->so_snd, TCP_SNDSPACE);
 	  sbreserve(&so->so_rcv, TCP_RCVSPACE);
 
+	  so->so_lfamily = AF_INET;
 	  so->so_laddr = ti->ti_src;
 	  so->so_lport = ti->ti_sport;
+	  so->so_ffamily = AF_INET;
 	  so->so_faddr = ti->ti_dst;
 	  so->so_fport = ti->ti_dport;
 
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index e161ed2..47262db 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -413,6 +413,7 @@ void tcp_connect(struct socket *inso)
             free(so); /* NOT sofree */
             return;
         }
+        so->so_lfamily = AF_INET;
         so->so_laddr = inso->so_laddr;
         so->so_lport = inso->so_lport;
     }
@@ -430,6 +431,7 @@ void tcp_connect(struct socket *inso)
     qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
     socket_set_nodelay(s);
 
+    so->so_ffamily = AF_INET;
     so->so_fport = addr.sin_port;
     so->so_faddr = addr.sin_addr;
     /* Translate connections from localhost to the real hostname */
diff --git a/slirp/udp.c b/slirp/udp.c
index ce63414..7a5c95b 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -190,6 +190,7 @@ udp_input(register struct mbuf *m, int iphlen)
 	  /*
 	   * Setup fields
 	   */
+	  so->so_lfamily = AF_INET;
 	  so->so_laddr = ip->ip_src;
 	  so->so_lport = uh->uh_sport;
 
@@ -202,6 +203,7 @@ udp_input(register struct mbuf *m, int iphlen)
 	   */
 	}
 
+        so->so_ffamily = AF_INET;
         so->so_faddr = ip->ip_dst; /* XXX */
         so->so_fport = uh->uh_dport; /* XXX */
 
@@ -376,6 +378,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 	socket_set_fast_reuse(so->s);
 
 	getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
+	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) {
@@ -383,6 +386,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 	} else {
 	   so->so_faddr = addr.sin_addr;
 	}
+	so->so_lfamily = AF_INET;
 	so->so_lport = lport;
 	so->so_laddr.s_addr = laddr;
 	if (flags != SS_FACCEPTONCE)
-- 
2.5.0

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

* [Qemu-devel] [PULL 09/17] slirp: Factorizing address translation
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (7 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 08/17] slirp: Make Socket structure IPv6 compatible Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 10/17] slirp: Factorizing and cleaning solookup() Jason Wang
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Samuel Thibault, Jason Wang, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

This patch factorizes some duplicate code into a new function,
sotranslate_out(). This function perform the address translation when a
packet is transmitted to the host network. If the packet is destinated
to the host, the loopback address is used, and if the packet is
destinated to the virtual DNS, the real DNS address is used. This code
is just a copy of the existent, but factorized and ready to manage the
IPv6 case.

On the same model, the major part of udp_output() code is moved into a
new sotranslate_in(). This function is directly used in sorecvfrom(),
like sotranslate_out() in sosendto().
udp_output() becoming useless, it is removed and udp_output2() is
renamed into udp_output(). This adds consistency with the udp6_output()
function introduced by further patches.

Lastly, this factorizes some duplicate code into sotranslate_accept(), which
performs the address translation when a connection is established on the host
for port forwarding: if it comes from localhost, the host virtual address is
used instead.

This prepares for IPv6 support.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 slirp/bootp.c    |   2 +-
 slirp/ip_icmp.c  |  19 ++--------
 slirp/socket.c   | 112 +++++++++++++++++++++++++++++++++++++++++++++----------
 slirp/socket.h   |   5 +++
 slirp/tcp_subr.c |  35 ++++-------------
 slirp/tftp.c     |   6 +--
 slirp/udp.c      |  37 ++----------------
 slirp/udp.h      |   3 +-
 8 files changed, 116 insertions(+), 103 deletions(-)

diff --git a/slirp/bootp.c b/slirp/bootp.c
index 1baaab1..0027279 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -325,7 +325,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
 
     m->m_len = sizeof(struct bootp_t) -
         sizeof(struct ip) - sizeof(struct udphdr);
-    udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+    udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
 }
 
 void bootp_input(struct mbuf *m)
diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 58b7ceb..3a29847 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -157,7 +157,7 @@ icmp_input(struct mbuf *m, int hlen)
         goto freeit;
     } else {
       struct socket *so;
-      struct sockaddr_in addr;
+      struct sockaddr_storage addr;
       if ((so = socreate(slirp)) == NULL) goto freeit;
       if (icmp_send(so, m, hlen) == 0) {
         return;
@@ -181,20 +181,9 @@ icmp_input(struct mbuf *m, int hlen)
       so->so_state = SS_ISFCONNECTED;
 
       /* Send the packet */
-      addr.sin_family = AF_INET;
-      if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
-          slirp->vnetwork_addr.s_addr) {
-	/* It's an alias */
-	if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
-	  if (get_dns_addr(&addr.sin_addr) < 0)
-	    addr.sin_addr = loopback_addr;
-	} else {
-	  addr.sin_addr = loopback_addr;
-	}
-      } else {
-	addr.sin_addr = so->so_faddr;
-      }
-      addr.sin_port = so->so_fport;
+      addr = so->fhost.ss;
+      sotranslate_out(so, &addr);
+
       if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,
 		(struct sockaddr *)&addr, sizeof(addr)) == -1) {
 	DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
diff --git a/slirp/socket.c b/slirp/socket.c
index bf603c9..d1034fb 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -438,6 +438,7 @@ void
 sorecvfrom(struct socket *so)
 {
 	struct sockaddr_storage addr;
+	struct sockaddr_storage saddr, daddr;
 	socklen_t addrlen = sizeof(struct sockaddr_storage);
 
 	DEBUG_CALL("sorecvfrom");
@@ -525,11 +526,17 @@ sorecvfrom(struct socket *so)
 
 	    /*
 	     * If this packet was destined for CTL_ADDR,
-	     * make it look like that's where it came from, done by udp_output
+	     * make it look like that's where it came from
 	     */
+	    saddr = addr;
+	    sotranslate_in(so, &saddr);
+	    daddr = so->lhost.ss;
+
 	    switch (so->so_ffamily) {
 	    case AF_INET:
-	        udp_output(so, m, (struct sockaddr_in *) &addr);
+	        udp_output(so, m, (struct sockaddr_in *) &saddr,
+	                   (struct sockaddr_in *) &daddr,
+	                   so->so_iptos);
 	        break;
 	    default:
 	        break;
@@ -544,33 +551,20 @@ sorecvfrom(struct socket *so)
 int
 sosendto(struct socket *so, struct mbuf *m)
 {
-	Slirp *slirp = so->slirp;
 	int ret;
-	struct sockaddr_in addr;
+	struct sockaddr_storage addr;
 
 	DEBUG_CALL("sosendto");
 	DEBUG_ARG("so = %p", so);
 	DEBUG_ARG("m = %p", m);
 
-        addr.sin_family = AF_INET;
-	if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
-	    slirp->vnetwork_addr.s_addr) {
-	  /* It's an alias */
-	  if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
-	    if (get_dns_addr(&addr.sin_addr) < 0)
-	      addr.sin_addr = loopback_addr;
-	  } else {
-	    addr.sin_addr = loopback_addr;
-	  }
-	} else
-	  addr.sin_addr = so->so_faddr;
-	addr.sin_port = so->so_fport;
-
-	DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
+	addr = so->fhost.ss;
+	DEBUG_CALL(" sendto()ing)");
+	sotranslate_out(so, &addr);
 
 	/* Don't care what port we get */
 	ret = sendto(so->s, m->m_data, m->m_len, 0,
-		     (struct sockaddr *)&addr, sizeof (struct sockaddr));
+		     (struct sockaddr *)&addr, sizeof(addr));
 	if (ret < 0)
 		return -1;
 
@@ -726,3 +720,81 @@ sofwdrain(struct socket *so)
 	else
 		sofcantsendmore(so);
 }
+
+/*
+ * Translate addr in host addr when it is a virtual address
+ */
+void sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
+{
+    Slirp *slirp = so->slirp;
+    struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+
+    switch (addr->ss_family) {
+    case AF_INET:
+        if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+                slirp->vnetwork_addr.s_addr) {
+            /* It's an alias */
+            if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
+                if (get_dns_addr(&sin->sin_addr) < 0) {
+                    sin->sin_addr = loopback_addr;
+                }
+            } else {
+                sin->sin_addr = loopback_addr;
+            }
+        }
+
+        DEBUG_MISC((dfd, " addr.sin_port=%d, "
+            "addr.sin_addr.s_addr=%.16s\n",
+            ntohs(sin->sin_port), inet_ntoa(sin->sin_addr)));
+        break;
+
+    default:
+        break;
+    }
+}
+
+void sotranslate_in(struct socket *so, struct sockaddr_storage *addr)
+{
+    Slirp *slirp = so->slirp;
+    struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+
+    switch (addr->ss_family) {
+    case AF_INET:
+        if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+            slirp->vnetwork_addr.s_addr) {
+            uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;
+
+            if ((so->so_faddr.s_addr & inv_mask) == inv_mask) {
+                sin->sin_addr = slirp->vhost_addr;
+            } else if (sin->sin_addr.s_addr == loopback_addr.s_addr ||
+                       so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
+                sin->sin_addr = so->so_faddr;
+            }
+        }
+        break;
+
+    default:
+        break;
+    }
+}
+
+/*
+ * Translate connections from localhost to the real hostname
+ */
+void sotranslate_accept(struct socket *so)
+{
+    Slirp *slirp = so->slirp;
+
+    switch (so->so_ffamily) {
+    case AF_INET:
+        if (so->so_faddr.s_addr == INADDR_ANY ||
+            (so->so_faddr.s_addr & loopback_mask) ==
+            (loopback_addr.s_addr & loopback_mask)) {
+           so->so_faddr = slirp->vhost_addr;
+        }
+        break;
+
+    default:
+        break;
+    }
+}
diff --git a/slirp/socket.h b/slirp/socket.h
index e854903..b27bbb2 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -105,4 +105,9 @@ struct iovec; /* For win32 */
 size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np);
 int soreadbuf(struct socket *so, const char *buf, int size);
 
+void sotranslate_out(struct socket *, struct sockaddr_storage *);
+void sotranslate_in(struct socket *, struct sockaddr_storage *);
+void sotranslate_accept(struct socket *);
+
+
 #endif /* _SOCKET_H_ */
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 47262db..76c716f 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -326,7 +326,6 @@ tcp_sockclosed(struct tcpcb *tp)
  */
 int tcp_fconnect(struct socket *so)
 {
-  Slirp *slirp = so->slirp;
   int ret=0;
 
   DEBUG_CALL("tcp_fconnect");
@@ -334,30 +333,17 @@ int tcp_fconnect(struct socket *so)
 
   if( (ret = so->s = qemu_socket(AF_INET,SOCK_STREAM,0)) >= 0) {
     int opt, s=so->s;
-    struct sockaddr_in addr;
+    struct sockaddr_storage addr;
 
     qemu_set_nonblock(s);
     socket_set_fast_reuse(s);
     opt = 1;
     qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
 
-    addr.sin_family = AF_INET;
-    if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
-        slirp->vnetwork_addr.s_addr) {
-      /* It's an alias */
-      if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
-	if (get_dns_addr(&addr.sin_addr) < 0)
-	  addr.sin_addr = loopback_addr;
-      } else {
-	addr.sin_addr = loopback_addr;
-      }
-    } else
-      addr.sin_addr = so->so_faddr;
-    addr.sin_port = so->so_fport;
-
-    DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, "
-		"addr.sin_addr.s_addr=%.16s\n",
-		ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
+    addr = so->fhost.ss;
+    DEBUG_CALL(" connect()ing")
+    sotranslate_out(so, &addr);
+
     /* We don't care what port we get */
     ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
 
@@ -431,15 +417,8 @@ void tcp_connect(struct socket *inso)
     qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
     socket_set_nodelay(s);
 
-    so->so_ffamily = AF_INET;
-    so->so_fport = addr.sin_port;
-    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_mask) ==
-        (loopback_addr.s_addr & loopback_mask)) {
-        so->so_faddr = slirp->vhost_addr;
-    }
+    so->fhost.sin = addr;
+    sotranslate_accept(so);
 
     /* Close the accept() socket, set right state */
     if (inso->so_state & SS_FACCEPTONCE) {
diff --git a/slirp/tftp.c b/slirp/tftp.c
index a329fb2..ccb6130 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -155,7 +155,7 @@ static int tftp_send_oack(struct tftp_session *spt,
 
     m->m_len = sizeof(struct tftp_t) - 514 + n -
         sizeof(struct ip) - sizeof(struct udphdr);
-    udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+    udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
 
     return 0;
 }
@@ -193,7 +193,7 @@ static void tftp_send_error(struct tftp_session *spt,
   m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
         sizeof(struct ip) - sizeof(struct udphdr);
 
-  udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+  udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
 
 out:
   tftp_session_terminate(spt);
@@ -243,7 +243,7 @@ static void tftp_send_next_block(struct tftp_session *spt,
   m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
         sizeof(struct ip) - sizeof(struct udphdr);
 
-  udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+  udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
 
   if (nobytes == 512) {
     tftp_session_update(spt);
diff --git a/slirp/udp.c b/slirp/udp.c
index 7a5c95b..8203eb1 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -236,7 +236,7 @@ bad:
 	m_free(m);
 }
 
-int udp_output2(struct socket *so, struct mbuf *m,
+int udp_output(struct socket *so, struct mbuf *m,
                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
                 int iptos)
 {
@@ -287,31 +287,6 @@ int udp_output2(struct socket *so, struct mbuf *m,
 	return (error);
 }
 
-int udp_output(struct socket *so, struct mbuf *m,
-               struct sockaddr_in *addr)
-
-{
-    Slirp *slirp = so->slirp;
-    struct sockaddr_in saddr, daddr;
-
-    saddr = *addr;
-    if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
-        slirp->vnetwork_addr.s_addr) {
-        uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;
-
-        if ((so->so_faddr.s_addr & inv_mask) == inv_mask) {
-            saddr.sin_addr = slirp->vhost_addr;
-        } else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||
-                   so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
-            saddr.sin_addr = so->so_faddr;
-        }
-    }
-    daddr.sin_addr = so->so_laddr;
-    daddr.sin_port = so->so_lport;
-
-    return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
-}
-
 int
 udp_attach(struct socket *so)
 {
@@ -378,14 +353,8 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 	socket_set_fast_reuse(so->s);
 
 	getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
-	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;
-	}
+	so->fhost.sin = addr;
+	sotranslate_accept(so);
 	so->so_lfamily = AF_INET;
 	so->so_lport = lport;
 	so->so_laddr.s_addr = laddr;
diff --git a/slirp/udp.h b/slirp/udp.h
index 9bf31fe..a04b8ce 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -76,12 +76,11 @@ struct mbuf;
 void udp_init(Slirp *);
 void udp_cleanup(Slirp *);
 void udp_input(register struct mbuf *, int);
-int udp_output(struct socket *, struct mbuf *, struct sockaddr_in *);
 int udp_attach(struct socket *);
 void udp_detach(struct socket *);
 struct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,
                            int);
-int udp_output2(struct socket *so, struct mbuf *m,
+int udp_output(struct socket *so, struct mbuf *m,
                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
                 int iptos);
 #endif
-- 
2.5.0

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

* [Qemu-devel] [PULL 10/17] slirp: Factorizing and cleaning solookup()
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (8 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 09/17] slirp: Factorizing address translation Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 11/17] slirp: Add sockaddr_equal, make solookup family-agnostic Jason Wang
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Samuel Thibault, Jason Wang, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

solookup() was only compatible with TCP. Having the socket list in
argument, it is now compatible with UDP too.

Some optimization code is factorized inside the function (the function
look at the last returned result before browsing the complete socket
list).

This prepares for IPv6 support.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 slirp/socket.c    | 37 ++++++++++++++++++++++++-------------
 slirp/socket.h    |  5 +++--
 slirp/tcp_input.c | 13 +++----------
 slirp/udp.c       | 21 ++-------------------
 4 files changed, 32 insertions(+), 44 deletions(-)

diff --git a/slirp/socket.c b/slirp/socket.c
index d1034fb..8f73e90 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -16,23 +16,34 @@ static void sofcantrcvmore(struct socket *so);
 static void sofcantsendmore(struct socket *so);
 
 struct socket *
-solookup(struct socket *head, struct in_addr laddr, u_int lport,
+solookup(struct socket **last, struct socket *head,
+         struct in_addr laddr, u_int lport,
          struct in_addr faddr, u_int fport)
 {
-	struct socket *so;
-
-	for (so = head->so_next; so != head; so = so->so_next) {
-		if (so->so_lport == lport &&
-		    so->so_laddr.s_addr == laddr.s_addr &&
-		    so->so_faddr.s_addr == faddr.s_addr &&
-		    so->so_fport == fport)
-		   break;
-	}
+    struct socket *so = *last;
+
+    /* Optimisation */
+    if (so != head &&
+            so->so_lport == lport &&
+            so->so_laddr.s_addr == laddr.s_addr &&
+            (!faddr.s_addr ||
+                (so->so_faddr.s_addr == faddr.s_addr &&
+                 so->so_fport == fport))) {
+        return so;
+    }
 
-	if (so == head)
-	   return (struct socket *)NULL;
-	return so;
+    for (so = head->so_next; so != head; so = so->so_next) {
+        if (so->so_lport == lport &&
+            so->so_laddr.s_addr == laddr.s_addr &&
+            (!faddr.s_addr ||
+                (so->so_faddr.s_addr == faddr.s_addr &&
+                 so->so_fport == fport))) {
+            *last = so;
+            return so;
+        }
+    }
 
+    return (struct socket *)NULL;
 }
 
 /*
diff --git a/slirp/socket.h b/slirp/socket.h
index b27bbb2..1c8c24c 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -87,8 +87,9 @@ struct socket {
 #define SS_HOSTFWD		0x1000	/* Socket describes host->guest forwarding */
 #define SS_INCOMING		0x2000	/* Connection was initiated by a host on the internet */
 
-struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int);
-struct socket * socreate(Slirp *);
+struct socket *solookup(struct socket **, struct socket *,
+        struct in_addr, u_int, struct in_addr, u_int);
+struct socket *socreate(Slirp *);
 void sofree(struct socket *);
 int soread(struct socket *);
 void sorecvoob(struct socket *);
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 4c3191d..5492061 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -320,16 +320,9 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	 * Locate pcb for segment.
 	 */
 findso:
-	so = slirp->tcp_last_so;
-	if (so->so_fport != ti->ti_dport ||
-	    so->so_lport != ti->ti_sport ||
-	    so->so_laddr.s_addr != ti->ti_src.s_addr ||
-	    so->so_faddr.s_addr != ti->ti_dst.s_addr) {
-		so = solookup(&slirp->tcb, ti->ti_src, ti->ti_sport,
-			       ti->ti_dst, ti->ti_dport);
-		if (so)
-			slirp->tcp_last_so = so;
-	}
+	so = solookup(&slirp->tcp_last_so, &slirp->tcb,
+		      ti->ti_src, ti->ti_sport,
+		      ti->ti_dst, ti->ti_dport);
 
 	/*
 	 * If the state is CLOSED (i.e., TCB does not exist) then
diff --git a/slirp/udp.c b/slirp/udp.c
index 8203eb1..126ef82 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -151,25 +151,8 @@ udp_input(register struct mbuf *m, int iphlen)
 	/*
 	 * Locate pcb for datagram.
 	 */
-	so = slirp->udp_last_so;
-	if (so == &slirp->udb || so->so_lport != uh->uh_sport ||
-	    so->so_laddr.s_addr != ip->ip_src.s_addr) {
-		struct socket *tmp;
-
-		for (tmp = slirp->udb.so_next; tmp != &slirp->udb;
-		     tmp = tmp->so_next) {
-			if (tmp->so_lport == uh->uh_sport &&
-			    tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
-				so = tmp;
-				break;
-			}
-		}
-		if (tmp == &slirp->udb) {
-		  so = NULL;
-		} else {
-		  slirp->udp_last_so = so;
-		}
-	}
+	so = solookup(&slirp->udp_last_so, &slirp->udb,
+		      ip->ip_src, uh->uh_sport, (struct in_addr) {0}, 0);
 
 	if (so == NULL) {
 	  /*
-- 
2.5.0

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

* [Qemu-devel] [PULL 11/17] slirp: Add sockaddr_equal, make solookup family-agnostic
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (9 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 10/17] slirp: Factorizing and cleaning solookup() Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 12/17] slirp: Make udp_attach IPv6 compatible Jason Wang
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Samuel Thibault, Jason Wang, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

This patch makes solookup() compatible with varying address
families, by using a new sockaddr_equal() function that compares
two sockaddr_storage.

This prepares for IPv6 support.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 slirp/socket.c    | 21 ++++++---------------
 slirp/socket.h    | 22 +++++++++++++++++++++-
 slirp/tcp_input.c | 23 ++++++++++++++---------
 slirp/udp.c       | 10 ++++++++--
 4 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/slirp/socket.c b/slirp/socket.c
index 8f73e90..f7e5968 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -15,29 +15,20 @@
 static void sofcantrcvmore(struct socket *so);
 static void sofcantsendmore(struct socket *so);
 
-struct socket *
-solookup(struct socket **last, struct socket *head,
-         struct in_addr laddr, u_int lport,
-         struct in_addr faddr, u_int fport)
+struct socket *solookup(struct socket **last, struct socket *head,
+        struct sockaddr_storage *lhost, struct sockaddr_storage *fhost)
 {
     struct socket *so = *last;
 
     /* Optimisation */
-    if (so != head &&
-            so->so_lport == lport &&
-            so->so_laddr.s_addr == laddr.s_addr &&
-            (!faddr.s_addr ||
-                (so->so_faddr.s_addr == faddr.s_addr &&
-                 so->so_fport == fport))) {
+    if (so != head && sockaddr_equal(&(so->lhost.ss), lhost)
+            && (!fhost || sockaddr_equal(&so->fhost.ss, fhost))) {
         return so;
     }
 
     for (so = head->so_next; so != head; so = so->so_next) {
-        if (so->so_lport == lport &&
-            so->so_laddr.s_addr == laddr.s_addr &&
-            (!faddr.s_addr ||
-                (so->so_faddr.s_addr == faddr.s_addr &&
-                 so->so_fport == fport))) {
+        if (sockaddr_equal(&(so->lhost.ss), lhost)
+                && (!fhost || sockaddr_equal(&so->fhost.ss, fhost))) {
             *last = so;
             return so;
         }
diff --git a/slirp/socket.h b/slirp/socket.h
index 1c8c24c..929af0a 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -87,8 +87,28 @@ struct socket {
 #define SS_HOSTFWD		0x1000	/* Socket describes host->guest forwarding */
 #define SS_INCOMING		0x2000	/* Connection was initiated by a host on the internet */
 
+static inline int sockaddr_equal(struct sockaddr_storage *a,
+        struct sockaddr_storage *b)
+{
+    if (a->ss_family != b->ss_family) {
+        return 0;
+    }
+
+    switch (a->ss_family) {
+    case AF_INET:
+    {
+        struct sockaddr_in *a4 = (struct sockaddr_in *) a;
+        struct sockaddr_in *b4 = (struct sockaddr_in *) b;
+        return a4->sin_addr.s_addr == b4->sin_addr.s_addr
+               && a4->sin_port == b4->sin_port;
+    }
+    default:
+        assert(0);
+    }
+}
+
 struct socket *solookup(struct socket **, struct socket *,
-        struct in_addr, u_int, struct in_addr, u_int);
+        struct sockaddr_storage *, struct sockaddr_storage *);
 struct socket *socreate(Slirp *);
 void sofree(struct socket *);
 int soread(struct socket *);
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 5492061..5e2773c 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -227,6 +227,8 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	int iss = 0;
 	u_long tiwin;
 	int ret;
+	struct sockaddr_storage lhost, fhost;
+	struct sockaddr_in *lhost4, *fhost4;
     struct ex_list *ex_ptr;
     Slirp *slirp;
 
@@ -320,9 +322,16 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	 * Locate pcb for segment.
 	 */
 findso:
-	so = solookup(&slirp->tcp_last_so, &slirp->tcb,
-		      ti->ti_src, ti->ti_sport,
-		      ti->ti_dst, ti->ti_dport);
+	lhost.ss_family = AF_INET;
+	lhost4 = (struct sockaddr_in *) &lhost;
+	lhost4->sin_addr = ti->ti_src;
+	lhost4->sin_port = ti->ti_sport;
+	fhost.ss_family = AF_INET;
+	fhost4 = (struct sockaddr_in *) &fhost;
+	fhost4->sin_addr = ti->ti_dst;
+	fhost4->sin_port = ti->ti_dport;
+
+	so = solookup(&slirp->tcp_last_so, &slirp->tcb, &lhost, &fhost);
 
 	/*
 	 * If the state is CLOSED (i.e., TCB does not exist) then
@@ -367,12 +376,8 @@ findso:
 	  sbreserve(&so->so_snd, TCP_SNDSPACE);
 	  sbreserve(&so->so_rcv, TCP_RCVSPACE);
 
-	  so->so_lfamily = AF_INET;
-	  so->so_laddr = ti->ti_src;
-	  so->so_lport = ti->ti_sport;
-	  so->so_ffamily = AF_INET;
-	  so->so_faddr = ti->ti_dst;
-	  so->so_fport = ti->ti_dport;
+	  so->lhost.ss = lhost;
+	  so->fhost.ss = fhost;
 
 	  if ((so->so_iptos = tcp_tos(so)) == 0)
 	    so->so_iptos = ((struct ip *)ti)->ip_tos;
diff --git a/slirp/udp.c b/slirp/udp.c
index 126ef82..63776c0 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -70,6 +70,8 @@ udp_input(register struct mbuf *m, int iphlen)
 	int len;
 	struct ip save_ip;
 	struct socket *so;
+	struct sockaddr_storage lhost;
+	struct sockaddr_in *lhost4;
 
 	DEBUG_CALL("udp_input");
 	DEBUG_ARG("m = %p", m);
@@ -151,8 +153,12 @@ udp_input(register struct mbuf *m, int iphlen)
 	/*
 	 * Locate pcb for datagram.
 	 */
-	so = solookup(&slirp->udp_last_so, &slirp->udb,
-		      ip->ip_src, uh->uh_sport, (struct in_addr) {0}, 0);
+	lhost.ss_family = AF_INET;
+	lhost4 = (struct sockaddr_in *) &lhost;
+	lhost4->sin_addr = ip->ip_src;
+	lhost4->sin_port = uh->uh_sport;
+
+	so = solookup(&slirp->udp_last_so, &slirp->udb, &lhost, NULL);
 
 	if (so == NULL) {
 	  /*
-- 
2.5.0

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

* [Qemu-devel] [PULL 12/17] slirp: Make udp_attach IPv6 compatible
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (10 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 11/17] slirp: Add sockaddr_equal, make solookup family-agnostic Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 13/17] slirp: Adding family argument to tcp_fconnect() Jason Wang
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Samuel Thibault, Jason Wang, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

A sa_family_t is now passed in argument to udp_attach instead of using a
hardcoded "AF_INET" to call qemu_socket().

This prepares for IPv6 support.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 slirp/ip_icmp.c | 2 +-
 slirp/udp.c     | 7 ++++---
 slirp/udp.h     | 2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 3a29847..592f33a 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -162,7 +162,7 @@ icmp_input(struct mbuf *m, int hlen)
       if (icmp_send(so, m, hlen) == 0) {
         return;
       }
-      if(udp_attach(so) == -1) {
+      if (udp_attach(so, AF_INET) == -1) {
 	DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
 		    errno,strerror(errno)));
 	sofree(so);
diff --git a/slirp/udp.c b/slirp/udp.c
index 63776c0..94e19b7 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -169,7 +169,7 @@ udp_input(register struct mbuf *m, int iphlen)
 	  if (!so) {
 	      goto bad;
 	  }
-	  if(udp_attach(so) == -1) {
+	  if (udp_attach(so, AF_INET) == -1) {
 	    DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
 			errno,strerror(errno)));
 	    sofree(so);
@@ -277,9 +277,10 @@ int udp_output(struct socket *so, struct mbuf *m,
 }
 
 int
-udp_attach(struct socket *so)
+udp_attach(struct socket *so, sa_family_t af)
 {
-  if((so->s = qemu_socket(AF_INET,SOCK_DGRAM,0)) != -1) {
+  so->s = qemu_socket(af, SOCK_DGRAM, 0);
+  if (so->s != -1) {
     so->so_expire = curtime + SO_EXPIRE;
     insque(so, &so->slirp->udb);
   }
diff --git a/slirp/udp.h b/slirp/udp.h
index a04b8ce..15e73c1 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -76,7 +76,7 @@ struct mbuf;
 void udp_init(Slirp *);
 void udp_cleanup(Slirp *);
 void udp_input(register struct mbuf *, int);
-int udp_attach(struct socket *);
+int udp_attach(struct socket *, sa_family_t af);
 void udp_detach(struct socket *);
 struct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,
                            int);
-- 
2.5.0

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

* [Qemu-devel] [PULL 13/17] slirp: Adding family argument to tcp_fconnect()
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (11 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 12/17] slirp: Make udp_attach IPv6 compatible Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 14/17] e1000: eliminate infinite loops on out-of-bounds transfer start Jason Wang
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Samuel Thibault, Jason Wang, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

This patch simply adds a sa_family_t argument to remove the hardcoded
"AF_INET" in the call of qemu_socket().

This prepares for IPv6 support.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 slirp/slirp.h     | 2 +-
 slirp/tcp_input.c | 2 +-
 slirp/tcp_subr.c  | 5 +++--
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/slirp/slirp.h b/slirp/slirp.h
index ec0a4c2..fcd4a05 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -327,7 +327,7 @@ void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbu
 struct tcpcb * tcp_newtcpcb(struct socket *);
 struct tcpcb * tcp_close(register struct tcpcb *);
 void tcp_sockclosed(struct tcpcb *);
-int tcp_fconnect(struct socket *);
+int tcp_fconnect(struct socket *, sa_family_t af);
 void tcp_connect(struct socket *);
 int tcp_attach(struct socket *);
 uint8_t tcp_tos(struct socket *);
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 5e2773c..f24e706 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -584,7 +584,7 @@ findso:
 	    goto cont_input;
 	  }
 
-          if ((tcp_fconnect(so) == -1) &&
+	  if ((tcp_fconnect(so, so->so_ffamily) == -1) &&
 #if defined(_WIN32)
               socket_error() != WSAEWOULDBLOCK
 #else
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 76c716f..8ec2729 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -324,14 +324,15 @@ tcp_sockclosed(struct tcpcb *tp)
  * nonblocking.  Connect returns after the SYN is sent, and does
  * not wait for ACK+SYN.
  */
-int tcp_fconnect(struct socket *so)
+int tcp_fconnect(struct socket *so, sa_family_t af)
 {
   int ret=0;
 
   DEBUG_CALL("tcp_fconnect");
   DEBUG_ARG("so = %p", so);
 
-  if( (ret = so->s = qemu_socket(AF_INET,SOCK_STREAM,0)) >= 0) {
+  ret = so->s = qemu_socket(af, SOCK_STREAM, 0);
+  if (ret >= 0) {
     int opt, s=so->s;
     struct sockaddr_storage addr;
 
-- 
2.5.0

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

* [Qemu-devel] [PULL 14/17] e1000: eliminate infinite loops on out-of-bounds transfer start
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (12 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 13/17] slirp: Adding family argument to tcp_fconnect() Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 15/17] net: netmap: use nm_open() to open netmap ports Jason Wang
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel
  Cc: Petr Matousek, Stefano Stabellini, Jason Wang,
	Michael S. Tsirkin, Michael Roth, Prasad Pandit, qemu-stable,
	Laszlo Ersek

From: Laszlo Ersek <lersek@redhat.com>

The start_xmit() and e1000_receive_iov() functions implement DMA transfers
iterating over a set of descriptors that the guest's e1000 driver
prepares:

- the TDLEN and RDLEN registers store the total size of the descriptor
  area,

- while the TDH and RDH registers store the offset (in whole tx / rx
  descriptors) into the area where the transfer is supposed to start.

Each time a descriptor is processed, the TDH and RDH register is bumped
(as appropriate for the transfer direction).

QEMU already contains logic to deal with bogus transfers submitted by the
guest:

- Normally, the transmit case wants to increase TDH from its initial value
  to TDT. (TDT is allowed to be numerically smaller than the initial TDH
  value; wrapping at or above TDLEN bytes to zero is normal.) The failsafe
  that QEMU currently has here is a check against reaching the original
  TDH value again -- a complete wraparound, which should never happen.

- In the receive case RDH is increased from its initial value until
  "total_size" bytes have been received; preferably in a single step, or
  in "s->rxbuf_size" byte steps, if the latter is smaller. However, null
  RX descriptors are skipped without receiving data, while RDH is
  incremented just the same. QEMU tries to prevent an infinite loop
  (processing only null RX descriptors) by detecting whether RDH assumes
  its original value during the loop. (Again, wrapping from RDLEN to 0 is
  normal.)

What both directions miss is that the guest could program TDLEN and RDLEN
so low, and the initial TDH and RDH so high, that these registers will
immediately be truncated to zero, and then never reassume their initial
values in the loop -- a full wraparound will never occur.

The condition that expresses this is:

  xdh_start >= s->mac_reg[XDLEN] / sizeof(desc)

i.e., TDH or RDH start out after the last whole rx or tx descriptor that
fits into the TDLEN or RDLEN sized area.

This condition could be checked before we enter the loops, but
pci_dma_read() / pci_dma_write() knows how to fill in buffers safely for
bogus DMA addresses, so we just extend the existing failsafes with the
above condition.

This is CVE-2016-1981.

Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Petr Matousek <pmatouse@redhat.com>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Prasad Pandit <ppandit@redhat.com>
Cc: Michael Roth <mdroth@linux.vnet.ibm.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: qemu-stable@nongnu.org
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1296044
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 hw/net/e1000.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 4eda7a3..0387fa0 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -909,7 +909,8 @@ start_xmit(E1000State *s)
          * bogus values to TDT/TDLEN.
          * there's nothing too intelligent we could do about this.
          */
-        if (s->mac_reg[TDH] == tdh_start) {
+        if (s->mac_reg[TDH] == tdh_start ||
+            tdh_start >= s->mac_reg[TDLEN] / sizeof(desc)) {
             DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n",
                    tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]);
             break;
@@ -1166,7 +1167,8 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
         if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
             s->mac_reg[RDH] = 0;
         /* see comment in start_xmit; same here */
-        if (s->mac_reg[RDH] == rdh_start) {
+        if (s->mac_reg[RDH] == rdh_start ||
+            rdh_start >= s->mac_reg[RDLEN] / sizeof(desc)) {
             DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",
                    rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]);
             set_ics(s, 0, E1000_ICS_RXO);
-- 
2.5.0

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

* [Qemu-devel] [PULL 15/17] net: netmap: use nm_open() to open netmap ports
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (13 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 14/17] e1000: eliminate infinite loops on out-of-bounds transfer start Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 16/17] net: always walk through filters in reverse if traffic is egress Jason Wang
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Jason Wang, Vincenzo Maffione

From: Vincenzo Maffione <v.maffione@gmail.com>

This patch simplifies the netmap backend code by means of the nm_open()
helper function provided by netmap_user.h, which hides the details of
open(), iotcl() and mmap() carried out on the netmap device.

Moreover, the semantic of nm_open() makes it possible to open special
netmap ports (e.g. pipes, monitors) and use special modes (e.g. host rings
only, single queue mode, exclusive access).

Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 net/netmap.c | 97 ++++++++++++++++++++----------------------------------------
 1 file changed, 32 insertions(+), 65 deletions(-)

diff --git a/net/netmap.c b/net/netmap.c
index 5558368..27295ab 100644
--- a/net/netmap.c
+++ b/net/netmap.c
@@ -39,21 +39,12 @@
 #include "qemu/error-report.h"
 #include "qemu/iov.h"
 
-/* Private netmap device info. */
-typedef struct NetmapPriv {
-    int                 fd;
-    size_t              memsize;
-    void                *mem;
-    struct netmap_if    *nifp;
-    struct netmap_ring  *rx;
-    struct netmap_ring  *tx;
-    char                fdname[PATH_MAX];        /* Normally "/dev/netmap". */
-    char                ifname[IFNAMSIZ];
-} NetmapPriv;
-
 typedef struct NetmapState {
     NetClientState      nc;
-    NetmapPriv          me;
+    struct nm_desc      *nmd;
+    char                ifname[IFNAMSIZ];
+    struct netmap_ring  *tx;
+    struct netmap_ring  *rx;
     bool                read_poll;
     bool                write_poll;
     struct iovec        iov[IOV_MAX];
@@ -90,44 +81,23 @@ pkt_copy(const void *_src, void *_dst, int l)
  * Open a netmap device. We assume there is only one queue
  * (which is the case for the VALE bridge).
  */
-static void netmap_open(NetmapPriv *me, Error **errp)
+static struct nm_desc *netmap_open(const NetdevNetmapOptions *nm_opts,
+                                   Error **errp)
 {
-    int fd;
-    int err;
-    size_t l;
+    struct nm_desc *nmd;
     struct nmreq req;
 
-    me->fd = fd = open(me->fdname, O_RDWR);
-    if (fd < 0) {
-        error_setg_file_open(errp, errno, me->fdname);
-        return;
-    }
     memset(&req, 0, sizeof(req));
-    pstrcpy(req.nr_name, sizeof(req.nr_name), me->ifname);
-    req.nr_ringid = NETMAP_NO_TX_POLL;
-    req.nr_version = NETMAP_API;
-    err = ioctl(fd, NIOCREGIF, &req);
-    if (err) {
-        error_setg_errno(errp, errno, "Unable to register %s", me->ifname);
-        goto error;
-    }
-    l = me->memsize = req.nr_memsize;
 
-    me->mem = mmap(0, l, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
-    if (me->mem == MAP_FAILED) {
-        error_setg_errno(errp, errno, "Unable to mmap netmap shared memory");
-        me->mem = NULL;
-        goto error;
+    nmd = nm_open(nm_opts->ifname, &req, NETMAP_NO_TX_POLL,
+                  NULL);
+    if (nmd == NULL) {
+        error_setg_errno(errp, errno, "Failed to nm_open() %s",
+                         nm_opts->ifname);
+        return NULL;
     }
 
-    me->nifp = NETMAP_IF(me->mem, req.nr_offset);
-    me->tx = NETMAP_TXRING(me->nifp, 0);
-    me->rx = NETMAP_RXRING(me->nifp, 0);
-
-    return;
-
-error:
-    close(me->fd);
+    return nmd;
 }
 
 static void netmap_send(void *opaque);
@@ -136,7 +106,7 @@ static void netmap_writable(void *opaque);
 /* Set the event-loop handlers for the netmap backend. */
 static void netmap_update_fd_handler(NetmapState *s)
 {
-    qemu_set_fd_handler(s->me.fd,
+    qemu_set_fd_handler(s->nmd->fd,
                         s->read_poll ? netmap_send : NULL,
                         s->write_poll ? netmap_writable : NULL,
                         s);
@@ -188,7 +158,7 @@ static ssize_t netmap_receive(NetClientState *nc,
       const uint8_t *buf, size_t size)
 {
     NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
-    struct netmap_ring *ring = s->me.tx;
+    struct netmap_ring *ring = s->tx;
     uint32_t i;
     uint32_t idx;
     uint8_t *dst;
@@ -218,7 +188,7 @@ static ssize_t netmap_receive(NetClientState *nc,
     ring->slot[i].flags = 0;
     pkt_copy(buf, dst, size);
     ring->cur = ring->head = nm_ring_next(ring, i);
-    ioctl(s->me.fd, NIOCTXSYNC, NULL);
+    ioctl(s->nmd->fd, NIOCTXSYNC, NULL);
 
     return size;
 }
@@ -227,7 +197,7 @@ static ssize_t netmap_receive_iov(NetClientState *nc,
                     const struct iovec *iov, int iovcnt)
 {
     NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
-    struct netmap_ring *ring = s->me.tx;
+    struct netmap_ring *ring = s->tx;
     uint32_t last;
     uint32_t idx;
     uint8_t *dst;
@@ -284,7 +254,7 @@ static ssize_t netmap_receive_iov(NetClientState *nc,
     /* Now update ring->cur and ring->head. */
     ring->cur = ring->head = i;
 
-    ioctl(s->me.fd, NIOCTXSYNC, NULL);
+    ioctl(s->nmd->fd, NIOCTXSYNC, NULL);
 
     return iov_size(iov, iovcnt);
 }
@@ -301,7 +271,7 @@ static void netmap_send_completed(NetClientState *nc, ssize_t len)
 static void netmap_send(void *opaque)
 {
     NetmapState *s = opaque;
-    struct netmap_ring *ring = s->me.rx;
+    struct netmap_ring *ring = s->rx;
 
     /* Keep sending while there are available packets into the netmap
        RX ring and the forwarding path towards the peer is open. */
@@ -349,10 +319,8 @@ static void netmap_cleanup(NetClientState *nc)
     qemu_purge_queued_packets(nc);
 
     netmap_poll(nc, false);
-    munmap(s->me.mem, s->me.memsize);
-    close(s->me.fd);
-
-    s->me.fd = -1;
+    nm_close(s->nmd);
+    s->nmd = NULL;
 }
 
 /* Offloading manipulation support callbacks. */
@@ -383,17 +351,17 @@ static void netmap_set_vnet_hdr_len(NetClientState *nc, int len)
     struct nmreq req;
 
     /* Issue a NETMAP_BDG_VNET_HDR command to change the virtio-net header
-     * length for the netmap adapter associated to 'me->ifname'.
+     * length for the netmap adapter associated to 's->ifname'.
      */
     memset(&req, 0, sizeof(req));
-    pstrcpy(req.nr_name, sizeof(req.nr_name), s->me.ifname);
+    pstrcpy(req.nr_name, sizeof(req.nr_name), s->ifname);
     req.nr_version = NETMAP_API;
     req.nr_cmd = NETMAP_BDG_VNET_HDR;
     req.nr_arg1 = len;
-    err = ioctl(s->me.fd, NIOCREGIF, &req);
+    err = ioctl(s->nmd->fd, NIOCREGIF, &req);
     if (err) {
         error_report("Unable to execute NETMAP_BDG_VNET_HDR on %s: %s",
-                     s->me.ifname, strerror(errno));
+                     s->ifname, strerror(errno));
     } else {
         /* Keep track of the current length. */
         s->vnet_hdr_len = len;
@@ -437,16 +405,12 @@ int net_init_netmap(const NetClientOptions *opts,
                     const char *name, NetClientState *peer, Error **errp)
 {
     const NetdevNetmapOptions *netmap_opts = opts->u.netmap;
+    struct nm_desc *nmd;
     NetClientState *nc;
     Error *err = NULL;
-    NetmapPriv me;
     NetmapState *s;
 
-    pstrcpy(me.fdname, sizeof(me.fdname),
-        netmap_opts->has_devname ? netmap_opts->devname : "/dev/netmap");
-    /* Set default name for the port if not supplied. */
-    pstrcpy(me.ifname, sizeof(me.ifname), netmap_opts->ifname);
-    netmap_open(&me, &err);
+    nmd = netmap_open(netmap_opts, &err);
     if (err) {
         error_propagate(errp, err);
         return -1;
@@ -454,8 +418,11 @@ int net_init_netmap(const NetClientOptions *opts,
     /* Create the object. */
     nc = qemu_new_net_client(&net_netmap_info, peer, "netmap", name);
     s = DO_UPCAST(NetmapState, nc, nc);
-    s->me = me;
+    s->nmd = nmd;
+    s->tx = NETMAP_TXRING(nmd->nifp, 0);
+    s->rx = NETMAP_RXRING(nmd->nifp, 0);
     s->vnet_hdr_len = 0;
+    pstrcpy(s->ifname, sizeof(s->ifname), netmap_opts->ifname);
     netmap_read_poll(s, true); /* Initially only poll for reads. */
 
     return 0;
-- 
2.5.0

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

* [Qemu-devel] [PULL 16/17] net: always walk through filters in reverse if traffic is egress
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (14 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 15/17] net: netmap: use nm_open() to open netmap ports Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02  2:36 ` [Qemu-devel] [PULL 17/17] net/filter: Fix the output information for command 'info network' Jason Wang
  2016-02-02 11:05 ` [Qemu-devel] [PULL 00/17] Net patches Peter Maydell
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: Jason Wang, Li Zhijian

From: Li Zhijian <lizhijian@cn.fujitsu.com>

Previously, if we attach more than one filters for a single netdev,
both ingress and egress traffic will go through net filters in same
order like:

ingress: netdev ->filter1 ->filter2 ->...filter[n] ->emulated device
egress: emulated device ->filter1 ->filter2 ->...filter[n] ->netdev.

This is against the natural feeling and will complicate filters
configuration since in some scenes, we hope filters handle the egress
traffic in a reverse order. For example, in colo-proxy (will be
implemented later), we have a redirector filter and a colo-rewriter
filter, we need the filter behave like:

ingress(->)/egress(<-): chardev<->redirector<->colo-rewriter<->emulated device

Since both buffer filter and dump do not require strict order of
filters, this patch switches to always let egress traffic walk through
net filters in reverse to simplify the possible filters configuration
in the future.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Reviewed-by: Yang Hongyang <hongyang.yang@easystack.cn>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 include/net/net.h |  2 +-
 net/filter.c      | 21 +++++++++++++++++++--
 net/net.c         | 20 +++++++++++++++-----
 3 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/include/net/net.h b/include/net/net.h
index 7af3e15..73e4c46 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -92,7 +92,7 @@ struct NetClientState {
     NetClientDestructor *destructor;
     unsigned int queue_index;
     unsigned rxfilter_notify_enabled:1;
-    QTAILQ_HEAD(, NetFilterState) filters;
+    QTAILQ_HEAD(NetFilterHead, NetFilterState) filters;
 };
 
 typedef struct NICState {
diff --git a/net/filter.c b/net/filter.c
index 5d90f83..17a8398 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -34,6 +34,22 @@ ssize_t qemu_netfilter_receive(NetFilterState *nf,
     return 0;
 }
 
+static NetFilterState *netfilter_next(NetFilterState *nf,
+                                      NetFilterDirection dir)
+{
+    NetFilterState *next;
+
+    if (dir == NET_FILTER_DIRECTION_TX) {
+        /* forward walk through filters */
+        next = QTAILQ_NEXT(nf, next);
+    } else {
+        /* reverse order */
+        next = QTAILQ_PREV(nf, NetFilterHead, next);
+    }
+
+    return next;
+}
+
 ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
                                     unsigned flags,
                                     const struct iovec *iov,
@@ -43,7 +59,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
     int ret = 0;
     int direction;
     NetFilterState *nf = opaque;
-    NetFilterState *next = QTAILQ_NEXT(nf, next);
+    NetFilterState *next = NULL;
 
     if (!sender || !sender->peer) {
         /* no receiver, or sender been deleted, no need to pass it further */
@@ -61,6 +77,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
         direction = nf->direction;
     }
 
+    next = netfilter_next(nf, direction);
     while (next) {
         /*
          * if qemu_netfilter_pass_to_next been called, means that
@@ -73,7 +90,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
         if (ret) {
             return ret;
         }
-        next = QTAILQ_NEXT(next, next);
+        next = netfilter_next(next, direction);
     }
 
     /*
diff --git a/net/net.c b/net/net.c
index 87dd356..c929c41 100644
--- a/net/net.c
+++ b/net/net.c
@@ -580,11 +580,21 @@ static ssize_t filter_receive_iov(NetClientState *nc,
     ssize_t ret = 0;
     NetFilterState *nf = NULL;
 
-    QTAILQ_FOREACH(nf, &nc->filters, next) {
-        ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
-                                     iovcnt, sent_cb);
-        if (ret) {
-            return ret;
+    if (direction == NET_FILTER_DIRECTION_TX) {
+        QTAILQ_FOREACH(nf, &nc->filters, next) {
+            ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
+                                         iovcnt, sent_cb);
+            if (ret) {
+                return ret;
+            }
+        }
+    } else {
+        QTAILQ_FOREACH_REVERSE(nf, &nc->filters, NetFilterHead, next) {
+            ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
+                                         iovcnt, sent_cb);
+            if (ret) {
+                return ret;
+            }
         }
     }
 
-- 
2.5.0

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

* [Qemu-devel] [PULL 17/17] net/filter: Fix the output information for command 'info network'
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (15 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 16/17] net: always walk through filters in reverse if traffic is egress Jason Wang
@ 2016-02-02  2:36 ` Jason Wang
  2016-02-02 11:05 ` [Qemu-devel] [PULL 00/17] Net patches Peter Maydell
  17 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-02  2:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel
  Cc: Jason Wang, Yang Hongyang, zhanghailiang, Markus Armbruster

From: zhanghailiang <zhang.zhanghailiang@huawei.com>

The properties of netfilter object could be changed by 'qom-set'
command, but the output of 'info network' command is not updated,
because it got the old information through nf->info_str, it will
not be updated while we change the value of netfilter's property.

Here we split a helper function that could collect the output
information for filter, and also remove the useless member
'info_str' from struct NetFilterState.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: Eric Blake <eblake@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Cc: Yang Hongyang <hongyang.yang@easystack.cn>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 include/net/filter.h |  1 -
 net/filter.c         | 22 ----------------------
 net/net.c            | 32 +++++++++++++++++++++++++++++---
 3 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/include/net/filter.h b/include/net/filter.h
index 2deda36..5639976 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -55,7 +55,6 @@ struct NetFilterState {
     char *netdev_id;
     NetClientState *netdev;
     NetFilterDirection direction;
-    char info_str[256];
     QTAILQ_ENTRY(NetFilterState) next;
 };
 
diff --git a/net/filter.c b/net/filter.c
index 17a8398..8f07b99 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -15,7 +15,6 @@
 #include "net/vhost_net.h"
 #include "qom/object_interfaces.h"
 #include "qemu/iov.h"
-#include "qapi/string-output-visitor.h"
 
 ssize_t qemu_netfilter_receive(NetFilterState *nf,
                                NetFilterDirection direction,
@@ -152,10 +151,6 @@ static void netfilter_complete(UserCreatable *uc, Error **errp)
     NetFilterClass *nfc = NETFILTER_GET_CLASS(uc);
     int queues;
     Error *local_err = NULL;
-    char *str, *info;
-    ObjectProperty *prop;
-    ObjectPropertyIterator iter;
-    StringOutputVisitor *ov;
 
     if (!nf->netdev_id) {
         error_setg(errp, "Parameter 'netdev' is required");
@@ -189,23 +184,6 @@ static void netfilter_complete(UserCreatable *uc, Error **errp)
         }
     }
     QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next);
-
-    /* generate info str */
-    object_property_iter_init(&iter, OBJECT(nf));
-    while ((prop = object_property_iter_next(&iter))) {
-        if (!strcmp(prop->name, "type")) {
-            continue;
-        }
-        ov = string_output_visitor_new(false);
-        object_property_get(OBJECT(nf), string_output_get_visitor(ov),
-                            prop->name, errp);
-        str = string_output_get_string(ov);
-        string_output_visitor_cleanup(ov);
-        info = g_strdup_printf(",%s=%s", prop->name, str);
-        g_strlcat(nf->info_str, info, sizeof(nf->info_str));
-        g_free(str);
-        g_free(info);
-    }
 }
 
 static void netfilter_finalize(Object *obj)
diff --git a/net/net.c b/net/net.c
index c929c41..55ce154 100644
--- a/net/net.c
+++ b/net/net.c
@@ -45,6 +45,7 @@
 #include "qapi/dealloc-visitor.h"
 #include "sysemu/sysemu.h"
 #include "net/filter.h"
+#include "qapi/string-output-visitor.h"
 
 /* Net bridge is currently not supported for W32. */
 #if !defined(_WIN32)
@@ -1195,6 +1196,30 @@ void qmp_netdev_del(const char *id, Error **errp)
     qemu_opts_del(opts);
 }
 
+static void netfilter_print_info(Monitor *mon, NetFilterState *nf)
+{
+    char *str;
+    ObjectProperty *prop;
+    ObjectPropertyIterator iter;
+    StringOutputVisitor *ov;
+
+    /* generate info str */
+    object_property_iter_init(&iter, OBJECT(nf));
+    while ((prop = object_property_iter_next(&iter))) {
+        if (!strcmp(prop->name, "type")) {
+            continue;
+        }
+        ov = string_output_visitor_new(false);
+        object_property_get(OBJECT(nf), string_output_get_visitor(ov),
+                            prop->name, NULL);
+        str = string_output_get_string(ov);
+        string_output_visitor_cleanup(ov);
+        monitor_printf(mon, ",%s=%s", prop->name, str);
+        g_free(str);
+    }
+    monitor_printf(mon, "\n");
+}
+
 void print_net_client(Monitor *mon, NetClientState *nc)
 {
     NetFilterState *nf;
@@ -1208,9 +1233,10 @@ void print_net_client(Monitor *mon, NetClientState *nc)
     }
     QTAILQ_FOREACH(nf, &nc->filters, next) {
         char *path = object_get_canonical_path_component(OBJECT(nf));
-        monitor_printf(mon, "  - %s: type=%s%s\n", path,
-                       object_get_typename(OBJECT(nf)),
-                       nf->info_str);
+
+        monitor_printf(mon, "  - %s: type=%s", path,
+                       object_get_typename(OBJECT(nf)));
+        netfilter_print_info(mon, nf);
         g_free(path);
     }
 }
-- 
2.5.0

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

* Re: [Qemu-devel] [PULL 00/17] Net patches
  2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
                   ` (16 preceding siblings ...)
  2016-02-02  2:36 ` [Qemu-devel] [PULL 17/17] net/filter: Fix the output information for command 'info network' Jason Wang
@ 2016-02-02 11:05 ` Peter Maydell
  2016-02-03  4:52   ` Jason Wang
  17 siblings, 1 reply; 22+ messages in thread
From: Peter Maydell @ 2016-02-02 11:05 UTC (permalink / raw)
  To: Jason Wang; +Cc: QEMU Developers

On 2 February 2016 at 02:36, Jason Wang <jasowang@redhat.com> wrote:
> The following changes since commit 0430891ce162b986c6e02a7729a942ecd2a32ca4:
>
>   hw: Clean up includes (2016-01-29 15:07:25 +0000)
>
> are available in the git repository at:
>
>   https://github.com/jasowang/qemu.git tags/net-pull-request
>
> for you to fetch changes up to e8a7a1a574ed6728422959c8aa79ca584cdd1d4d:
>
>   net/filter: Fix the output information for command 'info network' (2016-02-02 10:21:28 +0800)
>
> ----------------------------------------------------------------
>
> Major changes for net:
>
> - preparation for ipv6 support in slirp
> - fix tx infinite loops of e1000
> - fix cadence_gem buffer overflow
> - rx netfilter were gone in reverse for future complex netfilter setups

Hi. I'm afraid this failed to build on w32:

In file included from /home/petmay01/linaro/qemu-for-merges/slirp/slirp.h:146,
                 from /home/petmay01/linaro/qemu-for-merges/stubs/slirp.c:2:
/home/petmay01/linaro/qemu-for-merges/slirp/udp.h:79: error: expected
declaration specifiers or ‘...’ before ‘sa_family_t’
In file included from /home/petmay01/linaro/qemu-for-merges/stubs/slirp.c:2:
/home/petmay01/linaro/qemu-for-merges/slirp/slirp.h:330: error:
expected declaration specifiers or ‘...’ before ‘sa_family_t’

thanks
-- PMM

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

* Re: [Qemu-devel] [PULL 00/17] Net patches
  2016-02-02 11:05 ` [Qemu-devel] [PULL 00/17] Net patches Peter Maydell
@ 2016-02-03  4:52   ` Jason Wang
  2016-02-03  9:09     ` Samuel Thibault
  0 siblings, 1 reply; 22+ messages in thread
From: Jason Wang @ 2016-02-03  4:52 UTC (permalink / raw)
  To: Peter Maydell, maethor, samuel.thibault; +Cc: Thomas Huth, QEMU Developers



On 02/02/2016 07:05 PM, Peter Maydell wrote:
> On 2 February 2016 at 02:36, Jason Wang <jasowang@redhat.com> wrote:
>> The following changes since commit 0430891ce162b986c6e02a7729a942ecd2a32ca4:
>>
>>   hw: Clean up includes (2016-01-29 15:07:25 +0000)
>>
>> are available in the git repository at:
>>
>>   https://github.com/jasowang/qemu.git tags/net-pull-request
>>
>> for you to fetch changes up to e8a7a1a574ed6728422959c8aa79ca584cdd1d4d:
>>
>>   net/filter: Fix the output information for command 'info network' (2016-02-02 10:21:28 +0800)
>>
>> ----------------------------------------------------------------
>>
>> Major changes for net:
>>
>> - preparation for ipv6 support in slirp
>> - fix tx infinite loops of e1000
>> - fix cadence_gem buffer overflow
>> - rx netfilter were gone in reverse for future complex netfilter setups
> Hi. I'm afraid this failed to build on w32:
>
> In file included from /home/petmay01/linaro/qemu-for-merges/slirp/slirp.h:146,
>                  from /home/petmay01/linaro/qemu-for-merges/stubs/slirp.c:2:
> /home/petmay01/linaro/qemu-for-merges/slirp/udp.h:79: error: expected
> declaration specifiers or ‘...’ before ‘sa_family_t’
> In file included from /home/petmay01/linaro/qemu-for-merges/stubs/slirp.c:2:
> /home/petmay01/linaro/qemu-for-merges/slirp/slirp.h:330: error:
> expected declaration specifiers or ‘...’ before ‘sa_family_t’
>
> thanks
> -- PMM

Oops, very sorry for the build failure. I've setup a cross build
environment to test win32 build before each pull request in the future.

For this issue, looks like there's no sa_family_t for windows. Possible
solutions are:

- switch to use unsigned short
- or typedef sa_family_t as unsigned short for windows

Samuel and Guillaume, thoughts for this?

Thanks

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

* Re: [Qemu-devel] [PULL 00/17] Net patches
  2016-02-03  4:52   ` Jason Wang
@ 2016-02-03  9:09     ` Samuel Thibault
  2016-02-04  8:20       ` Jason Wang
  0 siblings, 1 reply; 22+ messages in thread
From: Samuel Thibault @ 2016-02-03  9:09 UTC (permalink / raw)
  To: Jason Wang; +Cc: Peter Maydell, Thomas Huth, QEMU Developers, maethor

Jason Wang, on Wed 03 Feb 2016 12:52:24 +0800, wrote:
> > Hi. I'm afraid this failed to build on w32:
> >
> > declaration specifiers or ‘...’ before ‘sa_family_t’
> 
> - switch to use unsigned short
> - or typedef sa_family_t as unsigned short for windows

Doing the second runs the risk of windows eventually catching up with
what posix requires. Using unsigned short instead should be fine.

Samuel

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

* Re: [Qemu-devel] [PULL 00/17] Net patches
  2016-02-03  9:09     ` Samuel Thibault
@ 2016-02-04  8:20       ` Jason Wang
  0 siblings, 0 replies; 22+ messages in thread
From: Jason Wang @ 2016-02-04  8:20 UTC (permalink / raw)
  To: Samuel Thibault; +Cc: Peter Maydell, Thomas Huth, QEMU Developers, maethor



On 02/03/2016 05:09 PM, Samuel Thibault wrote:
> Jason Wang, on Wed 03 Feb 2016 12:52:24 +0800, wrote:
>>> Hi. I'm afraid this failed to build on w32:
>>>
>>> declaration specifiers or ‘...’ before ‘sa_family_t’
>> - switch to use unsigned short
>> - or typedef sa_family_t as unsigned short for windows
> Doing the second runs the risk of windows eventually catching up with
> what posix requires. Using unsigned short instead should be fine.
>
> Samuel

Ok, fixed and will submit V2 of pull request soon.

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

end of thread, other threads:[~2016-02-04  8:20 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-02  2:36 [Qemu-devel] [PULL 00/17] Net patches Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 01/17] net/slirp: Tell the users when they are using deprecated options Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 02/17] qemu-doc: Do not promote deprecated -smb and -redir options Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 03/17] net: cadence_gem: check packet size in gem_recieve Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 04/17] cadence_gem: fix buffer overflow Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 05/17] slirp: goto bad in udp_input if sosendto fails Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 06/17] slirp: Generalizing and neutralizing ARP code Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 07/17] slirp: Adding address family switch for produced frames Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 08/17] slirp: Make Socket structure IPv6 compatible Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 09/17] slirp: Factorizing address translation Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 10/17] slirp: Factorizing and cleaning solookup() Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 11/17] slirp: Add sockaddr_equal, make solookup family-agnostic Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 12/17] slirp: Make udp_attach IPv6 compatible Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 13/17] slirp: Adding family argument to tcp_fconnect() Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 14/17] e1000: eliminate infinite loops on out-of-bounds transfer start Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 15/17] net: netmap: use nm_open() to open netmap ports Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 16/17] net: always walk through filters in reverse if traffic is egress Jason Wang
2016-02-02  2:36 ` [Qemu-devel] [PULL 17/17] net/filter: Fix the output information for command 'info network' Jason Wang
2016-02-02 11:05 ` [Qemu-devel] [PULL 00/17] Net patches Peter Maydell
2016-02-03  4:52   ` Jason Wang
2016-02-03  9:09     ` Samuel Thibault
2016-02-04  8:20       ` Jason Wang

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.