[Pkg-virtualbox-commits] [virtualbox] 01/03: Imported Upstream version 5.0.20-dfsg

Gianfranco Costamagna locutusofborg-guest at moszumanska.debian.org
Fri Apr 29 07:53:06 UTC 2016


This is an automated email from the git hooks/post-receive script.

locutusofborg-guest pushed a commit to branch master
in repository virtualbox.

commit 16d844666c1c91a91097c86de76cbfe91811c8e4
Author: Gianfranco Costamagna <costamagnagianfranco at yahoo.it>
Date:   Fri Apr 29 09:43:18 2016 +0200

    Imported Upstream version 5.0.20-dfsg
---
 Config.kmk                                         |    4 +-
 doc/manual/en_US/user_Frontends.xml                |    4 +-
 doc/manual/en_US/user_GuestAdditions.xml           |    4 +-
 doc/manual/en_US/user_Introduction.xml             |   12 +-
 doc/manual/en_US/user_Networking.xml               |    8 +-
 doc/manual/en_US/user_Troubleshooting.xml          |   14 +-
 doc/manual/en_US/user_VBoxManage.xml               |   32 +-
 doc/manual/user_ChangeLogImpl.xml                  |  100 +-
 include/VBox/GuestHost/GuestControl.h              |  189 +++
 include/VBox/HostServices/GuestControlSvc.h        |  133 +-
 include/VBox/err.h                                 |    6 +-
 include/iprt/asm.h                                 |   39 +
 src/VBox/Additions/common/VBoxGuest/Makefile.kmk   |    1 +
 .../Additions/common/VBoxGuest/VBoxGuest-linux.c   |    5 +-
 .../Additions/common/VBoxService/VBoxService.cpp   |    3 +
 .../common/VBoxService/VBoxServiceControl.h        |    3 +-
 .../VBoxService/VBoxServiceControlProcess.cpp      |    1 +
 .../common/VBoxService/VBoxServiceToolBox.cpp      |  173 ++-
 .../common/VBoxService/VBoxServiceToolBox.h        |   29 +
 src/VBox/Additions/linux/drm/Makefile.kmk          |    2 +
 src/VBox/Additions/linux/drm/files_vboxvideo_drv   |    1 +
 src/VBox/Additions/linux/drm/vbox_drv.c            |    6 +-
 .../Additions/linux/sharedfolders/Makefile.kmk     |    2 +
 .../Additions/linux/sharedfolders/files_vboxsf     |    1 +
 src/VBox/Additions/linux/sharedfolders/vfsmod.c    |    5 +-
 src/VBox/Additions/linux/sharedfolders/vfsmod.h    |    2 -
 src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd      |  Bin 1048576 -> 1048576 bytes
 src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd      |  Bin 1048576 -> 1048576 bytes
 .../Graphics/BIOS/VBoxVgaBiosAlternative.asm       |    6 +-
 .../Graphics/BIOS/VBoxVgaBiosAlternative.md5sum    |    2 +-
 src/VBox/Devices/Makefile.kmk                      |    8 +-
 src/VBox/Devices/Network/DrvNAT.cpp                |  142 +-
 src/VBox/Devices/Network/lwip-new/src/core/tcp.c   |   44 +-
 .../Devices/Network/lwip-new/src/core/tcp_in.c     |  113 +-
 .../Network/lwip-new/src/include/lwip/tcp.h        |   19 +-
 .../Network/lwip-new/src/include/lwip/tcp_impl.h   |    7 +-
 src/VBox/Devices/Network/slirp/bootp.c             |   15 +-
 src/VBox/Devices/Network/slirp/debug.c             |   16 +-
 src/VBox/Devices/Network/slirp/dnsproxy/dnsproxy.c |    8 +-
 src/VBox/Devices/Network/slirp/hostres.c           | 1513 ++++++++++++++++++++
 src/VBox/Devices/Network/slirp/ip_icmp.c           |    4 +-
 src/VBox/Devices/Network/slirp/ip_input.c          |    6 +
 .../Devices/Network/slirp/libalias/alias_dns.c     |  441 ------
 src/VBox/Devices/Network/slirp/libslirp.h          |   17 +-
 src/VBox/Devices/Network/slirp/misc.c              |    4 +-
 src/VBox/Devices/Network/slirp/slirp.c             |  379 ++---
 src/VBox/Devices/Network/slirp/slirp.h             |    5 +-
 src/VBox/Devices/Network/slirp/slirp_dns.c         |    6 -
 src/VBox/Devices/Network/slirp/slirp_state.h       |   23 +-
 src/VBox/Devices/Network/slirp/socket.c            |    2 +-
 src/VBox/Devices/Network/slirp/tcp_output.c        |    2 +-
 src/VBox/Devices/Network/slirp/tcp_subr.c          |   21 +-
 src/VBox/Devices/Network/slirp/udp.c               |   42 +-
 src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm   |    4 +-
 .../Devices/PC/BIOS/VBoxBiosAlternative.md5sum     |    2 +-
 src/VBox/Devices/PC/vbox-cpuhotplug.dsl            |   10 +-
 src/VBox/Devices/PC/vbox.dsl                       |    6 +-
 src/VBox/Devices/Storage/DevBusLogic.cpp           |   17 +-
 src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp       |    2 +-
 src/VBox/Frontends/VBoxManage/VBoxManageList.cpp   |   22 +-
 .../settings/global/UIGlobalSettingsLanguage.cpp   |    5 +
 src/VBox/HostDrivers/Support/Makefile.kmk          |    2 +
 src/VBox/HostDrivers/Support/SUPLibInternal.h      |    2 +-
 src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c  |    5 +-
 src/VBox/HostDrivers/Support/linux/files_vboxdrv   |    1 +
 .../Support/win/SUPHardenedVerify-win.h            |    2 +-
 .../Support/win/SUPHardenedVerifyProcess-win.cpp   |   39 +-
 .../Support/win/SUPR3HardenedMain-win.cpp          |   33 +-
 .../Support/win/SUPR3HardenedMainImports-win.cpp   |   53 +-
 src/VBox/HostDrivers/VBoxNetAdp/Makefile.kmk       |    1 +
 .../VBoxNetAdp/linux/VBoxNetAdp-linux.c            |    3 +-
 .../HostDrivers/VBoxNetAdp/linux/files_vboxnetadp  |    3 +-
 src/VBox/HostDrivers/VBoxNetFlt/Makefile.kmk       |    1 +
 .../VBoxNetFlt/linux/VBoxNetFlt-linux.c            |    6 +-
 .../HostDrivers/VBoxNetFlt/linux/files_vboxnetflt  |    1 +
 .../HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp  |  141 +-
 src/VBox/HostDrivers/VBoxPci/Makefile.kmk          |    1 +
 src/VBox/HostDrivers/VBoxPci/linux/VBoxPci-linux.c |    3 +-
 src/VBox/HostDrivers/VBoxPci/linux/files_vboxpci   |    1 +
 src/VBox/Main/include/GuestCtrlImplPrivate.h       |    7 +-
 src/VBox/Main/include/GuestDirectoryImpl.h         |    3 +-
 src/VBox/Main/include/GuestProcessImpl.h           |   43 +-
 src/VBox/Main/src-client/GuestCtrlImpl.cpp         |    8 +-
 src/VBox/Main/src-client/GuestDirectoryImpl.cpp    |   12 +-
 src/VBox/Main/src-client/GuestProcessImpl.cpp      |  244 +++-
 src/VBox/Main/src-client/GuestSessionImpl.cpp      |   43 +-
 src/VBox/Main/src-client/GuestSessionImplTasks.cpp |  254 ++--
 src/VBox/Main/src-server/MachineImpl.cpp           |   10 +-
 src/VBox/NetworkServices/NAT/proxy.h               |    9 -
 src/VBox/NetworkServices/NAT/pxdns.c               |   56 +
 src/VBox/NetworkServices/NAT/pxtcp.c               |  102 +-
 src/VBox/NetworkServices/NAT/pxtcp.h               |    7 +
 src/VBox/Runtime/common/ldr/ldrPE.cpp              |   50 +-
 src/VBox/Runtime/common/math/bignum-amd64-x86.asm  |   54 +-
 94 files changed, 3486 insertions(+), 1406 deletions(-)

diff --git a/Config.kmk b/Config.kmk
index a3578ac..91626cf 100644
--- a/Config.kmk
+++ b/Config.kmk
@@ -208,7 +208,7 @@ VBOX_VERSION_MINOR = 0
 # This is the current build number. It should be increased every time we publish a
 # new build. The define is available in every source file. Only even build numbers
 # will be published, odd numbers are set during development.
-VBOX_VERSION_BUILD = 18
+VBOX_VERSION_BUILD = 20
 # The raw version string. This *must not* contain any other information/fields than
 # major, minor and build revision (as it is now) -- also will be used for host/guest version
 # comparison.
@@ -6234,7 +6234,7 @@ endif
 SVN                    ?= svn$(HOSTSUFF_EXE)
 VBOX_SVN_REV_KMK        = $(PATH_OUT)/revision.kmk
 ifndef VBOX_SVN_REV
- VBOX_SVN_REV_FALLBACK := $(patsubst %:,,  $Rev: 106667 $  )
+ VBOX_SVN_REV_FALLBACK := $(patsubst %:,,  $Rev: 106931 $  )
  VBOX_SVN_DEP          := $(firstword $(wildcard $(PATH_ROOT)/.svn/wc.db $(abspath $(PATH_ROOT)/../.svn/wc.db) $(abspath $(PATH_ROOT)/../../.svn/wc.db) $(PATH_ROOT)/.svn/entries))
  ifeq ($(which $(SVN)),)
   VBOX_SVN_DEP         :=
diff --git a/doc/manual/en_US/user_Frontends.xml b/doc/manual/en_US/user_Frontends.xml
index 55579e6..3795c86 100644
--- a/doc/manual/en_US/user_Frontends.xml
+++ b/doc/manual/en_US/user_Frontends.xml
@@ -83,8 +83,8 @@
             Connector (<computeroutput>mstsc.exe</computeroutput>) that ships
             with Windows. You can start it by bringing up the "Run" dialog
             (press the Windows key and "R") and typing "mstsc". You can also
-            find it under "Start" -> "All Programs" -> "Accessories"
-            -> "Remote Desktop Connection". If you use the "Run" dialog,
+            find it under "Start" → "All Programs" → "Accessories"
+            → "Remote Desktop Connection". If you use the "Run" dialog,
             you can type in options directly:<screen>mstsc 1.2.3.4:3389</screen></para>
 
             <para>Replace <computeroutput>1.2.3.4</computeroutput> with the host IP address,
diff --git a/doc/manual/en_US/user_GuestAdditions.xml b/doc/manual/en_US/user_GuestAdditions.xml
index 7d0e51f..46b375b 100644
--- a/doc/manual/en_US/user_GuestAdditions.xml
+++ b/doc/manual/en_US/user_GuestAdditions.xml
@@ -1112,8 +1112,8 @@
             <para>In a Windows guest, shared folders are browseable and
             therefore visible in Windows Explorer. So, to attach the host's
             shared folder to your Windows guest, open Windows Explorer and
-            look for it under "My Networking Places" -> "Entire Network"
-            -> "VirtualBox Shared Folders". By right-clicking on a shared
+            look for it under "My Networking Places" → "Entire Network"
+            → "VirtualBox Shared Folders". By right-clicking on a shared
             folder and selecting "Map network drive" from the menu that pops
             up, you can assign a drive letter to that shared folder.</para>
 
diff --git a/doc/manual/en_US/user_Introduction.xml b/doc/manual/en_US/user_Introduction.xml
index 34d1ac9..cb6770b 100644
--- a/doc/manual/en_US/user_Introduction.xml
+++ b/doc/manual/en_US/user_Introduction.xml
@@ -1082,9 +1082,9 @@
 
           <itemizedlist>
             <listitem>
-              <para>Use the items in the "Machine" menu of the virtual machine
-              window. There you will find "Insert Ctrl+Alt+Delete" and
-              "Ctrl+Alt+Backspace"; the latter will only have an effect with
+              <para>Use the items in the "Input" → "Keyboard" menu of the
+              virtual machine window. There you will find "Insert Ctrl+Alt+Delete"
+              and "Ctrl+Alt+Backspace"; the latter will only have an effect with
               Linux or Solaris guests, however.</para>
             </listitem>
 
@@ -1121,7 +1121,7 @@
           VirtualBox allows you to configure whether these combinations will
           affect the host or the guest, if a virtual machine currently has the
           focus. This is a global setting for all virtual machines and can be
-          found under "File" -> "Preferences" -> "Input" ->
+          found under "File" → "Preferences" → "Input" →
           "Auto-capture keyboard".</para>
         </listitem>
       </itemizedlist>
@@ -1693,7 +1693,7 @@
         <para>Starting with version 4.0, VirtualBox creates file type
         associations for OVF and OVA files on your host operating
         system.</para>
-      </footnote> Alternatively, select "File" -> "Import appliance" from
+      </footnote> Alternatively, select "File" → "Import appliance" from
     the Manager window. In the file dialog that comes up, navigate to the file
     with either the <computeroutput>.ovf</computeroutput> or the
     <computeroutput>.ova</computeroutput> file extension.</para>
@@ -1723,7 +1723,7 @@
     linkend="vboxmanage-import" />.</para>
 
     <para>Conversely, to <emphasis role="bold">export</emphasis> virtual
-    machines that you already have in VirtualBox, select "File" -> "Export
+    machines that you already have in VirtualBox, select "File" → "Export
     appliance". A different dialog window shows up that allows you to combine
     several virtual machines into an OVF appliance. Then, select the target
     location where the target files should be stored, and the conversion
diff --git a/doc/manual/en_US/user_Networking.xml b/doc/manual/en_US/user_Networking.xml
index de8bd47..2b57aa0 100644
--- a/doc/manual/en_US/user_Networking.xml
+++ b/doc/manual/en_US/user_Networking.xml
@@ -700,8 +700,8 @@
 
     <para>Before you can attach a VM to a host-only network you have to
       create at least one host-only interface, either from the GUI:
-      "File" -> "Preferences" -> "Network" -> "Host-only network"
-      -> "(+)Add host-only network", or via command line with</para>
+      "File" → "Preferences" → "Network" → "Host-only network"
+      → "(+)Add host-only network", or via command line with</para>
       <screen>VBoxManage hostonlyif create</screen> 
       <para>see <xref linkend="vboxmanage-hostonlyif" /> for details.</para>
 
@@ -712,8 +712,8 @@
     statically.<itemizedlist>
         <listitem>
           <para>In the VirtualBox graphical user interface, you can configure
-          all these items in the global settings via "File" -> "Preferences"
-          -> "Network", which lists all host-only networks which are
+          all these items in the global settings via "File" → "Preferences"
+          → "Network", which lists all host-only networks which are
           presently in use. Click on the network name and then on the "Edit"
           button to the right, and you can modify the adapter and DHCP
           settings.</para>
diff --git a/doc/manual/en_US/user_Troubleshooting.xml b/doc/manual/en_US/user_Troubleshooting.xml
index 9516bb0..56e99e3 100644
--- a/doc/manual/en_US/user_Troubleshooting.xml
+++ b/doc/manual/en_US/user_Troubleshooting.xml
@@ -420,16 +420,16 @@
 
       <para><screen>[ ELF 64 Header]
 [ Program Header, type PT_NOTE ]
-  -> offset to COREDESCRIPTOR
+  → offset to COREDESCRIPTOR
 [ Program Header, type PT_LOAD ] - one for each contiguous physical memory range
-  -> Memory offset of range
-  -> File offset
+  → Memory offset of range
+  → File offset
 [ Note Header, type NT_VBOXCORE ]
 [ COREDESCRIPTOR ]
-  -> Magic
-  -> VM core file version
-  -> VBox version
-  -> Number of vCPUs etc.
+  → Magic
+  → VM core file version
+  → VBox version
+  → Number of vCPUs etc.
 [ Note Header, type NT_VBOXCPU ] - one for each vCPU
 [ vCPU 1 Note Header ]
   [ DBGFCORECPU - vCPU 1 dump ]
diff --git a/doc/manual/en_US/user_VBoxManage.xml b/doc/manual/en_US/user_VBoxManage.xml
index 5d6ae97..2a28f2d 100644
--- a/doc/manual/en_US/user_VBoxManage.xml
+++ b/doc/manual/en_US/user_VBoxManage.xml
@@ -2751,20 +2751,22 @@ Virtual system 0:
   </sect1>
 
   <sect1 id="vboxmanage-clonevdi">
-    <title>VBoxManage clonehd</title>
+    <title>VBoxManage clonemedium</title>
 
-    <para>This command duplicates a registered virtual hard disk image to a
-    new image file with a new unique identifier (UUID). The new image can be
-    transferred to another host system or imported into VirtualBox again using
-    the Virtual Media Manager; see <xref linkend="vdis" /> and <xref
-    linkend="cloningvdis" />. The syntax is as follows:</para>
+    <para>This command duplicates a virtual disk/DVD/floppy medium to a
+    new medium (usually an image file) with a new unique identifier (UUID).
+    The new image can be transferred to another host system or imported into
+    VirtualBox again using the Virtual Media Manager; see <xref linkend="vdis" />
+    and <xref linkend="cloningvdis" />. The syntax is as follows:</para>
 
-    <screen>VBoxManage clonehd         <uuid|inutfile> <uuid|outputfile>
-                           [--format VDI|VMDK|VHD|RAW|<other>]
-                           [--variant Standard,Fixed,Split2G,Stream,ESX]
-                           [--existing]</screen>
+    <screen>VBoxManage clonemedium      [disk|dvd|floppy] <uuid|inputfile> <uuid|outputfile>
 
-    <para>The disk image to clone as well as the target image must be described
+                            [--format VDI|VMDK|VHD|RAW|<other>]
+                            [--variant Standard,Fixed,Split2G,Stream,ESX]
+			    [--existing]</screen>
+
+
+    <para>The medium to clone as well as the target image must be described
        either by its UUIDs (if the mediums are registered) or by its filename.
        Registered images can be listed by <computeroutput>VBoxManage list hdds</computeroutput>
        (see <xref linkend="vboxmanage-list" /> for more information).
@@ -2805,8 +2807,8 @@ Virtual system 0:
         </glossentry>
       </glosslist> <note>
         <para>For compatibility with earlier versions of VirtualBox, the
-        "clonevdi" command is also supported and mapped internally to the
-        "clonehd" command.</para>
+ 	"clonevdi" and "clonehd" commands are still supported and mapped
+        internally to the "clonehd disk" command.</para>
       </note></para>
   </sect1>
 
@@ -3291,7 +3293,7 @@ Value: 2006.01.01</screen>
 
                 <glossdef><para>
                   Converts output from DOS/Windows guests to UNIX-compatible
-                  line endings (CR + LF -> LF). Not implemented yet.</para>
+                  line endings (CR + LF → LF). Not implemented yet.</para>
                 </glossdef>
               </glossentry>
 
@@ -3336,7 +3338,7 @@ Value: 2006.01.01</screen>
 
                 <glossdef><para>
                   Converts output from a UNIX/Linux guests to DOS-/Windows-compatible
-                  line endings (LF -> CR + LF). Not implemented yet.</para></glossdef>
+                  line endings (LF → CR + LF). Not implemented yet.</para></glossdef>
               </glossentry>
 
               <glossentry>
diff --git a/doc/manual/user_ChangeLogImpl.xml b/doc/manual/user_ChangeLogImpl.xml
index 8e13171..9988d43 100644
--- a/doc/manual/user_ChangeLogImpl.xml
+++ b/doc/manual/user_ChangeLogImpl.xml
@@ -3,6 +3,80 @@
 <chapter> <!-- HACK ALERT! Seems we must have a single top level element for xi:include to work.
                            So, we use chapter and xpointer="xpointer(/chapter/)" with xi:include. -->
   <sect1>
+    <title>Version 5.0.20 (2016-04-28)</title>
+
+    <para>This is a maintenance release. The following items were fixed and/or
+      added:</para>
+
+    <itemizedlist>
+
+      <listitem>
+        <para>Storage: fixed a regression causing write requests from the BIOS
+          to cause a Guru Meditation with the LsiLogic SCSI controller
+          (5.0.18 regression; bug #15317)</para>
+      </listitem>
+
+      <listitem>
+        <para>Storage: several emulation fixes in the BusLogic SCSI
+          controller emulation</para>
+      </listitem>
+
+      <listitem>
+        <para>NAT Network: support TCP in DNS proxy (same problem as
+          in bug #14736 for NAT)</para>
+      </listitem>
+
+      <listitem>
+        <para>NAT: rework handling of port-forwarding rules (bug #13570)</para>
+      </listitem>
+
+      <listitem>
+        <para>NAT: rewrite host resolver to handle more query types
+          and make it asynchronous so that a stalled lookup doesn't block all
+          NAT traffic</para>
+      </listitem>
+
+      <listitem>
+        <para>Snapshots: don't crash when restoring a snapshot which has more
+          network adapters than the current state (ie when the snapshot uses
+          ICH9 and the current state uses PIIX3)</para>
+      </listitem>
+
+      <listitem>
+        <para>Guest Control: various bugfixes for the <emphasis>copyfrom</emphasis>
+          and <emphasis>copyto</emphasis> commands / API (bug #14336)</para>
+      </listitem>
+
+      <listitem>
+        <para>VBoxManage: list processor features on <emphasis>list
+            hostinfo</emphasis> (bug #15334)</para>
+      </listitem>
+
+      <listitem>
+        <para>Linux hosts: fix for Linux 4.5 if
+          <emphasis>CONFIG_NET_CLS_ACT</emphasis> is enabled (bug #15327)</para>
+      </listitem>
+
+      <listitem>
+        <para>Windows hosts: another fix for recent Windows 10 insider builds
+          (bug #15337)</para>
+      </listitem>
+
+      <listitem>
+        <para>Windows hosts: make it work on Windows XP again (5.0.18
+          regression)</para>
+      </listitem>
+
+      <listitem>
+        <para>Windows Additions: fixed performance issues with PowerPoint
+          2010 and the WDDM graphics drivers if Aero is disabled</para>
+      </listitem>
+
+    </itemizedlist>
+
+  </sect1>
+
+  <sect1>
     <title>Version 5.0.18 (2016-04-18)</title>
 
     <para>This is a maintenance release. The following items were fixed and/or
@@ -769,13 +843,13 @@
       </listitem>
 
       <listitem>
-        <para>VBoxManage: fixed wrong output of <computeroutput>debugvm show</computeroutput>
+        <para>VBoxManage: fixed wrong output of <emphasis>debugvm show</emphasis>
           command</para>
       </listitem>
 
       <listitem>
         <para>VBoxManage: fixed hang when specifying logging groups with
-          <computeroutput>debugvm log</computeroutput> starting with
+          <emphasis>debugvm log</emphasis> starting with
           <emphasis>h</emphasis>, for example <emphasis>hex</emphasis></para>
       </listitem>
 
@@ -974,7 +1048,7 @@
       </listitem>
 
       <listitem>
-        <para>VBoxManage: fixed broken <computeroutput>guestcontrol <VM-Name> list</computeroutput>
+        <para>VBoxManage: fixed broken <emphasis>guestcontrol <VM-Name> list</emphasis>
           command (5.0 regression)</para>
       </listitem>
 
@@ -3857,7 +3931,7 @@
 
       <listitem>
         <para>VBoxManage: list more information about hard disk/DVD/floppy
-          media, and support the <computeroutput>--long</computeroutput>
+          media, and support the <emphasis>--long</emphasis>
           option to show really all available details</para>
       </listitem>
 
@@ -3869,35 +3943,35 @@
       <listitem>
         <para>VBoxManage: added support for listing active guest sessions, guest
           processes and/or guest files via
-          <computeroutput>guestcontrol list <all|sessions|processes|files></computeroutput>
+          <emphasis>guestcontrol list <all|sessions|processes|files></emphasis>
         </para>
       </listitem>
 
       <listitem>
         <para>VBoxManage: added support for closing active guest sessions via
-          <computeroutput>guestcontrol session close --session-id <ID>|
-            --session-name <name or pattern>|--all</computeroutput>
+          <emphasis>guestcontrol session close --session-id <ID>|
+            --session-name <name or pattern>|--all</emphasis>
         </para>
       </listitem>
 
       <listitem>
         <para>VBoxManage: added support for terminating active guest processes via
-          <computeroutput>guestcontrol process kill|close|terminate --session-id <ID>|
-            --session-name <name or pattern> <PID> ... <PID n></computeroutput>
+          <emphasis>guestcontrol process kill|close|terminate --session-id <ID>|
+            --session-name <name or pattern> <PID> ... <PID n></emphasis>
           or
-          <computeroutput>guestcontrol [p[s]]kill --session-id <ID>|
-            --session-name <name or pattern> <PID> ... <PID n></computeroutput>
+          <emphasis>guestcontrol [p[s]]kill --session-id <ID>|
+            --session-name <name or pattern> <PID> ... <PID n></emphasis>
         </para>
       </listitem>
 
       <listitem>
         <para>VBoxManage: added support for watching guest sessions via
-          <computeroutput>guestcontrol watch</computeroutput>
+          <emphasis>guestcontrol watch</emphasis>
         </para>
       </listitem>
 
       <listitem>
-        <para>VBoxManage: added <computeroutput>modifyvm --triplefaultreset</computeroutput>
+        <para>VBoxManage: added <emphasis>modifyvm --triplefaultreset</emphasis>
           to make the VM reset on triple fault instead of triggering a Guru Meditation
           (see <xref linkend="vboxmanage-modifyvm"/>)</para>
       </listitem>
diff --git a/include/VBox/GuestHost/GuestControl.h b/include/VBox/GuestHost/GuestControl.h
new file mode 100644
index 0000000..f72498d
--- /dev/null
+++ b/include/VBox/GuestHost/GuestControl.h
@@ -0,0 +1,189 @@
+/* $Id: GuestControl.h $ */
+/** @file
+ * Guest Control - Common Guest and Host Code.
+ */
+
+/*
+ * Copyright (C) 2016 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_GuestHost_GuestControl_h
+#define ___VBox_GuestHost_GuestControl_h
+
+/* Everything defined in this file lives in this namespace. */
+namespace guestControl {
+
+/**
+ * Process status when executed in the guest.
+ */
+enum eProcessStatus
+{
+    /** Process is in an undefined state. */
+    PROC_STS_UNDEFINED = 0,
+    /** Process has been started. */
+    PROC_STS_STARTED = 1,
+    /** Process terminated normally. */
+    PROC_STS_TEN = 2,
+    /** Process terminated via signal. */
+    PROC_STS_TES = 3,
+    /** Process terminated abnormally. */
+    PROC_STS_TEA = 4,
+    /** Process timed out and was killed. */
+    PROC_STS_TOK = 5,
+    /** Process timed out and was not killed successfully. */
+    PROC_STS_TOA = 6,
+    /** Service/OS is stopping, process was killed. */
+    PROC_STS_DWN = 7,
+    /** Something went wrong (error code in flags). */
+    PROC_STS_ERROR = 8
+};
+
+/** @todo r=bird: Most defines in this file needs to be scoped a little
+ *        better!  For instance INPUT_FLAG_NONE is very generic. */
+
+/**
+ * Input flags, set by the host. This is needed for
+ * handling flags on the guest side.
+ * Note: Has to match Main's ProcessInputFlag_* flags!
+ */
+#define INPUT_FLAG_NONE                     0x0
+#define INPUT_FLAG_EOF                      RT_BIT(0)
+
+/**
+ * Guest session creation flags.
+ * Only handled internally at the moment.
+ */
+#define SESSIONCREATIONFLAG_NONE            0x0
+
+/**
+ * Guest directory removement flags.
+ * Essentially using what IPRT's RTDIRRMREC_F_
+ * defines have to offer.
+ */
+#define DIRREMOVE_FLAG_RECURSIVE            RT_BIT(0)
+/** Delete the content of the directory and the directory itself. */
+#define DIRREMOVE_FLAG_CONTENT_AND_DIR      RT_BIT(1)
+/** Only delete the content of the directory, omit the directory it self. */
+#define DIRREMOVE_FLAG_CONTENT_ONLY         RT_BIT(2)
+/** Mask of valid flags. */
+#define DIRREMOVE_FLAG_VALID_MASK           UINT32_C(0x00000003)
+
+/** @name EXECUTEPROCESSFLAG_XXX Guest process creation flags.
+ * @note Has to match Main's ProcessCreateFlag_* flags!
+ */
+#define EXECUTEPROCESSFLAG_NONE             UINT32_C(0x0)
+#define EXECUTEPROCESSFLAG_WAIT_START       RT_BIT(0)
+#define EXECUTEPROCESSFLAG_IGNORE_ORPHANED  RT_BIT(1)
+#define EXECUTEPROCESSFLAG_HIDDEN           RT_BIT(2)
+#define EXECUTEPROCESSFLAG_NO_PROFILE       RT_BIT(3) /** @todo Rename to EXECUTEPROCESSFLAG_PROFILE in next API change. */
+#define EXECUTEPROCESSFLAG_WAIT_STDOUT      RT_BIT(4)
+#define EXECUTEPROCESSFLAG_WAIT_STDERR      RT_BIT(5)
+#define EXECUTEPROCESSFLAG_EXPAND_ARGUMENTS RT_BIT(6)
+#define EXECUTEPROCESSFLAG_UNQUOTED_ARGS    RT_BIT(7)
+/** @} */
+
+/**
+ * Pipe handle IDs used internally for referencing to
+ * a certain pipe buffer.
+ */
+#define OUTPUT_HANDLE_ID_STDOUT_DEPRECATED  0 /* Needed for VBox hosts < 4.1.0. */
+#define OUTPUT_HANDLE_ID_STDOUT             1
+#define OUTPUT_HANDLE_ID_STDERR             2
+
+/**
+ * Guest path rename flags.
+ * Essentially using what IPRT's RTPATHRENAME_FLAGS_
+ * defines have to offer.
+ */
+/** Do not replace anything. */
+#define PATHRENAME_FLAG_NO_REPLACE          UINT32_C(0)
+/** This will replace attempt any target which isn't a directory. */
+#define PATHRENAME_FLAG_REPLACE             RT_BIT(0)
+/** Don't allow symbolic links as part of the path. */
+#define PATHRENAME_FLAG_NO_SYMLINKS         RT_BIT(1)
+/** Mask of valid flags. */
+#define PATHRENAME_FLAG_VALID_MASK          UINT32_C(0x00000002)
+
+/**
+ * Defines for guest process array lengths.
+ */
+#define GUESTPROCESS_MAX_CMD_LEN            _1K
+#define GUESTPROCESS_MAX_ARGS_LEN           _1K
+#define GUESTPROCESS_MAX_ENV_LEN            _64K
+#define GUESTPROCESS_MAX_USER_LEN           128
+#define GUESTPROCESS_MAX_PASSWORD_LEN       128
+#define GUESTPROCESS_MAX_DOMAIN_LEN         256
+
+/** @name Internal tools built into VBoxService which are used in order to
+ *        accomplish tasks host<->guest.
+ * @{
+ */
+#define VBOXSERVICE_TOOL_CAT        "vbox_cat"
+#define VBOXSERVICE_TOOL_LS         "vbox_ls"
+#define VBOXSERVICE_TOOL_RM         "vbox_rm"
+#define VBOXSERVICE_TOOL_MKDIR      "vbox_mkdir"
+#define VBOXSERVICE_TOOL_MKTEMP     "vbox_mktemp"
+#define VBOXSERVICE_TOOL_STAT       "vbox_stat"
+/** @} */
+
+/** Special process exit codes for "vbox_cat". */
+typedef enum VBOXSERVICETOOLBOX_CAT_EXITCODE
+{
+    VBOXSERVICETOOLBOX_CAT_EXITCODE_ACCESS_DENIED = RTEXITCODE_END,
+    VBOXSERVICETOOLBOX_CAT_EXITCODE_FILE_NOT_FOUND,
+    VBOXSERVICETOOLBOX_CAT_EXITCODE_PATH_NOT_FOUND,
+    VBOXSERVICETOOLBOX_CAT_EXITCODE_SHARING_VIOLATION,
+    /** The usual 32-bit type hack. */
+    VBOXSERVICETOOLBOX_CAT_32BIT_HACK = 0x7fffffff
+} VBOXSERVICETOOLBOX_CAT_EXITCODE;
+
+/** Special process exit codes for "vbox_stat". */
+typedef enum VBOXSERVICETOOLBOX_STAT_EXITCODE
+{
+    VBOXSERVICETOOLBOX_STAT_EXITCODE_ACCESS_DENIED = RTEXITCODE_END,
+    VBOXSERVICETOOLBOX_STAT_EXITCODE_FILE_NOT_FOUND,
+    VBOXSERVICETOOLBOX_STAT_EXITCODE_PATH_NOT_FOUND,
+    /** The usual 32-bit type hack. */
+    VBOXSERVICETOOLBOX_STAT_32BIT_HACK = 0x7fffffff
+} VBOXSERVICETOOLBOX_STAT_EXITCODE;
+
+/**
+ * Input status, reported by the client.
+ */
+enum eInputStatus
+{
+    /** Input is in an undefined state. */
+    INPUT_STS_UNDEFINED = 0,
+    /** Input was written (partially, see cbProcessed). */
+    INPUT_STS_WRITTEN = 1,
+    /** Input failed with an error (see flags for rc). */
+    INPUT_STS_ERROR = 20,
+    /** Process has abandoned / terminated input handling. */
+    INPUT_STS_TERMINATED = 21,
+    /** Too much input data. */
+    INPUT_STS_OVERFLOW = 30
+};
+
+
+
+} /* namespace guestControl */
+
+#endif /* ___VBox_GuestHost_GuestControl_h */
+
diff --git a/include/VBox/HostServices/GuestControlSvc.h b/include/VBox/HostServices/GuestControlSvc.h
index 50abbc1..0554bad 100644
--- a/include/VBox/HostServices/GuestControlSvc.h
+++ b/include/VBox/HostServices/GuestControlSvc.h
@@ -1,9 +1,10 @@
+/* $Id: GuestControlSvc.h $ */
 /** @file
  * Guest control service - Common header for host service and guest clients.
  */
 
 /*
- * Copyright (C) 2011-2015 Oracle Corporation
+ * Copyright (C) 2011-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -81,136 +82,6 @@ namespace guestControl {
     (VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(uSession) | 0xF8000000)
 
 /**
- * Process status when executed in the guest.
- */
-enum eProcessStatus
-{
-    /** Process is in an undefined state. */
-    PROC_STS_UNDEFINED = 0,
-    /** Process has been started. */
-    PROC_STS_STARTED = 1,
-    /** Process terminated normally. */
-    PROC_STS_TEN = 2,
-    /** Process terminated via signal. */
-    PROC_STS_TES = 3,
-    /** Process terminated abnormally. */
-    PROC_STS_TEA = 4,
-    /** Process timed out and was killed. */
-    PROC_STS_TOK = 5,
-    /** Process timed out and was not killed successfully. */
-    PROC_STS_TOA = 6,
-    /** Service/OS is stopping, process was killed. */
-    PROC_STS_DWN = 7,
-    /** Something went wrong (error code in flags). */
-    PROC_STS_ERROR = 8
-};
-
-/** @todo r=bird: Most defines in this file needs to be scoped a little
- *        better!  For instance INPUT_FLAG_NONE is very generic. */
-
-/**
- * Input flags, set by the host. This is needed for
- * handling flags on the guest side.
- * Note: Has to match Main's ProcessInputFlag_* flags!
- */
-#define INPUT_FLAG_NONE                     0x0
-#define INPUT_FLAG_EOF                      RT_BIT(0)
-
-/**
- * Guest session creation flags.
- * Only handled internally at the moment.
- */
-#define SESSIONCREATIONFLAG_NONE            0x0
-
-/**
- * Guest directory removement flags.
- * Essentially using what IPRT's RTDIRRMREC_F_
- * defines have to offer.
- */
-#define DIRREMOVE_FLAG_RECURSIVE            RT_BIT(0)
-/** Delete the content of the directory and the directory itself. */
-#define DIRREMOVE_FLAG_CONTENT_AND_DIR      RT_BIT(1)
-/** Only delete the content of the directory, omit the directory it self. */
-#define DIRREMOVE_FLAG_CONTENT_ONLY         RT_BIT(2)
-/** Mask of valid flags. */
-#define DIRREMOVE_FLAG_VALID_MASK           UINT32_C(0x00000003)
-
-/** @name EXECUTEPROCESSFLAG_XXX Guest process creation flags.
- * @note Has to match Main's ProcessCreateFlag_* flags!
- */
-#define EXECUTEPROCESSFLAG_NONE             UINT32_C(0x0)
-#define EXECUTEPROCESSFLAG_WAIT_START       RT_BIT(0)
-#define EXECUTEPROCESSFLAG_IGNORE_ORPHANED  RT_BIT(1)
-#define EXECUTEPROCESSFLAG_HIDDEN           RT_BIT(2)
-#define EXECUTEPROCESSFLAG_NO_PROFILE       RT_BIT(3) /** @todo Rename to EXECUTEPROCESSFLAG_PROFILE in next API change. */
-#define EXECUTEPROCESSFLAG_WAIT_STDOUT      RT_BIT(4)
-#define EXECUTEPROCESSFLAG_WAIT_STDERR      RT_BIT(5)
-#define EXECUTEPROCESSFLAG_EXPAND_ARGUMENTS RT_BIT(6)
-#define EXECUTEPROCESSFLAG_UNQUOTED_ARGS    RT_BIT(7)
-/** @} */
-
-/**
- * Pipe handle IDs used internally for referencing to
- * a certain pipe buffer.
- */
-#define OUTPUT_HANDLE_ID_STDOUT_DEPRECATED  0 /* Needed for VBox hosts < 4.1.0. */
-#define OUTPUT_HANDLE_ID_STDOUT             1
-#define OUTPUT_HANDLE_ID_STDERR             2
-
-/**
- * Guest path rename flags.
- * Essentially using what IPRT's RTPATHRENAME_FLAGS_
- * defines have to offer.
- */
-/** Do not replace anything. */
-#define PATHRENAME_FLAG_NO_REPLACE          UINT32_C(0)
-/** This will replace attempt any target which isn't a directory. */
-#define PATHRENAME_FLAG_REPLACE             RT_BIT(0)
-/** Don't allow symbolic links as part of the path. */
-#define PATHRENAME_FLAG_NO_SYMLINKS         RT_BIT(1)
-/** Mask of valid flags. */
-#define PATHRENAME_FLAG_VALID_MASK          UINT32_C(0x00000002)
-
-/**
- * Defines for guest process array lengths.
- */
-#define GUESTPROCESS_MAX_CMD_LEN            _1K
-#define GUESTPROCESS_MAX_ARGS_LEN           _1K
-#define GUESTPROCESS_MAX_ENV_LEN            _64K
-#define GUESTPROCESS_MAX_USER_LEN           128
-#define GUESTPROCESS_MAX_PASSWORD_LEN       128
-#define GUESTPROCESS_MAX_DOMAIN_LEN         256
-
-/** @name Internal tools built into VBoxService which are used in order to
- *        accomplish tasks host<->guest.
- * @{
- */
-#define VBOXSERVICE_TOOL_CAT        "vbox_cat"
-#define VBOXSERVICE_TOOL_LS         "vbox_ls"
-#define VBOXSERVICE_TOOL_RM         "vbox_rm"
-#define VBOXSERVICE_TOOL_MKDIR      "vbox_mkdir"
-#define VBOXSERVICE_TOOL_MKTEMP     "vbox_mktemp"
-#define VBOXSERVICE_TOOL_STAT       "vbox_stat"
-/** @} */
-
-/**
- * Input status, reported by the client.
- */
-enum eInputStatus
-{
-    /** Input is in an undefined state. */
-    INPUT_STS_UNDEFINED = 0,
-    /** Input was written (partially, see cbProcessed). */
-    INPUT_STS_WRITTEN = 1,
-    /** Input failed with an error (see flags for rc). */
-    INPUT_STS_ERROR = 20,
-    /** Process has abandoned / terminated input handling. */
-    INPUT_STS_TERMINATED = 21,
-    /** Too much input data. */
-    INPUT_STS_OVERFLOW = 30
-};
-
-/**
  * Structure keeping the context of a host callback.
  */
 typedef struct VBoxGuestCtrlHostCbCtx
diff --git a/include/VBox/err.h b/include/VBox/err.h
index 7ca4a5c..b8e911e 100644
--- a/include/VBox/err.h
+++ b/include/VBox/err.h
@@ -3,7 +3,7 @@
  */
 
 /*
- * Copyright (C) 2006-2015 Oracle Corporation
+ * Copyright (C) 2006-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -2642,6 +2642,10 @@
 #define VERR_GSTCTL_GUEST_ERROR                     (-6200)
 /** A guest control object has changed its overall status. */
 #define VWRN_GSTCTL_OBJECTSTATE_CHANGED             6220
+/** Guest process is in a wrong state. */
+#define VERR_GSTCTL_PROCESS_WRONG_STATE             (-6221)
+/** Started guest process terminated with an exit code <> 0. */
+#define VWRN_GSTCTL_PROCESS_EXIT_CODE               6221
 /** @} */
 
 
diff --git a/include/iprt/asm.h b/include/iprt/asm.h
index dafc70c..0cf67e0 100644
--- a/include/iprt/asm.h
+++ b/include/iprt/asm.h
@@ -3520,6 +3520,45 @@ DECLINLINE(void) ASMMemFill32(volatile void *pv, size_t cb, uint32_t u32)
 
 
 /**
+ * Checks if a memory block is all zeros.
+ *
+ * @returns Pointer to the first non-zero byte.
+ * @returns NULL if all zero.
+ *
+ * @param   pv      Pointer to the memory block.
+ * @param   cb      Number of bytes in the block.
+ *
+ * @todo Fix name, it is a predicate function but it's not returning boolean!
+ */
+DECLINLINE(void *) ASMMemFirstNonZero(void const *pv, size_t cb)
+{
+    uint8_t const *pb = (uint8_t const *)pv;
+    for (; cb; cb--, pb++)
+        if (RT_LIKELY(*pb == 0))
+        { /* likely */ }
+        else
+            return (void *)pb;
+    return NULL;
+}
+
+
+/**
+ * Checks if a memory block is all zeros.
+ *
+ * @returns true if zero, false if not.
+ *
+ * @param   pv      Pointer to the memory block.
+ * @param   cb      Number of bytes in the block.
+ *
+ * @sa      ASMMemFirstNonZero
+ */
+DECLINLINE(bool) ASMMemIsZero(void const *pv, size_t cb)
+{
+    return ASMMemFirstNonZero(pv, cb) == NULL;
+}
+
+
+/**
  * Checks if a memory page is all zeros.
  *
  * @returns true / false.
diff --git a/src/VBox/Additions/common/VBoxGuest/Makefile.kmk b/src/VBox/Additions/common/VBoxGuest/Makefile.kmk
index cfa0275..88edfad 100644
--- a/src/VBox/Additions/common/VBoxGuest/Makefile.kmk
+++ b/src/VBox/Additions/common/VBoxGuest/Makefile.kmk
@@ -84,6 +84,7 @@ if1of ($(KBUILD_TARGET), darwin freebsd haiku $(if $(defined VBOX_WITH_ADDITION_
    VBoxGuest_SOURCES    = VBoxGuest-$(KBUILD_TARGET).cpp
   else
    VBoxGuest_SOURCES    = VBoxGuest-$(KBUILD_TARGET).c
+   VBoxGuest_$(KBUILD_TARGET).c_DEPS = $(VBOX_SVN_REV_HEADER)
   endif
   VBoxGuest_SOURCES     += \
   	VBoxGuest.cpp
diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c
index abc038d..84e7696 100644
--- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c
+++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c
@@ -1,4 +1,4 @@
-/* $Rev: 103598 $ */
+/* $Rev: 106728 $ */
 /** @file
  * VBoxGuest - Linux specifics.
  *
@@ -37,6 +37,7 @@
 #include <linux/miscdevice.h>
 #include <linux/poll.h>
 #include <VBox/version.h>
+#include "revision-generated.h"
 
 #include <iprt/assert.h>
 #include <iprt/asm.h>
@@ -1081,6 +1082,6 @@ MODULE_AUTHOR(VBOX_VENDOR);
 MODULE_DESCRIPTION(VBOX_PRODUCT " Guest Additions for Linux Module");
 MODULE_LICENSE("GPL");
 #ifdef MODULE_VERSION
-MODULE_VERSION(VBOX_VERSION_STRING);
+MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
 #endif
 
diff --git a/src/VBox/Additions/common/VBoxService/VBoxService.cpp b/src/VBox/Additions/common/VBoxService/VBoxService.cpp
index 77741de..ecd8ef7 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxService.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxService.cpp
@@ -91,6 +91,9 @@
 #ifdef VBOX_WITH_GUEST_CONTROL
 # include "VBoxServiceControl.h"
 #endif
+#ifdef VBOXSERVICE_TOOLBOX
+# include "VBoxServiceToolBox.h"
+#endif
 
 
 /*********************************************************************************************************************************
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h b/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h
index 3858f08..ab764e3 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2013-2015 Oracle Corporation
+ * Copyright (C) 2013-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -23,6 +23,7 @@
 #include <iprt/req.h>
 
 #include <VBox/VBoxGuestLib.h>
+#include <VBox/GuestHost/GuestControl.h>
 #include <VBox/HostServices/GuestControlSvc.h>
 
 
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp b/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp
index 225ac3c..4c7300f 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp
@@ -39,6 +39,7 @@
 
 #include "VBoxServiceInternal.h"
 #include "VBoxServiceControl.h"
+#include "VBoxServiceToolBox.h"
 
 using namespace guestControl;
 
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp b/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp
index 758d75b..dd73b1f 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2012-2015 Oracle Corporation
+ * Copyright (C) 2012-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -40,9 +40,14 @@
 
 #include <VBox/VBoxGuestLib.h>
 #include <VBox/version.h>
+
+#include <VBox/GuestHost/GuestControl.h>
+
 #include "VBoxServiceInternal.h"
+#include "VBoxServiceToolBox.h"
 #include "VBoxServiceUtils.h"
 
+using namespace guestControl;
 
 /*********************************************************************************************************************************
 *   Defined Constants And Macros                                                                                                 *
@@ -77,13 +82,43 @@ typedef enum VBOXSERVICETOOLBOXOUTPUTFLAG
     VBOXSERVICETOOLBOXOUTPUTFLAG_PARSEABLE =    0x2
 } VBOXSERVICETOOLBOXOUTPUTFLAG;
 
+/*********************************************************************************************************************************
+*   Prototypes                                                                                                                   *
+*********************************************************************************************************************************/
+static RTEXITCODE vgsvcToolboxCat(int argc, char **argv);
+static RTEXITCODE vgsvcToolboxLs(int argc, char **argv);
+static RTEXITCODE vgsvcToolboxRm(int argc, char **argv);
+static RTEXITCODE vgsvcToolboxMkTemp(int argc, char **argv);
+static RTEXITCODE vgsvcToolboxMkDir(int argc, char **argv);
+static RTEXITCODE vgsvcToolboxStat(int argc, char **argv);
 
 /*********************************************************************************************************************************
 *   Structures and Typedefs                                                                                                      *
 *********************************************************************************************************************************/
-/** Pointer to a handler function. */
+/** Pointer to a tool handler function. */
 typedef RTEXITCODE (*PFNHANDLER)(int , char **);
 
+/** Definition for a specific toolbox tool. */
+typedef struct VBOXSERVICETOOLBOXTOOL
+{
+    /** Friendly name of the tool. */
+    const char *pszName;
+    /** Main handler to be invoked to use the tool. */
+    RTEXITCODE (*pfnHandler)(int argc, char **argv);
+    /** Conversion routine to convert the tool's exit code back to an IPRT rc. Optional. */
+    int        (*pfnExitCodeConvertToRc)(RTEXITCODE rcExit);
+} VBOXSERVICETOOLBOXTOOL, *PVBOXSERVICETOOLBOXTOOL;
+
+static VBOXSERVICETOOLBOXTOOL s_aTools[] =
+{
+    { VBOXSERVICE_TOOL_CAT,    vgsvcToolboxCat   , NULL },
+    { VBOXSERVICE_TOOL_LS,     vgsvcToolboxLs    , NULL },
+    { VBOXSERVICE_TOOL_RM,     vgsvcToolboxRm    , NULL },
+    { VBOXSERVICE_TOOL_MKTEMP, vgsvcToolboxMkTemp, NULL },
+    { VBOXSERVICE_TOOL_MKDIR,  vgsvcToolboxMkDir , NULL },
+    { VBOXSERVICE_TOOL_STAT,   vgsvcToolboxStat  , NULL }
+};
+
 /**
  * An file/directory entry. Used to cache
  * file names/paths for later processing.
@@ -467,7 +502,7 @@ static RTEXITCODE vgsvcToolboxCat(int argc, char **argv)
                     break;
             }
 
-            /* If not input files were defined, process stdin. */
+            /* If no input files were defined, process stdin. */
             if (RTListNodeIsFirst(&inputList, &inputList))
                 rc = vgsvcToolboxCatOutput(hInput, hOutput);
         }
@@ -477,7 +512,33 @@ static RTEXITCODE vgsvcToolboxCat(int argc, char **argv)
         RTFileClose(hOutput);
     vgsvcToolboxPathBufDestroy(&inputList);
 
-    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
+    if (RT_FAILURE(rc))
+    {
+        switch (rc)
+        {
+            case VERR_ACCESS_DENIED:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_ACCESS_DENIED;
+
+            case VERR_FILE_NOT_FOUND:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_FILE_NOT_FOUND;
+
+            case VERR_PATH_NOT_FOUND:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_PATH_NOT_FOUND;
+
+            case VERR_SHARING_VIOLATION:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_SHARING_VIOLATION;
+
+            default:
+#ifdef DEBUG_andy
+                AssertMsgFailed(("Exit code for %Rrc not implemented\n", rc));
+#endif
+                break;
+        }
+
+        return RTEXITCODE_FAILURE;
+    }
+
+    return RTEXITCODE_SUCCESS;
 }
 
 /**
@@ -1402,12 +1463,8 @@ static RTEXITCODE vgsvcToolboxStat(int argc, char **argv)
             int rc2 = RTPathQueryInfoEx(pNodeIt->pszName, &objInfo, RTFSOBJATTRADD_UNIX, fQueryInfoFlags);
             if (RT_FAILURE(rc2))
             {
-/** @todo r=bird: You can get a number of other errors here, like access denied. */
                 if (!(fOutputFlags & VBOXSERVICETOOLBOXOUTPUTFLAG_PARSEABLE))
-                    RTMsgError("Cannot stat for '%s': No such file or directory (%Rrc)\n", pNodeIt->pszName, rc);
-                rc = VERR_FILE_NOT_FOUND;
-                /* Do not break here -- process every element in the list
-                 * and keep failing rc. */
+                    RTMsgError("Cannot stat for '%s': %Rrc\n", pNodeIt->pszName, rc2);
             }
             else
             {
@@ -1415,9 +1472,12 @@ static RTEXITCODE vgsvcToolboxStat(int argc, char **argv)
                                               strlen(pNodeIt->pszName) /* cbName */,
                                               fOutputFlags,
                                               &objInfo);
-                if (RT_FAILURE(rc2))
-                    rc = rc2;
             }
+
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+            /* Do not break here -- process every element in the list
+             * and keep (initial) failing rc. */
         }
 
         if (fOutputFlags & VBOXSERVICETOOLBOXOUTPUTFLAG_PARSEABLE) /* Output termination. */
@@ -1432,52 +1492,74 @@ static RTEXITCODE vgsvcToolboxStat(int argc, char **argv)
         RTMsgError("Failed with rc=%Rrc\n", rc);
 
     vgsvcToolboxPathBufDestroy(&fileList);
-    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
-}
 
+    if (RT_FAILURE(rc))
+    {
+        switch (rc)
+        {
+            case VERR_ACCESS_DENIED:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_STAT_EXITCODE_ACCESS_DENIED;
+
+            case VERR_FILE_NOT_FOUND:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_STAT_EXITCODE_FILE_NOT_FOUND;
+
+            case VERR_PATH_NOT_FOUND:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_STAT_EXITCODE_PATH_NOT_FOUND;
+
+            default:
+#ifdef DEBUG_andy
+                AssertMsgFailed(("Exit code for %Rrc not implemented\n", rc));
+#endif
+                break;
+        }
+
+        return RTEXITCODE_FAILURE;
+    }
+
+    return RTEXITCODE_SUCCESS;
+}
 
 
 /**
- * Looks up the handler for the tool give by @a pszTool.
+ * Looks up the tool definition entry for the tool give by @a pszTool.
  *
- * @returns Pointer to handler function.  NULL if not found.
+ * @returns Pointer to the tool definition.  NULL if not found.
  * @param   pszTool     The name of the tool.
  */
-static PFNHANDLER vgsvcToolboxLookUpHandler(const char *pszTool)
+static PVBOXSERVICETOOLBOXTOOL const vgsvcToolboxLookUp(const char *pszTool)
 {
-    static struct
-    {
-        const char *pszName;
-        RTEXITCODE (*pfnHandler)(int argc, char **argv);
-    }
-    const s_aTools[] =
-    {
-        { "cat",    vgsvcToolboxCat    },
-        { "ls",     vgsvcToolboxLs     },
-        { "rm",     vgsvcToolboxRm     },
-        { "mktemp", vgsvcToolboxMkTemp },
-        { "mkdir",  vgsvcToolboxMkDir  },
-        { "stat",   vgsvcToolboxStat   },
-    };
-
-    /* Skip optional 'vbox_' prefix. */
-    if (   pszTool[0] == 'v'
-        && pszTool[1] == 'b'
-        && pszTool[2] == 'o'
-        && pszTool[3] == 'x'
-        && pszTool[4] == '_')
-        pszTool += 5;
+    AssertPtrReturn(pszTool, NULL);
 
     /* Do a linear search, since we don't have that much stuff in the table. */
     for (unsigned i = 0; i < RT_ELEMENTS(s_aTools); i++)
         if (!strcmp(s_aTools[i].pszName, pszTool))
-            return s_aTools[i].pfnHandler;
+            return &s_aTools[i];
 
     return NULL;
 }
 
 
 /**
+ * Converts a tool's exit code back to an IPRT error code.
+ *
+ * @return  Converted IPRT status code.
+ * @param   pszTool                 Name of the toolbox tool to convert exit code for.
+ * @param   rcExit                  The tool's exit code to convert.
+ */
+int VGSvcToolboxExitCodeConvertToRc(const char *pszTool, RTEXITCODE rcExit)
+{
+    AssertPtrReturn(pszTool, VERR_INVALID_POINTER);
+
+    PVBOXSERVICETOOLBOXTOOL pTool = vgsvcToolboxLookUp(pszTool);
+    if (pTool)
+        return pTool->pfnExitCodeConvertToRc(rcExit);
+
+    AssertMsgFailed(("Tool '%s' not found\n", pszTool));
+    return VERR_GENERAL_FAILURE; /* Lookup failed, should not happen. */
+}
+
+
+/**
  * Entry point for internal toolbox.
  *
  * @return  True if an internal tool was handled, false if not.
@@ -1493,9 +1575,9 @@ bool VGSvcToolboxMain(int argc, char **argv, RTEXITCODE *prcExit)
      * Check if the file named in argv[0] is one of the toolbox programs.
      */
     AssertReturn(argc > 0, false);
-    const char *pszTool    = RTPathFilename(argv[0]);
-    PFNHANDLER  pfnHandler = vgsvcToolboxLookUpHandler(pszTool);
-    if (!pfnHandler)
+    const char              *pszTool = RTPathFilename(argv[0]);
+    PVBOXSERVICETOOLBOXTOOL  pTool   = vgsvcToolboxLookUp(pszTool);
+    if (!pTool)
     {
         /*
          * For debugging and testing purposes we also allow toolbox program access
@@ -1506,8 +1588,8 @@ bool VGSvcToolboxMain(int argc, char **argv, RTEXITCODE *prcExit)
         argc -= 2;
         argv += 2;
         pszTool = argv[0];
-        pfnHandler = vgsvcToolboxLookUpHandler(pszTool);
-        if (!pfnHandler)
+        pTool = vgsvcToolboxLookUp(pszTool);
+        if (!pTool)
         {
            *prcExit = RTEXITCODE_SUCCESS;
            if (!strcmp(pszTool, "-V"))
@@ -1527,7 +1609,8 @@ bool VGSvcToolboxMain(int argc, char **argv, RTEXITCODE *prcExit)
      * Invoke the handler.
      */
     RTMsgSetProgName("VBoxService/%s", pszTool);
-    *prcExit = pfnHandler(argc, argv);
+    AssertPtr(pTool);
+    *prcExit = pTool->pfnHandler(argc, argv);
 
     return true;
 }
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.h b/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.h
new file mode 100644
index 0000000..5e4cc61
--- /dev/null
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.h
@@ -0,0 +1,29 @@
+/* $Id: VBoxServiceToolBox.h $ */
+/** @file
+ * VBoxService - Toolbox header for sharing defines between toolbox binary and VBoxService.
+ */
+
+/*
+ * Copyright (C) 2016 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ___VBoxServiceToolBox_h
+#define ___VBoxServiceToolBox_h
+
+#include <VBox/GuestHost/GuestControl.h>
+
+RT_C_DECLS_BEGIN
+extern bool                     VGSvcToolboxMain(int argc, char **argv, RTEXITCODE *prcExit);
+extern int                      VGSvcToolboxExitCodeConvertToRc(const char *pszTool, RTEXITCODE rcExit);
+RT_C_DECLS_END
+
+#endif /* ___VBoxServiceToolBox_h */
+
diff --git a/src/VBox/Additions/linux/drm/Makefile.kmk b/src/VBox/Additions/linux/drm/Makefile.kmk
index 6dd6f4e..dcdcd99 100644
--- a/src/VBox/Additions/linux/drm/Makefile.kmk
+++ b/src/VBox/Additions/linux/drm/Makefile.kmk
@@ -68,5 +68,7 @@ vboxvideo_drm_SOURCES         = \
 	vbox_mode.c \
 	vbox_ttm.c
 
+vbox_drv.c_DEPS               = $(VBOX_SVN_REV_HEADER)
+
 include $(FILE_KBUILD_SUB_FOOTER)
 
diff --git a/src/VBox/Additions/linux/drm/files_vboxvideo_drv b/src/VBox/Additions/linux/drm/files_vboxvideo_drv
index a4d0475..8fcd72c 100755
--- a/src/VBox/Additions/linux/drm/files_vboxvideo_drv
+++ b/src/VBox/Additions/linux/drm/files_vboxvideo_drv
@@ -18,6 +18,7 @@
 
 FILES_VBOXVIDEO_DRM_NOBIN=" \
     ${PATH_OUT}/version-generated.h=>version-generated.h \
+    ${PATH_OUT}/revision-generated.h=>revision-generated.h \
     ${PATH_OUT}/product-generated.h=>product-generated.h \
     ${PATH_ROOT}/include/iprt/asm.h=>include/iprt/asm.h \
     ${PATH_ROOT}/include/iprt/asm-amd64-x86.h=>include/iprt/asm-amd64-x86.h \
diff --git a/src/VBox/Additions/linux/drm/vbox_drv.c b/src/VBox/Additions/linux/drm/vbox_drv.c
index 7aeaee7..d68ec15 100644
--- a/src/VBox/Additions/linux/drm/vbox_drv.c
+++ b/src/VBox/Additions/linux/drm/vbox_drv.c
@@ -48,6 +48,8 @@
 #include "vbox_drv.h"
 
 #include <VBox/VBoxGuest.h>
+#include "version-generated.h"
+#include "revision-generated.h"
 
 #include <linux/module.h>
 #include <linux/console.h>
@@ -293,4 +295,6 @@ module_exit(vbox_exit);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL and additional rights");
-
+#ifdef MODULE_VERSION
+MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
+#endif
diff --git a/src/VBox/Additions/linux/sharedfolders/Makefile.kmk b/src/VBox/Additions/linux/sharedfolders/Makefile.kmk
index df78ef0..b1f69ba 100644
--- a/src/VBox/Additions/linux/sharedfolders/Makefile.kmk
+++ b/src/VBox/Additions/linux/sharedfolders/Makefile.kmk
@@ -68,6 +68,8 @@ ifdef VBOX_WITH_ADDITION_DRIVERS
  	regops.c
  vboxsf_LIBS            = \
  	$(VBOX_LIB_VBGL_R0)
+
+vfsmod.c_DEPS           = $(VBOX_SVN_REV_HEADER)
 endif
 
 #
diff --git a/src/VBox/Additions/linux/sharedfolders/files_vboxsf b/src/VBox/Additions/linux/sharedfolders/files_vboxsf
index ba97287..072855a 100755
--- a/src/VBox/Additions/linux/sharedfolders/files_vboxsf
+++ b/src/VBox/Additions/linux/sharedfolders/files_vboxsf
@@ -84,6 +84,7 @@ FILES_VBOXSF_NOBIN=" \
     ${PATH_ROOT}/src/VBox/Additions/linux/sharedfolders/vfsmod.c=>vfsmod.c \
     ${PATH_ROOT}/src/VBox/Additions/linux/sharedfolders/vfsmod.h=>vfsmod.h \
     ${PATH_OUT}/version-generated.h=>version-generated.h \
+    ${PATH_OUT}/revision-generated.h=>revision-generated.h \
     ${PATH_OUT}/product-generated.h=>product-generated.h \
 "
 
diff --git a/src/VBox/Additions/linux/sharedfolders/vfsmod.c b/src/VBox/Additions/linux/sharedfolders/vfsmod.c
index a3cd550..7cf384f 100644
--- a/src/VBox/Additions/linux/sharedfolders/vfsmod.c
+++ b/src/VBox/Additions/linux/sharedfolders/vfsmod.c
@@ -29,12 +29,15 @@
  */
 
 #include "vfsmod.h"
+#include "version-generated.h"
+#include "revision-generated.h"
+#include "product-generated.h"
 
 MODULE_DESCRIPTION(VBOX_PRODUCT " VFS Module for Host File System Access");
 MODULE_AUTHOR(VBOX_VENDOR);
 MODULE_LICENSE("GPL");
 #ifdef MODULE_VERSION
-MODULE_VERSION(VBOX_VERSION_STRING " (interface " RT_XSTR(VMMDEV_VERSION) ")");
+MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
 #endif
 
 /* globals */
diff --git a/src/VBox/Additions/linux/sharedfolders/vfsmod.h b/src/VBox/Additions/linux/sharedfolders/vfsmod.h
index 482a848..5c74454 100644
--- a/src/VBox/Additions/linux/sharedfolders/vfsmod.h
+++ b/src/VBox/Additions/linux/sharedfolders/vfsmod.h
@@ -19,8 +19,6 @@
 
 #define LOG_GROUP LOG_GROUP_SHARED_FOLDERS
 #include "the-linux-kernel.h"
-#include "version-generated.h"
-#include "product-generated.h"
 #include <VBox/log.h>
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
diff --git a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd
index 911c0a1..fcec762 100644
Binary files a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd and b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd differ
diff --git a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd
index 46653d5..e715cd2 100644
Binary files a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd and b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd differ
diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm
index fad26b5..8085290 100644
--- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm
+++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm
@@ -6769,7 +6769,7 @@ vesa_pm_end:                                 ; 0xc4514 LB 0x1
 
 section _DATA progbits vstart=0x4600 align=1 ; size=0x371f class=DATA group=DGROUP
 _msg_vga_init:                               ; 0xc4600 LB 0x2f
-    db  'Oracle VM VirtualBox Version 5.0.18 VGA BIOS', 00dh, 00ah, 000h
+    db  'Oracle VM VirtualBox Version 5.0.20 VGA BIOS', 00dh, 00ah, 000h
 _vga_modes:                                  ; 0xc462f LB 0x80
     db  000h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 001h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h
     db  002h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 003h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h
@@ -7664,7 +7664,7 @@ _vbebios_vendor_name:                        ; 0xc7c73 LB 0x13
 _vbebios_product_name:                       ; 0xc7c86 LB 0x21
     db  'Oracle VM VirtualBox VBE Adapter', 000h
 _vbebios_product_revision:                   ; 0xc7ca7 LB 0x24
-    db  'Oracle VM VirtualBox Version 5.0.18', 000h
+    db  'Oracle VM VirtualBox Version 5.0.20', 000h
 _vbebios_info_string:                        ; 0xc7ccb LB 0x2b
     db  'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h
 _no_vbebios_info_string:                     ; 0xc7cf6 LB 0x29
@@ -7723,4 +7723,4 @@ section CONST2 progbits vstart=0x7d20 align=1 ; size=0x0 class=DATA group=DGROUP
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
     db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
-    db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0f2h
+    db  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum
index 0f902b7..a0ecb4e 100644
--- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum
+++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum
@@ -1 +1 @@
-4a37bf744161cfd7e332ef9a484791b7 *VBoxVgaBios.rom
+4a89d95410a44107932b81c95b25d2a5 *VBoxVgaBios.rom
diff --git a/src/VBox/Devices/Makefile.kmk b/src/VBox/Devices/Makefile.kmk
index 5f0195c..8c8be27 100644
--- a/src/VBox/Devices/Makefile.kmk
+++ b/src/VBox/Devices/Makefile.kmk
@@ -600,6 +600,7 @@ if !defined(VBOX_ONLY_EXTPACKS)         # Goes on almost to the end of the file.
  	Network/slirp/tcp_subr.c \
  	Network/slirp/tcp_timer.c \
  	Network/slirp/udp.c \
+	Network/slirp/hostres.c \
  	Network/slirp/dnsproxy/hash.c \
  	Network/slirp/tftp.c \
  	Network/slirp/dnsproxy/dnsproxy.c
@@ -628,7 +629,6 @@ if !defined(VBOX_ONLY_EXTPACKS)         # Goes on almost to the end of the file.
  	Network/slirp/libalias/alias_mod.c \
  	Network/slirp/libalias/alias_proxy.c \
  	Network/slirp/libalias/alias_ftp.c \
- 	Network/slirp/libalias/alias_dns.c \
  	Network/slirp/libalias/alias_nbt.c \
  	Network/slirp/libalias/alias_util.c
 
@@ -816,11 +816,13 @@ if !defined(VBOX_ONLY_EXTPACKS)         # Goes on almost to the end of the file.
 	$(call MSG_TOOL,iasl,VBoxDD,$<,$@)
 	$(QUIET)$(RM) -f $@ $@.tmp $@.pre
 	$(QUIET)$(TOOL_$(VBOX_GCC_TOOL)_CC) -E -P -x c -o $@.pre $<
-	$(QUIET)$(VBOX_IASLCMD) -tc -vs -p $@ $@.pre
+	$(QUIET)$(SED) "s/<NL>/\n/g" \
+		--output $@.pre1 $@.pre
+	$(QUIET)$(VBOX_IASLCMD) -tc -vs -p $@ $@.pre1
 	$(QUIET)$(MV) -f $@ $@.tmp
 	$(QUIET)$(SED) "s/AmlCode/AmlCodeSsdtCpuHotPlug/g" \
 		--output $@ $@.tmp
-	$(QUIET)$(RM) -f $@.tmp $@.pre
+	$(QUIET)$(RM) -f $@.tmp $@.pre $@.pre1
 
 
   vboxssdt-cpuhotplug.hex:: $$(VBoxDD_0_OUTDIR)/vboxssdt-cpuhotplug.hex
diff --git a/src/VBox/Devices/Network/DrvNAT.cpp b/src/VBox/Devices/Network/DrvNAT.cpp
index 6f39646..98086fb 100644
--- a/src/VBox/Devices/Network/DrvNAT.cpp
+++ b/src/VBox/Devices/Network/DrvNAT.cpp
@@ -210,6 +210,11 @@ typedef struct DRVNAT
     /** Transmit lock taken by BeginXmit and released by EndXmit. */
     RTCRITSECT              XmitLock;
 
+    /** Request queue for the async host resolver. */
+    RTREQQUEUE               hHostResQueue;
+    /** Async host resolver thread. */
+    PPDMTHREAD               pHostResThread;
+
 #ifdef RT_OS_DARWIN
     /* Handle of the DNS watcher runloop source. */
     CFRunLoopSourceRef      hRunLoopSrcDnsWatcher;
@@ -692,11 +697,6 @@ static void drvNATNotifyApplyPortForwardCommand(PDRVNAT pThis, bool fRemove,
                                                 bool fUdp, const char *pHostIp,
                                                 uint16_t u16HostPort, const char *pGuestIp, uint16_t u16GuestPort)
 {
-    RTMAC Mac;
-    RT_ZERO(Mac); /* can't get MAC here */
-    if (pThis->pIAboveConfig)
-        pThis->pIAboveConfig->pfnGetMac(pThis->pIAboveConfig, &Mac);
-
     struct in_addr guestIp, hostIp;
 
     if (   pHostIp == NULL
@@ -710,7 +710,7 @@ static void drvNATNotifyApplyPortForwardCommand(PDRVNAT pThis, bool fRemove,
     if (fRemove)
         slirp_remove_redirect(pThis->pNATState, fUdp, hostIp, u16HostPort, guestIp, u16GuestPort);
     else
-        slirp_add_redirect(pThis->pNATState, fUdp, hostIp, u16HostPort, guestIp, u16GuestPort, Mac.au8);
+        slirp_add_redirect(pThis->pNATState, fUdp, hostIp, u16HostPort, guestIp, u16GuestPort);
 }
 
 static DECLCALLBACK(int) drvNATNetworkNatConfigRedirect(PPDMINETWORKNATCONFIG pInterface, bool fRemove,
@@ -896,6 +896,46 @@ static DECLCALLBACK(int) drvNATAsyncIoWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThr
     return VINF_SUCCESS;
 }
 
+
+static DECLCALLBACK(int) drvNATHostResThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
+{
+    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
+
+    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
+        return VINF_SUCCESS;
+
+    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
+    {
+        RTReqQueueProcess(pThis->hHostResQueue, RT_INDEFINITE_WAIT);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+static DECLCALLBACK(int) drvNATReqQueueInterrupt()
+{
+    /*
+     * RTReqQueueProcess loops until request returns a warning or info
+     * status code (other than VINF_SUCCESS).
+     */
+    return VINF_INTERRUPTED;
+}
+
+
+static DECLCALLBACK(int) drvNATHostResWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
+{
+    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
+    Assert(pThis != NULL);
+
+    int rc;
+    rc = RTReqQueueCallEx(pThis->hHostResQueue, NULL /*ppReq*/, 0 /*cMillies*/,
+                          RTREQFLAGS_IPRT_STATUS | RTREQFLAGS_NO_WAIT,
+                          (PFNRT)drvNATReqQueueInterrupt, 0);
+    return rc;
+}
+
+
 /**
  * Function called by slirp to check if it's possible to feed incoming data to the network port.
  * @returns 1 if possible.
@@ -970,6 +1010,56 @@ void slirp_output(void *pvUser, struct mbuf *m, const uint8_t *pu8Buf, int cb)
 }
 
 
+/*
+ * Call a function on the slirp thread.
+ */
+int slirp_call(void *pvUser, PRTREQ *ppReq, RTMSINTERVAL cMillies,
+               unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...)
+{
+    PDRVNAT pThis = (PDRVNAT)pvUser;
+    Assert(pThis);
+
+    int rc;
+
+    va_list va;
+    va_start(va, cArgs);
+
+    rc = RTReqQueueCallV(pThis->hSlirpReqQueue, ppReq, cMillies, fFlags, pfnFunction, cArgs, va);
+
+    va_end(va);
+
+    if (RT_SUCCESS(rc))
+        drvNATNotifyNATThread(pThis, "slirp_vcall");
+
+    return rc;
+}
+
+
+/*
+ * Call a function on the host resolver thread.
+ */
+int slirp_call_hostres(void *pvUser, PRTREQ *ppReq, RTMSINTERVAL cMillies,
+                       unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...)
+{
+    PDRVNAT pThis = (PDRVNAT)pvUser;
+    Assert(pThis);
+
+    int rc;
+
+    AssertReturn((pThis->hHostResQueue != NIL_RTREQQUEUE), VERR_INVALID_STATE);
+    AssertReturn((pThis->pHostResThread != NULL), VERR_INVALID_STATE);
+
+    va_list va;
+    va_start(va, cArgs);
+
+    rc = RTReqQueueCallV(pThis->hHostResQueue, ppReq, cMillies, fFlags,
+                         pfnFunction, cArgs, va);
+
+    va_end(va);
+    return rc;
+}
+
+
 /**
  * @interface_method_impl{PDMINETWORKNATCONFIG,pfnNotifyDnsChanged}
  *
@@ -1065,13 +1155,13 @@ static DECLCALLBACK(void *) drvNATQueryInterface(PPDMIBASE pInterface, const cha
  */
 static void drvNATSetMac(PDRVNAT pThis)
 {
+#if 0 /* XXX: do we still need this for anything? */
     if (pThis->pIAboveConfig)
     {
         RTMAC Mac;
         pThis->pIAboveConfig->pfnGetMac(pThis->pIAboveConfig, &Mac);
-        /* Re-activate the port forwarding. If  */
-        slirp_set_ethaddr_and_activate_port_forwarding(pThis->pNATState, Mac.au8, pThis->GuestIP);
     }
+#endif
 }
 
 
@@ -1209,7 +1299,7 @@ static int drvNATConstructDNSMappings(unsigned iInstance, PDRVNAT pThis, PCFGMNO
             return PDMDRV_SET_ERROR(pThis->pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
                                     N_("Unknown configuration in dns mapping"));
         char szHostNameOrPattern[255];
-        bool fMatch = false;    /* false used for equal matching, and true if wildcard pattern is used. */
+        bool fPattern = false;
         RT_ZERO(szHostNameOrPattern);
         GET_STRING(rc, pThis, pNode, "HostName", szHostNameOrPattern[0], sizeof(szHostNameOrPattern));
         if (rc == VERR_CFGM_VALUE_NOT_FOUND)
@@ -1223,7 +1313,7 @@ static int drvNATConstructDNSMappings(unsigned iInstance, PDRVNAT pThis, PCFGMNO
                 LogRel(("NAT: Neither 'HostName' nor 'HostNamePattern' is specified for mapping %s\n", szNodeName));
                 continue;
             }
-            fMatch = true;
+            fPattern = true;
         }
         struct in_addr HostIP;
         GETIP_DEF(rc, pThis, pNode, HostIP, INADDR_ANY);
@@ -1232,7 +1322,7 @@ static int drvNATConstructDNSMappings(unsigned iInstance, PDRVNAT pThis, PCFGMNO
             LogRel(("NAT: DNS mapping %s is ignored (address not pointed)\n", szHostNameOrPattern));
             continue;
         }
-        slirp_add_host_resolver_mapping(pThis->pNATState, fMatch ? NULL : szHostNameOrPattern, fMatch ? szHostNameOrPattern : NULL, HostIP.s_addr);
+        slirp_add_host_resolver_mapping(pThis->pNATState, szHostNameOrPattern, fPattern, HostIP.s_addr);
     }
     LogFlowFunc(("LEAVE: %Rrc\n", rc));
     return rc;
@@ -1248,9 +1338,6 @@ static int drvNATConstructDNSMappings(unsigned iInstance, PDRVNAT pThis, PCFGMNO
  */
 static int drvNATConstructRedir(unsigned iInstance, PDRVNAT pThis, PCFGMNODE pCfg, PRTNETADDRIPV4 pNetwork)
 {
-    RTMAC Mac;
-    RT_ZERO(Mac); /* can't get MAC here */
-
     /*
      * Enumerate redirections.
      */
@@ -1303,21 +1390,18 @@ static int drvNATConstructRedir(unsigned iInstance, PDRVNAT pThis, PCFGMNODE pCf
         int32_t iGuestPort;
         GET_S32_STRICT(rc, pThis, pNode, "GuestPort", iGuestPort);
 
+        /* host address ("BindIP" name is rather unfortunate given "HostPort" to go with it) */
+        struct in_addr BindIP;
+        GETIP_DEF(rc, pThis, pNode, BindIP, INADDR_ANY);
+
         /* guest address */
         struct in_addr GuestIP;
-        GETIP_DEF(rc, pThis, pNode, GuestIP, RT_H2N_U32(pNetwork->u | CTL_GUEST));
-
-        /* Store the guest IP for re-establishing the port-forwarding rules. Note that GuestIP
-         * is not documented. Without */
-        if (pThis->GuestIP == INADDR_ANY)
-            pThis->GuestIP = GuestIP.s_addr;
+        GETIP_DEF(rc, pThis, pNode, GuestIP, INADDR_ANY);
 
         /*
          * Call slirp about it.
          */
-        struct in_addr BindIP;
-        GETIP_DEF(rc, pThis, pNode, BindIP, INADDR_ANY);
-        if (slirp_add_redirect(pThis->pNATState, fUDP, BindIP, iHostPort, GuestIP, iGuestPort, Mac.au8) < 0)
+        if (slirp_add_redirect(pThis->pNATState, fUDP, BindIP, iHostPort, GuestIP, iGuestPort) < 0)
             return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_NAT_REDIR_SETUP, RT_SRC_POS,
                                        N_("NAT#%d: configuration error: failed to set up "
                                        "redirection of %d to %d. Probably a conflict with "
@@ -1355,6 +1439,9 @@ static DECLCALLBACK(void) drvNATDestruct(PPDMDRVINS pDrvIns)
         pThis->pNATState = NULL;
     }
 
+    RTReqQueueDestroy(pThis->hHostResQueue);
+    pThis->hHostResQueue = NIL_RTREQQUEUE;
+
     RTReqQueueDestroy(pThis->hSlirpReqQueue);
     pThis->hSlirpReqQueue = NIL_RTREQQUEUE;
 
@@ -1406,6 +1493,7 @@ static DECLCALLBACK(int) drvNATConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uin
     pThis->pszNextServer                = NULL;
     pThis->hSlirpReqQueue               = NIL_RTREQQUEUE;
     pThis->hUrgRecvReqQueue             = NIL_RTREQQUEUE;
+    pThis->hHostResQueue                = NIL_RTREQQUEUE;
     pThis->EventRecv                    = NIL_RTSEMEVENT;
     pThis->EventUrgRecv                 = NIL_RTSEMEVENT;
 #ifdef RT_OS_DARWIN
@@ -1602,6 +1690,14 @@ static DECLCALLBACK(int) drvNATConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uin
             rc = RTSemEventCreate(&pThis->EventUrgRecv);
             AssertRCReturn(rc, rc);
 
+            rc = RTReqQueueCreate(&pThis->hHostResQueue);
+            AssertRCReturn(rc, rc);
+
+            rc = PDMDrvHlpThreadCreate(pThis->pDrvIns, &pThis->pHostResThread,
+                                       pThis, drvNATHostResThread, drvNATHostResWakeup,
+                                       64 * _1K, RTTHREADTYPE_IO, "HOSTRES");
+            AssertRCReturn(rc, rc);
+
             rc = RTCritSectInit(&pThis->DevAccessLock);
             AssertRCReturn(rc, rc);
 
diff --git a/src/VBox/Devices/Network/lwip-new/src/core/tcp.c b/src/VBox/Devices/Network/lwip-new/src/core/tcp.c
index ebf6f48..c2fdfa2 100644
--- a/src/VBox/Devices/Network/lwip-new/src/core/tcp.c
+++ b/src/VBox/Devices/Network/lwip-new/src/core/tcp.c
@@ -531,17 +531,32 @@ tcp_proxy_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
 /**
  * Default accept callback if no accept callback is specified by the user.
  */
-static err_t
+err_t
 tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
 {
   LWIP_UNUSED_ARG(arg);
-  LWIP_UNUSED_ARG(pcb);
   LWIP_UNUSED_ARG(err);
 
+  tcp_abort(pcb);
   return ERR_ABRT;
 }
 #endif /* LWIP_CALLBACK_API */
 
+#if LWIP_CONNECTION_PROXY
+/**
+ * Default proxy accept syn callback if no accept callback is specified by the user.
+ */
+err_t
+tcp_accept_syn_null(void *arg, struct tcp_pcb *newpcb, struct pbuf *syn)
+{
+  LWIP_UNUSED_ARG(arg);
+  LWIP_UNUSED_ARG(syn);
+
+  tcp_abort(newpcb);
+  return ERR_ABRT;
+}
+#endif /* LWIP_CONNECTION_PROXY */
+
 /**
  * Set the state of the connection to be LISTEN, which means that it
  * is able to accept incoming connections. The protocol control block
@@ -600,6 +615,9 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
   PCB_ISIPV6(lpcb) = PCB_ISIPV6(pcb);
   lpcb->accept_any_ip_version = 0;
 #endif /* LWIP_IPV6 */
+#if LWIP_CONNECTION_PROXY
+  lpcb->accept_on_syn = 0;
+#endif
   ipX_addr_copy(PCB_ISIPV6(pcb), lpcb->local_ip, pcb->local_ip);
   if (pcb->local_port != 0) {
     TCP_RMV(&tcp_bound_pcbs, pcb);
@@ -1555,9 +1573,27 @@ tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept)
  *        host
  */ 
 void
-tcp_proxy_accept(tcp_accept_fn accept)
+tcp_proxy_accept(tcp_accept_syn_fn accept_syn)
+{
+  tcp_proxy_accept_callback = accept_syn;
+}
+
+
+/**
+ * A cross between normal accept and proxy early accept.  Like with
+ * normal accept there's a normal LISTENing pcb.  Like with proxy, the
+ * accept callback will be called on the first SYN.
+ */
+void
+tcp_accept_syn(struct tcp_pcb *pcb, tcp_accept_syn_fn accept_syn)
 {
-  tcp_proxy_accept_callback = accept;
+  struct tcp_pcb_listen *lpcb;
+
+  LWIP_ASSERT("invalid socket state for accept callback", pcb->state == LISTEN);
+  lpcb = (struct tcp_pcb_listen *)pcb;
+
+  lpcb->accept = (tcp_accept_fn)accept_syn;
+  lpcb->accept_on_syn = 1;
 }
 #endif /* LWIP_CONNECTION_PROXY */
 
diff --git a/src/VBox/Devices/Network/lwip-new/src/core/tcp_in.c b/src/VBox/Devices/Network/lwip-new/src/core/tcp_in.c
index 966978a..4973a75 100644
--- a/src/VBox/Devices/Network/lwip-new/src/core/tcp_in.c
+++ b/src/VBox/Devices/Network/lwip-new/src/core/tcp_in.c
@@ -63,9 +63,7 @@
 #endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
 
 #if LWIP_CONNECTION_PROXY
-static err_t tcp_proxy_accept_null(void *arg, struct tcp_pcb *pcb, err_t err);
-
-tcp_accept_fn tcp_proxy_accept_callback = tcp_proxy_accept_null;
+tcp_accept_syn_fn tcp_proxy_accept_callback = tcp_accept_syn_null;
 #endif
 
 /* These variables are global to all functions involved in the input
@@ -91,11 +89,12 @@ static err_t tcp_process(struct tcp_pcb *pcb);
 static void tcp_receive(struct tcp_pcb *pcb);
 static void tcp_parseopt(struct tcp_pcb *pcb);
 
-static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
+static err_t tcp_listen_input(struct tcp_pcb_listen *pcb, struct pbuf *syn);
 static err_t tcp_timewait_input(struct tcp_pcb *pcb);
 
 #if LWIP_CONNECTION_PROXY
-static err_t tcp_proxy_listen_input(struct pbuf *p);
+static err_t tcp_proxy_listen_input(struct pbuf *syn);
+static void tcp_restore_pbuf(struct pbuf *p);
 
 void
 tcp_proxy_input(struct pbuf *p, struct netif *inp)
@@ -256,7 +255,6 @@ tcp_input1(struct pbuf *p, struct netif *inp)
        * IP header so that proxy can save it and use it later to
        * create ICMP datagram.
        */
-      pbuf_header(p, ip_current_header_tot_len() + hdrlen * 4);
       tcp_proxy_listen_input(p);
       pbuf_free(p);
       return;
@@ -315,7 +313,7 @@ tcp_input1(struct pbuf *p, struct netif *inp)
       }
     
       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
-      tcp_listen_input(lpcb);
+      tcp_listen_input(lpcb, p);
       pbuf_free(p);
       return;
     }
@@ -499,7 +497,7 @@ dropped:
  *       involved is passed as a parameter to this function
  */
 static err_t
-tcp_listen_input(struct tcp_pcb_listen *pcb)
+tcp_listen_input(struct tcp_pcb_listen *pcb, struct pbuf *syn)
 {
   struct tcp_pcb *npcb;
   err_t rc;
@@ -569,6 +567,46 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
       &npcb->remote_ip, PCB_ISIPV6(npcb));
 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
 
+
+#if LWIP_CONNECTION_PROXY
+    /* Early accept on SYN, like we do in tcp_proxy_listen_input() */
+    if (pcb->accept_on_syn) {
+      tcp_accept_syn_fn accept_syn;
+      err_t err;
+
+      /* back off to "delayed" SYN_RCVD, see comments in proxy */
+      npcb->state = SYN_RCVD_0;
+
+      /*
+       * Call the accept syn function.  Note, that it comes from the
+       * listening pcb and we reset the normal accept callback of the
+       * new pcb.  The latter should be set by the client along with
+       * other callbacks if necessary.
+       */
+      accept_syn = (tcp_accept_syn_fn)npcb->accept;
+      npcb->accept = tcp_accept_null;
+
+      /* TCP_EVENT_ACCEPT_SYN */
+      if (accept_syn != NULL)
+        err = (*accept_syn)(npcb->callback_arg, npcb, syn);
+      else
+        err = ERR_ARG;
+
+      if (err != ERR_OK) {
+        /* If the accept function returns with an error, we abort
+         * the connection. */
+        /* Already aborted? */
+        if (err != ERR_ABRT) {
+          tcp_abort(npcb);
+        }
+        return ERR_ABRT;
+      }
+      /* Don't send SYN|ACK now, client will call
+       * tcp_proxy_accept_confirm(). */
+      return ERR_OK;
+    }
+#endif
+
     snmp_inc_tcppassiveopens();
 
     /* Send a SYN|ACK together with the MSS option. */
@@ -583,23 +621,26 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
 }
 
 #if LWIP_CONNECTION_PROXY
-/**
- * XXX: This is a copy-pasted tcp_accept_null(), a static function
- * from tcp.c.  For normal listening PCB tcp_pcb::accept is set to
- * that function when PCB is created in tcp_listen_with_backlog().  I
- * don't want to shuffle code around or mess with visibility for now,
- * so just provide a copy here.
- *
- * XXX: tcp_accept_null() is buggy, it should call tcp_abort().
+/*
+ * Proxy accept callback will be passed the pbuf with the SYN segment
+ * so that it can use it for ICMP errors if necessary.  Undo changes
+ * we've done to the pbuf so that it's suitable to be passed to
+ * icmp_send_response().
  */
-static err_t
-tcp_proxy_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
+static void
+tcp_restore_pbuf(struct pbuf *p)
 {
-  LWIP_UNUSED_ARG(arg);
-  LWIP_UNUSED_ARG(err);
+    u8_t hdrlen = TCPH_HDRLEN(tcphdr);
+
+    /* Reveal IP and TCP headers. */
+    pbuf_header(p, ip_current_header_tot_len() + hdrlen * 4);
 
-  tcp_abort(pcb);
-  return ERR_ABRT;
+    /* Convert fields in the TCP header back to network byte order. */
+    tcphdr->src = htons(tcphdr->src);
+    tcphdr->dest = htons(tcphdr->dest);
+    tcphdr->seqno = htonl(tcphdr->seqno);
+    tcphdr->ackno = htonl(tcphdr->ackno);
+    tcphdr->wnd = htons(tcphdr->wnd);
 }
 
 
@@ -612,7 +653,7 @@ tcp_proxy_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
  * all ports of all IP addresses.
  */
 static err_t
-tcp_proxy_listen_input(struct pbuf *p)
+tcp_proxy_listen_input(struct pbuf *syn)
 {
   struct tcp_pcb *npcb;
   err_t err;
@@ -667,7 +708,7 @@ tcp_proxy_listen_input(struct pbuf *p)
     npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
     npcb->callback_arg = /* pcb->callback_arg */ NULL;
 #if LWIP_CALLBACK_API
-    npcb->accept = /* pcb->accept */ tcp_proxy_accept_callback;
+    npcb->accept = /* pcb->accept */ tcp_accept_null;
 #endif /* LWIP_CALLBACK_API */
     /* inherit socket options */
     npcb->so_options = /* pcb->so_options & SOF_INHERITED */ 0;
@@ -697,25 +738,17 @@ tcp_proxy_listen_input(struct pbuf *p)
      *
      * For the proxy to be able to create ICMP unreachable datagram we
      * need to keep the beginning of the pbuf around.  We pass is as
-     * callback arg here and let callback decide.  Payload is already
-     * moved back to the IP header by the caller.
+     * callback arg here and let callback decide.
      */
 
-    /*
-     * Convert fields in the TCP header back to network byte order
-     * (for ICMP).  I think it's safe to do now, as tcphdr will not be
-     * accessed after this.
-     */
-    tcphdr->src = htons(tcphdr->src);
-    tcphdr->dest = htons(tcphdr->dest);
-    tcphdr->seqno = htonl(tcphdr->seqno);
-    tcphdr->ackno = htonl(tcphdr->ackno);
-    tcphdr->wnd = htons(tcphdr->wnd);
+    tcp_restore_pbuf(syn);
+
+    /* TCP_EVENT_ACCEPT_SYN */
+    if (tcp_proxy_accept_callback != NULL)
+      err = (*tcp_proxy_accept_callback)(NULL, npcb, syn);
+    else
+      err = ERR_ARG;
 
-    npcb->callback_arg = (void *)p;
- 
-    /* Call the accept function. */
-    TCP_EVENT_ACCEPT(npcb, ERR_OK, err);
     if (err != ERR_OK) {
         /* If the accept function returns with an error, we abort
          * the connection. */
diff --git a/src/VBox/Devices/Network/lwip-new/src/include/lwip/tcp.h b/src/VBox/Devices/Network/lwip-new/src/include/lwip/tcp.h
index 5f05fc3..2da4291 100644
--- a/src/VBox/Devices/Network/lwip-new/src/include/lwip/tcp.h
+++ b/src/VBox/Devices/Network/lwip-new/src/include/lwip/tcp.h
@@ -61,6 +61,18 @@ struct tcp_pcb;
  */
 typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err);
 
+#if LWIP_CONNECTION_PROXY
+/** Function prototype for tcp accept callback functions. Called when
+ * a new connection is about to be accepted by the proxy or on a
+ * listening pcb that requested proxy-like accept on syn.
+ *
+ * @param arg Additional argument to pass to the callback function (@see tcp_arg())
+ * @param newpcb The new connection pcb
+ * @param syn The pbuf with the SYN segment (may be used to reply with ICMP).
+ */
+typedef err_t (*tcp_accept_syn_fn)(void *arg, struct tcp_pcb *newpcb, struct pbuf *syn);
+#endif /* LWIP_CONNECTION_PROXY */
+
 /** Function prototype for tcp receive callback functions. Called when data has
  * been received.
  *
@@ -300,6 +312,9 @@ struct tcp_pcb_listen {
 #if LWIP_IPV6
   u8_t accept_any_ip_version;
 #endif /* LWIP_IPV6 */
+#if LWIP_CONNECTION_PROXY
+  u8_t accept_on_syn;
+#endif
 };
 
 #if LWIP_EVENT_API
@@ -329,7 +344,9 @@ void             tcp_accept  (struct tcp_pcb *pcb, tcp_accept_fn accept);
 #if LWIP_CONNECTION_PROXY
 /* when proxied connection is accepted there's no listening pcb */
 void             tcp_proxy_arg(void *arg);
-void             tcp_proxy_accept(tcp_accept_fn accept);
+void             tcp_proxy_accept(tcp_accept_syn_fn accept);
+/* but we also provide proxy-like early accept for listening pcbs */
+void             tcp_accept_syn(struct tcp_pcb *lpcb, tcp_accept_syn_fn accept);
 #endif
 void             tcp_recv    (struct tcp_pcb *pcb, tcp_recv_fn recv);
 void             tcp_sent    (struct tcp_pcb *pcb, tcp_sent_fn sent);
diff --git a/src/VBox/Devices/Network/lwip-new/src/include/lwip/tcp_impl.h b/src/VBox/Devices/Network/lwip-new/src/include/lwip/tcp_impl.h
index 4199cec..dc57b53 100644
--- a/src/VBox/Devices/Network/lwip-new/src/include/lwip/tcp_impl.h
+++ b/src/VBox/Devices/Network/lwip-new/src/include/lwip/tcp_impl.h
@@ -313,7 +313,7 @@ extern u32_t tcp_ticks;
 extern u8_t tcp_active_pcbs_changed;
 
 #if LWIP_CONNECTION_PROXY
-extern tcp_accept_fn tcp_proxy_accept_callback;
+extern tcp_accept_syn_fn tcp_proxy_accept_callback;
 #endif
 
 /* The TCP PCB lists. */
@@ -484,9 +484,14 @@ u16_t tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest
 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
 
 #if LWIP_CALLBACK_API
+err_t tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err);
 err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
 #endif /* LWIP_CALLBACK_API */
 
+#if LWIP_CONNECTION_PROXY
+err_t tcp_accept_syn_null(void *arg, struct tcp_pcb *newpcb, struct pbuf *syn);
+#endif /* LWIP_CONNECTION_PROXY */
+
 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
 void tcp_debug_print(struct tcp_hdr *tcphdr);
 void tcp_debug_print_flags(u8_t flags);
diff --git a/src/VBox/Devices/Network/slirp/bootp.c b/src/VBox/Devices/Network/slirp/bootp.c
index 401cfd9..df266e2 100644
--- a/src/VBox/Devices/Network/slirp/bootp.c
+++ b/src/VBox/Devices/Network/slirp/bootp.c
@@ -58,7 +58,7 @@ typedef struct
 #define bootp_clients ((BOOTPClient *)pData->pbootp_clients)
 
 /* XXX: only DHCP is supported */
-static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
+static const uint8_t rfc1533_cookie[4] = { RFC1533_COOKIE };
 
 static void bootp_reply(PNATState pData, struct mbuf *m0, int offReply, uint16_t flags);
 
@@ -362,6 +362,7 @@ static int dhcp_send_ack(PNATState pData, struct bootp_t *bp, BOOTPClient *bc, s
     int offReply = 0; /* boot_reply will fill general options and add END before sending response */
 
     dhcp_create_msg(pData, bp, m, DHCPACK);
+    slirp_update_guest_addr_guess(pData, bc->addr.s_addr, "DHCP ACK");
     offReply = dhcp_do_ack_offer(pData, m, bc, fDhcpRequest);
     return offReply;
 }
@@ -472,7 +473,7 @@ static int dhcp_decode_request(PNATState pData, struct bootp_t *bp, struct mbuf
                 || req_ip
                 || bp->bp_ciaddr.s_addr == INADDR_ANY)
             {
-                LogRel(("NAT: invalid RENEWING dhcp request\n"));
+                LogRel(("NAT: Invalid RENEWING dhcp request\n"));
                 return -1; /* silent ignorance */
             }
             if (bc != NULL)
@@ -492,7 +493,7 @@ static int dhcp_decode_request(PNATState pData, struct bootp_t *bp, struct mbuf
                bc = bc_alloc_client(pData);
                if (!bc)
                {
-                   LogRel(("NAT: can't alloc address. RENEW has been silently ignored.\n"));
+                   LogRel(("NAT: Can't allocate address. RENEW has been silently ignored\n"));
                    return -1;
                }
 
@@ -527,7 +528,7 @@ static int dhcp_decode_request(PNATState pData, struct bootp_t *bp, struct mbuf
             ui32 = *(uint32_t *)(req_ip + 2);
             if ((ui32 & RT_H2N_U32(pData->netmask)) != pData->special_addr.s_addr)
             {
-                LogRel(("NAT: address %RTnaipv4 has been requested -- sending NAK\n", ui32));
+                LogRel(("NAT: Address %RTnaipv4 has been requested -- sending NAK\n", ui32));
                 offReply = dhcp_send_nack(pData, bp, bc, m);
                 return offReply;
             }
@@ -538,7 +539,7 @@ static int dhcp_decode_request(PNATState pData, struct bootp_t *bp, struct mbuf
                 bc = bc_alloc_client(pData);
                 if (!bc)
                 {
-                    LogRel(("NAT: can't alloc address. RENEW has been silently ignored\n"));
+                    LogRel(("NAT: Can't allocate address. RENEW has been silently ignored\n"));
                     return -1;
                 }
             }
@@ -739,7 +740,7 @@ static void dhcp_decode(PNATState pData, struct bootp_t *bp, const uint8_t *buf,
     m = m_getcl(pData, M_DONTWAIT, MT_HEADER, M_PKTHDR);
     if (!m)
     {
-        LogRel(("NAT: can't alocate memory for response!\n"));
+        LogRel(("NAT: Can't allocate memory for response!\n"));
         return;
     }
 
@@ -785,7 +786,7 @@ static void dhcp_decode(PNATState pData, struct bootp_t *bp, const uint8_t *buf,
                 Assert(bc);
                 if (!bc)
                 {
-                    LogRel(("NAT: can't allocate bootp client object\n"));
+                    LogRel(("NAT: Can't allocate bootp client object\n"));
                     break;
                 }
                 bc->addr.s_addr = req_ip.s_addr;
diff --git a/src/VBox/Devices/Network/slirp/debug.c b/src/VBox/Devices/Network/slirp/debug.c
index 51d96a8..5098074 100644
--- a/src/VBox/Devices/Network/slirp/debug.c
+++ b/src/VBox/Devices/Network/slirp/debug.c
@@ -301,13 +301,25 @@ printSocket(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
                 "socket(%d)", so->s);
 
     cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
-            "socket %d:(proto:%u) exp. in %d"
+            "socket %d", so->s);
+
+    if (so->so_type == IPPROTO_TCP)
+        cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                " (tcp)");
+    else if (so->so_type == IPPROTO_UDP)
+        cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                " (udp)");
+    else
+        cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                " (proto %u)", so->so_type);
+
+    cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+            " exp. in %d"
             " state=%R[natsockstate]"
             "%s" /* fUnderPolling */
             "%s" /* fShouldBeRemoved */
             " f_(addr:port)=%RTnaipv4:%d"
             " l_(addr:port)=%RTnaipv4:%d",
-            so->s, so->so_type,
             so->so_expire ? so->so_expire - curtime : 0,
             so->so_state,
             so->fUnderPolling ? " fUnderPolling" : "",
diff --git a/src/VBox/Devices/Network/slirp/dnsproxy/dnsproxy.c b/src/VBox/Devices/Network/slirp/dnsproxy/dnsproxy.c
index dc4ffc3..831ca4e 100644
--- a/src/VBox/Devices/Network/slirp/dnsproxy/dnsproxy.c
+++ b/src/VBox/Devices/Network/slirp/dnsproxy/dnsproxy.c
@@ -339,7 +339,7 @@ dnsproxy_query(PNATState pData, struct socket *so, struct mbuf *m, int iphlen)
 
     /* check for minimum dns packet length */
     if (byte < 12) {
-        LogRel(("query too short from %RTnaipv4\n", fromaddr.sin_addr));
+        LogRel(("NAT: Query too short from %RTnaipv4\n", fromaddr.sin_addr));
         ++dropped_queries;
         return;
     }
@@ -353,7 +353,7 @@ dnsproxy_query(PNATState pData, struct socket *so, struct mbuf *m, int iphlen)
 
         if ((req = RTMemAllocZ(sizeof(struct request) + byte)) == NULL)
         {
-            LogRel(("calloc failed\n"));
+            LogRel(("NAT: calloc failed\n"));
             ++dropped_queries;
             return;
         }
@@ -427,7 +427,7 @@ dnsproxy_query(PNATState pData, struct socket *so, struct mbuf *m, int iphlen)
     if (byte == -1)
     {
         /* XXX: is it really enough? */
-        LogRel(("sendto failed: %s\n", strerror(errno)));
+        LogRel(("NAT: sendto failed: %s\n", strerror(errno)));
         ++dropped_queries;
         return;
     }
@@ -529,7 +529,7 @@ dnsproxy_answer(PNATState pData, struct socket *so, struct mbuf *m)
 
     /* check for minimum dns packet length */
     if (byte < 12) {
-        LogRel(("answer too short\n"));
+        LogRel(("NAT: Answer too short\n"));
         ++dropped_answers;
         return;
     }
diff --git a/src/VBox/Devices/Network/slirp/hostres.c b/src/VBox/Devices/Network/slirp/hostres.c
new file mode 100644
index 0000000..036dccd
--- /dev/null
+++ b/src/VBox/Devices/Network/slirp/hostres.c
@@ -0,0 +1,1513 @@
+/* $Id: hostres.c $ */
+/** @file
+ * Host resolver
+ */
+
+/*
+ * Copyright (C) 2009-2015 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef RT_OS_WINDOWS
+# include <netdb.h>
+#endif
+#include <iprt/ctype.h>
+#include <iprt/assert.h>
+#include <slirp.h>
+
+#define isdigit(ch)    RT_C_IS_DIGIT(ch)
+#define isalpha(ch)    RT_C_IS_ALPHA(ch)
+
+#define DNS_CONTROL_PORT_NUMBER 53
+/* see RFC 1035(4.1.1) */
+struct dnsmsg_header
+{
+    uint16_t id;
+
+#ifdef RT_OS_WINDOWS
+  /* size of the type forces alignment */
+# define U16_BIT_FIELD_T uint16_t
+#else
+  /* gcc -pedantic complains about implementaion-defined types */
+# define U16_BIT_FIELD_T unsigned int
+#endif
+
+    /* XXX: endianness */
+    U16_BIT_FIELD_T rd:1;
+    U16_BIT_FIELD_T tc:1;
+    U16_BIT_FIELD_T aa:1;
+    U16_BIT_FIELD_T opcode:4;
+    U16_BIT_FIELD_T qr:1;
+    U16_BIT_FIELD_T rcode:4;
+    U16_BIT_FIELD_T Z:3;
+    U16_BIT_FIELD_T ra:1;
+
+    uint16_t qdcount;
+    uint16_t ancount;
+    uint16_t nscount;
+    uint16_t arcount;
+};
+AssertCompileSize(struct dnsmsg_header, 12);
+
+#define QR_Query                0
+#define QR_Response             1
+
+#define OpCode_Query            0
+
+#define RCode_NoError           0
+#define RCode_FormErr           1
+#define RCode_ServFail          2
+#define RCode_NXDomain          3
+#define RCode_NotImp            4
+#define RCode_Refused           5
+
+#define Type_A                  1
+#define Type_CNAME              5
+#define Type_PTR                12
+#define Type_ANY                255
+
+#define Class_IN                1
+#define Class_ANY               255
+
+/* compressed label encoding */
+#define DNS_LABEL_PTR           0xc0
+
+#define DNS_MAX_UDP_LEN         512
+#define DNS_MAX_LABEL_LEN       63
+#define DNS_MAX_NAME_LEN        255
+
+
+/*
+ * A tree of labels.
+ *
+ * rfc1035#section-3.1
+ * rfc1035#section-4.1.4
+ */
+struct label
+{
+    const uint8_t *buf;
+    ssize_t off;
+    struct label *children;
+    struct label *sibling;
+};
+
+
+/*
+ * A structure to build DNS response.
+ */
+struct response
+{
+    PNATState pData;
+
+    uint32_t src;
+    uint16_t sport;
+
+    struct label *labels;       /* already encoded in buf */
+    size_t qlen;                /* original question */
+    size_t end;                 /* of data in buf */
+
+    /* continuous buffer to build the response */
+    uint8_t buf[DNS_MAX_UDP_LEN];
+};
+
+
+static int verify_header(PNATState pData, struct mbuf **pMBuf);
+static struct mbuf *refuse_mbuf(struct mbuf *m, unsigned int rcode);
+
+static int respond(struct response *res);
+static int resolve(struct response *res, uint16_t qtype, size_t qname);
+static int resolve_reverse(struct response *res, uint16_t qtype, size_t qname,
+                            struct in_addr addr);
+
+static int refuse(struct response *res, unsigned int rcode);
+
+
+static ssize_t append_a(struct response *res, const char *name, struct in_addr addr);
+static ssize_t append_cname(struct response *res, const char *name, const char *cname);
+static ssize_t append_ptr(struct response *res, const char *inaddrname, const char *name);
+static ssize_t append_name_rr(struct response *res, const char *question, int type, const char *answer);
+static ssize_t append_rrhdr(struct response *res, const char *name, uint16_t type, uint32_t ttl);
+static ssize_t append_name(struct response *res, const char *name);
+static ssize_t append_u32(struct response *res, uint32_t value);
+static ssize_t append_u16(struct response *res, uint16_t value);
+static ssize_t append_u8(struct response *res, uint8_t value);
+static ssize_t append_bytes(struct response *res, uint8_t *p, size_t size);
+static ssize_t check_space(struct response *res, size_t size);
+
+static int get_in_addr_arpa(struct in_addr *paddr, struct label *root);
+static int labelstrcmp(struct label *l, const char *s);
+static void strnlabels(char *namebuf, size_t nbuflen, const uint8_t *msg, size_t off);
+
+static void LogLabelsTree(const char *before, struct label *l, const char *after);
+static void free_labels(struct label *root);
+
+#ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
+static void alterHostentWithDataFromDNSMap(PNATState pData, struct hostent *h);
+static PDNSMAPPINGENTRY getDNSMapByName(PNATState pData, const char *name);
+static PDNSMAPPINGENTRY getDNSMapByAddr(PNATState pData, const uint32_t *pu32IpAddress);
+#endif
+
+#if 1 /* XXX */
+# define LogErr(args) Log2(args)
+# define LogDbg(args) Log3(args)
+#else
+# define LogErr(args) LogRel(args)
+# define LogDbg(args) LogRel(args)
+#endif
+
+
+static void hostres_async(struct response *res);
+static void hostres_slirp_reply(struct response *res);
+
+
+/*
+ * Host resolver is called on slirp thread from udp.c
+ */
+struct mbuf *
+hostresolver(PNATState pData, struct mbuf *m, uint32_t src, uint16_t sport)
+{
+    struct response *res;
+    size_t mlen;
+    int rc;
+
+    rc = verify_header(pData, &m);
+    if (RT_FAILURE(rc))
+        return m;
+
+    res = RTMemAllocZ(sizeof(*res));
+    if (res == NULL)
+        return refuse_mbuf(m, RCode_ServFail);
+
+    res->pData = pData;
+    res->src = src;
+    res->sport = sport;
+
+    mlen = m_length(m, NULL);
+    m_copydata(m, 0, mlen, (char *)res->buf);
+    res->end = res->qlen = mlen;
+
+    rc = slirp_call_hostres(pData->pvUser, NULL, 0,
+                            RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
+                            (PFNRT)hostres_async, 1, res);
+
+    if (RT_FAILURE(rc))
+    {
+        LogErr(("NAT: hostres: failed to post async request: %Rrc\n", rc));
+        RTMemFree(res);
+        return refuse_mbuf(m, RCode_ServFail);
+    }
+
+    m_freem(pData, m);
+    return NULL;
+}
+
+
+/*
+ * Do quick sanity-checks on the request before doing async
+ * resolution.  If we don't like it, immediately drop or convert to
+ * response in place and bounce back the mbuf.
+ */
+static int
+verify_header(PNATState pData, struct mbuf **pMBuf)
+{
+    struct mbuf *m;
+    struct dnsmsg_header *pHdr;
+    size_t mlen;
+
+    m = *pMBuf;
+    mlen = m_length(m, NULL);
+
+    /*
+     * In theory we should have called
+     *
+     *   m = m_pullup(m, sizeof(struct dnsmsg_header));
+     *
+     * here first (which should have been a nop), but the way mbufs
+     * are used in NAT will always cause a copy that will have no
+     * leading space.  We can use m_copyup() instead, but if we are
+     * peeking under the hood anyway, we might as well just rely on
+     * the fact that this header will be contiguous.
+     */
+    pHdr = mtod(m, struct dnsmsg_header *);
+
+    if (RT_UNLIKELY(mlen < sizeof(*pHdr)))
+    {
+        LogErr(("NAT: hostres: packet too small: %zu bytes\n", mlen));
+        goto drop;              /* can't even refuse it */
+    }
+
+    if (RT_UNLIKELY(mlen > DNS_MAX_UDP_LEN))
+    {
+        LogErr(("NAT: hostres: packet too large: %zu bytes\n", mlen));
+        goto drop;              /* don't echo back huge packets */
+    }
+
+    if (RT_UNLIKELY(pHdr->qr != QR_Query))
+    {
+        LogErr(("NAT: hostres: unexpected response\n"));
+        goto drop;              /* ignore */
+    }
+
+    if (RT_UNLIKELY(pHdr->opcode != OpCode_Query))
+    {
+        LogErr(("NAT: hostres: unsupported opcode %d\n", pHdr->opcode));
+        refuse_mbuf(m, RCode_NotImp);
+        return VERR_PARSE_ERROR;
+    }
+
+    if (RT_UNLIKELY(pHdr->qdcount != RT_H2N_U16_C(1)))
+    {
+        LogErr(("NAT: hostres: multiple questions\n"));
+        refuse_mbuf(m, RCode_NotImp);
+        return VERR_PARSE_ERROR;
+    }
+
+    if (RT_UNLIKELY(pHdr->ancount != 0))
+    {
+        LogErr(("NAT: hostres: answers in query\n"));
+        refuse_mbuf(m, RCode_NotImp);
+        return VERR_PARSE_ERROR;
+    }
+
+    /* XXX: let it fail when we parse it? */
+    if (RT_UNLIKELY(mlen < sizeof(*pHdr)
+                             + /* qname  */ 1
+                             + /* qtype  */ 2
+                             + /* qclass */ 2))
+    {
+        LogErr(("NAT: hostres: packet too small: %zu bytes\n", mlen));
+        refuse_mbuf(m, RCode_FormErr);
+        return VERR_PARSE_ERROR;
+    }
+
+    return VINF_SUCCESS;
+
+  drop:
+    if (m != NULL)
+        m_freem(pData, m);
+    *pMBuf = NULL;
+    return VERR_PARSE_ERROR;
+}
+
+
+/*
+ * Turn the request in mbuf into an error response.  This is used on
+ * slirp thread for pre-checks before we do async resolution.
+ */
+static struct mbuf *
+refuse_mbuf(struct mbuf *m, unsigned int rcode)
+{
+    struct dnsmsg_header *pHdr;
+
+    pHdr = mtod(m, struct dnsmsg_header *);
+    pHdr->qr = QR_Response;
+    pHdr->rcode = rcode;
+    pHdr->ra = 1;
+    pHdr->aa = 0;
+
+    return m;
+}
+
+
+/*
+ * Actuall resolution runs on the dedicated host resolver thread.
+ */
+static void
+hostres_async(struct response *res)
+{
+    int rc;
+
+    /* build reply in res->buf[] */
+    respond(res);
+
+    free_labels(res->labels);
+
+    rc = slirp_call(res->pData->pvUser, NULL, 0,
+                    RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
+                    (PFNRT)hostres_slirp_reply, 1, res);
+
+    if (RT_FAILURE(rc))
+    {
+        LogErr(("NAT: hostres: failed to post async reply: %Rrc\n", rc));
+        RTMemFree(res);
+    }
+}
+
+
+/*
+ * We are  back to the slirp thread to send the reply.
+ */
+static void
+hostres_slirp_reply(struct response *res)
+{
+    PNATState pData = res->pData;
+    struct sockaddr_in src, dst;
+    struct mbuf *m = NULL;
+    size_t mlen;
+    int ok;
+
+    mlen = if_maxlinkhdr + sizeof(struct ip) + sizeof(struct udphdr);
+    mlen += res->end;
+
+    if (mlen <= MHLEN)
+    {
+        m = m_gethdr(pData, M_NOWAIT, MT_HEADER);
+    }
+    else
+    {
+        void *pvBuf;            /* ignored */
+        size_t cbBuf;
+
+        m = slirp_ext_m_get(pData, mlen, &pvBuf, &cbBuf);
+    }
+
+    if (m == NULL)
+        goto out;
+
+    /* reserve leading space for ethernet header */
+    m->m_data += if_maxlinkhdr;
+
+    /* reserve leading space for protocol headers */
+    m->m_pkthdr.header = mtod(m, void *);
+    m->m_data += sizeof(struct ip) + sizeof(struct udphdr);
+
+    m->m_len = 0;
+    ok = m_append(pData, m, res->end, (c_caddr_t)res->buf);
+    if (!ok)
+    {
+        m_freem(pData, m);
+        goto out;
+    }
+
+    src.sin_addr.s_addr = RT_H2N_U32(RT_N2H_U32(pData->special_addr.s_addr) | CTL_DNS);
+    src.sin_port = RT_H2N_U16_C(53);
+    dst.sin_addr.s_addr = res->src;
+    dst.sin_port = res->sport;
+
+    udp_output2(pData, NULL, m, &src, &dst, IPTOS_LOWDELAY);
+
+  out:
+    RTMemFree(res);
+}
+
+
+static int
+respond(struct response *res)
+{
+    struct dnsmsg_header *pHdr;
+    size_t mlen;
+    size_t off;
+    size_t qname;
+    uint16_t qtype, qclass;
+    struct in_addr in_addr_arpa;
+    struct label *l;
+
+    /* convert header to response */
+    pHdr = (struct dnsmsg_header *)res->buf;
+    pHdr->qr = QR_Response;
+    pHdr->rcode = RCode_NoError;
+    pHdr->ra = 1;               /* the host provides recursion */
+    pHdr->aa = 0;               /* we are not authoritative */
+    pHdr->Z = 0;                /* clear rfc2535 dnssec bits */
+
+    off = sizeof(*pHdr);
+    qname = off;
+
+    /*
+     * Parse/verify QNAME and collect the suffixes to be used for
+     * compression in the answer.
+     */
+    while (off < res->qlen) {
+        size_t loff, llen;
+        uint8_t c;
+
+        c = res->buf[off];
+
+        /*
+         * There's just one question with just one name, so there are
+         * no other labels it can point to.  Thus all well-formed
+         * names with a pointer can only be infinite loops.
+         */
+        if ((c & DNS_LABEL_PTR) == DNS_LABEL_PTR)
+        {
+            LogErr(("NAT: hostres: label pointer in the qname\n"));
+            return refuse(res, RCode_FormErr);
+        }
+
+        if ((c & DNS_LABEL_PTR) != 0)
+        {
+            LogErr(("NAT: hostres: unexpected high bits\n"));
+            return refuse(res, RCode_FormErr);
+        }
+
+        /*
+         * label of "llen" chars starts at offset "loff".
+         */
+        loff = off;
+        llen = c;
+        ++off;
+
+        if (loff + 1 + llen > res->qlen)
+        {
+            LogErr(("NAT: hostres: length byte points beyound packet boundary\n"));
+            return refuse(res, RCode_FormErr);
+        }
+
+        if (llen == 0)             /* end of the label list */
+        {
+            break;
+        }
+
+        /* do only minimal verification of the label */
+        while (off < loff + 1 + llen)
+        {
+            c = res->buf[off];
+            ++off;
+
+            if (c == '.')
+            {
+                LogErr(("NAT: hostres: dot inside label\n"));
+                return refuse(res, RCode_FormErr);
+            }
+
+            if (c == '\0')
+            {
+                LogErr(("NAT: hostres: nul byte inside label\n"));
+                return refuse(res, RCode_FormErr);
+            }
+        }
+
+        l = RTMemAllocZ(sizeof(*l));
+        l->buf = res->buf;
+        l->off = loff;
+        l->children = res->labels;
+        res->labels = l;
+    }
+
+    /*
+     * QTYPE and QCLASS
+     */
+    if (RT_UNLIKELY(off + 4 > res->qlen))
+    {
+        LogErr(("NAT: hostres: question too short\n"));
+        return refuse(res, RCode_FormErr);
+    }
+
+    memcpy(&qtype, &res->buf[off], sizeof(qtype));
+    qtype = RT_N2H_U16(qtype);
+    off += sizeof(qtype);
+
+    memcpy(&qclass, &res->buf[off], sizeof(qclass));
+    qclass = RT_N2H_U16(qclass);
+    off += sizeof(qclass);
+
+    if (   qclass != Class_IN
+        && qclass != Class_ANY)
+    {
+        LogErr(("NAT: hostres: unsupported qclass %d\n", qclass));
+        return refuse(res, RCode_NotImp);
+    }
+
+    if (   qtype != Type_A
+        && qtype != Type_CNAME
+        && qtype != Type_PTR
+        && qtype != Type_ANY)
+    {
+        LogErr(("NAT: hostres: unsupported qtype %d\n", qtype));
+        return refuse(res, RCode_NotImp);
+    }
+
+
+    /**
+     * Check if there's anything after the question.  If query says it
+     * has authority or additional records, ignore and drop them
+     * without parsing.
+     *
+     * We have already rejected queries with answer(s) before.  We
+     * have ensured that qname in the question doesn't contain
+     * pointers, so truncating the buffer is safe.
+     */
+    if (off < res->qlen)
+    {
+        int trailer = res->qlen - off;
+
+        LogDbg(("NAT: hostres: question %zu < mlen %zu\n", off, res->qlen));
+
+        if (pHdr->nscount == 0 && pHdr->arcount == 0)
+        {
+            LogErr(("NAT: hostres: unexpected %d bytes after the question\n", trailer));
+            return refuse(res, RCode_FormErr);
+        }
+
+        LogDbg(("NAT: hostres: ignoring %d bytes of %s%s%s records\n",
+                trailer,
+                pHdr->nscount != 0 ? "authority" : "",
+                pHdr->nscount != 0 && pHdr->arcount != 0 ? " and " : "",
+                pHdr->arcount != 0 ? "additional" : ""));
+
+        res->qlen -= trailer;
+        res->end = res->qlen;
+
+        pHdr->nscount = 0;
+        pHdr->arcount = 0;
+    }
+
+
+    /*
+     * Check for IN-ADDR.ARPA.  Use the fact that res->labels at this
+     * point contains only the qname, so we have easy top-down access
+     * to its components.
+     */
+    if (get_in_addr_arpa(&in_addr_arpa, res->labels))
+        return resolve_reverse(res, qtype, qname, in_addr_arpa);
+    else
+        return resolve(res, qtype, qname);
+}
+
+
+static int
+resolve(struct response *res, uint16_t qtype, size_t qname)
+{
+    struct dnsmsg_header *pHdr;
+    struct hostent *h;
+    struct hostent hostent;
+    char *h_aliases[1];
+    char *h_addr_list[2];
+    size_t oend;
+    size_t nanswers;
+    ssize_t nbytes;
+    int i;
+
+    char name[DNS_MAX_NAME_LEN+1];
+
+    pHdr = (struct dnsmsg_header *)res->buf;
+    nanswers = 0;
+    oend = res->end;
+
+    strnlabels(name, sizeof(name), res->buf, qname);
+    LogDbg(("NAT: hostres: qname=\"%s\"\n", name));
+
+    if (qtype != Type_A && qtype != Type_CNAME && qtype != Type_ANY)
+    {
+        goto out; /* NB: RCode_NoError without an answer, not RCode_NXDomain */
+    }
+
+    h = NULL;
+#ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
+    {
+        PDNSMAPPINGENTRY pDNSMapingEntry = getDNSMapByName(res->pData, name);
+        if (pDNSMapingEntry != NULL)
+        {
+            LogDbg(("NAT: hostres: %s resolved from %s%s\n",
+                    name,
+                    pDNSMapingEntry->fPattern ? "pattern " : "mapping",
+                    pDNSMapingEntry->fPattern ? pDNSMapingEntry->pszName : ""));
+
+            if (qtype == Type_CNAME)
+            {
+                goto out;
+            }
+
+            hostent.h_name = name;
+            hostent.h_aliases = h_aliases;
+            h_aliases[0] = NULL;
+            hostent.h_addrtype = AF_INET;
+            hostent.h_length = sizeof(RTNETADDRIPV4);
+            hostent.h_addr_list = h_addr_list;
+            h_addr_list[0] = (char *)&pDNSMapingEntry->u32IpAddress;
+            h_addr_list[1] = NULL;
+
+            h = &hostent;
+        }
+    }
+#endif
+
+    if (h == NULL)
+    {
+        h = gethostbyname(name);
+    }
+
+    if (h == NULL)
+    {
+        /* LogErr: h_errno */
+        return refuse(res, RCode_NXDomain);
+    }
+
+    if (h->h_length != sizeof(RTNETADDRIPV4))
+    {
+        /* Log: what kind of address did we get?! */
+        goto out;
+    }
+
+    if (   h->h_addr_list == NULL
+        || h->h_addr_list[0] == NULL)
+    {
+        /* Log: shouldn't happen */
+        goto out;
+    }
+
+#ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
+    alterHostentWithDataFromDNSMap(res->pData, h);
+#endif
+
+    /*
+     * Emit CNAME record if canonical name differs from the qname.
+     */
+    if (   h->h_name != NULL
+        && RTStrICmp(h->h_name, name) != 0)
+    {
+        LogDbg(("NAT: hostres: %s CNAME %s\n", name, h->h_name));
+        nbytes = append_cname(res, name, h->h_name);
+        if (nbytes > 0)
+        {
+            ++nanswers;
+        }
+        else
+        {
+            LogErr(("NAT: hostres: failed to add %s CNAME %s\n",
+                    name, h->h_name));
+            if (nbytes < 0)
+                return refuse(res, RCode_ServFail);
+            else
+            {
+                pHdr->tc = 1;
+                goto out;
+            }
+        }
+
+        /*
+         * rfc1034#section-3.6.2 - ... a type CNAME or * query should
+         * return just the CNAME.
+         */
+        if (qtype == Type_CNAME || qtype == Type_ANY)
+            goto out;
+    }
+    else if (qtype == Type_CNAME)
+    {
+        LogDbg(("NAT: hostres: %s is already canonical\n", name));
+        goto out; /* NB: RCode_NoError without an answer, not RCode_NXDomain */
+    }
+
+    /*
+     * Emit A records.
+     */
+    for (i = 0; h->h_addr_list[i] != NULL; ++i)
+    {
+        const char *cname = h->h_name ? h->h_name : name;
+        struct in_addr addr;
+
+        addr.s_addr = *(uint32_t *)h->h_addr_list[i];
+        nbytes = append_a(res, cname, addr);
+
+        if (nbytes > 0)
+        {
+            ++nanswers;
+        }
+        else
+        {
+            LogErr(("NAT: hostres: failed to add %s A %RTnaipv4\n",
+                    cname, addr.s_addr));
+            if (nbytes < 0)
+                return refuse(res, RCode_ServFail);
+            else
+            {
+                pHdr->tc = 1;
+                goto out;
+            }
+        }
+    }
+
+#if 0
+    /*
+     * It's not clear what to do with h_aliases.
+     *
+     * For names from the DNS it seems to contain the chain of CNAMEs,
+     * starting with the original qname from the question.  So for
+     * them we'd need to reply with a chain of:
+     *
+     *     h_aliases[i] CNAME h_aliases[i+1]
+     *
+     * OTOH, for the names from the hosts file it seems to contain all
+     * the names except the first one (which is considered primary and
+     * is reported as h_name).  In which case the reply should be:
+     *
+     *     h_aliases[i] CNAME h_name
+     *
+     * Obviously, we have no idea how the name was resolved, so we
+     * generate at most one CNAME for h_host (if differs) and ignore
+     * aliases altogehter.
+     */
+    for (i = 0; h->h_aliases[i] != NULL; ++i)
+    {
+        LogDbg(("NAT: hostres: ... %s\n", h->h_aliases[i]));
+    }
+#endif
+
+  out:
+    pHdr->ancount = RT_H2N_U16(nanswers);
+    return VINF_SUCCESS;
+}
+
+
+static int
+resolve_reverse(struct response *res, uint16_t qtype, size_t qname,
+                struct in_addr in_addr_arpa)
+{
+    struct dnsmsg_header *pHdr;
+    struct hostent *h;
+    struct hostent hostent;
+    char *h_aliases[1];
+    char *h_addr_list[2];
+    size_t oend;
+    size_t nanswers;
+    ssize_t nbytes;
+    int i;
+
+    pHdr = (struct dnsmsg_header *)res->buf;
+    nanswers = 0;
+    oend = res->end;
+
+    LogDbg(("NAT: hostres: %RTnaipv4\n", in_addr_arpa.s_addr));
+
+    if (qtype != Type_PTR && qtype != Type_ANY)
+    {
+        /* can't answer CNAME to PTR queries using gethostby* */
+        goto out; /* NB: RCode_NoError without an answer, not RCode_NXDomain */
+    }
+
+    h = NULL;
+#ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
+    /*
+     * If the address in the question is unknown to the real resolver
+     * but has a mapping, and if we do the real lookup first, then the
+     * guest will time out before our lookup times out and even though
+     * we reply with the answer from the map, the answer will be lost.
+     */
+    {
+        PDNSMAPPINGENTRY pReverseMapping = getDNSMapByAddr(res->pData, &in_addr_arpa.s_addr);
+        if (pReverseMapping != NULL)
+        {
+            LogDbg(("NAT: hostres: %RTnaipv4 resolved from mapping\n",
+                    in_addr_arpa.s_addr));
+
+            hostent.h_name = pReverseMapping->pszName;
+            hostent.h_aliases = h_aliases;
+            h_aliases[0] = NULL;
+            hostent.h_addrtype = AF_INET;
+            hostent.h_length = sizeof(RTNETADDRIPV4);
+            hostent.h_addr_list = h_addr_list;
+            h_addr_list[0] = (char *)&in_addr_arpa.s_addr;
+            h_addr_list[1] = NULL;
+
+            h = &hostent;
+        }
+    }
+#endif
+
+    if (h == NULL)
+    {
+        h = gethostbyaddr(&in_addr_arpa, sizeof(struct in_addr), AF_INET);
+    }
+
+    if (h == NULL)
+    {
+        /* LogErr: h_errno */
+        return refuse(res, RCode_NXDomain);
+    }
+
+    if (h->h_name != NULL)
+    {
+        char name[DNS_MAX_NAME_LEN+1];
+        strnlabels(name, sizeof(name), res->buf, qname);
+
+        LogDbg(("NAT: hostres: %s PTR %s\n", name, h->h_name));
+        nbytes = append_ptr(res, name, h->h_name);
+        if (nbytes > 0)
+        {
+            ++nanswers;
+        }
+        else
+        {
+            LogErr(("NAT: hostres: failed to add %s PTR %s\n",
+                    name, h->h_name));
+            if (nbytes < 0)
+                return refuse(res, RCode_ServFail);
+            else
+            {
+                pHdr->tc = 1;
+                goto out;
+            }
+        }
+    }
+
+  out:
+    pHdr->ancount = RT_H2N_U16(nanswers);
+    return VINF_SUCCESS;
+}
+
+
+static int
+refuse(struct response *res, unsigned int rcode)
+{
+    struct dnsmsg_header *pHdr = (struct dnsmsg_header *)res->buf;
+    pHdr->rcode = rcode;
+
+    return VINF_SUCCESS;
+}
+
+
+#define APPEND_PROLOGUE()                       \
+    ssize_t size = -1;                          \
+    size_t oend = res->end;                     \
+    ssize_t nbytes;                             \
+    do {} while (0)
+
+#define CHECKED(_append)                        \
+    do {                                        \
+        nbytes = (_append);                     \
+        if (RT_UNLIKELY(nbytes <= 0))           \
+        {                                       \
+            if (nbytes == 0)                    \
+                size = 0;                       \
+            goto out;                           \
+        }                                       \
+    } while (0)
+
+#define APPEND_EPILOGUE()                       \
+    do {                                        \
+        size = res->end - oend;                 \
+      out:                                      \
+        if (RT_UNLIKELY(size <= 0))             \
+            res->end = oend;                    \
+        return size;                            \
+    } while (0)
+
+
+/*
+ * A RR - rfc1035#section-3.4.1
+ */
+static ssize_t
+append_a(struct response *res, const char *name, struct in_addr addr)
+{
+    APPEND_PROLOGUE();
+
+    CHECKED( append_rrhdr(res, name, Type_A, 3600) );
+    CHECKED( append_u16(res, RT_H2N_U16_C(sizeof(addr))) );
+    CHECKED( append_u32(res, addr.s_addr) );
+ 
+    APPEND_EPILOGUE();
+}
+
+
+/*
+ * CNAME RR - rfc1035#section-3.3.1
+ */
+static ssize_t
+append_cname(struct response *res, const char *name, const char *cname)
+{
+    return append_name_rr(res, name, Type_CNAME, cname);
+}
+
+
+/*
+ * PTR RR - rfc1035#section-3.3.12
+ */
+static ssize_t
+append_ptr(struct response *res, const char *inaddrname, const char *name)
+{
+    return append_name_rr(res, inaddrname, Type_PTR, name);
+}
+
+
+static ssize_t
+append_name_rr(struct response *res, const char *question,
+               int type, const char *answer)
+{
+    size_t rdlpos;
+    uint16_t rdlength;
+
+    APPEND_PROLOGUE();
+
+    CHECKED( append_rrhdr(res, question, type, 3600) );
+
+    rdlpos = res->end;
+    CHECKED( append_u16(res, 0) ); /* RDLENGTH placeholder */
+
+    CHECKED( append_name(res, answer) );
+
+    rdlength = RT_H2N_U16(nbytes);
+    memcpy(&res->buf[rdlpos], &rdlength, sizeof(rdlength));
+
+    APPEND_EPILOGUE();
+}
+
+
+/*
+ * Append common RR header, up to but not including RDLENGTH and RDATA
+ * proper (rfc1035#section-3.2.1).
+ */
+static ssize_t
+append_rrhdr(struct response *res, const char *name, uint16_t type, uint32_t ttl)
+{
+    APPEND_PROLOGUE();
+
+    CHECKED( append_name(res, name) );
+    CHECKED( append_u16(res, RT_H2N_U16(type)) );
+    CHECKED( append_u16(res, RT_H2N_U16_C(Class_IN)) );
+    CHECKED( append_u32(res, RT_H2N_U32(ttl)) );
+
+    APPEND_EPILOGUE();
+}
+
+
+static ssize_t
+append_name(struct response *res, const char *name)
+{
+    ssize_t size, nbytes;
+    struct label *root;
+    struct label *haystack, *needle;
+    struct label *head, **neck;
+    struct label *tail, **graft;
+    uint8_t *buf;
+    size_t wr, oend;
+    const char *s;
+
+    size = -1;
+    oend = res->end;
+
+    /**
+     * Split new name into a list of labels encoding it into the
+     * temporary buffer.
+     */
+    root = NULL;
+
+    buf = RTMemAllocZ(strlen(name) + 1);
+    if (buf == NULL)
+        return -1;
+    wr = 0;
+
+    s = name;
+    while (*s != '\0') {
+        const char *part;
+        size_t poff, plen;
+        struct label *l;
+
+        part = s;
+        while (*s != '\0' && *s != '.')
+            ++s;
+
+        plen = s - part;
+
+        if (plen > DNS_MAX_LABEL_LEN)
+        {
+            LogErr(("NAT: hostres: name component too long\n"));
+            goto out;
+        }
+
+        if (*s == '.')
+        {
+            if (plen == 0)
+            {
+                LogErr(("NAT: hostres: empty name component\n"));
+                goto out;
+            }
+
+            ++s;
+        }
+        
+        poff = wr;
+
+        buf[poff] = (uint8_t)plen; /* length byte */
+        ++wr;
+
+        memcpy(&buf[wr], part, plen); /* label text */
+        wr += plen;
+
+        l = RTMemAllocZ(sizeof(*l));
+        if (l == NULL)
+            goto out;
+
+        l->buf = buf;
+        l->off = poff;
+        l->children = root;
+        root = l;
+    }
+
+
+    /**
+     * Search for a tail that is already encoded in the message.
+     */
+    neck = &root;               /* where needle head is connected */
+    needle = root;
+
+    tail = NULL;                /* tail in the haystack */
+    graft = &res->labels;
+    haystack = res->labels;
+
+    while (needle != NULL && haystack != NULL)
+    {
+        size_t nlen, hlen;
+
+        nlen = needle->buf[needle->off];
+        Assert((nlen & DNS_LABEL_PTR) == 0);
+
+        hlen = haystack->buf[haystack->off];
+        Assert((hlen & DNS_LABEL_PTR) == 0);
+
+        if (   nlen == hlen
+            && RTStrNICmp((char *)&needle->buf[needle->off+1],
+                          (char *)&haystack->buf[haystack->off+1],
+                          nlen) == 0)
+        {
+            neck = &needle->children;
+            needle = needle->children;
+
+            tail = haystack;
+            graft = &haystack->children;
+            haystack = haystack->children;
+        }
+        else
+        {
+            haystack = haystack->sibling;
+        }
+    }
+
+
+    /**
+     * Head contains (in reverse) the prefix that needs to be encoded
+     * and added to the haystack.  Tail points to existing suffix that
+     * can be compressed to a pointer into the haystack.
+     */
+    head = *neck;
+    if (head != NULL)
+    {
+        struct label *l;
+        size_t nlen, pfxlen, pfxdst;
+
+        nlen = needle->buf[head->off]; /* last component */
+        pfxlen = head->off + 1 + nlen; /* all prefix */
+        pfxdst = res->end;             /* in response buffer */
+
+        /* copy new prefix into response buffer */
+        nbytes = append_bytes(res, buf, pfxlen);
+        if (nbytes <= 0)
+        {
+            if (nbytes == 0)
+                size = 0;
+            goto out;
+        }
+
+        /* adjust labels to point to the response */
+        for (l = head; l != NULL; l = l->children)
+        {
+            l->buf = res->buf;
+            l->off += pfxdst;
+        }
+
+        *neck = NULL;           /* decapitate */
+
+        l = *graft;             /* graft to the labels tree */
+        *graft = head;
+        head->sibling = l;
+    }
+
+    if (tail == NULL)
+        nbytes = append_u8(res, 0);
+    else
+        nbytes = append_u16(res, RT_H2N_U16((DNS_LABEL_PTR << 8) | tail->off));
+    if (nbytes <= 0)
+    {
+        if (nbytes == 0)
+            size = 0;
+        goto out;
+    }
+
+    size = res->end - oend;
+  out:
+    if (RT_UNLIKELY(size <= 0))
+        res->end = oend;
+    free_labels(root);
+    RTMemFree(buf);
+    return size;
+}
+
+
+static ssize_t
+append_u32(struct response *res, uint32_t value)
+{
+    return append_bytes(res, (uint8_t *)&value, sizeof(value));
+}
+
+
+static ssize_t
+append_u16(struct response *res, uint16_t value)
+{
+    return append_bytes(res, (uint8_t *)&value, sizeof(value));
+}
+
+
+static ssize_t
+append_u8(struct response *res, uint8_t value)
+{
+    return append_bytes(res, &value, sizeof(value));
+}
+
+
+static ssize_t
+append_bytes(struct response *res, uint8_t *p, size_t size)
+{
+    if (check_space(res, size) == 0)
+        return 0;
+
+    memcpy(&res->buf[res->end], p, size);
+    res->end += size;
+    return size;
+}
+
+
+static ssize_t
+check_space(struct response *res, size_t size)
+{
+    if (   size > sizeof(res->buf)
+        || res->end > sizeof(res->buf) - size)
+        return 0;
+
+    return size;
+}
+
+
+static int
+get_in_addr_arpa(struct in_addr *paddr, struct label *root)
+{
+    RTNETADDRIPV4 addr;
+    struct label *l;
+    int i;
+
+    l = root;
+    if (l == NULL || labelstrcmp(l, "arpa") != 0)
+        return 0;
+
+    l = l->children;
+    if (l == NULL || labelstrcmp(l, "in-addr") != 0)
+        return 0;
+
+    for (i = 0; i < 4; ++i)
+    {
+        char buf[4];
+        size_t llen;
+        int rc;
+        uint8_t octet;
+
+        l = l->children;
+        if (l == NULL)
+            return 0;
+
+        llen = l->buf[l->off];
+        Assert((llen & DNS_LABEL_PTR) == 0);
+
+        /* valid octet values are at most 3 digits */
+        if (llen > 3)
+            return 0;
+
+        /* copy to avoid dealing with trailing bytes */
+        memcpy(buf, &l->buf[l->off + 1], llen);
+        buf[llen] = '\0';
+
+        rc = RTStrToUInt8Full(buf, 10, &octet);
+        if (rc != VINF_SUCCESS)
+            return 0;
+
+        addr.au8[i] = octet;
+    }
+
+    if (l->children != NULL)
+        return 0;               /* too many components */
+
+    if (paddr != NULL)
+        paddr->s_addr = addr.u;
+
+    return 1;
+}
+
+
+/*
+ * Compare label with string.
+ */
+static int
+labelstrcmp(struct label *l, const char *s)
+{
+    size_t llen;
+
+    llen = l->buf[l->off];
+    Assert((llen & DNS_LABEL_PTR) == 0);
+
+    return RTStrNICmp((char *)&l->buf[l->off + 1], s, llen);
+}
+
+
+/*
+ * Convert a chain of labels to a C string.
+ *
+ * I'd rather use a custom formatter for e.g. %R[label] , but it needs
+ * two arguments and microsoft VC doesn't support compound literals.
+ */
+static void
+strnlabels(char *namebuf, size_t nbuflen, const uint8_t *msg, size_t off)
+{
+    size_t cb;
+    size_t llen;
+
+    namebuf[0] = '\0';
+    cb = 0;
+
+    llen = 0;
+
+    while (cb < nbuflen - 1) {
+        llen = msg[off];
+        if ((llen & DNS_LABEL_PTR) == DNS_LABEL_PTR)
+        {
+            off = ((llen & ~DNS_LABEL_PTR) << 8) | msg[off + 1];
+            llen = msg[off];
+        }
+
+        /* pointers to pointers should not happen */
+        if ((llen & DNS_LABEL_PTR) != 0)
+        {
+            cb += RTStrPrintf(namebuf + cb, nbuflen - cb, "[???]");
+            return;
+        }
+
+        if (llen == 0)
+        {
+            if (namebuf[0] == '\0')
+                cb += RTStrPrintf(namebuf + cb, nbuflen - cb, ".");
+            break;
+        }
+
+        if (namebuf[0] != '\0')
+            cb += RTStrPrintf(namebuf + cb, nbuflen - cb, ".");
+
+        cb += RTStrPrintf(namebuf + cb, nbuflen - cb,
+                          "%.*s", llen, (char *)&msg[off+1]);
+        off = off + 1 + llen;
+    }
+}
+
+
+static void
+LogLabelsTree(const char *before, struct label *l, const char *after)
+{
+    size_t llen;
+
+    if (before != NULL)
+        LogDbg(("%s", before));
+
+    if (l == NULL)
+    {
+        LogDbg(("NULL%s", after ? after : ""));
+        return;
+    }
+
+    if (l->children)
+        LogDbg(("("));
+
+    if (l->buf != NULL)
+    {
+        llen = l->buf[l->off];
+        if ((llen & DNS_LABEL_PTR) == 0)
+        {
+            LogDbg(("\"%.*s\"@%zu", llen, &l->buf[l->off+1], l->off));
+        }
+        else
+        {
+            LogDbg(("<invalid byte 0t%zu/0x%zf at offset %zd>",
+                    llen, llen, l->off));
+        }
+    }
+    else
+    {
+        LogDbg(("<*>"));
+    }
+
+    if (l->children)
+        LogLabelsTree(" ", l->children, ")");
+
+    if (l->sibling)
+        LogLabelsTree(" ", l->sibling, NULL);
+
+    if (after != NULL)
+        LogDbg(("%s", after));
+}
+
+
+static void
+free_labels(struct label *root)
+{
+    struct label TOP;    /* traverse the tree with pointer reversal */
+    struct label *b, *f;
+
+    if (root == NULL)
+        return;
+
+    RT_ZERO(TOP);
+
+    b = &TOP;
+    f = root;
+
+    while (f != &TOP) {
+        if (f->children) {      /* recurse left */
+            struct label *oldf = f;
+            struct label *newf = f->children;
+            oldf->children = b; /* reverse the pointer */
+            b = oldf;
+            f = newf;
+        }
+        else if (f->sibling) { /* turn right */
+            f->children = f->sibling;
+            f->sibling = NULL;
+        }
+        else {                  /* backtrack */
+            struct label *oldf = f; /* garbage */
+            struct label *oldb = b;
+            b = oldb->children;
+            oldb->children = NULL; /* oldf, but we are g/c'ing it */
+            f = oldb;
+
+            RTMemFree(oldf);
+        }
+    }
+}
+
+#ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
+void
+slirp_add_host_resolver_mapping(PNATState pData,
+                                const char *pszHostName, bool fPattern,
+                                uint32_t u32HostIP)
+{
+    LogRel(("ENTER: pszHostName:%s%s, u32HostIP:%RTnaipv4\n",
+                 pszHostName ? pszHostName : "(null)",
+                 fPattern ? " (pattern)" : "",
+                 u32HostIP));
+
+    if (   pszHostName != NULL
+        && u32HostIP != INADDR_ANY
+        && u32HostIP != INADDR_BROADCAST)
+    {
+        PDNSMAPPINGENTRY pDnsMapping = RTMemAllocZ(sizeof(DNSMAPPINGENTRY));
+        if (!pDnsMapping)
+        {
+            LogFunc(("Can't allocate DNSMAPPINGENTRY\n"));
+            LogFlowFuncLeave();
+            return;
+        }
+
+        pDnsMapping->u32IpAddress = u32HostIP;
+        pDnsMapping->fPattern = fPattern;
+        pDnsMapping->pszName = RTStrDup(pszHostName);
+
+        if (pDnsMapping->pszName == NULL)
+        {
+            LogFunc(("Can't allocate enough room for host name\n"));
+            RTMemFree(pDnsMapping);
+            LogFlowFuncLeave();
+            return;
+        }
+
+        if (fPattern) /* there's no case-insensitive pattern-match function */
+            RTStrToLower(pDnsMapping->pszName);
+
+        STAILQ_INSERT_TAIL(fPattern ? &pData->DNSMapPatterns : &pData->DNSMapNames,
+                           pDnsMapping, MapList);
+
+        LogRel(("NAT: User-defined mapping %s%s = %RTnaipv4 is registered\n",
+                pDnsMapping->pszName,
+                pDnsMapping->fPattern ? " (pattern)" : "",
+                pDnsMapping->u32IpAddress));
+    }
+    LogFlowFuncLeave();
+}
+
+
+static PDNSMAPPINGENTRY
+getDNSMapByName(PNATState pData, const char *pszName)
+{
+    PDNSMAPPINGENTRY pDNSMapingEntry;
+    char *pszNameLower;
+
+    pszNameLower = RTStrDup(pszName);
+    if (RT_UNLIKELY(pszNameLower == NULL))
+        return NULL;
+    RTStrToLower(pszNameLower);
+
+    STAILQ_FOREACH(pDNSMapingEntry, &pData->DNSMapNames, MapList)
+    {
+        if (RTStrICmp(pDNSMapingEntry->pszName, pszNameLower) == 0)
+            goto done;
+    }
+
+    STAILQ_FOREACH(pDNSMapingEntry, &pData->DNSMapPatterns, MapList)
+    {
+        if (RTStrSimplePatternMultiMatch(pDNSMapingEntry->pszName, RTSTR_MAX,
+                                         pszNameLower, RTSTR_MAX, NULL))
+            goto done;
+    }
+
+  done:
+    RTStrFree(pszNameLower);
+    return pDNSMapingEntry;
+}
+
+
+static PDNSMAPPINGENTRY
+getDNSMapByAddr(PNATState pData, const uint32_t *pu32IpAddress)
+{
+    PDNSMAPPINGENTRY pDNSMapingEntry;
+
+    if (pu32IpAddress == NULL)
+        return NULL;
+
+    STAILQ_FOREACH(pDNSMapingEntry, &pData->DNSMapNames, MapList)
+    {
+        if (pDNSMapingEntry->u32IpAddress == *pu32IpAddress)
+            return pDNSMapingEntry;
+    }
+
+    return NULL;
+}
+
+
+static void
+alterHostentWithDataFromDNSMap(PNATState pData, struct hostent *h)
+{
+    PDNSMAPPINGENTRY pDNSMapingEntry = NULL;
+    char **ppszAlias;
+
+    if (h->h_name != NULL)
+    {
+        pDNSMapingEntry = getDNSMapByName(pData, h->h_name);
+        if (pDNSMapingEntry != NULL)
+            goto done;
+    }
+
+    for (ppszAlias = h->h_aliases; *ppszAlias != NULL; ++ppszAlias)
+    {
+        pDNSMapingEntry = getDNSMapByName(pData, *ppszAlias);
+        if (pDNSMapingEntry != NULL)
+            goto done;
+    }
+
+  done:
+    if (pDNSMapingEntry != NULL)
+    {
+        *(uint32_t *)h->h_addr_list[0] = pDNSMapingEntry->u32IpAddress;
+        h->h_addr_list[1] = NULL;
+    }
+}
+#endif /* VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER */
diff --git a/src/VBox/Devices/Network/slirp/ip_icmp.c b/src/VBox/Devices/Network/slirp/ip_icmp.c
index 5384a82..c5d7519 100644
--- a/src/VBox/Devices/Network/slirp/ip_icmp.c
+++ b/src/VBox/Devices/Network/slirp/ip_icmp.c
@@ -551,7 +551,7 @@ icmp_input(PNATState pData, struct mbuf *m, int hlen)
 
                     if (!fIcmpSocketErrorReported)
                     {
-                        LogRel(("icmp_input udp sendto tx errno = %d (%s)\n",
+                        LogRel(("NAT: icmp_input udp sendto tx errno = %d (%s)\n",
                                 errno, strerror(errno)));
                         fIcmpSocketErrorReported = true;
                     }
@@ -734,7 +734,7 @@ end_error:
         static bool fIcmpErrorReported;
         if (!fIcmpErrorReported)
         {
-            LogRel(("NAT: error occurred while sending ICMP error message\n"));
+            LogRel(("NAT: Error occurred while sending ICMP error message\n"));
             fIcmpErrorReported = true;
         }
     }
diff --git a/src/VBox/Devices/Network/slirp/ip_input.c b/src/VBox/Devices/Network/slirp/ip_input.c
index d945ba1..e5d2e00 100644
--- a/src/VBox/Devices/Network/slirp/ip_input.c
+++ b/src/VBox/Devices/Network/slirp/ip_input.c
@@ -113,6 +113,12 @@ ip_input(PNATState pData, struct mbuf *m)
         }
         else
             m->m_flags &= ~M_SKIP_FIREWALL;
+
+        /*
+         * XXX: TODO: this is most likely a leftover spooky action at
+         * a distance from alias_dns.c host resolver code and can be
+         * g/c'ed.
+         */
         if (m->m_len != RT_N2H_U16(ip->ip_len))
             m->m_len = RT_N2H_U16(ip->ip_len);
     }
diff --git a/src/VBox/Devices/Network/slirp/libalias/alias_dns.c b/src/VBox/Devices/Network/slirp/libalias/alias_dns.c
deleted file mode 100644
index 46c95aa..0000000
--- a/src/VBox/Devices/Network/slirp/libalias/alias_dns.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/* $Id: alias_dns.c $ */
-/** @file
- * libalias helper for using the host resolver instead of dnsproxy.
- */
-
-/*
- * Copyright (C) 2009-2015 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#ifndef RT_OS_WINDOWS
-# include <netdb.h>
-#endif
-#include <iprt/ctype.h>
-#include <iprt/assert.h>
-#include <slirp.h>
-#include "alias.h"
-#include "alias_local.h"
-#include "alias_mod.h"
-#define isdigit(ch)    RT_C_IS_DIGIT(ch)
-#define isalpha(ch)    RT_C_IS_ALPHA(ch)
-
-#define DNS_CONTROL_PORT_NUMBER 53
-/* see RFC 1035(4.1.1) */
-union dnsmsg_header
-{
-    struct
-    {
-        unsigned id:16;
-        unsigned rd:1;
-        unsigned tc:1;
-        unsigned aa:1;
-        unsigned opcode:4;
-        unsigned qr:1;
-        unsigned rcode:4;
-        unsigned Z:3;
-        unsigned ra:1;
-        uint16_t qdcount;
-        uint16_t ancount;
-        uint16_t nscount;
-        uint16_t arcount;
-    } X;
-    uint16_t raw[6];
-};
-AssertCompileSize(union dnsmsg_header, 12);
-
-struct dns_meta_data
-{
-    uint16_t type;
-    uint16_t class;
-};
-
-struct dnsmsg_answer
-{
-    uint16_t name;
-    struct dns_meta_data meta;
-    uint16_t ttl[2];
-    uint16_t rdata_len;
-    uint8_t  rdata[1];  /* depends on value at rdata_len */
-};
-
-/* see RFC 1035(4.1) */
-static int  dns_alias_handler(PNATState pData, int type);
-static void CStr2QStr(const char *pcszStr, char *pszQStr, size_t cQStr);
-static void QStr2CStr(const char *pcszQStr, char *pszStr, size_t cStr);
-#ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
-static void alterHostentWithDataFromDNSMap(PNATState pData, struct hostent *pHostent);
-#endif
-
-static int
-fingerprint(struct libalias *la, struct ip *pIp, struct alias_data *ah)
-{
-
-    NOREF(la);
-    NOREF(pIp);
-    if (!ah->dport || !ah->sport || !ah->lnk)
-        return -1;
-
-    Log(("NAT:%s: ah(dport: %hd, sport: %hd) oaddr:%RTnaipv4 aaddr:%RTnaipv4\n",
-        RT_GCC_EXTENSION __FUNCTION__, ntohs(*ah->dport), ntohs(*ah->sport),
-        ah->oaddr, ah->aaddr));
-
-    if (   (ntohs(*ah->dport) == DNS_CONTROL_PORT_NUMBER
-        || ntohs(*ah->sport) == DNS_CONTROL_PORT_NUMBER)
-        && (ah->oaddr->s_addr == htonl(ntohl(la->pData->special_addr.s_addr)|CTL_DNS)))
-        return 0;
-
-    return -1;
-}
-
-static void doanswer(union dnsmsg_header *pHdr, struct dns_meta_data *pReqMeta, char *pszQname, struct ip *pIp, struct hostent *pHostent)
-{
-    int i;
-
-    if (!pHostent)
-    {
-        pHdr->X.qr = 1; /* response */
-        pHdr->X.aa = 1;
-        pHdr->X.rd = 1;
-        pHdr->X.rcode = 3;
-    }
-    else
-    {
-        char *query;
-        char *answers;
-        uint16_t off;
-        char **cstr;
-        char *c;
-        uint16_t packet_len = 0;
-        uint16_t addr_off = (uint16_t)~0;
-        struct dns_meta_data *meta;
-
-#if 0
-        /* here is no compressed names+answers + new query */
-        m_inc(m, pHostent->h_length * sizeof(struct dnsmsg_answer) + strlen(pszQname) + 2 * sizeof(uint16_t));
-#endif
-        packet_len = (pIp->ip_hl << 2)
-                   + sizeof(struct udphdr)
-                   + sizeof(union dnsmsg_header)
-                   + strlen(pszQname)
-                   + sizeof(struct dns_meta_data); /* ip + udp + header + query */
-        query = (char *)&pHdr[1];
-
-        strcpy(query, pszQname);
-        query += strlen(pszQname) + 1;
-        /* class & type informations lay right after symbolic inforamtion. */
-        meta = (struct dns_meta_data *)query;
-        meta->type = pReqMeta->type;
-        meta->class = pReqMeta->class;
-
-        /* answers zone lays after query in response packet */
-        answers = (char *)&meta[1];
-
-        off = (char *)&pHdr[1] - (char *)pHdr;
-        off |= (0x3 << 14);
-
-        /* add aliases */
-        for (cstr = pHostent->h_aliases; cstr && *cstr; cstr++)
-        {
-            uint16_t len;
-            struct dnsmsg_answer *ans = (struct dnsmsg_answer *)answers;
-            ans->name = htons(off);
-            ans->meta.type = htons(5); /* CNAME */
-            ans->meta.class = htons(1);
-            *(uint32_t *)ans->ttl = htonl(3600); /* 1h */
-            c = (addr_off == (uint16_t)~0 ? pHostent->h_name : *cstr);
-            len = strlen(c) + 2;
-            ans->rdata_len = htons(len);
-            ans->rdata[len - 1] = 0;
-            CStr2QStr(c, (char *)ans->rdata, len);
-            off = (char *)&ans->rdata - (char *)pHdr;
-            off |= (0x3 << 14);
-            if (addr_off == (uint16_t)~0)
-                addr_off = off;
-            answers = (char *)&ans[1] + len - 2;  /* note: 1 symbol already counted */
-            packet_len += sizeof(struct dnsmsg_answer) + len - 2;
-            pHdr->X.ancount++;
-        }
-        /* add addresses */
-
-        for(i = 0; i < pHostent->h_length && pHostent->h_addr_list[i] != NULL; ++i)
-        {
-            struct dnsmsg_answer *ans = (struct dnsmsg_answer *)answers;
-
-            ans->name = htons(off);
-            ans->meta.type = htons(1);
-            ans->meta.class = htons(1);
-            *(uint32_t *)ans->ttl = htonl(3600); /* 1h */
-            ans->rdata_len = htons(4); /* IPv4 */
-            *(uint32_t *)ans->rdata = *(uint32_t *)pHostent->h_addr_list[i];
-            answers = (char *)&ans[1] + 2;
-            packet_len += sizeof(struct dnsmsg_answer) + 3;
-            pHdr->X.ancount++;
-        }
-        pHdr->X.qr = 1; /* response */
-        pHdr->X.aa = 1;
-        pHdr->X.rd = 1;
-        pHdr->X.ra = 1;
-        pHdr->X.rcode = 0;
-        HTONS(pHdr->X.ancount);
-        /* don't forget update m_len */
-        pIp->ip_len = htons(packet_len);
-    }
-}
-
-static int
-protohandler(struct libalias *la, struct ip *pIp, struct alias_data *ah)
-{
-    int i;
-    /* Parse dns request */
-    char *qw_qname = NULL;
-    struct hostent *pHostent = NULL;
-    char pszCname[255];
-    int cname_len = 0;
-    struct dns_meta_data *meta;
-
-    struct udphdr *udp = NULL;
-    union dnsmsg_header *pHdr = NULL;
-    NOREF(la);
-    NOREF(ah);
-    udp = (struct udphdr *)ip_next(pIp);
-    pHdr = (union dnsmsg_header *)udp_next(udp);
-
-    if (pHdr->X.qr == 1)
-        return 0; /* this is respose */
-
-    memset(pszCname, 0, sizeof(pszCname));
-    qw_qname = (char *)&pHdr[1];
-    Assert((ntohs(pHdr->X.qdcount) == 1));
-    if ((ntohs(pHdr->X.qdcount) != 1))
-    {
-        static bool fMultiWarn;
-        if (!fMultiWarn)
-        {
-            LogRel(("NAT:alias_dns: multiple quieries isn't supported\n"));
-            fMultiWarn = true;
-        }
-        return 1;
-    }
-
-    for (i = 0; i < ntohs(pHdr->X.qdcount); ++i)
-    {
-        meta = (struct dns_meta_data *)(qw_qname + strlen(qw_qname) + 1);
-        Log(("pszQname:%s qtype:%hd qclass:%hd\n",
-            qw_qname, ntohs(meta->type), ntohs(meta->class)));
-
-        QStr2CStr(qw_qname, pszCname, sizeof(pszCname));
-        cname_len = RTStrNLen(pszCname, sizeof(pszCname));
-        /* Some guests like win-xp adds _dot_ after host name
-         * and after domain name (not passed with host resolver)
-         * that confuses host resolver.
-         */
-        if (   cname_len > 2
-            && pszCname[cname_len - 1] == '.'
-            && pszCname[cname_len - 2] == '.')
-        {
-            pszCname[cname_len - 1] = 0;
-            pszCname[cname_len - 2] = 0;
-        }
-        pHostent = gethostbyname(pszCname);
-#ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
-        if (   pHostent
-            && !LIST_EMPTY(&la->pData->DNSMapHead))
-            alterHostentWithDataFromDNSMap(la->pData, pHostent);
-#endif
-        doanswer(pHdr, meta, qw_qname, pIp, pHostent);
-    }
-
-    /*
-     * We have changed the size and the content of udp, to avoid double csum calculation
-     * will assign to zero
-     */
-    udp->uh_sum = 0;
-    udp->uh_ulen = ntohs(htons(pIp->ip_len) - (pIp->ip_hl << 2));
-    pIp->ip_sum = 0;
-    pIp->ip_sum = LibAliasInternetChecksum(la, (uint16_t *)pIp, pIp->ip_hl << 2);
-    return 0;
-}
-
-/*
- * qstr is z-string with -dot- replaced with \count to next -dot-
- * e.g. ya.ru is \02ya\02ru
- * Note: it's assumed that caller allocates buffer for cstr
- */
-static void QStr2CStr(const char *pcszQStr, char *pszStr, size_t cStr)
-{
-    const char *q;
-    char *c;
-    size_t cLen = 0;
-
-    Assert(cStr > 0);
-    for (q = pcszQStr, c = pszStr; *q != '\0' && cLen < cStr-1; q++, cLen++)
-    {
-        if (   isalpha(*q)
-            || isdigit(*q)
-            || *q == '-'
-            || *q == '_')
-        {
-           *c = *q;
-            c++;
-        }
-        else if (c != &pszStr[0])
-        {
-            *c = '.';
-            c++;
-        }
-    }
-    *c = '\0';
-}
-
-/*
- *
- */
-static void CStr2QStr(const char *pcszStr, char *pszQStr, size_t cQStr)
-{
-    const char *c;
-    const char *pc;
-    char *q;
-    size_t cLen = 0;
-
-    Assert(cQStr > 0);
-    for (c = pcszStr, q = pszQStr; *c != '\0' && cLen < cQStr-1; q++, cLen++)
-    {
-        /* at the begining or at -dot- position */
-        if (*c == '.' || (c == pcszStr && q == pszQStr))
-        {
-            if (c != pcszStr)
-                c++;
-            pc = strchr(c, '.');
-            *q = pc ? (pc - c) : strlen(c);
-        }
-        else
-        {
-            *q = *c;
-            c++;
-        }
-    }
-    *q = '\0';
-}
-
-
-int
-dns_alias_load(PNATState pData)
-{
-    return dns_alias_handler(pData, MOD_LOAD);
-}
-
-int
-dns_alias_unload(PNATState pData)
-{
-    return dns_alias_handler(pData, MOD_UNLOAD);
-}
-
-#define handlers pData->dns_module
-static int
-dns_alias_handler(PNATState pData, int type)
-{
-    int error;
-
-    if (!handlers)
-        handlers = RTMemAllocZ(2 * sizeof(struct proto_handler));
-
-    handlers[0].pri = 20;
-    handlers[0].dir = IN;
-    handlers[0].proto = UDP;
-    handlers[0].fingerprint = &fingerprint;
-    handlers[0].protohandler = &protohandler;
-    handlers[1].pri = EOH;
-
-    switch (type)
-    {
-        case MOD_LOAD:
-            error = 0;
-            LibAliasAttachHandlers(pData, handlers);
-            break;
-
-        case MOD_UNLOAD:
-            error = 0;
-            LibAliasDetachHandlers(pData, handlers);
-            RTMemFree(handlers);
-            handlers = NULL;
-            break;
-
-        default:
-            error = EINVAL;
-    }
-    return error;
-}
-
-#ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
-static bool isDnsMappingEntryMatchOrEqual2Str(const PDNSMAPPINGENTRY pDNSMapingEntry, const char *pcszString)
-{
-    return (    (   pDNSMapingEntry->pszCName
-                 && !strcmp(pDNSMapingEntry->pszCName, pcszString))
-            || (   pDNSMapingEntry->pszPattern
-                && RTStrSimplePatternMultiMatch(pDNSMapingEntry->pszPattern, RTSTR_MAX, pcszString, RTSTR_MAX, NULL)));
-}
-
-static void alterHostentWithDataFromDNSMap(PNATState pData, struct hostent *pHostent)
-{
-    PDNSMAPPINGENTRY pDNSMapingEntry = NULL;
-    bool fMatch = false;
-    LIST_FOREACH(pDNSMapingEntry, &pData->DNSMapHead, MapList)
-    {
-        char **pszAlias = NULL;
-        if (isDnsMappingEntryMatchOrEqual2Str(pDNSMapingEntry, pHostent->h_name))
-        {
-            fMatch = true;
-            break;
-        }
-
-        for (pszAlias = pHostent->h_aliases; *pszAlias && !fMatch; pszAlias++)
-        {
-            if (isDnsMappingEntryMatchOrEqual2Str(pDNSMapingEntry, *pszAlias))
-            {
-
-                PDNSMAPPINGENTRY pDnsMapping = RTMemAllocZ(sizeof(DNSMAPPINGENTRY));
-                fMatch = true;
-                if (!pDnsMapping)
-                {
-                    LogFunc(("Can't allocate DNSMAPPINGENTRY\n"));
-                    LogFlowFuncLeave();
-                    return;
-                }
-                pDnsMapping->u32IpAddress = pDNSMapingEntry->u32IpAddress;
-                pDnsMapping->pszCName = RTStrDup(pHostent->h_name);
-                if (!pDnsMapping->pszCName)
-                {
-                    LogFunc(("Can't allocate enough room for %s\n", pHostent->h_name));
-                    RTMemFree(pDnsMapping);
-                    LogFlowFuncLeave();
-                    return;
-                }
-                LIST_INSERT_HEAD(&pData->DNSMapHead, pDnsMapping, MapList);
-                LogRel(("NAT: user-defined mapping %s: %RTnaipv4 is registered\n",
-                        pDnsMapping->pszCName ? pDnsMapping->pszCName : pDnsMapping->pszPattern,
-                        pDnsMapping->u32IpAddress));
-            }
-        }
-        if (fMatch)
-            break;
-    }
-
-    /* h_lenght is lenght of h_addr_list in bytes, so we check that we have enough space for IPv4 address */
-    if (   fMatch
-        && pHostent->h_length >= sizeof(uint32_t)
-        && pDNSMapingEntry)
-    {
-        pHostent->h_length = 1;
-        *(uint32_t *)pHostent->h_addr_list[0] = pDNSMapingEntry->u32IpAddress;
-    }
-
-}
-#endif
diff --git a/src/VBox/Devices/Network/slirp/libslirp.h b/src/VBox/Devices/Network/slirp/libslirp.h
index 50be8ed..4771306 100644
--- a/src/VBox/Devices/Network/slirp/libslirp.h
+++ b/src/VBox/Devices/Network/slirp/libslirp.h
@@ -37,6 +37,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
 #endif
 
 #include <VBox/types.h>
+#include <iprt/req.h>
 
 typedef struct NATState *PNATState;
 struct mbuf;
@@ -62,7 +63,6 @@ void slirp_select_poll(PNATState pData, struct pollfd *polls, int ndfs);
 #endif /* !RT_OS_WINDOWS */
 
 void slirp_input(PNATState pData, struct mbuf *m, size_t cbBuf);
-void slirp_set_ethaddr_and_activate_port_forwarding(PNATState pData, const uint8_t *ethaddr, uint32_t GuestIP);
 
 /* you must provide the following functions: */
 void slirp_arm_fast_timer(void *pvUser);
@@ -72,9 +72,18 @@ void slirp_output_pending(void * pvUser);
 void slirp_urg_output(void *pvUser, struct mbuf *, const uint8_t *pu8Buf, int cb);
 void slirp_post_sent(PNATState pData, void *pvArg);
 
+int slirp_call(void *pvUser, PRTREQ *ppReq, RTMSINTERVAL cMillies,
+               unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
+
+int slirp_call_hostres(void *pvUser, PRTREQ *ppReq, RTMSINTERVAL cMillies,
+                       unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
+
+
+void slirp_update_guest_addr_guess(PNATState pData, uint32_t guess, const char *msg);
+
 int slirp_add_redirect(PNATState pData, int is_udp, struct in_addr host_addr,
                 int host_port, struct in_addr guest_addr,
-                int guest_port, const uint8_t *);
+                int guest_port);
 int slirp_remove_redirect(PNATState pData, int is_udp, struct in_addr host_addr,
                 int host_port, struct in_addr guest_addr,
                 int guest_port);
@@ -169,7 +178,9 @@ int slirp_get_nsock(PNATState pData);
 # endif
 
 #ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
-void  slirp_add_host_resolver_mapping(PNATState pData, const char *pszHostName, const char *pszHostNamePattern, uint32_t u32HostIP);
+void slirp_add_host_resolver_mapping(PNATState pData,
+                                     const char *pszHostName, bool fPattern,
+                                     uint32_t u32HostIP);
 #endif
 
 #ifdef __cplusplus
diff --git a/src/VBox/Devices/Network/slirp/misc.c b/src/VBox/Devices/Network/slirp/misc.c
index 3126050..8588260 100644
--- a/src/VBox/Devices/Network/slirp/misc.c
+++ b/src/VBox/Devices/Network/slirp/misc.c
@@ -223,7 +223,7 @@ static void *slirp_uma_alloc(uma_zone_t zone,
         it->magic = ITEM_MAGIC;
         LIST_INSERT_HEAD(&zone->free_items, it, list);
         if (zone->cur_items >= zone->max_items)
-            LogRel(("NAT: zone(%s) has reached it maximum\n", zone->name));
+            LogRel(("NAT: Zone(%s) has reached it maximum\n", zone->name));
     }
     RTCritSectLeave(&zone->csZone);
     LogFlowFunc(("LEAVE: %p\n", ret));
@@ -535,7 +535,7 @@ static void zone_destroy(uma_zone_t zone)
 {
     RTCritSectEnter(&zone->csZone);
     LogFlowFunc(("ENTER: zone:%R[mzone]\n", zone));
-    LogRel(("NAT: zone(nm:%s, used:%d)\n", zone->name, zone->cur_items));
+    LogRel(("NAT: Zone(nm:%s, used:%d)\n", zone->name, zone->cur_items));
     RTMemFree(zone->area);
     RTCritSectLeave(&zone->csZone);
     RTCritSectDelete(&zone->csZone);
diff --git a/src/VBox/Devices/Network/slirp/slirp.c b/src/VBox/Devices/Network/slirp/slirp.c
index cc9c50b..b8459b4 100644
--- a/src/VBox/Devices/Network/slirp/slirp.c
+++ b/src/VBox/Devices/Network/slirp/slirp.c
@@ -260,8 +260,6 @@
 #define LOG_NAT_SOCK(so, proto, winevent, r_fdset, w_fdset, x_fdset) \
     DO_LOG_NAT_SOCK((so), proto, (winevent), r_fdset, w_fdset, x_fdset)
 
-static void activate_port_forwarding(PNATState, const uint8_t *pEther);
-
 static const uint8_t special_ethaddr[6] =
 {
     0x52, 0x54, 0x00, 0x12, 0x35, 0x00
@@ -306,7 +304,7 @@ int slirp_init(PNATState *ppData, uint32_t u32NetAddr, uint32_t u32Netmask,
     if (u32Netmask & 0x1f)
     {
         /* CTL is x.x.x.15, bootp passes up to 16 IPs (15..31) */
-        LogRel(("The last 5 bits of the netmask (%RTnaipv4) need to be unset\n", RT_BE2H_U32(u32Netmask)));
+        LogRel(("NAT: The last 5 bits of the netmask (%RTnaipv4) need to be unset\n", RT_BE2H_U32(u32Netmask)));
         return VERR_INVALID_PARAMETER;
     }
     pData = RTMemAllocZ(RT_ALIGN_Z(sizeof(NATState), sizeof(uint64_t)));
@@ -408,8 +406,6 @@ int slirp_init(PNATState *ppData, uint32_t u32NetAddr, uint32_t u32Netmask,
         LibAliasSetAddress(pData->proxy_alias, proxy_addr);
         ftp_alias_load(pData);
         nbt_alias_load(pData);
-        if (pData->fUseHostResolver)
-            dns_alias_load(pData);
     }
 #ifdef VBOX_WITH_NAT_SEND2HOME
     /* @todo: we should know all interfaces available on host. */
@@ -422,6 +418,11 @@ int slirp_init(PNATState *ppData, uint32_t u32NetAddr, uint32_t u32Netmask,
 # endif
 #endif
 
+#ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
+    STAILQ_INIT(&pData->DNSMapNames);
+    STAILQ_INIT(&pData->DNSMapPatterns);
+#endif
+
     slirp_link_up(pData);
     return VINF_SUCCESS;
 }
@@ -476,14 +477,6 @@ void slirp_link_up(PNATState pData)
 
     if (!pData->fUseHostResolverPermanent)
         slirpInitializeDnsSettings(pData);
-
-    if (LIST_EMPTY(&pData->arp_cache))
-        return;
-
-    LIST_FOREACH(ac, &pData->arp_cache, list)
-    {
-        activate_port_forwarding(pData, ac->ether);
-    }
 }
 
 /**
@@ -498,16 +491,6 @@ void slirp_link_down(PNATState pData)
 
     slirpReleaseDnsSettings(pData);
 
-    /*
-     *  Clear the active state of port-forwarding rules to force
-     *  re-setup on restoration of communications.
-     */
-    LIST_FOREACH(rule, &pData->port_forward_rule_head, list)
-    {
-        rule->activated = 0;
-    }
-    pData->cRedirectionsActive = 0;
-
     link_up = 0;
 }
 
@@ -540,19 +523,27 @@ void slirp_term(PNATState pData)
     slirp_link_down(pData);
     ftp_alias_unload(pData);
     nbt_alias_unload(pData);
-    if (pData->fUseHostResolver)
-    {
-        dns_alias_unload(pData);
+
 #ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
-        while (!LIST_EMPTY(&pData->DNSMapHead))
+    {
+        DNSMAPPINGHEAD *heads[2];
+        int i;
+
+        heads[0] = &pData->DNSMapNames;
+        heads[1] = &pData->DNSMapPatterns;
+        for (i = 0; i < RT_ELEMENTS(heads); ++i)
         {
-            PDNSMAPPINGENTRY pDnsEntry = LIST_FIRST(&pData->DNSMapHead);
-            LIST_REMOVE(pDnsEntry, MapList);
-            RTStrFree(pDnsEntry->pszCName);
-            RTMemFree(pDnsEntry);
+            while (!STAILQ_EMPTY(heads[i]))
+            {
+                PDNSMAPPINGENTRY pDnsEntry = STAILQ_FIRST(heads[i]);
+                STAILQ_REMOVE_HEAD(heads[i], MapList);
+                RTStrFree(pDnsEntry->pszName);
+                RTMemFree(pDnsEntry);
+            }
         }
-#endif
     }
+#endif
+
     while (!LIST_EMPTY(&instancehead))
     {
         struct libalias *la = LIST_FIRST(&instancehead);
@@ -1306,7 +1297,7 @@ static void arp_output(PNATState pData, const uint8_t *pcu8EtherSource, const st
         static bool fTagErrorReported;
         if (!fTagErrorReported)
         {
-            LogRel(("NAT: couldn't add the tag(PACKET_SERVICE:%d)\n",
+            LogRel(("NAT: Couldn't add the tag(PACKET_SERVICE:%d)\n",
                         (uint8_t)(ip4TargetAddressInHostFormat & ~pData->netmask)));
             fTagErrorReported = true;
         }
@@ -1318,6 +1309,7 @@ static void arp_output(PNATState pData, const uint8_t *pcu8EtherSource, const st
     memcpy(pARPHeaderResponse->ar_tip, pcARPHeaderSource->ar_sip, 4);
     if_encap(pData, ETH_P_ARP, pMbufResponse, ETH_ENCAP_URG);
 }
+
 /**
  * @note This function will free m!
  */
@@ -1340,23 +1332,21 @@ static void arp_input(PNATState pData, struct mbuf *m)
             if (   CTL_CHECK(ip4TargetAddress, CTL_DNS)
                 || CTL_CHECK(ip4TargetAddress, CTL_ALIAS)
                 || CTL_CHECK(ip4TargetAddress, CTL_TFTP))
+            {
+                slirp_update_guest_addr_guess(pData, *(uint32_t *)pARPHeader->ar_sip, "arp request");
                 arp_output(pData, pEtherHeader->h_source, pARPHeader, ip4TargetAddress);
+                break;
+            }
 
             /* Gratuitous ARP */
-            if (  *(uint32_t *)pARPHeader->ar_sip == *(uint32_t *)pARPHeader->ar_tip
-                && memcmp(pARPHeader->ar_tha, broadcast_ethaddr, ETH_ALEN) == 0
+            if (   *(uint32_t *)pARPHeader->ar_sip == *(uint32_t *)pARPHeader->ar_tip
+                && (   memcmp(pARPHeader->ar_tha, zerro_ethaddr, ETH_ALEN) == 0
+                    || memcmp(pARPHeader->ar_tha, broadcast_ethaddr, ETH_ALEN) == 0)
                 && memcmp(pEtherHeader->h_dest, broadcast_ethaddr, ETH_ALEN) == 0)
             {
-                /* We've received an announce about address assignment,
-                 * let's do an ARP cache update
-                 */
-                static bool fGratuitousArpReported;
-                if (!fGratuitousArpReported)
-                {
-                    LogRel(("NAT: Gratuitous ARP [IP:%RTnaipv4, ether:%RTmac]\n",
-                            *(uint32_t *)pARPHeader->ar_sip, pARPHeader->ar_sha));
-                    fGratuitousArpReported = true;
-                }
+                LogRel2(("NAT: Gratuitous ARP from %RTnaipv4 at %RTmac\n",
+                         *(uint32_t *)pARPHeader->ar_sip, pARPHeader->ar_sha));
+                slirp_update_guest_addr_guess(pData, *(uint32_t *)pARPHeader->ar_sip, "gratuitous arp");
                 slirp_arp_cache_update_or_add(pData, *(uint32_t *)pARPHeader->ar_sip, &pARPHeader->ar_sha[0]);
             }
             break;
@@ -1427,9 +1417,6 @@ void slirp_input(PNATState pData, struct mbuf *m, size_t cbBuf)
             m_freem(pData, m);
             break;
     }
-
-    if (pData->cRedirectionsActive != pData->cRedirectionsStored)
-        activate_port_forwarding(pData, au8Ether);
 }
 
 /**
@@ -1497,134 +1484,71 @@ done:
     LogFlowFuncLeave();
 }
 
-/**
- * Still we're using dhcp server leasing to map ether to IP
- * @todo  see rt_lookup_in_cache
- */
-static uint32_t find_guest_ip(PNATState pData, const uint8_t *eth_addr)
-{
-    uint32_t ip = INADDR_ANY;
-    int rc;
-
-    if (eth_addr == NULL)
-        return INADDR_ANY;
 
-    if (   memcmp(eth_addr, zerro_ethaddr, ETH_ALEN) == 0
-        || memcmp(eth_addr, broadcast_ethaddr, ETH_ALEN) == 0)
-        return INADDR_ANY;
+void
+slirp_update_guest_addr_guess(PNATState pData, uint32_t guess, const char *msg)
+{
+    Assert(msg != NULL);
 
-    rc = slirp_arp_lookup_ip_by_ether(pData, eth_addr, &ip);
-    if (RT_SUCCESS(rc))
-        return ip;
+    if (pData->guest_addr_guess.s_addr == guess)
+    {
+        LogRel2(("NAT: Guest address guess %RTnaipv4 re-confirmed by %s\n",
+                 pData->guest_addr_guess.s_addr, msg));
+        return;
+    }
 
-    bootp_cache_lookup_ip_by_ether(pData, eth_addr, &ip);
-    /* ignore return code, ip will be set to INADDR_ANY on error */
-    return ip;
+    if (pData->guest_addr_guess.s_addr == INADDR_ANY)
+    {
+        pData->guest_addr_guess.s_addr = guess;
+        LogRel(("NAT: Guest address guess set to %RTnaipv4 by %s\n",
+                pData->guest_addr_guess.s_addr, msg));
+        return;
+    }
+    else
+    {
+        LogRel(("NAT: Guest address guess changed from %RTnaipv4 to %RTnaipv4 by %s\n",
+                pData->guest_addr_guess.s_addr, guess, msg));
+        pData->guest_addr_guess.s_addr = guess;
+        return;
+    }
 }
 
-/**
- * We need check if we've activated port forwarding
- * for specific machine ... that of course relates to
- * service mode
- * @todo finish this for service case
- */
-static void activate_port_forwarding(PNATState pData, const uint8_t *h_source)
+
+static struct port_forward_rule *
+slirp_find_redirect(PNATState pData,
+                    int is_udp,
+                    struct in_addr host_addr, int host_port,
+                    struct in_addr guest_addr, int guest_port)
 {
-    struct port_forward_rule *rule, *tmp;
-    const uint8_t *pu8EthSource = h_source;
+    struct port_forward_rule *rule;
+    uint16_t proto = (is_udp ? IPPROTO_UDP : IPPROTO_TCP);
 
-    /* check mac here */
-    LIST_FOREACH_SAFE(rule, &pData->port_forward_rule_head, list, tmp)
+    LIST_FOREACH(rule, &pData->port_forward_rule_head, list)
     {
-        struct socket *so;
-        struct sockaddr sa;
-        struct sockaddr_in *psin;
-        socklen_t socketlen;
-        int rc;
-        uint32_t guest_addr; /* need to understand if we already give address to guest */
-
-        if (rule->activated)
-            continue;
-
-        guest_addr = find_guest_ip(pData, pu8EthSource);
-        if (guest_addr == INADDR_ANY)
+        if (   rule->proto == proto
+            && rule->host_port == host_port
+            && rule->bind_ip.s_addr == host_addr.s_addr
+            && rule->guest_port == guest_port
+            && rule->guest_addr.s_addr == guest_addr.s_addr)
         {
-            /* the address wasn't granted */
-            return;
+            return rule;
         }
-
-        if (   rule->guest_addr.s_addr != guest_addr
-            && rule->guest_addr.s_addr != INADDR_ANY)
-            continue;
-        if (rule->guest_addr.s_addr == INADDR_ANY)
-            rule->guest_addr.s_addr = guest_addr;
-
-        LogRel(("NAT: set redirect %s host %RTnaipv4:%d => guest %RTnaipv4:%d\n",
-                rule->proto == IPPROTO_UDP ? "UDP" : "TCP",
-                rule->bind_ip.s_addr, rule->host_port,
-                guest_addr, rule->guest_port));
-
-        if (rule->proto == IPPROTO_UDP)
-            so = udp_listen(pData, rule->bind_ip.s_addr, RT_H2N_U16(rule->host_port), guest_addr,
-                            RT_H2N_U16(rule->guest_port), 0);
-        else
-            so = solisten(pData, rule->bind_ip.s_addr, RT_H2N_U16(rule->host_port), guest_addr,
-                          RT_H2N_U16(rule->guest_port), 0);
-
-        if (so == NULL)
-            goto remove_port_forwarding;
-
-        psin = (struct sockaddr_in *)&sa;
-        psin->sin_family = AF_INET;
-        psin->sin_port = 0;
-        psin->sin_addr.s_addr = INADDR_ANY;
-        socketlen = sizeof(struct sockaddr);
-
-        rc = getsockname(so->s, &sa, &socketlen);
-        if (rc < 0 || sa.sa_family != AF_INET)
-            goto remove_port_forwarding;
-
-        rule->activated = 1;
-        rule->so = so;
-        pData->cRedirectionsActive++;
-        continue;
-
-    remove_port_forwarding:
-        LogRel(("NAT: failed to redirect %s %RTnaipv4:%d => %RTnaipv4:%d (%s)\n",
-                (rule->proto == IPPROTO_UDP ? "UDP" : "TCP"),
-                rule->bind_ip.s_addr, rule->host_port,
-                guest_addr, rule->guest_port, strerror(errno)));
-        LIST_REMOVE(rule, list);
-        pData->cRedirectionsStored--;
-        RTMemFree(rule);
     }
+
+    return NULL;
 }
 
-/**
- * Changes in 3.1 instead of opening new socket do the following:
- * gain more information:
- *  1. bind IP
- *  2. host port
- *  3. guest port
- *  4. proto
- *  5. guest MAC address
- * the guest's MAC address is rather important for service, but we easily
- * could get it from VM configuration in DrvNAT or Service, the idea is activating
- * corresponding port-forwarding
- */
+
 int slirp_add_redirect(PNATState pData, int is_udp, struct in_addr host_addr, int host_port,
-                struct in_addr guest_addr, int guest_port, const uint8_t *ethaddr)
+                struct in_addr guest_addr, int guest_port)
 {
-    struct port_forward_rule *rule = NULL;
-    LIST_FOREACH(rule, &pData->port_forward_rule_head, list)
+    struct port_forward_rule *rule;
+
+    rule = slirp_find_redirect(pData, is_udp, host_addr, host_port, guest_addr, guest_port);
+    if (rule != NULL) /* rule has been already registered */
     {
-        if (   rule->proto == (is_udp ? IPPROTO_UDP : IPPROTO_TCP)
-            && rule->host_port == host_port
-            && rule->bind_ip.s_addr == host_addr.s_addr
-            && rule->guest_port == guest_port
-            && rule->guest_addr.s_addr == guest_addr.s_addr
-            )
-            return 0; /* rule has been already registered */
+        /* XXX: this shouldn't happen */
+        return 0;
     }
 
     rule = RTMemAllocZ(sizeof(struct port_forward_rule));
@@ -1632,63 +1556,71 @@ int slirp_add_redirect(PNATState pData, int is_udp, struct in_addr host_addr, in
         return 1;
 
     rule->proto = (is_udp ? IPPROTO_UDP : IPPROTO_TCP);
+    rule->bind_ip.s_addr = host_addr.s_addr;
     rule->host_port = host_port;
-    rule->guest_port = guest_port;
     rule->guest_addr.s_addr = guest_addr.s_addr;
-    rule->bind_ip.s_addr = host_addr.s_addr;
-    if (ethaddr != NULL)
-        memcpy(rule->mac_address, ethaddr, ETH_ALEN);
-    /* @todo add mac address */
+    rule->guest_port = guest_port;
+
+    if (rule->proto == IPPROTO_UDP)
+        rule->so = udp_listen(pData, rule->bind_ip.s_addr, RT_H2N_U16(rule->host_port),
+                              rule->guest_addr.s_addr, RT_H2N_U16(rule->guest_port), 0);
+    else
+        rule->so = solisten(pData, rule->bind_ip.s_addr, RT_H2N_U16(rule->host_port),
+                            rule->guest_addr.s_addr, RT_H2N_U16(rule->guest_port), 0);
+
+    if (rule->so == NULL)
+    {
+        LogRel(("NAT: Failed to redirect %s %RTnaipv4:%d -> %RTnaipv4:%d (%s)\n",
+                rule->proto == IPPROTO_UDP ? "UDP" : "TCP",
+                rule->bind_ip.s_addr, rule->host_port,
+                guest_addr, rule->guest_port, strerror(errno)));
+        RTMemFree(rule);
+        return 1;
+    }
+
+    LogRel(("NAT: Set redirect %s %RTnaipv4:%d -> %RTnaipv4:%d\n",
+            rule->proto == IPPROTO_UDP ? "UDP" : "TCP",
+            rule->bind_ip.s_addr, rule->host_port,
+            guest_addr, rule->guest_port));
+
     LIST_INSERT_HEAD(&pData->port_forward_rule_head, rule, list);
-    pData->cRedirectionsStored++;
-    /* activate port-forwarding if guest has already got assigned IP */
-    if (   ethaddr
-        && memcmp(ethaddr, zerro_ethaddr, ETH_ALEN))
-        activate_port_forwarding(pData, ethaddr);
     return 0;
 }
 
+
 int slirp_remove_redirect(PNATState pData, int is_udp, struct in_addr host_addr, int host_port,
                 struct in_addr guest_addr, int guest_port)
 {
-    struct port_forward_rule *rule = NULL;
-    LIST_FOREACH(rule, &pData->port_forward_rule_head, list)
+    struct port_forward_rule *rule;
+
+    rule = slirp_find_redirect(pData, is_udp, host_addr, host_port, guest_addr, guest_port);
+    if (rule == NULL)
     {
-        if (   rule->proto == (is_udp ? IPPROTO_UDP : IPPROTO_TCP)
-            && rule->host_port == host_port
-            && rule->guest_port == guest_port
-            && rule->bind_ip.s_addr == host_addr.s_addr
-            && rule->guest_addr.s_addr == guest_addr.s_addr
-            && rule->activated)
-        {
-            LogRel(("NAT: remove redirect %s host %RTnaipv4:%d => guest %RTnaipv4:%d\n",
-                    rule->proto == IPPROTO_UDP ? "UDP" : "TCP",
-                    rule->bind_ip.s_addr, rule->host_port,
-                    guest_addr.s_addr, rule->guest_port));
+        LogRel(("NAT: Unable to find redirect %s %RTnaipv4:%d -> %RTnaipv4:%d\n",
+                is_udp ? "UDP" : "TCP",
+                host_addr.s_addr, host_port,
+                guest_addr.s_addr, guest_port));
+        return 0;
+    }
 
-            if (is_udp)
-                udp_detach(pData, rule->so);
-            else
-                tcp_close(pData, sototcpcb(rule->so));
-            LIST_REMOVE(rule, list);
-            RTMemFree(rule);
-            pData->cRedirectionsStored--;
-            break;
-        }
+    LogRel(("NAT: Remove redirect %s %RTnaipv4:%d -> %RTnaipv4:%d\n",
+            rule->proto == IPPROTO_UDP ? "UDP" : "TCP",
+            rule->bind_ip.s_addr, rule->host_port,
+            guest_addr.s_addr, rule->guest_port));
 
+    if (rule->so != NULL)
+    {
+        if (is_udp)
+            udp_detach(pData, rule->so);
+        else
+            tcp_close(pData, sototcpcb(rule->so));
     }
+
+    LIST_REMOVE(rule, list);
+    RTMemFree(rule);
     return 0;
 }
 
-void slirp_set_ethaddr_and_activate_port_forwarding(PNATState pData, const uint8_t *ethaddr, uint32_t GuestIP)
-{
-    memcpy(client_ethaddr, ethaddr, ETH_ALEN);
-    if (GuestIP != INADDR_ANY)
-    {
-        slirp_arp_cache_update_or_add(pData, GuestIP, ethaddr);
-        activate_port_forwarding(pData, ethaddr);
-    }
-}
 
 #if defined(RT_OS_WINDOWS)
 HANDLE *slirp_get_events(PNATState pData)
@@ -1903,7 +1835,7 @@ void slirp_arp_who_has(PNATState pData, uint32_t dst)
     if (   dst == INADDR_ANY
         && !fWarned)
     {
-        LogRel(("NAT:ARP: \"WHO HAS INADDR_ANY\" request has been detected\n"));
+        LogRel(("NAT: ARP: \"WHO HAS INADDR_ANY\" request has been detected\n"));
         fWarned = true;
     }
 #endif /* !DEBUG_vvl */
@@ -1936,46 +1868,7 @@ void slirp_arp_who_has(PNATState pData, uint32_t dst)
     if_encap(pData, ETH_P_ARP, m, ETH_ENCAP_URG);
     LogFlowFuncLeave();
 }
-#ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
-void  slirp_add_host_resolver_mapping(PNATState pData, const char *pszHostName, const char *pszHostNamePattern, uint32_t u32HostIP)
-{
-    LogFlowFunc(("ENTER: pszHostName:%s, pszHostNamePattern:%s u32HostIP:%RTnaipv4\n",
-                pszHostName ? pszHostName : "(null)",
-                pszHostNamePattern ? pszHostNamePattern : "(null)",
-                u32HostIP));
-    if (   (   pszHostName
-            || pszHostNamePattern)
-        && u32HostIP != INADDR_ANY
-        && u32HostIP != INADDR_BROADCAST)
-    {
-        PDNSMAPPINGENTRY pDnsMapping = RTMemAllocZ(sizeof(DNSMAPPINGENTRY));
-        if (!pDnsMapping)
-        {
-            LogFunc(("Can't allocate DNSMAPPINGENTRY\n"));
-            LogFlowFuncLeave();
-            return;
-        }
-        pDnsMapping->u32IpAddress = u32HostIP;
-        if (pszHostName)
-            pDnsMapping->pszCName = RTStrDup(pszHostName);
-        else if (pszHostNamePattern)
-            pDnsMapping->pszPattern = RTStrDup(pszHostNamePattern);
-        if (   !pDnsMapping->pszCName
-            && !pDnsMapping->pszPattern)
-        {
-            LogFunc(("Can't allocate enough room for %s\n", pszHostName ? pszHostName : pszHostNamePattern));
-            RTMemFree(pDnsMapping);
-            LogFlowFuncLeave();
-            return;
-        }
-        LIST_INSERT_HEAD(&pData->DNSMapHead, pDnsMapping, MapList);
-        LogRel(("NAT: user-defined mapping %s: %RTnaipv4 is registered\n",
-                pDnsMapping->pszCName ? pDnsMapping->pszCName : pDnsMapping->pszPattern,
-                pDnsMapping->u32IpAddress));
-    }
-    LogFlowFuncLeave();
-}
-#endif
+
 
 /* updates the arp cache
  * @note: this is helper function, slirp_arp_cache_update_or_add should be used.
@@ -2047,7 +1940,7 @@ void slirp_set_mtu(PNATState pData, int mtu)
 {
     if (mtu < 20 || mtu >= 16000)
     {
-        LogRel(("NAT: mtu(%d) is out of range (20;16000] mtu forcely assigned to 1500\n", mtu));
+        LogRel(("NAT: MTU(%d) is out of range (20;16000] mtu forcely assigned to 1500\n", mtu));
         mtu = 1500;
     }
     /* MTU is maximum transition unit on */
diff --git a/src/VBox/Devices/Network/slirp/slirp.h b/src/VBox/Devices/Network/slirp/slirp.h
index 7c7db80..412795a 100644
--- a/src/VBox/Devices/Network/slirp/slirp.h
+++ b/src/VBox/Devices/Network/slirp/slirp.h
@@ -350,6 +350,9 @@ u_int8_t tcp_tos (struct socket *);
 int tcp_ctl (PNATState, struct socket *);
 struct tcpcb *tcp_drop(PNATState, struct tcpcb *tp, int err);
 
+/* hostres.c */
+struct mbuf *hostresolver(PNATState, struct mbuf *, uint32_t src, uint16_t sport);
+
 /*slirp.c*/
 void slirp_arp_who_has(PNATState pData, uint32_t dst);
 int slirp_arp_cache_update_or_add(PNATState pData, uint32_t dst, const uint8_t *mac);
@@ -464,8 +467,6 @@ int ftp_alias_load(PNATState);
 int ftp_alias_unload(PNATState);
 int nbt_alias_load(PNATState);
 int nbt_alias_unload(PNATState);
-int dns_alias_load(PNATState);
-int dns_alias_unload(PNATState);
 int slirp_arp_lookup_ip_by_ether(PNATState, const uint8_t *, uint32_t *);
 int slirp_arp_lookup_ether_by_ip(PNATState, uint32_t, uint8_t *);
 
diff --git a/src/VBox/Devices/Network/slirp/slirp_dns.c b/src/VBox/Devices/Network/slirp/slirp_dns.c
index d52ebcb..4349070 100644
--- a/src/VBox/Devices/Network/slirp/slirp_dns.c
+++ b/src/VBox/Devices/Network/slirp/slirp_dns.c
@@ -245,16 +245,10 @@ int slirpInitializeDnsSettings(PNATState pData)
          */
         if (get_dns_addr_domain(pData, NULL) < 0)
         {
-            /* Load the DNS handler if host resolver mode was not used before. */
-            if (!pData->fUseHostResolver)
-                dns_alias_load(pData);
             pData->fUseHostResolver = true;
         }
         else
         {
-            /* Unload to not intercept in the future. */
-            if (pData->fUseHostResolver)
-                dns_alias_unload(pData);
             pData->fUseHostResolver = false;
             dnsproxy_init(pData);
         }
diff --git a/src/VBox/Devices/Network/slirp/slirp_state.h b/src/VBox/Devices/Network/slirp/slirp_state.h
index 5844325..f10ec1e 100644
--- a/src/VBox/Devices/Network/slirp/slirp_state.h
+++ b/src/VBox/Devices/Network/slirp/slirp_state.h
@@ -57,19 +57,16 @@ LIST_HEAD(dns_domain_list_head, dns_domain_entry);
 #ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
 typedef struct DNSMAPPINGENTRY
 {
-    /** host name to map.
-     * @note If pszCName isn't null pszPattern won't be used (see alias_dns.c for
-     *       details).
-     */
-    char        *pszCName;
-    /** Pattern (simple) of hostnames to map to the specified IP. */
-    char        *pszPattern;
+    /** Literal or pattern. */
+    bool        fPattern;
+    /** Host name or pattern to map. */
+    char        *pszName;
     /** The IP Address. */
     uint32_t    u32IpAddress;
     /** List entry.  */
-    LIST_ENTRY(DNSMAPPINGENTRY) MapList;
+    STAILQ_ENTRY(DNSMAPPINGENTRY) MapList;
 } DNSMAPPINGENTRY, *PDNSMAPPINGENTRY;
-typedef LIST_HEAD(DNSMAPPINGLISTHEAD, DNSMAPPINGENTRY) DNSMAPPINGLISTHEAD;
+typedef STAILQ_HEAD(DNSMAPPINGHEAD, DNSMAPPINGENTRY) DNSMAPPINGHEAD;
 #endif
 
 struct dns_entry
@@ -87,7 +84,6 @@ struct port_forward_rule
     uint16_t guest_port;
     struct in_addr guest_addr;
     struct in_addr bind_ip;
-    uint8_t mac_address[6]; /*need ETH_ALEN here */
     int activated;
     struct socket *so;
     LIST_ENTRY(port_forward_rule) list;
@@ -139,6 +135,7 @@ typedef struct NATState
     struct in_addr our_addr;
     struct in_addr alias_addr;
     struct in_addr special_addr;
+    struct in_addr guest_addr_guess;
 
     int tcp_rcvspace;
     int tcp_sndspace;
@@ -298,13 +295,10 @@ typedef struct NATState
     /** Critical R/W section to protect the handler chain list. */
     RTCRITSECTRW CsRwHandlerChain;
     struct port_forward_rule_list port_forward_rule_head;
-    int cRedirectionsActive;
-    int cRedirectionsStored;
     struct arp_cache_head arp_cache;
     /* libalis modules' handlers*/
     struct proto_handler *ftp_module;
     struct proto_handler *nbt_module;
-    struct proto_handler *dns_module;
 #ifdef VBOX_WITH_NAT_SEND2HOME
     /* array of home addresses */
     struct sockaddr_in *pInSockAddrHomeAddress;
@@ -312,7 +306,8 @@ typedef struct NATState
     int cInHomeAddressSize;
 #endif
 #ifdef VBOX_WITH_DNSMAPPING_IN_HOSTRESOLVER
-    DNSMAPPINGLISTHEAD DNSMapHead;
+    DNSMAPPINGHEAD DNSMapNames;
+    DNSMAPPINGHEAD DNSMapPatterns;
 #endif
 } NATState;
 
diff --git a/src/VBox/Devices/Network/slirp/socket.c b/src/VBox/Devices/Network/slirp/socket.c
index b75fb6c..4e5af6a 100644
--- a/src/VBox/Devices/Network/slirp/socket.c
+++ b/src/VBox/Devices/Network/slirp/socket.c
@@ -1336,7 +1336,7 @@ static void sorecvfrom_icmp_unix(PNATState pData, struct socket *so)
         else if (errno == ENETUNREACH)
             code = ICMP_UNREACH_NET;
 
-        LogRel((" udp icmp rx errno = %d (%s)\n", errno, strerror(errno)));
+        LogRel(("NAT: UDP ICMP rx errno=%d (%s)\n", errno, strerror(errno)));
         icmp_error(pData, so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
         so->so_m = NULL;
         Log(("sorecvfrom_icmp_unix: 1 - step can't read IP datagramm\n"));
diff --git a/src/VBox/Devices/Network/slirp/tcp_output.c b/src/VBox/Devices/Network/slirp/tcp_output.c
index c2da476..869bf6a 100644
--- a/src/VBox/Devices/Network/slirp/tcp_output.c
+++ b/src/VBox/Devices/Network/slirp/tcp_output.c
@@ -496,7 +496,7 @@ send:
             tcp_template(tp);
             if(!fWarn)
             {
-                LogRel(("NAT:TCP: TCP template was created forcely from socket information\n"));
+                LogRel(("NAT: TCP: TCP template was created forcely from socket information\n"));
                 fWarn = true;
             }
         }
diff --git a/src/VBox/Devices/Network/slirp/tcp_subr.c b/src/VBox/Devices/Network/slirp/tcp_subr.c
index 8851404..2405aaa 100644
--- a/src/VBox/Devices/Network/slirp/tcp_subr.c
+++ b/src/VBox/Devices/Network/slirp/tcp_subr.c
@@ -492,6 +492,16 @@ tcp_connect(PNATState pData, struct socket *inso)
 
     LogFlowFunc(("ENTER: inso = %R[natsock]\n", inso));
 
+    if (   inso->so_laddr.s_addr == INADDR_ANY /* delayed port-forwarding? */
+        && pData->guest_addr_guess.s_addr == INADDR_ANY)
+    {
+        LogRel2(("NAT: Port-forward: guest address unknown for %R[natsock]\n", inso));
+        closesocket(accept(inso->s, NULL, NULL));
+        if (inso->so_state & SS_FACCEPTONCE)
+            tcp_close(pData, sototcpcb(inso));
+        return;
+    }
+
     /*
      * If it's an SS_ACCEPTONCE socket, no need to socreate()
      * another socket, just use the accept() socket.
@@ -518,6 +528,13 @@ tcp_connect(PNATState pData, struct socket *inso)
         so->so_lport = inso->so_lport;
     }
 
+    if (so->so_laddr.s_addr == INADDR_ANY)
+    {
+        LogRel2(("NAT: Port-forward: using %RTnaipv4 for %R[natsock]\n",
+                 pData->guest_addr_guess.s_addr, inso));
+        so->so_laddr = pData->guest_addr_guess;
+    }
+
     (void) tcp_mss(pData, sototcpcb(so), 0);
 
     fd_nonblock(inso->s);
@@ -544,7 +561,7 @@ tcp_connect(PNATState pData, struct socket *inso)
         goto no_sockopt;
     }
     if (cVerbose > 0)
-        LogRel(("NAT: old socket rcv size: %dKB\n", opt / 1024));
+        LogRel(("NAT: Old socket recv size: %dKB\n", opt / 1024));
     /* @todo (r-vvl) make it configurable (via extra data) */
     opt = pData->socket_rcv;
     status = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, sizeof(int));
@@ -561,7 +578,7 @@ tcp_connect(PNATState pData, struct socket *inso)
         goto no_sockopt;
     }
     if (cVerbose > 0)
-        LogRel(("NAT: old socket snd size: %dKB\n", opt / 1024));
+        LogRel(("NAT: Old socket send size: %dKB\n", opt / 1024));
     opt = pData->socket_rcv;
     status = setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&opt, sizeof(int));
     if (status < 0)
diff --git a/src/VBox/Devices/Network/slirp/udp.c b/src/VBox/Devices/Network/slirp/udp.c
index 15df749..becaef1 100644
--- a/src/VBox/Devices/Network/slirp/udp.c
+++ b/src/VBox/Devices/Network/slirp/udp.c
@@ -178,25 +178,37 @@ udp_input(PNATState pData, register struct mbuf *m, int iphlen)
         goto done_free_mbuf;
     }
 
-    LogFunc(("uh src: %RTnaipv4:%d, dst: %RTnaipv4:%d\n", ip->ip_src, RT_H2N_U16_C(uh->uh_sport), ip->ip_dst, RT_H2N_U16_C(uh->uh_dport)));
+    LogFunc(("uh src: %RTnaipv4:%d, dst: %RTnaipv4:%d\n",
+             ip->ip_src.s_addr, RT_N2H_U16(uh->uh_sport),
+             ip->ip_dst.s_addr, RT_N2H_U16(uh->uh_dport)));
+
+    /*
+     * handle DNS host resolver without creating a socket
+     */
     if (   pData->fUseHostResolver
         && uh->uh_dport == RT_H2N_U16_C(53)
         && CTL_CHECK(ip->ip_dst.s_addr, CTL_DNS))
     {
         struct sockaddr_in dst, src;
+
         src.sin_addr.s_addr = ip->ip_dst.s_addr;
         src.sin_port = uh->uh_dport;
         dst.sin_addr.s_addr = ip->ip_src.s_addr;
         dst.sin_port = uh->uh_sport;
 
+        m_adj(m, sizeof(struct udpiphdr));
+
+        m = hostresolver(pData, m, ip->ip_src.s_addr, uh->uh_sport);
+        if (m == NULL)
+            goto done_free_mbuf;
+
         slirpMbufTagService(pData, m, CTL_DNS);
-        /* udp_output2() expects a pointer to the body of UDP packet. */
-        m->m_data += sizeof(struct udpiphdr);
-        m->m_len -= sizeof(struct udpiphdr);
+
         udp_output2(pData, NULL, m, &src, &dst, IPTOS_LOWDELAY);
         LogFlowFuncLeave();
         return;
     }
+
     /*
      *  handle TFTP
      */
@@ -383,7 +395,8 @@ done_free_mbuf:
      * and create new m'buffers to send them to guest, so we'll free their incomming
      * buffers here.
      */
-    m_freem(pData, m);
+    if (m != NULL)
+        m_freem(pData, m);
     LogFlowFuncLeave();
     return;
 }
@@ -463,6 +476,22 @@ int udp_output(PNATState pData, struct socket *so, struct mbuf *m,
     LogFlowFunc(("ENTER: so = %R[natsock], m = %p, saddr = %RTnaipv4\n",
                  so, (long)m, addr->sin_addr.s_addr));
 
+    if (so->so_laddr.s_addr == INADDR_ANY)
+    {
+        if (pData->guest_addr_guess.s_addr != INADDR_ANY)
+        {
+            LogRel2(("NAT: port-forward: using %RTnaipv4 for %R[natsock]\n",
+                     pData->guest_addr_guess.s_addr, so));
+            so->so_laddr = pData->guest_addr_guess;
+        }
+        else
+        {
+            LogRel2(("NAT: port-forward: guest address unknown for %R[natsock]\n", so));
+            m_freem(pData, m);
+            return 0;
+        }
+    }
+
     saddr = *addr;
     if ((so->so_faddr.s_addr & RT_H2N_U32(pData->netmask)) == pData->special_addr.s_addr)
     {
@@ -641,7 +670,8 @@ udp_listen(PNATState pData, u_int32_t bind_addr, u_int port, u_int32_t laddr, u_
 
     if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0)
     {
-        LogRel(("NAT: bind to %RTnaipv4 has been failed\n", addr.sin_addr));
+        LogRel(("NAT: udp bind to %RTnaipv4:%d failed, error %d\n",
+                addr.sin_addr, RT_N2H_U16(port), errno));
         udp_detach(pData, so);
         LogFlowFunc(("LEAVE: NULL\n"));
         return NULL;
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm
index 73d91f0..812716d 100644
--- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm
@@ -983,7 +983,7 @@ section CONST progbits vstart=0xb0 align=1 ; size=0xcde class=DATA group=DGROUP
 
 section CONST2 progbits vstart=0xd8e align=1 ; size=0x3fa class=DATA group=DGROUP
 _bios_cvs_version_string:                    ; 0xf0d8e LB 0x12
-    db  'VirtualBox 5.0.18', 000h
+    db  'VirtualBox 5.0.20', 000h
 _bios_prefix_string:                         ; 0xf0da0 LB 0x8
     db  'BIOS: ', 000h, 000h
 _isotag:                                     ; 0xf0da8 LB 0x6
@@ -16860,4 +16860,4 @@ dummy_iret:                                  ; 0xfff53 LB 0x9d
     db  'XM'
 cpu_reset:                                   ; 0xffff0 LB 0x10
     jmp far 0f000h:0e05bh                     ; ea 5b e0 00 f0
-    db  030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 07eh
+    db  030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 085h
diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum
index 2b01604..fdc023f 100644
--- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum
+++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum
@@ -1 +1 @@
-7b4bf822a23c29293441c9b0b478ed70 *VBoxPcBios.rom
+187b5fd5d1a01ebcb7596749244e1b04 *VBoxPcBios.rom
diff --git a/src/VBox/Devices/PC/vbox-cpuhotplug.dsl b/src/VBox/Devices/PC/vbox-cpuhotplug.dsl
index 5032d7a..fef7b72 100644
--- a/src/VBox/Devices/PC/vbox-cpuhotplug.dsl
+++ b/src/VBox/Devices/PC/vbox-cpuhotplug.dsl
@@ -42,13 +42,13 @@ DefinitionBlock ("SSDT-cpuhotplug.aml", "SSDT", 1, "VBOX  ", "VBOXCPUT", 2)
     Scope (\_SB)
     {
 
-#define GENERATE_CPU_OBJECT(id, sck, sckuid, cpu, cpuuid)                  \
+#define GENERATE_CPU_OBJECT(id, sck, sckuid, cpu, cpuuid)<NL>              \
     Device (sck)                                                           \
     {                                                                      \
         Name (_HID, "ACPI0004")                                            \
         Name (_UID, sckuid)                                                \
                                                                            \
-                                                                           \
+        <NL>                                                               \
         Processor (cpu, /* Name */                                         \
                    id,  /* Id */                                           \
                    0x0, /* Processor IO ports range start */               \
@@ -58,8 +58,8 @@ DefinitionBlock ("SSDT-cpuhotplug.aml", "SSDT", 1, "VBOX  ", "VBOXCPUT", 2)
             Name (_HID, "ACPI0007")                                        \
             Name (_UID, cpuuid)                                            \
             Name (_PXM, 0x00)                                              \
-                                                                           \
-            Method(_MAT, 0)                                                \
+            <NL>                                                           \
+            Method(_MAT, 0, Serialized)                                    \
             {                                                              \
                 Name (APIC, Buffer (8) {0x00, 0x08, id, id})               \
                 IF (CPCK(id))                                              \
@@ -72,6 +72,7 @@ DefinitionBlock ("SSDT-cpuhotplug.aml", "SSDT", 1, "VBOX  ", "VBOXCPUT", 2)
                 }                                                          \
                 Return (APIC)                                              \
             }                                                              \
+            <NL>                                                           \
             Method(_STA) /* Used for device presence detection */          \
             {                                                              \
                 IF (CPCK(id))                                              \
@@ -83,6 +84,7 @@ DefinitionBlock ("SSDT-cpuhotplug.aml", "SSDT", 1, "VBOX  ", "VBOXCPUT", 2)
                     Return (0x0)                                           \
                 }                                                          \
             }                                                              \
+            <NL>                                                           \
             Method(_EJ0, 1)                                                \
             {                                                              \
                 CPLO(id) /* Unlock the CPU */                              \
diff --git a/src/VBox/Devices/PC/vbox.dsl b/src/VBox/Devices/PC/vbox.dsl
index 29d1347..ad047f4 100644
--- a/src/VBox/Devices/PC/vbox.dsl
+++ b/src/VBox/Devices/PC/vbox.dsl
@@ -78,7 +78,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "VBOX  ", "VBOXBIOS", 2)
     //
     // S2BF(Str) - Convert a string object into a buffer object.
     //
-    Method(S2BF, 1)
+    Method(S2BF, 1, Serialized)
     {
         //
         // Note: The caller must make sure that the argument is a string object.
@@ -236,7 +236,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "VBOX  ", "VBOXBIOS", 2)
         DBG("\n")
 
         // Does OS provide the _OSI method?
-        If (CondRefOf(_OSI, Local1))
+        If (CondRefOf(_OSI))
         {
             DBG("_OSI exists\n")
             // OS returns non-zero value in response to _OSI query if it
@@ -294,7 +294,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "VBOX  ", "VBOXBIOS", 2)
         }
 
         // Does OS provide the _REV method?
-        If (CondRefOf(_REV, Local2))
+        If (CondRefOf(_REV))
         {
             DBG("_REV: ")
             HEX4(_REV)
diff --git a/src/VBox/Devices/Storage/DevBusLogic.cpp b/src/VBox/Devices/Storage/DevBusLogic.cpp
index 06e2925..d8a1905 100644
--- a/src/VBox/Devices/Storage/DevBusLogic.cpp
+++ b/src/VBox/Devices/Storage/DevBusLogic.cpp
@@ -1724,6 +1724,12 @@ static int buslogicProcessCommand(PBUSLOGIC pBusLogic)
             pBusLogic->cbReplyParametersLeft = sizeof(ReplyInquirePCIHostAdapterInformation);
             break;
         }
+        case BUSLOGICCOMMAND_SET_SCSI_SELECTION_TIMEOUT:
+        {
+            /* no-op */
+            pBusLogic->cbReplyParametersLeft = 0;
+            break;
+        }
         case BUSLOGICCOMMAND_MODIFY_IO_ADDRESS:
         {
             /* Modify the ISA-compatible I/O port base. Note that this technically
@@ -1815,11 +1821,11 @@ static int buslogicProcessCommand(PBUSLOGIC pBusLogic)
         {
             /* The reply length is set by the guest and is found in the first byte of the command buffer. */
             pBusLogic->cbReplyParametersLeft = pBusLogic->aCommandBuffer[0];
-            memset(pBusLogic->aReplyBuffer, ' ', pBusLogic->cbReplyParametersLeft);
-            const char aModelName[] = "958";
-            int cCharsToTransfer =   (pBusLogic->cbReplyParametersLeft <= (sizeof(aModelName) - 1))
+            memset(pBusLogic->aReplyBuffer, 0, pBusLogic->cbReplyParametersLeft);
+            const char aModelName[] = "958D ";  /* Trailing \0 is fine, that's the filler anyway. */
+            int cCharsToTransfer =   pBusLogic->cbReplyParametersLeft <= sizeof(aModelName)
                                    ? pBusLogic->cbReplyParametersLeft
-                                   : sizeof(aModelName) - 1;
+                                   : sizeof(aModelName);
 
             for (int i = 0; i < cCharsToTransfer; i++)
                 pBusLogic->aReplyBuffer[i] = aModelName[i];
@@ -2312,6 +2318,9 @@ static int buslogicRegisterWrite(PBUSLOGIC pBusLogic, unsigned iRegister, uint8_
                     case BUSLOGICCOMMAND_WRITE_BUSMASTER_CHIP_FIFO:
                         pBusLogic->cbCommandParametersLeft = 3;
                         break;
+                    case BUSLOGICCOMMAND_SET_SCSI_SELECTION_TIMEOUT:
+                        pBusLogic->cbCommandParametersLeft = 4;
+                        break;
                     case BUSLOGICCOMMAND_INITIALIZE_MAILBOX:
                         pBusLogic->cbCommandParametersLeft = sizeof(RequestInitMbx);
                         break;
diff --git a/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp b/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
index 573fab2..662520e 100644
--- a/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
+++ b/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
@@ -3889,7 +3889,7 @@ static DECLCALLBACK(int) lsilogicR3IsaIOPortWriteStr(PPDMDEVINS pDevIns, void *p
     else if (RT_FAILURE(rc))
         AssertMsgFailed(("Writing BIOS register failed %Rrc\n", rc));
 
-    return rc;
+    return VINF_SUCCESS;
 }
 
 /**
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp
index fc5a037..e76de26 100644
--- a/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp
+++ b/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp
@@ -178,6 +178,18 @@ static HRESULT listNetworkInterfaces(const ComPtr<IVirtualBox> pVirtualBox,
  */
 static HRESULT listHostInfo(const ComPtr<IVirtualBox> pVirtualBox)
 {
+    static struct
+    {
+        ProcessorFeature_T feature;
+        const char *pszName;
+    } features[]
+    =
+    {
+        { ProcessorFeature_HWVirtEx,     "HW virtualization" },
+        { ProcessorFeature_PAE,          "PAE" },
+        { ProcessorFeature_LongMode,     "long mode" },
+        { ProcessorFeature_NestedPaging, "nested paging" },
+    };
     HRESULT rc;
     ComPtr<IHost> Host;
     CHECK_ERROR(pVirtualBox, COMGETTER(Host)(Host.asOutParam()));
@@ -202,15 +214,21 @@ static HRESULT listHostInfo(const ComPtr<IVirtualBox> pVirtualBox)
     ULONG processorCoreCount = 0;
     CHECK_ERROR(Host, COMGETTER(ProcessorCoreCount)(&processorCoreCount));
     RTPrintf("Processor core count: %lu\n", processorCoreCount);
-    ULONG processorSpeed = 0;
-    Bstr processorDescription;
+    for (unsigned i = 0; i < RT_ELEMENTS(features); i++)
+    {
+        BOOL supported;
+        CHECK_ERROR(Host, GetProcessorFeature(features[i].feature, &supported));
+        RTPrintf("Processor supports %s: %s\n", features[i].pszName, supported ? "yes" : "no");
+    }
     for (ULONG i = 0; i < processorCount; i++)
     {
+        ULONG processorSpeed = 0;
         CHECK_ERROR(Host, GetProcessorSpeed(i, &processorSpeed));
         if (processorSpeed)
             RTPrintf("Processor#%u speed: %lu MHz\n", i, processorSpeed);
         else
             RTPrintf("Processor#%u speed: unknown\n", i);
+        Bstr processorDescription;
         CHECK_ERROR(Host, GetProcessorDescription(i, processorDescription.asOutParam()));
         RTPrintf("Processor#%u description: %ls\n", i, processorDescription.raw());
     }
diff --git a/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsLanguage.cpp b/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsLanguage.cpp
index 64c683d..ea8824c 100644
--- a/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsLanguage.cpp
+++ b/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsLanguage.cpp
@@ -139,6 +139,11 @@ public:
          * from being shrinked too much when the list wants to be wider */
         setText(2, "                ");
         setText(3, "                ");
+
+        /* Default language item appears in italic: */
+        QFont fnt = font(0);
+        fnt.setItalic(true);
+        setFont(0, fnt);
     }
 
     bool isBuiltIn() const { return m_fBuiltIn; }
diff --git a/src/VBox/HostDrivers/Support/Makefile.kmk b/src/VBox/HostDrivers/Support/Makefile.kmk
index 8957098..7f51421 100644
--- a/src/VBox/HostDrivers/Support/Makefile.kmk
+++ b/src/VBox/HostDrivers/Support/Makefile.kmk
@@ -648,6 +648,8 @@ if1of ($(KBUILD_TARGET), darwin freebsd linux solaris win)
  	linux/SUPDrv-linux.mod.c
  endif
 
+ linux/SUPDrv-linux.c_DEPS = $(VBOX_SVN_REV_HEADER)
+
 endif
 
 
diff --git a/src/VBox/HostDrivers/Support/SUPLibInternal.h b/src/VBox/HostDrivers/Support/SUPLibInternal.h
index 3848d0f..85f7741 100644
--- a/src/VBox/HostDrivers/Support/SUPLibInternal.h
+++ b/src/VBox/HostDrivers/Support/SUPLibInternal.h
@@ -460,7 +460,7 @@ DECLHIDDEN(void)    supR3HardenedWinGetVeryEarlyImports(uintptr_t uNtDllAddr,
                                                         PFNNTSETEVENT *ppfnNtSetEvent);
 # endif
 DECLHIDDEN(void)    supR3HardenedWinInitImportsEarly(uintptr_t uNtDllAddr);
-DECLHIDDEN(void)    supR3HardenedWinInitSyscalls(bool fReportErrors);
+DECLHIDDEN(void)    supR3HardenedWinInitSyscalls(bool fReportErrors, PRTERRINFO pErrInfo);
 DECLHIDDEN(PFNRT)   supR3HardenedWinGetRealDllSymbol(const char *pszDll, const char *pszProcedure);
 DECLHIDDEN(void)    supR3HardenedWinEnableThreadCreation(void);
 DECLHIDDEN(void)    supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(const char *pszProgName);
diff --git a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
index f171418..c86d2a5 100644
--- a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
+++ b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
@@ -1,4 +1,4 @@
-/* $Rev: 103607 $ */
+/* $Rev: 106728 $ */
 /** @file
  * VBoxDrv - The VirtualBox Support Driver - Linux specifics.
  */
@@ -33,6 +33,7 @@
 #include "the-linux-kernel.h"
 #include "version-generated.h"
 #include "product-generated.h"
+#include "revision-generated.h"
 
 #include <iprt/assert.h>
 #include <iprt/spinlock.h>
@@ -1165,7 +1166,7 @@ MODULE_AUTHOR(VBOX_VENDOR);
 MODULE_DESCRIPTION(VBOX_PRODUCT " Support Driver");
 MODULE_LICENSE("GPL");
 #ifdef MODULE_VERSION
-MODULE_VERSION(VBOX_VERSION_STRING " (" RT_XSTR(SUPDRV_IOC_VERSION) ")");
+MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV) " (" RT_XSTR(SUPDRV_IOC_VERSION) ")");
 #endif
 
 module_param(force_async_tsc, int, 0444);
diff --git a/src/VBox/HostDrivers/Support/linux/files_vboxdrv b/src/VBox/HostDrivers/Support/linux/files_vboxdrv
index 204b55a..61c6d53 100755
--- a/src/VBox/HostDrivers/Support/linux/files_vboxdrv
+++ b/src/VBox/HostDrivers/Support/linux/files_vboxdrv
@@ -199,6 +199,7 @@ FILES_VBOXDRV_NOBIN=" \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/memobj-r0drv.cpp=>r0drv/memobj-r0drv.c \
     ${PATH_ROOT}/src/VBox/Runtime/VBox/log-vbox.cpp=>VBox/log-vbox.c \
     ${PATH_OUT}/version-generated.h=>version-generated.h \
+    ${PATH_OUT}/revision-generated.h=>revision-generated.h \
     ${PATH_OUT}/product-generated.h=>product-generated.h \
 "
 
diff --git a/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h b/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h
index d46b3bf..14c9064 100644
--- a/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h
+++ b/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h
@@ -168,7 +168,7 @@ typedef struct SUPHNTLDRCACHEENTRY
 } SUPHNTLDRCACHEENTRY;
 /** Pointer to a loader cache entry. */
 typedef SUPHNTLDRCACHEENTRY *PSUPHNTLDRCACHEENTRY;
-DECLHIDDEN(int)  supHardNtLdrCacheOpen(const char *pszName, PSUPHNTLDRCACHEENTRY *ppEntry);
+DECLHIDDEN(int)  supHardNtLdrCacheOpen(const char *pszName, PSUPHNTLDRCACHEENTRY *ppEntry, PRTERRINFO pErrInfo);
 DECLHIDDEN(int)  supHardNtLdrCacheEntryVerify(PSUPHNTLDRCACHEENTRY pEntry, PCRTUTF16 pwszName, PRTERRINFO pErrInfo);
 DECLHIDDEN(int)  supHardNtLdrCacheEntryGetBits(PSUPHNTLDRCACHEENTRY pEntry, uint8_t **ppbBits, RTLDRADDR uBaseAddress,
                                                PFNRTLDRIMPORT pfnGetImport, void *pvUser, PRTERRINFO pErrInfo);
diff --git a/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp b/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
index 5e60eec..a006571 100644
--- a/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
+++ b/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
@@ -277,6 +277,37 @@ static int supHardNtVpSetInfo1(PRTERRINFO pErrInfo, int rc, const char *pszMsg,
 
 
 /**
+ * Adds error information.
+ *
+ * @returns @a rc.
+ * @param   pErrInfo            Pointer to the extended error info structure
+ *                              which may contain some details already.  Can be
+ *                              NULL.
+ * @param   rc                  The status to return.
+ * @param   pszMsg              The format string for the message.
+ * @param   ...                 The arguments for the format string.
+ */
+static int supHardNtVpAddInfo1(PRTERRINFO pErrInfo, int rc, const char *pszMsg, ...)
+{
+    va_list va;
+#ifdef IN_RING3
+    va_start(va, pszMsg);
+    if (pErrInfo && pErrInfo->pszMsg)
+        supR3HardenedError(rc, false /*fFatal*/, "%N - %s\n", pszMsg, &va, pErrInfo->pszMsg);
+    else
+        supR3HardenedError(rc, false /*fFatal*/, "%N\n", pszMsg, &va);
+    va_end(va);
+#endif
+
+    va_start(va, pszMsg);
+    RTErrInfoAddV(pErrInfo, rc, pszMsg, va);
+    va_end(va);
+
+    return rc;
+}
+
+
+/**
  * Fills in error information.
  *
  * @returns @a rc.
@@ -2028,7 +2059,7 @@ static int supHardNtLdrCacheNewEntry(PSUPHNTLDRCACHEENTRY pEntry, const char *ps
         enmArch = RTLDRARCH_WHATEVER;
     rc = RTLdrOpenWithReader(&pNtViRdr->Core, RTLDR_O_FOR_VALIDATION, enmArch, &hLdrMod, pErrInfo);
     if (RT_FAILURE(rc))
-        return supHardNtVpSetInfo1(pErrInfo, rc, "RTLdrOpenWithReader failed: %Rrc (Image='%ls').",
+        return supHardNtVpAddInfo1(pErrInfo, rc, "RTLdrOpenWithReader failed: %Rrc (Image='%ls').",
                                    rc, pUniStrPath->Buffer);
 
     /*
@@ -2065,8 +2096,10 @@ static int supHardNtLdrCacheNewEntry(PSUPHNTLDRCACHEENTRY pEntry, const char *ps
  * @param   pszName             The DLL name.  Must be one from the
  *                              g_apszSupNtVpAllowedDlls array.
  * @param   ppEntry             Where to return the entry we've opened/found.
+ * @param   pErrInfo            Optional buffer where to return additional error
+ *                              information.
  */
-DECLHIDDEN(int) supHardNtLdrCacheOpen(const char *pszName, PSUPHNTLDRCACHEENTRY *ppEntry)
+DECLHIDDEN(int) supHardNtLdrCacheOpen(const char *pszName, PSUPHNTLDRCACHEENTRY *ppEntry, PRTERRINFO pErrInfo)
 {
     /*
      * Locate the dll.
@@ -2104,7 +2137,7 @@ DECLHIDDEN(int) supHardNtLdrCacheOpen(const char *pszName, PSUPHNTLDRCACHEENTRY
     UniStr.MaximumLength = UniStr.Length + sizeof(WCHAR);
 
     int rc = supHardNtLdrCacheNewEntry(&g_aSupNtVpLdrCacheEntries[g_cSupNtVpLdrCacheEntries], pszName, &UniStr,
-                                       true /*fDll*/, false /*f32bitResourceDll*/, NULL /*pErrInfo*/);
+                                       true /*fDll*/, false /*f32bitResourceDll*/, pErrInfo);
     if (RT_SUCCESS(rc))
     {
         *ppEntry = &g_aSupNtVpLdrCacheEntries[g_cSupNtVpLdrCacheEntries];
diff --git a/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp b/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
index ab5a237..5afcb0b 100644
--- a/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
+++ b/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
@@ -367,8 +367,10 @@ static uint32_t             g_fSupAdversaries = 0;
 #define SUPHARDNT_ADVERSARY_ZONE_ALARM              RT_BIT_32(12)
 /** Digital guardian.  */
 #define SUPHARDNT_ADVERSARY_DIGITAL_GUARDIAN        RT_BIT_32(13)
-/** Cylance protect or something (from googling, no available sample copy ).  */
-#define SUPHARDNT_CYLANCE                           RT_BIT_32(14)
+/** Cylance protect or something (from googling, no available sample copy). */
+#define SUPHARDNT_ADVERSARY_CYLANCE                 RT_BIT_32(14)
+/** BeyondTrust / PowerBroker / something (googling, no available sample copy). */
+#define SUPHARDNT_ADVERSARY_BEYONDTRUST             RT_BIT_32(15)
 /** Unknown adversary detected while waiting on child. */
 #define SUPHARDNT_ADVERSARY_UNKNOWN                 RT_BIT_32(31)
 /** @} */
@@ -3563,7 +3565,7 @@ static void supR3HardNtChildSetUpChildInit(PSUPR3HARDNTCHILD pThis)
      * code bits for it.
      */
     PSUPHNTLDRCACHEENTRY pLdrEntry;
-    int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry);
+    int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry, NULL /*pErrInfo*/);
     if (RT_FAILURE(rc))
         supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rc,
                                   "supHardNtLdrCacheOpen failed on NTDLL: %Rrc\n", rc);
@@ -5221,7 +5223,9 @@ static uint32_t supR3HardenedWinFindAdversaries(void)
 
         { SUPHARDNT_ADVERSARY_DIGITAL_GUARDIAN,     "dgmaster" }, /* Not verified. */
 
-        { SUPHARDNT_CYLANCE,                        "cyprotectdrv" }, /* Not verified. */
+        { SUPHARDNT_ADVERSARY_CYLANCE,              "cyprotectdrv" }, /* Not verified. */
+
+        { SUPHARDNT_ADVERSARY_BEYONDTRUST,          "privman" }, /* Not verified. */
     };
 
     static const struct
@@ -5337,8 +5341,12 @@ static uint32_t supR3HardenedWinFindAdversaries(void)
 
         { SUPHARDNT_ADVERSARY_DIGITAL_GUARDIAN, L"\\SystemRoot\\System32\\drivers\\dgmaster.sys" },
 
-        { SUPHARDNT_CYLANCE, L"\\SystemRoot\\System32\\drivers\\cyprotectdrv32.sys" },
-        { SUPHARDNT_CYLANCE, L"\\SystemRoot\\System32\\drivers\\cyprotectdrv64.sys" },
+        { SUPHARDNT_ADVERSARY_CYLANCE, L"\\SystemRoot\\System32\\drivers\\cyprotectdrv32.sys" },
+        { SUPHARDNT_ADVERSARY_CYLANCE, L"\\SystemRoot\\System32\\drivers\\cyprotectdrv64.sys" },
+
+        { SUPHARDNT_ADVERSARY_BEYONDTRUST, L"\\SystemRoot\\System32\\drivers\\privman.sys" },
+        { SUPHARDNT_ADVERSARY_BEYONDTRUST, L"\\SystemRoot\\System32\\privman64.dll" },
+        { SUPHARDNT_ADVERSARY_BEYONDTRUST, L"\\SystemRoot\\System32\\privman32.dll" },
     };
 
     uint32_t fFound = 0;
@@ -5733,7 +5741,8 @@ DECLASM(uintptr_t) supR3HardenedEarlyProcessInit(void)
     /*
      * Set up the direct system calls so we can more easily hook NtCreateSection.
      */
-    supR3HardenedWinInitSyscalls(true /*fReportErrors*/);
+    RTERRINFOSTATIC ErrInfo;
+    supR3HardenedWinInitSyscalls(true /*fReportErrors*/, RTErrInfoInitStatic(&ErrInfo));
 
     /*
      * Determine the executable path and name.  Will NOT determine the windows style
@@ -5792,14 +5801,16 @@ DECLASM(uintptr_t) supR3HardenedEarlyProcessInit(void)
      */
     SUP_DPRINTF(("supR3HardenedVmProcessInit: Restoring LdrInitializeThunk...\n"));
     PSUPHNTLDRCACHEENTRY pLdrEntry;
-    int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry);
+    int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry, RTErrInfoInitStatic(&ErrInfo));
     if (RT_FAILURE(rc))
-        supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheOpen failed on NTDLL: %Rrc\n", rc);
+        supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheOpen failed on NTDLL: %Rrc %s\n",
+                           rc, ErrInfo.Core.pszMsg);
 
     uint8_t *pbBits;
-    rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, uNtDllAddr, NULL, NULL, NULL /*pErrInfo*/);
+    rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, uNtDllAddr, NULL, NULL, RTErrInfoInitStatic(&ErrInfo));
     if (RT_FAILURE(rc))
-        supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheEntryGetBits failed on NTDLL: %Rrc\n", rc);
+        supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheEntryGetBits failed on NTDLL: %Rrc %s\n",
+                           rc, ErrInfo.Core.pszMsg);
 
     RTLDRADDR uValue;
     rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pbBits, uNtDllAddr, UINT32_MAX, "LdrInitializeThunk", &uValue);
diff --git a/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainImports-win.cpp b/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainImports-win.cpp
index 205d6b3..bcfcbfe 100644
--- a/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainImports-win.cpp
+++ b/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainImports-win.cpp
@@ -587,7 +587,7 @@ static void supR3HardenedDirectSyscall(PSUPHNTIMPDLL pDll, PCSUPHNTIMPFUNC pImpo
     volatile uint8_t abCopy[16];
     memcpy((void *)&abCopy[0], pbFunction, sizeof(abCopy));
     SUPHNTIMP_ERROR(fReportErrors, 17, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,
-                    "%ls: supHardNtLdrCacheOpen failed: '%s': %.16Rhxs",
+                    "%ls: failed to parse syscall: '%s': %.16Rhxs",
                     pDll->pwszName, pImport->pszName, &abCopy[0]);
 }
 
@@ -600,19 +600,22 @@ static void supR3HardenedDirectSyscall(PSUPHNTIMPDLL pDll, PCSUPHNTIMPFUNC pImpo
  *
  * @param   fReportErrors       Whether we've got the machinery for reporting
  *                              errors going already.
+ * @param   pErrInfo            Buffer for gathering additional error info. This
+ *                              is mainly to avoid consuming lots of stacks with
+ *                              RTERRINFOSTATIC structures.
  */
-DECLHIDDEN(void) supR3HardenedWinInitSyscalls(bool fReportErrors)
+DECLHIDDEN(void) supR3HardenedWinInitSyscalls(bool fReportErrors, PRTERRINFO pErrInfo)
 {
     for (uint32_t iDll = 0; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++)
         if (g_aSupNtImpDlls[iDll].paSyscalls)
         {
             PSUPHNTLDRCACHEENTRY pLdrEntry;
-            int rc = supHardNtLdrCacheOpen(g_aSupNtImpDlls[iDll].pszName, &pLdrEntry);
+            int rc = supHardNtLdrCacheOpen(g_aSupNtImpDlls[iDll].pszName, &pLdrEntry, pErrInfo);
             if (RT_SUCCESS(rc))
             {
                 uint8_t *pbBits;
-                rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, (uintptr_t)g_aSupNtImpDlls[iDll].pbImageBase, NULL, NULL,
-                                                   NULL /*pErrInfo*/);
+                rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, (uintptr_t)g_aSupNtImpDlls[iDll].pbImageBase,
+                                                   NULL, NULL, pErrInfo);
                 if (RT_SUCCESS(rc))
                 {
                     for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++)
@@ -621,11 +624,13 @@ DECLHIDDEN(void) supR3HardenedWinInitSyscalls(bool fReportErrors)
                 }
                 else
                     SUPHNTIMP_ERROR(fReportErrors, 20, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,
-                                    "%ls: supHardNtLdrCacheEntryGetBits failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc);
+                                    "%ls: supHardNtLdrCacheEntryGetBits failed: %Rrc %s",
+                                    g_aSupNtImpDlls[iDll].pwszName, rc, pErrInfo ? pErrInfo->pszMsg : "");
             }
             else
                 SUPHNTIMP_ERROR(fReportErrors, 21, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,
-                                "%ls: supHardNtLdrCacheOpen failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc);
+                                "%ls: supHardNtLdrCacheOpen failed: %Rrc %s",
+                                g_aSupNtImpDlls[iDll].pwszName, rc, pErrInfo ? pErrInfo->pszMsg : "");
         }
 }
 
@@ -662,12 +667,12 @@ DECLHIDDEN(void) supR3HardenedWinGetVeryEarlyImports(uintptr_t uNtDllAddr,
     };
 
     for (uint32_t i = 0; i < RT_ELEMENTS(aImports); i++)
-        {
-            const char *pszForwarder = supR3HardenedResolveImport(&g_aSupNtImpDlls[0], &aImports[i], false);
-            if (pszForwarder)
-                SUPHNTIMP_ERROR(false, 31, "supR3HardenedWinGetVeryEarlyImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND,
-                                "ntdll: Failed to resolve forwarder '%s'.", pszForwarder);
-        }
+    {
+        const char *pszForwarder = supR3HardenedResolveImport(&g_aSupNtImpDlls[0], &aImports[i], false);
+        if (pszForwarder)
+            SUPHNTIMP_ERROR(false, 31, "supR3HardenedWinGetVeryEarlyImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND,
+                            "ntdll: Failed to resolve forwarder '%s'.", pszForwarder);
+    }
 
     /*
      * Restore the NtDll entry.
@@ -722,6 +727,8 @@ DECLHIDDEN(void) supR3HardenedWinInitImportsEarly(uintptr_t uNtDllAddr)
  */
 DECLHIDDEN(void) supR3HardenedWinInitImports(void)
 {
+    RTERRINFOSTATIC ErrInfo;
+
     /*
      * Find the DLLs we will be needing first (forwarders).
      */
@@ -759,7 +766,7 @@ DECLHIDDEN(void) supR3HardenedWinInitImports(void)
     /*
      * Do system calls directly.
      */
-    supR3HardenedWinInitSyscalls(false);
+    supR3HardenedWinInitSyscalls(false, RTErrInfoInitStatic(&ErrInfo));
 
     /*
      * Use the on disk image to avoid export table patching.  Currently
@@ -769,12 +776,12 @@ DECLHIDDEN(void) supR3HardenedWinInitImports(void)
         if (g_aSupNtImpDlls[iDll].cPatchedExports > 0)
         {
             PSUPHNTLDRCACHEENTRY pLdrEntry;
-            int rc = supHardNtLdrCacheOpen(g_aSupNtImpDlls[iDll].pszName, &pLdrEntry);
+            int rc = supHardNtLdrCacheOpen(g_aSupNtImpDlls[iDll].pszName, &pLdrEntry, RTErrInfoInitStatic(&ErrInfo));
             if (RT_SUCCESS(rc))
             {
                 uint8_t *pbBits;
                 rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, (uintptr_t)g_aSupNtImpDlls[iDll].pbImageBase, NULL, NULL,
-                                                   NULL /*pErrInfo*/);
+                                                   RTErrInfoInitStatic(&ErrInfo));
                 if (RT_SUCCESS(rc))
                     for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++)
                     {
@@ -806,6 +813,8 @@ DECLHIDDEN(void) supR3HardenedWinInitImports(void)
  */
 DECLHIDDEN(PFNRT) supR3HardenedWinGetRealDllSymbol(const char *pszDll, const char *pszProcedure)
 {
+    RTERRINFOSTATIC ErrInfo;
+
     /*
      * Look the DLL up in the import DLL table.
      */
@@ -814,12 +823,12 @@ DECLHIDDEN(PFNRT) supR3HardenedWinGetRealDllSymbol(const char *pszDll, const cha
         {
 
             PSUPHNTLDRCACHEENTRY pLdrEntry;
-            int rc = supHardNtLdrCacheOpen(g_aSupNtImpDlls[iDll].pszName, &pLdrEntry);
+            int rc = supHardNtLdrCacheOpen(g_aSupNtImpDlls[iDll].pszName, &pLdrEntry, RTErrInfoInitStatic(&ErrInfo));
             if (RT_SUCCESS(rc))
             {
                 uint8_t *pbBits;
                 rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, (uintptr_t)g_aSupNtImpDlls[iDll].pbImageBase, NULL, NULL,
-                                                   NULL /*pErrInfo*/);
+                                                   RTErrInfoInitStatic(&ErrInfo));
                 if (RT_SUCCESS(rc))
                 {
                     RTLDRADDR uValue;
@@ -830,12 +839,12 @@ DECLHIDDEN(PFNRT) supR3HardenedWinGetRealDllSymbol(const char *pszDll, const cha
                     SUP_DPRINTF(("supR3HardenedWinGetRealDllSymbol: Error getting %s in %s -> %Rrc\n", pszProcedure, pszDll, rc));
                 }
                 else
-                    SUP_DPRINTF(("supR3HardenedWinGetRealDllSymbol: supHardNtLdrCacheEntryAllocBits failed on %s: %Rrc\n",
-                                 pszDll, rc));
+                    SUP_DPRINTF(("supR3HardenedWinGetRealDllSymbol: supHardNtLdrCacheEntryAllocBits failed on %s: %Rrc %s\n",
+                                 pszDll, rc, ErrInfo.Core.pszMsg));
             }
             else
-                SUP_DPRINTF(("supR3HardenedWinGetRealDllSymbol: supHardNtLdrCacheOpen failed on %s: %Rrc\n",
-                             pszDll, rc));
+                SUP_DPRINTF(("supR3HardenedWinGetRealDllSymbol: supHardNtLdrCacheOpen failed on %s: %Rrc %s\n",
+                             pszDll, rc, ErrInfo.Core.pszMsg));
 
             /* Complications, just call GetProcAddress. */
             if (g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED)
diff --git a/src/VBox/HostDrivers/VBoxNetAdp/Makefile.kmk b/src/VBox/HostDrivers/VBoxNetAdp/Makefile.kmk
index dede0bf..4051529 100644
--- a/src/VBox/HostDrivers/VBoxNetAdp/Makefile.kmk
+++ b/src/VBox/HostDrivers/VBoxNetAdp/Makefile.kmk
@@ -56,6 +56,7 @@ if1of ($(KBUILD_TARGET), solaris darwin linux freebsd)
   #	VBoxNetAdp.c
   VBoxNetAdp_LIBS            += \
   	$(PATH_STAGE_LIB)/SUPR0IdcClient$(VBOX_SUFF_LIB)
+  linux/VBoxNetAdp-linux.c_DEPS = $(VBOX_SVN_REV_HEADER)
  endif
 endif
 
diff --git a/src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c b/src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c
index 92e1724..67761c4 100644
--- a/src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c
+++ b/src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c
@@ -21,6 +21,7 @@
 *********************************************************************************************************************************/
 #include "the-linux-kernel.h"
 #include "version-generated.h"
+#include "revision-generated.h"
 #include "product-generated.h"
 #include <linux/ethtool.h>
 #include <linux/netdevice.h>
@@ -87,7 +88,7 @@ MODULE_AUTHOR(VBOX_VENDOR);
 MODULE_DESCRIPTION(VBOX_PRODUCT " Network Adapter Driver");
 MODULE_LICENSE("GPL");
 #ifdef MODULE_VERSION
-MODULE_VERSION(VBOX_VERSION_STRING " (" RT_XSTR(INTNETTRUNKIFPORT_VERSION) ")");
+MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV) " (" RT_XSTR(INTNETTRUNKIFPORT_VERSION) ")");
 #endif
 
 /**
diff --git a/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp b/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp
index da6dd35..8bf41a3 100755
--- a/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp
+++ b/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Revision: 103594 $
+# $Revision: 106728 $
 ## @files
 # Shared file between Makefile.kmk and export_modules
 #
@@ -79,6 +79,7 @@ VBOX_VBOXNETADP_SOURCES=" \
     ${PATH_ROOT}/src/VBox/Runtime/include/internal/iprt.h=>include/internal/iprt.h \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h=>r0drv/linux/the-linux-kernel.h \
     ${PATH_OUT}/version-generated.h=>version-generated.h \
+    ${PATH_OUT}/revision-generated.h=>revision-generated.h \
     ${PATH_OUT}/product-generated.h=>product-generated.h \
 "
 
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/Makefile.kmk b/src/VBox/HostDrivers/VBoxNetFlt/Makefile.kmk
index d621dd6..4661a9b 100644
--- a/src/VBox/HostDrivers/VBoxNetFlt/Makefile.kmk
+++ b/src/VBox/HostDrivers/VBoxNetFlt/Makefile.kmk
@@ -480,6 +480,7 @@ else if1of ($(KBUILD_TARGET), linux solaris freebsd) ## @todo merge this with th
   vboxnetflt_SOURCES.solaris = solaris/VBoxNetFlt-solaris.c
   vboxnetflt_SOURCES.freebsd = freebsd/VBoxNetFlt-freebsd.c
   vboxnetflt_SOURCES = VBoxNetFlt.c
+  linux/VBoxNetFlt-linux.c_DEPS = $(VBOX_SVN_REV_HEADER)
   solaris/VBoxNetFlt-solaris.c_DEFS = VBOX_SVN_REV=$(VBOX_SVN_REV)
 
   ifdef VBOX_WITH_NETFLT_CROSSBOW
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c b/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c
index 997765b..cdf8f51 100644
--- a/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c
+++ b/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c
@@ -23,6 +23,7 @@
 #define VBOXNETFLT_LINUX_NO_XMIT_QUEUE
 #include "the-linux-kernel.h"
 #include "version-generated.h"
+#include "revision-generated.h"
 #include "product-generated.h"
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
 #include <linux/nsproxy.h>
@@ -35,6 +36,9 @@
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/if_vlan.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+#include <uapi/linux/pkt_cls.h>
+#endif
 #include <net/ipv6.h>
 #include <net/if_inet6.h>
 #include <net/addrconf.h>
@@ -206,7 +210,7 @@ MODULE_AUTHOR(VBOX_VENDOR);
 MODULE_DESCRIPTION(VBOX_PRODUCT " Network Filter Driver");
 MODULE_LICENSE("GPL");
 #ifdef MODULE_VERSION
-MODULE_VERSION(VBOX_VERSION_STRING " (" RT_XSTR(INTNETTRUNKIFPORT_VERSION) ")");
+MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV) " (" RT_XSTR(INTNETTRUNKIFPORT_VERSION) ")");
 #endif
 
 
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt b/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt
index 94adfe4..1bfb739 100755
--- a/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt
+++ b/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt
@@ -80,6 +80,7 @@ VBOX_VBOXNETFLT_SOURCES=" \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/umoddi3.c=>math/gcc/umoddi3.c \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h=>r0drv/linux/the-linux-kernel.h \
     ${PATH_OUT}/version-generated.h=>version-generated.h \
+    ${PATH_OUT}/revision-generated.h=>revision-generated.h \
     ${PATH_OUT}/product-generated.h=>product-generated.h \
 "
 
diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp b/src/VBox/HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp
index 44286ae..96d0d77 100644
--- a/src/VBox/HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp
+++ b/src/VBox/HostDrivers/VBoxNetFlt/win/cfg/VBoxNetCfg.cpp
@@ -60,12 +60,32 @@ static VOID DoLogging(LPCSTR szString, ...);
 
 #define VBOX_NETCFG_LOCK_TIME_OUT     5000  /** @todo r=bird: What does this do? */
 
+#define VBOXNETCFGWIN_NETADP_ID L"sun_VBoxNetAdp"
+
+/*
+* Wrappers for HelpAPI functions
+*/
+typedef void FNINITIALIZEIPINTERFACEENTRY( _Inout_ PMIB_IPINTERFACE_ROW row);
+typedef FNINITIALIZEIPINTERFACEENTRY *PFNINITIALIZEIPINTERFACEENTRY;
+
+typedef NETIOAPI_API FNGETIPINTERFACEENTRY( _Inout_ PMIB_IPINTERFACE_ROW row);
+typedef FNGETIPINTERFACEENTRY *PFNGETIPINTERFACEENTRY;
+
+typedef NETIOAPI_API FNSETIPINTERFACEENTRY( _Inout_ PMIB_IPINTERFACE_ROW row);
+typedef FNSETIPINTERFACEENTRY *PFNSETIPINTERFACEENTRY;
+
+static  PFNINITIALIZEIPINTERFACEENTRY   g_pfnInitializeIpInterfaceEntry = NULL;
+static  PFNGETIPINTERFACEENTRY          g_pfnGetIpInterfaceEntry        = NULL;
+static  PFNSETIPINTERFACEENTRY          g_pfnSetIpInterfaceEntry        = NULL;
+
+
 /*
 * Forward declaration for using vboxNetCfgWinSetupMetric()
 */
 HRESULT vboxNetCfgWinSetupMetric(IN HKEY hKey);
 HRESULT vboxNetCfgWinGetInterfaceLUID(IN HKEY hKey, OUT NET_LUID* pLUID);
 
+
 /*
  * For some weird reason we do not want to use IPRT here, hence the following
  * function provides a replacement for BstrFmt.
@@ -297,7 +317,6 @@ VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinInstallComponent(IN INetCfg *pNetCfg, I
         if (pTempComponent != NULL)
         {
             HKEY hkey;
-            NET_LUID luid;
             HRESULT res;
 
             /*
@@ -305,17 +324,21 @@ VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinInstallComponent(IN INetCfg *pNetCfg, I
             *   See @bugref{6379} for details.
             */
             res = pTempComponent->OpenParamKey(&hkey);
-            if(SUCCEEDED(res) && hkey != NULL)
-                res = vboxNetCfgWinSetupMetric(hkey);
-            if (FAILED(res))
+
+            /* Set default metric value for host-only interface only */
+            if (SUCCEEDED(res) && hkey != NULL && wcsnicmp(pszwComponentId, VBOXNETCFGWIN_NETADP_ID, 256) == 0)
             {
-                /*  
-                 *   The setting of Metric is not very important functionality,
-                 *   So we will not break installation process due to this error.
-                 */
-                NonStandardLogFlow(("VBoxNetCfgWinInstallComponent Warning! "
-                                    "vboxNetCfgWinSetupMetric failed, default metric "
-                                    "for new interface will not be set, hr (0x%x)\n", res));
+                res = vboxNetCfgWinSetupMetric(hkey);
+                if (FAILED(res))
+                {
+                    /*
+                     *   The setting of Metric is not very important functionality,
+                     *   So we will not break installation process due to this error.
+                     */
+                    NonStandardLogFlow(("VBoxNetCfgWinInstallComponent Warning! "
+                        "vboxNetCfgWinSetupMetric failed, default metric "
+                        "for new interface will not be set, hr (0x%x)\n", res));
+                }
             }
             if (ppComponent != NULL)
                 *ppComponent = pTempComponent;
@@ -2146,7 +2169,6 @@ VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetFltInstall(IN INetCfg *pNc,
     return hr;
 }
 
-#define VBOXNETCFGWIN_NETADP_ID L"sun_VBoxNetAdp"
 static HRESULT vboxNetCfgWinNetAdpUninstall(IN INetCfg *pNc, LPCWSTR pwszId, DWORD InfRmFlags)
 {
     HRESULT hr = S_OK;
@@ -3356,22 +3378,62 @@ VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface(IN LPCWS
 }
 
 
+HRESULT vboxLoadIpHelpFunctions(HINSTANCE& pIpHlpInstance)
+{
+    Assert(pIpHlpInstance != NULL);
+
+    pIpHlpInstance = loadSystemDll("Iphlpapi.dll");
+    if (pIpHlpInstance == NULL)
+        return E_FAIL;
+    
+    g_pfnInitializeIpInterfaceEntry = 
+        (PFNINITIALIZEIPINTERFACEENTRY)GetProcAddress(pIpHlpInstance, "InitializeIpInterfaceEntry");
+    Assert(g_pfnInitializeIpInterfaceEntry);
+
+    if (g_pfnInitializeIpInterfaceEntry)
+    {
+        g_pfnGetIpInterfaceEntry = 
+            (PFNGETIPINTERFACEENTRY)GetProcAddress(pIpHlpInstance, "GetIpInterfaceEntry");
+        Assert(g_pfnGetIpInterfaceEntry);
+    }
+
+    if (g_pfnGetIpInterfaceEntry)
+    {
+        g_pfnSetIpInterfaceEntry = 
+            (PFNSETIPINTERFACEENTRY)GetProcAddress(pIpHlpInstance, "SetIpInterfaceEntry");
+        Assert(g_pfnSetIpInterfaceEntry);
+    }
+
+    if (g_pfnInitializeIpInterfaceEntry == NULL)
+    {
+        FreeLibrary(pIpHlpInstance);
+        pIpHlpInstance = NULL;
+        return E_FAIL;
+    }
+
+    return S_OK;
+}
+
+
 HRESULT vboxNetCfgWinGetLoopbackMetric(OUT int* Metric)
 {
-    HRESULT status = S_OK;
+    HRESULT rc = S_OK;
     MIB_IPINTERFACE_ROW row;
 
-    InitializeIpInterfaceEntry(&row);
+    Assert(g_pfnInitializeIpInterfaceEntry != NULL);
+    Assert(g_pfnGetIpInterfaceEntry != NULL);
+
+    g_pfnInitializeIpInterfaceEntry(&row);
     row.Family = AF_INET;
     row.InterfaceLuid.Info.IfType = IF_TYPE_SOFTWARE_LOOPBACK;
 
-    status = GetIpInterfaceEntry(&row);
-    if (status != 0)
-        return E_FAIL;
+    rc = g_pfnGetIpInterfaceEntry(&row);
+    if (rc != NO_ERROR)
+        return HRESULT_FROM_WIN32(rc);
 
     *Metric = row.Metric;
 
-    return status;
+    return rc;
 }
 
 
@@ -3380,7 +3442,11 @@ HRESULT vboxNetCfgWinSetInterfaceMetric(
     IN DWORD metric)
 {
     MIB_IPINTERFACE_ROW newRow;
-    InitializeIpInterfaceEntry(&newRow);
+
+    Assert(g_pfnInitializeIpInterfaceEntry != NULL);
+    Assert(g_pfnSetIpInterfaceEntry != NULL);
+
+    g_pfnInitializeIpInterfaceEntry(&newRow);
     // identificate the interface to change
     newRow.InterfaceLuid = *pInterfaceLuid;
     newRow.Family = AF_INET;
@@ -3389,7 +3455,7 @@ HRESULT vboxNetCfgWinSetInterfaceMetric(
     newRow.Metric = metric;
 
     // change settings
-    return SetIpInterfaceEntry(&newRow);
+    return HRESULT_FROM_WIN32(g_pfnSetIpInterfaceEntry(&newRow));
 }
 
 
@@ -3406,15 +3472,15 @@ HRESULT vboxNetCfgWinGetInterfaceLUID(IN HKEY hKey, OUT NET_LUID* pLUID)
     
     res = RegQueryValueExW(hKey, L"NetLuidIndex", NULL,
         &dwValueType, (LPBYTE)&luidIndex, &cbSize);
-    if (FAILED(res))
-        return res;
+    if (res != 0)
+        return HRESULT_FROM_WIN32(res);
 
     cbSize = sizeof(ifType);
     dwValueType = REG_DWORD;
     res = RegQueryValueExW(hKey, L"*IfType", NULL,
         &dwValueType, (LPBYTE)&ifType, &cbSize);
-    if (FAILED(res))
-        return res;
+    if (res != 0)
+        return HRESULT_FROM_WIN32(res);
 
     ZeroMemory(pLUID, sizeof(NET_LUID));
     pLUID->Info.IfType = ifType;
@@ -3426,24 +3492,29 @@ HRESULT vboxNetCfgWinGetInterfaceLUID(IN HKEY hKey, OUT NET_LUID* pLUID)
 
 HRESULT vboxNetCfgWinSetupMetric(IN HKEY hKey)
 {
-    HRESULT status = S_OK;
+    HRESULT rc = S_OK;
+    HINSTANCE hModule = NULL;
     NET_LUID luid;
     int loopbackMetric;
+    
+    rc = vboxLoadIpHelpFunctions(hModule);
 
-    status = vboxNetCfgWinGetInterfaceLUID(hKey, &luid);
-    if (FAILED(status))
-        return status;
-
-    status = vboxNetCfgWinGetLoopbackMetric(&loopbackMetric);
-    if (FAILED(status))
-        return status;
+    if(SUCCEEDED(rc))
+        rc = vboxNetCfgWinGetInterfaceLUID(hKey, &luid);
 
-    status = vboxNetCfgWinSetInterfaceMetric(&luid, loopbackMetric - 1);
+    if(SUCCEEDED(rc))
+        rc = vboxNetCfgWinGetLoopbackMetric(&loopbackMetric);
 
-    return status;
-}
+    if(SUCCEEDED(rc))
+        rc = vboxNetCfgWinSetInterfaceMetric(&luid, loopbackMetric - 1);
 
+    g_pfnInitializeIpInterfaceEntry = NULL;
+    g_pfnSetIpInterfaceEntry = NULL;
+    g_pfnGetIpInterfaceEntry = NULL;
 
+    FreeLibrary(hModule);
+    return rc;
+}
 #ifdef VBOXNETCFG_DELAYEDRENAME
 VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameHostOnlyConnection(IN const GUID *pGuid, IN LPCWSTR pwszId, OUT BSTR *pDevName)
 {
diff --git a/src/VBox/HostDrivers/VBoxPci/Makefile.kmk b/src/VBox/HostDrivers/VBoxPci/Makefile.kmk
index dbff7a5..6e0db03 100644
--- a/src/VBox/HostDrivers/VBoxPci/Makefile.kmk
+++ b/src/VBox/HostDrivers/VBoxPci/Makefile.kmk
@@ -40,6 +40,7 @@ if1of ($(KBUILD_TARGET), linux)
  	VBoxPci.c
   VBoxPci_LIBS          += \
  	$(PATH_STAGE_LIB)/SUPR0IdcClient$(VBOX_SUFF_LIB)
+  linux/VBoxPci-linux.c_DEPS = $(VBOX_SVN_REV_HEADER)
  endif
 
  #
diff --git a/src/VBox/HostDrivers/VBoxPci/linux/VBoxPci-linux.c b/src/VBox/HostDrivers/VBoxPci/linux/VBoxPci-linux.c
index 04e88e3..00fe94c 100644
--- a/src/VBox/HostDrivers/VBoxPci/linux/VBoxPci-linux.c
+++ b/src/VBox/HostDrivers/VBoxPci/linux/VBoxPci-linux.c
@@ -21,6 +21,7 @@
 *********************************************************************************************************************************/
 #include "the-linux-kernel.h"
 #include "version-generated.h"
+#include "revision-generated.h"
 #include "product-generated.h"
 
 #define LOG_GROUP LOG_GROUP_DEV_PCI_RAW
@@ -72,7 +73,7 @@ MODULE_AUTHOR(VBOX_VENDOR);
 MODULE_DESCRIPTION(VBOX_PRODUCT " PCI access Driver");
 MODULE_LICENSE("GPL");
 #ifdef MODULE_VERSION
-MODULE_VERSION(VBOX_VERSION_STRING);
+MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
 #endif
 
 
diff --git a/src/VBox/HostDrivers/VBoxPci/linux/files_vboxpci b/src/VBox/HostDrivers/VBoxPci/linux/files_vboxpci
index 7b1db27..9c5a986 100755
--- a/src/VBox/HostDrivers/VBoxPci/linux/files_vboxpci
+++ b/src/VBox/HostDrivers/VBoxPci/linux/files_vboxpci
@@ -78,6 +78,7 @@ VBOX_VBOXPCI_SOURCES=" \
     ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/umoddi3.c=>math/gcc/umoddi3.c \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h=>r0drv/linux/the-linux-kernel.h \
     ${PATH_OUT}/version-generated.h=>version-generated.h \
+    ${PATH_OUT}/revision-generated.h=>revision-generated.h \
     ${PATH_OUT}/product-generated.h=>product-generated.h \
 "
 
diff --git a/src/VBox/Main/include/GuestCtrlImplPrivate.h b/src/VBox/Main/include/GuestCtrlImplPrivate.h
index 4abb5e5..0ba4743 100644
--- a/src/VBox/Main/include/GuestCtrlImplPrivate.h
+++ b/src/VBox/Main/include/GuestCtrlImplPrivate.h
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2011-2015 Oracle Corporation
+ * Copyright (C) 2011-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -37,6 +37,7 @@
 using namespace com;
 
 #ifdef VBOX_WITH_GUEST_CONTROL
+# include <VBox/GuestHost/GuestControl.h>
 # include <VBox/HostServices/GuestControlSvc.h>
 using namespace guestControl;
 #endif
@@ -701,7 +702,7 @@ public:
 
     GuestProcessStartupInfo(void)
         : mFlags(ProcessCreateFlag_None),
-          mTimeoutMS(30 * 1000 /* 30s timeout by default */),
+          mTimeoutMS(UINT32_MAX /* No timeout by default */),
           mPriority(ProcessPriority_Default) { }
 
     /** The process' friendly name. */
@@ -714,6 +715,8 @@ public:
     GuestEnvironmentChanges     mEnvironmentChanges;
     /** Process creation flags. */
     uint32_t                    mFlags;
+    /** Timeout (in ms) the process is allowed to run.
+     *  Specify UINT32_MAX if no timeout (unlimited run time) is given. */
     ULONG                       mTimeoutMS;
     /** Process priority. */
     ProcessPriority_T           mPriority;
diff --git a/src/VBox/Main/include/GuestDirectoryImpl.h b/src/VBox/Main/include/GuestDirectoryImpl.h
index bc8a579..1a0bcba 100644
--- a/src/VBox/Main/include/GuestDirectoryImpl.h
+++ b/src/VBox/Main/include/GuestDirectoryImpl.h
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2012-2014 Oracle Corporation
+ * Copyright (C) 2012-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -72,6 +72,7 @@ private:
         GuestDirectoryOpenInfo     mOpenInfo;
         /** The directory's ID. */
         uint32_t                   mID;
+        /** The process tool instance to use. */
         GuestProcessTool           mProcessTool;
     } mData;
 };
diff --git a/src/VBox/Main/include/GuestProcessImpl.h b/src/VBox/Main/include/GuestProcessImpl.h
index f376bf6..960e540 100644
--- a/src/VBox/Main/include/GuestProcessImpl.h
+++ b/src/VBox/Main/include/GuestProcessImpl.h
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2012-2014 Oracle Corporation
+ * Copyright (C) 2012-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -181,7 +181,25 @@ private:
 #define GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK    RT_BIT(0)
 
 /**
- * Internal class for handling a VBoxService tool ("vbox_ls", vbox_stat", ...).
+ * Structure for keeping a VBoxService toolbox tool's error info around.
+ */
+struct GuestProcessToolErrorInfo
+{
+    /** Return code from the guest side for executing the process tool. */
+    int  guestRc;
+    /** The process tool's returned exit code. */
+    LONG lExitCode;
+};
+
+/**
+ * Internal class for handling the BusyBox-like tools built into VBoxService
+ * on the guest side. It's also called the VBoxService Toolbox (tm).
+ *
+ * Those initially were necessary to guarantee execution of commands (like "ls", "cat")
+ * under the behalf of a certain guest user.
+ *
+ * This class essentially helps to wrap all the gory details like process creation,
+ * information extraction and maintaining the overall status.
  */
 class GuestProcessTool
 {
@@ -195,6 +213,10 @@ public:
 
     int Init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, bool fAsync, int *pGuestRc);
 
+    int i_getCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock);
+
+    int i_getRc(void) const;
+
     GuestProcessStream &i_getStdOut(void) { return mStdOut; }
 
     GuestProcessStream &i_getStdErr(void) { return mStdErr; }
@@ -203,18 +225,27 @@ public:
 
     int i_waitEx(uint32_t fFlags, GuestProcessStreamBlock *pStreamBlock, int *pGuestRc);
 
-    int i_getCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock);
-
     bool i_isRunning(void);
 
+    int i_terminatedOk(LONG *plExitCode = NULL);
+
+    int i_terminate(uint32_t uTimeoutMS, int *pGuestRc);
+
+public:
+
     static int i_run(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, int *pGuestRc);
 
+    static int i_runErrorInfo(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, GuestProcessToolErrorInfo &errorInfo);
+
     static int i_runEx(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
                        GuestCtrlStreamObjects *pStrmOutObjects, uint32_t cStrmOutObjects, int *pGuestRc);
 
-    int i_terminatedOk(LONG *pExitCode);
+    static int i_runExErrorInfo(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
+                                GuestCtrlStreamObjects *pStrmOutObjects, uint32_t cStrmOutObjects, GuestProcessToolErrorInfo &errorInfo);
 
-    int i_terminate(uint32_t uTimeoutMS, int *pGuestRc);
+    static int i_exitCodeToRc(const GuestProcessStartupInfo &startupInfo, LONG lExitCode);
+
+    static int i_exitCodeToRc(const char *pszTool, LONG lExitCode);
 
 protected:
 
diff --git a/src/VBox/Main/src-client/GuestCtrlImpl.cpp b/src/VBox/Main/src-client/GuestCtrlImpl.cpp
index 2da9035..67433e8 100644
--- a/src/VBox/Main/src-client/GuestCtrlImpl.cpp
+++ b/src/VBox/Main/src-client/GuestCtrlImpl.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2006-2014 Oracle Corporation
+ * Copyright (C) 2006-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -577,8 +577,14 @@ HRESULT Guest::updateGuestAdditions(const com::Utf8Str &aSource, const std::vect
             {
                 hr = E_OUTOFMEMORY;
             }
+            catch(...)
+            {
+                LogFlowThisFunc(("Exception was caught in the function\n"));
+            }
         }
     }
+
+    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
     return hr;
 #endif /* VBOX_WITH_GUEST_CONTROL */
 }
diff --git a/src/VBox/Main/src-client/GuestDirectoryImpl.cpp b/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
index 97028fe..5883022 100644
--- a/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
+++ b/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2012-2015 Oracle Corporation
+ * Copyright (C) 2012-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -321,9 +321,7 @@ HRESULT GuestDirectory::read(ComPtr<IFsObjInfo> &aObjInfo)
     if (   RT_SUCCESS(rc)
         && !mData.mProcessTool.i_isRunning())
     {
-        rc = mData.mProcessTool.i_terminatedOk(NULL /* Exit code */);
-        if (rc == VERR_NOT_EQUAL)
-            rc = VERR_ACCESS_DENIED;
+        rc = mData.mProcessTool.i_terminatedOk();
     }
 
     if (RT_SUCCESS(rc))
@@ -372,9 +370,9 @@ HRESULT GuestDirectory::read(ComPtr<IFsObjInfo> &aObjInfo)
                 hr = GuestProcess::i_setErrorExternal(this, guestRc);
                 break;
 
-            case VERR_ACCESS_DENIED:
-                hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Unable to read / access denied"),
-                              mData.mOpenInfo.mPath.c_str());
+            case VWRN_GSTCTL_PROCESS_EXIT_CODE:
+                hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: %Rrc"),
+                              mData.mOpenInfo.mPath.c_str(), mData.mProcessTool.i_getRc());
                 break;
 
             case VERR_PATH_NOT_FOUND:
diff --git a/src/VBox/Main/src-client/GuestProcessImpl.cpp b/src/VBox/Main/src-client/GuestProcessImpl.cpp
index cbc9371..1620b72 100644
--- a/src/VBox/Main/src-client/GuestProcessImpl.cpp
+++ b/src/VBox/Main/src-client/GuestProcessImpl.cpp
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (C) 2012-2015 Oracle Corporation
+ * Copyright (C) 2012-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
  * available from http://www.virtualbox.org. This file is free software;
@@ -532,10 +532,6 @@ Utf8Str GuestProcess::i_guestErrorToString(int guestRc)
             strError += Utf8StrFmt(tr("Maximum number of concurrent guest processes has been reached"));
             break;
 
-        case VERR_NOT_EQUAL: /** @todo Imprecise to the user; can mean anything and all. */
-            strError += Utf8StrFmt(tr("Unable to retrieve requested information"));
-            break;
-
         case VERR_NOT_FOUND:
             strError += Utf8StrFmt(tr("The guest execution service is not ready (yet)"));
             break;
@@ -1937,18 +1933,21 @@ int GuestProcessTool::Init(GuestSession *pGuestSession, const GuestProcessStartu
 
     int vrc = pSession->i_processCreateExInternal(mStartupInfo, pProcess);
     if (RT_SUCCESS(vrc))
+    {
+        int guestRc;
         vrc = fAsync
             ? pProcess->i_startProcessAsync()
-            : pProcess->i_startProcess(30 * 1000 /* 30s timeout */, pGuestRc);
+            : pProcess->i_startProcess(30 * 1000 /* 30s timeout */, &guestRc);
 
-    if (   RT_SUCCESS(vrc)
-        && !fAsync
-        && (   pGuestRc
-            && RT_FAILURE(*pGuestRc)
+        if (   RT_SUCCESS(vrc)
+            && !fAsync
+            && RT_FAILURE(guestRc)
            )
-       )
-    {
-        vrc = VERR_GSTCTL_GUEST_ERROR;
+        {
+            if (pGuestRc)
+                *pGuestRc = guestRc;
+            vrc = VERR_GSTCTL_GUEST_ERROR;
+        }
     }
 
     LogFlowFuncLeaveRC(vrc);
@@ -1980,6 +1979,15 @@ int GuestProcessTool::i_getCurrentBlock(uint32_t uHandle, GuestProcessStreamBloc
     return vrc;
 }
 
+int GuestProcessTool::i_getRc(void) const
+{
+    LONG exitCode;
+    HRESULT hr = pProcess->COMGETTER(ExitCode(&exitCode));
+    Assert(SUCCEEDED(hr));
+
+    return GuestProcessTool::i_exitCodeToRc(mStartupInfo, exitCode);
+}
+
 bool GuestProcessTool::i_isRunning(void)
 {
     AssertReturn(!pProcess.isNull(), false);
@@ -1999,33 +2007,96 @@ bool GuestProcessTool::i_isRunning(void)
 }
 
 /* static */
-int GuestProcessTool::i_run(      GuestSession            *pGuestSession,
-                            const GuestProcessStartupInfo &startupInfo,
-                            int                           *pGuestRc)
+int GuestProcessTool::i_run(      GuestSession              *pGuestSession,
+                            const GuestProcessStartupInfo   &startupInfo,
+                                  int                       *pGuestRc /* = NULL */)
+{
+    int guestRc;
+
+    GuestProcessToolErrorInfo errorInfo;
+    int vrc = i_runErrorInfo(pGuestSession, startupInfo, errorInfo);
+    if (RT_SUCCESS(vrc))
+    {
+        if (errorInfo.guestRc == VWRN_GSTCTL_PROCESS_EXIT_CODE)
+        {
+            guestRc = GuestProcessTool::i_exitCodeToRc(startupInfo, errorInfo.lExitCode);
+        }
+        else
+            guestRc = errorInfo.guestRc;
+
+        if (pGuestRc)
+            *pGuestRc = guestRc;
+    }
+
+    return vrc;
+}
+
+/* static */
+int GuestProcessTool::i_runErrorInfo(      GuestSession              *pGuestSession,
+                                     const GuestProcessStartupInfo   &startupInfo,
+                                           GuestProcessToolErrorInfo &errorInfo)
+{
+    return i_runExErrorInfo(pGuestSession, startupInfo,
+                            NULL /* pStrmOutObjects */, 0 /* cStrmOutObjects */,
+                            errorInfo);
+}
+
+/* static */
+int GuestProcessTool::i_runEx(      GuestSession              *pGuestSession,
+                              const GuestProcessStartupInfo   &startupInfo,
+                                    GuestCtrlStreamObjects    *pStrmOutObjects,
+                                    uint32_t                   cStrmOutObjects,
+                                    int                       *pGuestRc /* = NULL */)
 {
-    return i_runEx(pGuestSession, startupInfo,
-                   NULL /* pStrmOutObjects */, 0 /* cStrmOutObjects */,
-                   pGuestRc);
+    int guestRc;
+
+    GuestProcessToolErrorInfo errorInfo;
+    int vrc = GuestProcessTool::i_runExErrorInfo(pGuestSession, startupInfo, pStrmOutObjects, cStrmOutObjects, errorInfo);
+    if (RT_SUCCESS(vrc))
+    {
+        if (errorInfo.guestRc == VWRN_GSTCTL_PROCESS_EXIT_CODE)
+        {
+            guestRc = GuestProcessTool::i_exitCodeToRc(startupInfo, errorInfo.lExitCode);
+        }
+        else
+            guestRc = errorInfo.guestRc;
+
+        if (pGuestRc)
+            *pGuestRc = guestRc;
+    }
+
+    return vrc;
 }
 
 /**
- * <Someone write documentation, pretty please!>
+ * Static helper function to start and wait for output of a certain toolbox tool.
+ *
+ * This is the extended version, which addds the possibility of retrieving parsable so-called guest stream
+ * objects. Those objects are issued on the guest side as part of VBoxService's toolbox tools (think of a BusyBox-like approach)
+ * on stdout and can be used on the host side to retrieve more information about the actual command issued on the guest side.
  *
- * @param   pGuestRc        Optional.  Will be set to VINF_SUCCESS,
- *                          VERR_NOT_EQUAL or VERR_INVALID_STATE if the
- *                          process completed.  Should it fail earlier that,
- *                          you're feel free to enlighten the rest of us...
+ * @return  IPRT status code.
+ * @param   pGuestSession           Guest control session to use for starting the toolbox tool in.
+ * @param   startupInfo             Startup information about the toolbox tool.
+ * @param   pStrmOutObjects         Pointer to stream objects array to use for retrieving the output of the toolbox tool.
+ *                                  Optional.
+ * @param   cStrmOutObjects         Number of stream objects passed in. Optional.
+ * @param   errorInfo               Error information returned for error handling.
  */
 /* static */
-int GuestProcessTool::i_runEx(      GuestSession            *pGuestSession,
-                              const GuestProcessStartupInfo &startupInfo,
-                                    GuestCtrlStreamObjects  *pStrmOutObjects,
-                                    uint32_t                 cStrmOutObjects,
-                                    int                     *pGuestRc)
+int GuestProcessTool::i_runExErrorInfo(      GuestSession              *pGuestSession,
+                                       const GuestProcessStartupInfo   &startupInfo,
+                                             GuestCtrlStreamObjects    *paStrmOutObjects,
+                                             uint32_t                   cStrmOutObjects,
+                                             GuestProcessToolErrorInfo &errorInfo)
 {
+    AssertPtrReturn(pGuestSession, VERR_INVALID_POINTER);
+    /* paStrmOutObjects is optional. */
+
+    /** @todo Check if this is a valid toolbox. */
+
     GuestProcessTool procTool;
-    int guestRc;
-    int vrc = procTool.Init(pGuestSession, startupInfo, false /* Async */, &guestRc);
+    int vrc = procTool.Init(pGuestSession, startupInfo, false /* Async */, &errorInfo.guestRc);
     if (RT_SUCCESS(vrc))
     {
         while (cStrmOutObjects--)
@@ -2033,11 +2104,11 @@ int GuestProcessTool::i_runEx(      GuestSession            *pGuestSession,
             try
             {
                 GuestProcessStreamBlock strmBlk;
-                vrc = procTool.i_waitEx(  pStrmOutObjects
+                vrc = procTool.i_waitEx(  paStrmOutObjects
                                         ? GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK
-                                        : GUESTPROCESSTOOL_FLAG_NONE, &strmBlk, &guestRc);
-                if (pStrmOutObjects)
-                    pStrmOutObjects->push_back(strmBlk);
+                                        : GUESTPROCESSTOOL_FLAG_NONE, &strmBlk, &errorInfo.guestRc);
+                if (paStrmOutObjects)
+                    paStrmOutObjects->push_back(strmBlk);
             }
             catch (std::bad_alloc)
             {
@@ -2049,23 +2120,25 @@ int GuestProcessTool::i_runEx(      GuestSession            *pGuestSession,
     if (RT_SUCCESS(vrc))
     {
         /* Make sure the process runs until completion. */
-        vrc = procTool.i_wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
+        vrc = procTool.i_wait(GUESTPROCESSTOOL_FLAG_NONE, &errorInfo.guestRc);
         if (RT_SUCCESS(vrc))
-        {
-            guestRc = procTool.i_terminatedOk(NULL /* Exit code */);
-            if (RT_FAILURE(guestRc))
-                vrc = VERR_GSTCTL_GUEST_ERROR;
-        }
+            errorInfo.guestRc = procTool.i_terminatedOk(&errorInfo.lExitCode);
     }
 
-    if (pGuestRc)
-        *pGuestRc = guestRc;
-
-    LogFlowFunc(("Returned rc=%Rrc, guestRc=%Rrc\n", vrc, guestRc));
+    LogFlowFunc(("Returned rc=%Rrc, guestRc=%Rrc, exitCode=%ld\n", vrc, errorInfo.guestRc, errorInfo.lExitCode));
     return vrc;
 }
 
-int GuestProcessTool::i_terminatedOk(LONG *pExitCode)
+/**
+ * Reports if the tool has been run correctly.
+ *
+ * @return  Will return VWRN_GSTCTL_PROCESS_EXIT_CODE if the tool process returned an exit code <> 0,
+ *          VERR_GSTCTL_PROCESS_WRONG_STATE if the tool process is in a wrong state (e.g. still running),
+ *          or VINF_SUCCESS otherwise.
+ *
+ * @param   plExitCode      Exit code of the tool. Optional.
+ */
+int GuestProcessTool::i_terminatedOk(LONG *plExitCode /* = NULL */)
 {
     Assert(!pProcess.isNull());
     /* pExitCode is optional. */
@@ -2073,19 +2146,18 @@ int GuestProcessTool::i_terminatedOk(LONG *pExitCode)
     int vrc;
     if (!i_isRunning())
     {
-        LONG exitCode;
-        HRESULT hr = pProcess->COMGETTER(ExitCode(&exitCode));
+        LONG lExitCode;
+        HRESULT hr = pProcess->COMGETTER(ExitCode(&lExitCode));
         Assert(SUCCEEDED(hr));
 
-        if (pExitCode)
-            *pExitCode = exitCode;
+        if (plExitCode)
+            *plExitCode = lExitCode;
 
-        vrc = (exitCode != 0)
-              /** @todo Special guest control rc needed! */
-            ? VERR_NOT_EQUAL : VINF_SUCCESS;
+        vrc = (lExitCode != 0)
+            ? VWRN_GSTCTL_PROCESS_EXIT_CODE : VINF_SUCCESS;
     }
     else
-        vrc = VERR_INVALID_STATE; /** @todo Special guest control rc needed! */
+        vrc = VERR_GSTCTL_PROCESS_WRONG_STATE;
 
     LogFlowFuncLeaveRC(vrc);
     return vrc;
@@ -2302,3 +2374,67 @@ int GuestProcessTool::i_terminate(uint32_t uTimeoutMS, int *pGuestRc)
     return rc;
 }
 
+/**
+ * Converts a toolbox tool's exit code to an IPRT error code.
+ *
+ * @return  int             Returned IPRT error for the particular tool.
+ * @param   startupInfo     Startup info of the toolbox tool to lookup error code for.
+ * @param   lExitCode       The toolbox tool's exit code to lookup IPRT error for.
+ */
+/* static */
+int GuestProcessTool::i_exitCodeToRc(const GuestProcessStartupInfo &startupInfo, LONG lExitCode)
+{
+    if (startupInfo.mArguments.size() == 0)
+    {
+        AssertFailed();
+        return VERR_GENERAL_FAILURE; /* Should not happen. */
+    }
+
+    return i_exitCodeToRc(startupInfo.mArguments[0].c_str(), lExitCode);
+}
+
+/**
+ * Converts a toolbox tool's exit code to an IPRT error code.
+ *
+ * @return  int             Returned IPRT error for the particular tool.
+ * @param   pszTool         Name of toolbox tool to lookup error code for.
+ * @param   rcExit          The toolbox tool's exit code to lookup IPRT error for.
+ */
+/* static */
+int GuestProcessTool::i_exitCodeToRc(const char *pszTool, LONG lExitCode)
+{
+    AssertPtrReturn(pszTool, VERR_INVALID_POINTER);
+
+    LogFlowFunc(("%s: %ld\n", pszTool, lExitCode));
+
+    if (lExitCode == 0) /* No error? Bail out early. */
+        return VINF_SUCCESS;
+
+    if (!RTStrICmp(pszTool, VBOXSERVICE_TOOL_CAT))
+    {
+        switch (lExitCode)
+        {
+            case VBOXSERVICETOOLBOX_CAT_EXITCODE_ACCESS_DENIED:     return VERR_ACCESS_DENIED;
+            case VBOXSERVICETOOLBOX_CAT_EXITCODE_FILE_NOT_FOUND:    return VERR_FILE_NOT_FOUND;
+            case VBOXSERVICETOOLBOX_CAT_EXITCODE_PATH_NOT_FOUND:    return VERR_PATH_NOT_FOUND;
+            case VBOXSERVICETOOLBOX_CAT_EXITCODE_SHARING_VIOLATION: return VERR_SHARING_VIOLATION;
+            default:
+                break;
+        }
+    }
+    else if (!RTStrICmp(pszTool, VBOXSERVICE_TOOL_STAT))
+    {
+        switch (lExitCode)
+        {
+            case VBOXSERVICETOOLBOX_STAT_EXITCODE_ACCESS_DENIED:    return VERR_ACCESS_DENIED;
+            case VBOXSERVICETOOLBOX_STAT_EXITCODE_FILE_NOT_FOUND:   return VERR_FILE_NOT_FOUND;
+            case VBOXSERVICETOOLBOX_STAT_EXITCODE_PATH_NOT_FOUND:   return VERR_PATH_NOT_FOUND;
+            default:
+                break;
+        }
+    }
+
+    AssertMsgFailed(("Error code %ld for tool '%s' not handled\n", lExitCode, pszTool));
+    return VERR_GENERAL_FAILURE;
+}
+
diff --git a/src/VBox/Main/src-client/GuestSessionImpl.cpp b/src/VBox/Main/src-client/GuestSessionImpl.cpp
index 64dd9b2..de1b3c9 100644
--- a/src/VBox/Main/src-client/GuestSessionImpl.cpp
+++ b/src/VBox/Main/src-client/GuestSessionImpl.cpp
@@ -578,6 +578,8 @@ HRESULT GuestSession::getEventSource(ComPtr<IEventSource> &aEventSource)
 
 int GuestSession::i_closeSession(uint32_t uFlags, uint32_t uTimeoutMS, int *pGuestRc)
 {
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
+
     LogFlowThisFunc(("uFlags=%x, uTimeoutMS=%RU32\n", uFlags, uTimeoutMS));
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -640,10 +642,11 @@ int GuestSession::i_closeSession(uint32_t uFlags, uint32_t uTimeoutMS, int *pGue
 }
 
 int GuestSession::i_directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode,
-                                          uint32_t uFlags, int *pGuestRc)
+                                            uint32_t uFlags, int *pGuestRc)
 {
-    LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n",
-                     strPath.c_str(), uMode, uFlags));
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
+
+    LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n", strPath.c_str(), uMode, uFlags));
 
     int vrc = VINF_SUCCESS;
 
@@ -706,7 +709,9 @@ inline bool GuestSession::i_directoryExists(uint32_t uDirID, ComObjPtr<GuestDire
 int GuestSession::i_directoryQueryInfoInternal(const Utf8Str &strPath, bool fFollowSymlinks,
                                                GuestFsObjData &objData, int *pGuestRc)
 {
-    LogFlowThisFunc(("strPath=%s fFollowSymlinks=%RTbool\n", strPath.c_str(), fFollowSymlinks));
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
+
+    LogFlowThisFunc(("strPath=%s, fFollowSymlinks=%RTbool\n", strPath.c_str(), fFollowSymlinks));
 
     int vrc = i_fsQueryInfoInternal(strPath, fFollowSymlinks, objData, pGuestRc);
     if (RT_SUCCESS(vrc))
@@ -721,6 +726,8 @@ int GuestSession::i_directoryQueryInfoInternal(const Utf8Str &strPath, bool fFol
 
 int GuestSession::i_directoryRemoveFromList(GuestDirectory *pDirectory)
 {
+    AssertPtrReturn(pDirectory, VERR_INVALID_POINTER);
+
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
     int rc = VERR_NOT_FOUND;
@@ -762,6 +769,7 @@ int GuestSession::i_directoryRemoveInternal(const Utf8Str &strPath, uint32_t uFl
                                             int *pGuestRc)
 {
     AssertReturn(!(uFlags & ~DIRREMOVE_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
 
     LogFlowThisFunc(("strPath=%s, uFlags=0x%x\n", strPath.c_str(), uFlags));
 
@@ -801,6 +809,8 @@ int GuestSession::i_directoryRemoveInternal(const Utf8Str &strPath, uint32_t uFl
 int GuestSession::i_objectCreateTempInternal(const Utf8Str &strTemplate, const Utf8Str &strPath,
                                              bool fDirectory, Utf8Str &strName, int *pGuestRc)
 {
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
+
     LogFlowThisFunc(("strTemplate=%s, strPath=%s, fDirectory=%RTbool\n",
                      strTemplate.c_str(), strPath.c_str(), fDirectory));
 
@@ -867,6 +877,8 @@ int GuestSession::i_objectCreateTempInternal(const Utf8Str &strTemplate, const U
 int GuestSession::i_directoryOpenInternal(const GuestDirectoryOpenInfo &openInfo,
                                           ComObjPtr<GuestDirectory> &pDirectory, int *pGuestRc)
 {
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
+
     LogFlowThisFunc(("strPath=%s, strPath=%s, uFlags=%x\n",
                      openInfo.mPath.c_str(), openInfo.mFilter.c_str(), openInfo.mFlags));
 
@@ -1418,8 +1430,7 @@ int GuestSession::i_fsQueryInfoInternal(const Utf8Str &strPath, bool fFollowSyml
         && pGuestRc)
         *pGuestRc = guestRc;
 
-    LogFlowThisFunc(("Returning rc=%Rrc, guestRc=%Rrc\n",
-                     vrc, guestRc));
+    LogFlowThisFunc(("Returning rc=%Rrc, guestRc=%Rrc\n", vrc, guestRc));
     return vrc;
 }
 
@@ -1473,10 +1484,6 @@ Utf8Str GuestSession::i_guestErrorToString(int guestRc)
             strError += Utf8StrFmt(tr("Maximum number of concurrent guest processes has been reached"));
             break;
 
-        case VERR_NOT_EQUAL: /** @todo Imprecise to the user; can mean anything and all. */
-            strError += Utf8StrFmt(tr("Unable to retrieve requested information"));
-            break;
-
         case VERR_NOT_FOUND:
             strError += Utf8StrFmt(tr("The guest execution service is not ready (yet)"));
             break;
@@ -1917,8 +1924,8 @@ int GuestSession::i_processCreateExInternal(GuestProcessStartupInfo &procInfo, C
         return VERR_INVALID_PARAMETER;
     }
 
-    /* Adjust timeout. If set to 0, we define
-     * an infinite timeout. */
+    /* Adjust timeout.
+     * If set to 0, we define an infinite timeout (unlimited process run time). */
     if (procInfo.mTimeoutMS == 0)
         procInfo.mTimeoutMS = UINT32_MAX;
 
@@ -2579,8 +2586,8 @@ HRESULT GuestSession::directoryCreate(const com::Utf8Str &aPath, ULONG aMode,
         switch (rc)
         {
             case VERR_GSTCTL_GUEST_ERROR:
-                /** @todo Handle VERR_NOT_EQUAL (meaning process exit code <> 0). */
-                hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Could not create directory"));
+                hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: %s",
+                                                    GuestDirectory::i_guestErrorToString(guestRc).c_str()));
                 break;
 
             case VERR_INVALID_PARAMETER:
@@ -3374,8 +3381,8 @@ HRESULT GuestSession::processCreateEx(const com::Utf8Str &aExecutable, const std
         vrc = i_processCreateExInternal(procInfo, pProcess);
         if (RT_SUCCESS(vrc))
         {
-            /* Return guest session to the caller. */
-            hr = pProcess.queryInterfaceTo(aGuestProcess.asOutParam());
+            ComPtr<IGuestProcess> pIProcess;
+            hr = pProcess.queryInterfaceTo(pIProcess.asOutParam());
             if (SUCCEEDED(hr))
             {
                 /*
@@ -3384,13 +3391,13 @@ HRESULT GuestSession::processCreateEx(const com::Utf8Str &aExecutable, const std
                 vrc = pProcess->i_startProcessAsync();
                 if (RT_SUCCESS(vrc))
                 {
+                    aGuestProcess = pIProcess;
+
                     LogFlowFuncLeaveRC(vrc);
                     return S_OK;
                 }
 
                 hr = setErrorVrc(vrc, tr("Failed to start guest process: %Rrc"), vrc);
-                /** @todo r=bird: What happens to the interface that *aGuestProcess points to
-                 *        now?  Looks like a leak or an undocument hack of sorts... */
             }
         }
         else if (vrc == VERR_MAX_PROCS_REACHED)
diff --git a/src/VBox/Main/src-client/GuestSessionImplTasks.cpp b/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
index df27609..4e42dab 100644
--- a/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
+++ b/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
@@ -35,6 +35,7 @@
 
 #include <iprt/env.h>
 #include <iprt/file.h> /* For CopyTo/From. */
+#include <iprt/path.h>
 
 #ifdef LOG_GROUP
  #undef LOG_GROUP
@@ -269,6 +270,8 @@ int SessionTaskCopyTo::Run(void)
 
     int rc;
 
+    RTMSINTERVAL msTimeout = 30 * 1000; /** @todo 30s timeout for all actions. Make this configurable? */
+
     RTFILE fileLocal;
     PRTFILE pFile = &fileLocal;
 
@@ -310,6 +313,30 @@ int SessionTaskCopyTo::Run(void)
         /* Size + offset are optional. */
     }
 
+    /*
+     * Query information about our destination first.
+     */
+    int guestRc;
+    if (RT_SUCCESS(rc))
+    {
+        GuestFsObjData objData;
+        rc = pSession->i_directoryQueryInfoInternal(mDest, true /* fFollowSymlinks */, objData, &guestRc);
+        if (RT_SUCCESS(rc))
+        {
+            mDest = Utf8StrFmt("%s/%s", mDest.c_str(), RTPathFilename(mSource.c_str()));
+        }
+        else if (rc == VERR_NOT_A_DIRECTORY)
+        {
+            rc = VINF_SUCCESS;
+        }
+    }
+
+    /** @todo Implement sparse file support? */
+
+    /*
+     * Start the actual copying process by cat'ing the source file to the
+     * destination file on the guest.
+     */
     GuestProcessStartupInfo procInfo;
     procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_CAT);
     procInfo.mFlags      = ProcessCreateFlag_Hidden;
@@ -319,14 +346,13 @@ int SessionTaskCopyTo::Run(void)
     procInfo.mArguments.push_back(Utf8StrFmt("--output=%s", mDest.c_str())); /** @todo Do we need path conversion? */
 
     /* Startup process. */
-    ComObjPtr<GuestProcess> pProcess; int guestRc;
+    ComObjPtr<GuestProcess> pProcess;
     if (RT_SUCCESS(rc))
         rc = pSession->i_processCreateExInternal(procInfo, pProcess);
     if (RT_SUCCESS(rc))
     {
         Assert(!pProcess.isNull());
-        rc = pProcess->i_startProcess(30 * 1000 /* 30s timeout */,
-                                      &guestRc);
+        rc = pProcess->i_startProcess(msTimeout, &guestRc);
     }
 
     if (RT_FAILURE(rc))
@@ -342,7 +368,7 @@ int SessionTaskCopyTo::Run(void)
                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                     Utf8StrFmt(GuestSession::tr(
                                     "Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),
-                                               mSource.c_str(), rc));
+                                    mSource.c_str(), rc));
                 break;
         }
     }
@@ -358,8 +384,7 @@ int SessionTaskCopyTo::Run(void)
 
         for (;;)
         {
-            rc = pProcess->i_waitFor(ProcessWaitForFlag_StdIn,
-                                     30 * 1000 /* Timeout */, waitRes, &guestRc);
+            rc = pProcess->i_waitFor(ProcessWaitForFlag_StdIn, msTimeout, waitRes, &guestRc);
             if (   RT_FAILURE(rc)
                 || (   waitRes != ProcessWaitResult_StdIn
                     && waitRes != ProcessWaitResult_WaitFlagNotSupported))
@@ -390,7 +415,7 @@ int SessionTaskCopyTo::Run(void)
                     if (RT_FAILURE(rc))
                     {
                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr("Could not read from file \"%s\" (%Rrc)"),
+                                            Utf8StrFmt(GuestSession::tr("Could not read from host file \"%s\" (%Rrc)"),
                                                        mSource.c_str(), rc));
                         break;
                     }
@@ -398,7 +423,7 @@ int SessionTaskCopyTo::Run(void)
                 else
                 {
                     setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                        Utf8StrFmt(GuestSession::tr("Seeking file \"%s\" to offset %RU64 failed: %Rrc"),
+                                        Utf8StrFmt(GuestSession::tr("Seeking host file \"%s\" to offset %RU64 failed: %Rrc"),
                                                    mSource.c_str(), cbWrittenTotal, rc));
                     break;
                 }
@@ -424,7 +449,7 @@ int SessionTaskCopyTo::Run(void)
             Assert(sizeof(byBuf) >= cbRead);
             rc = pProcess->i_writeData(0 /* StdIn */, fFlags,
                                        byBuf, cbRead,
-                                       30 * 1000 /* Timeout */, &cbWritten, &guestRc);
+                                       msTimeout, &cbWritten, &guestRc);
             if (RT_FAILURE(rc))
             {
                 switch (rc)
@@ -436,7 +461,7 @@ int SessionTaskCopyTo::Run(void)
 
                     default:
                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr("Writing to file \"%s\" (offset %RU64) failed: %Rrc"),
+                                            Utf8StrFmt(GuestSession::tr("Writing to guest file \"%s\" (offset %RU64) failed: %Rrc"),
                                             mDest.c_str(), cbWrittenTotal, rc));
                         break;
                 }
@@ -475,75 +500,77 @@ int SessionTaskCopyTo::Run(void)
         LogFlowThisFunc(("Copy loop ended with rc=%Rrc, cbToRead=%RU64, cbWrittenTotal=%RU64, cbFileSize=%RU64\n",
                          rc, cbToRead, cbWrittenTotal, mSourceSize));
 
+        /*
+         * Wait on termination of guest process until it completed all operations.
+         */
         if (   !fCanceled
             || RT_SUCCESS(rc))
         {
+            rc = pProcess->i_waitFor(ProcessWaitForFlag_Terminate, msTimeout, waitRes, &guestRc);
+            if (   RT_FAILURE(rc)
+                || waitRes != ProcessWaitResult_Terminate)
+            {
+                if (RT_FAILURE(rc))
+                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                        Utf8StrFmt(
+                                        GuestSession::tr("Waiting on termination for copying file \"%s\" to guest failed: %Rrc"),
+                                        mSource.c_str(), rc));
+                else
+                {
+                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                        Utf8StrFmt(GuestSession::tr(
+                                                   "Waiting on termination for copying file \"%s\" to guest failed with wait result %ld"),
+                                                   mSource.c_str(), waitRes));
+                    rc = VERR_GENERAL_FAILURE; /* Fudge. */
+                }
+            }
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            /*
+             * Newer VBoxService toolbox versions report what went wrong via exit code.
+             * So handle this first.
+             */
+            ProcessStatus_T procStatus;
+            LONG exitCode;
+            if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
+                    && procStatus != ProcessStatus_TerminatedNormally)
+                || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
+                    && exitCode != 0)
+               )
+            {
+                LogFlowThisFunc(("procStatus=%ld, exitCode=%ld\n", procStatus, exitCode));
+                rc = GuestProcessTool::i_exitCodeToRc(procInfo, exitCode);
+                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                    Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to guest failed: %Rrc"),
+                                               mSource.c_str(), rc));
+            }
             /*
              * Even if we succeeded until here make sure to check whether we really transfered
              * everything.
              */
-            if (   mSourceSize > 0
-                && cbWrittenTotal == 0)
+            else if (   mSourceSize > 0
+                     && cbWrittenTotal == 0)
             {
                 /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
                  * to the destination -> access denied. */
                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                    Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
+                                    Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to guest \"%s\""),
                                                mSource.c_str(), mDest.c_str()));
-                rc = VERR_GENERAL_FAILURE; /* Fudge. */
+                rc = VERR_ACCESS_DENIED;
             }
             else if (cbWrittenTotal < mSourceSize)
             {
                 /* If we did not copy all let the user know. */
                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                    Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"),
+                                    Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to guest failed (%RU64/%RU64 bytes transfered)"),
                                                mSource.c_str(), cbWrittenTotal, mSourceSize));
-                rc = VERR_GENERAL_FAILURE; /* Fudge. */
+                rc = VERR_INTERRUPTED;
             }
-            else
-            {
-                rc = pProcess->i_waitFor(ProcessWaitForFlag_Terminate,
-                                         30 * 1000 /* Timeout */, waitRes, &guestRc);
-                if (   RT_FAILURE(rc)
-                    || waitRes != ProcessWaitResult_Terminate)
-                {
-                    if (RT_FAILURE(rc))
-                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(
-                                            GuestSession::tr("Waiting on termination for copying file \"%s\" failed: %Rrc"),
-                                                       mSource.c_str(), rc));
-                    else
-                    {
-                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr(
-                                            "Waiting on termination for copying file \"%s\" failed with wait result %ld"),
-                                                       mSource.c_str(), waitRes));
-                        rc = VERR_GENERAL_FAILURE; /* Fudge. */
-                    }
-                }
 
-                if (RT_SUCCESS(rc))
-                {
-                    ProcessStatus_T procStatus;
-                    LONG exitCode;
-                    if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
-                            && procStatus != ProcessStatus_TerminatedNormally)
-                        || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
-                            && exitCode != 0)
-                       )
-                    {
-                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr(
-                                            "Copying file \"%s\" failed with status %ld, exit code %ld"),
-                                                       mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */
-                        rc = VERR_GENERAL_FAILURE; /* Fudge. */
-                    }
-                }
-
-
-                if (RT_SUCCESS(rc))
-                    rc = setProgressSuccess();
-            }
+            if (RT_SUCCESS(rc))
+                rc = setProgressSuccess();
         }
     } /* processCreateExInteral */
 
@@ -603,6 +630,8 @@ int SessionTaskCopyFrom::Run(void)
     AutoCaller autoCaller(pSession);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
+    RTMSINTERVAL msTimeout = 30 * 1000; /** @todo 30s timeout for all actions. Make this configurable? */
+
     /*
      * Note: There will be races between querying file size + reading the guest file's
      *       content because we currently *do not* lock down the guest file when doing the
@@ -621,7 +650,7 @@ int SessionTaskCopyFrom::Run(void)
     {
         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                             Utf8StrFmt(GuestSession::tr("Object \"%s\" on the guest is not a file"), mSource.c_str()));
-        rc = VERR_GENERAL_FAILURE; /* Fudge. */
+        rc = VERR_NOT_A_FILE;
     }
 
     if (RT_SUCCESS(rc))
@@ -632,7 +661,7 @@ int SessionTaskCopyFrom::Run(void)
         if (RT_FAILURE(rc))
         {
             setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                Utf8StrFmt(GuestSession::tr("Error opening destination file \"%s\": %Rrc"),
+                                Utf8StrFmt(GuestSession::tr("Opening/creating destination file on host \"%s\" failed: %Rrc"),
                                            mDest.c_str(), rc));
         }
         else
@@ -651,22 +680,20 @@ int SessionTaskCopyFrom::Run(void)
             ComObjPtr<GuestProcess> pProcess;
             rc = pSession->i_processCreateExInternal(procInfo, pProcess);
             if (RT_SUCCESS(rc))
-                rc = pProcess->i_startProcess(30 * 1000 /* 30s timeout */,
-                                              &guestRc);
+                rc = pProcess->i_startProcess(msTimeout, &guestRc);
             if (RT_FAILURE(rc))
             {
                 switch (rc)
                 {
                     case VERR_GSTCTL_GUEST_ERROR:
-                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            GuestProcess::i_guestErrorToString(guestRc));
+                        setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestProcess::i_guestErrorToString(guestRc));
                         break;
 
                     default:
                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                             Utf8StrFmt(GuestSession::tr(
                                            "Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),
-                                                       mSource.c_str(), rc));
+                                           mSource.c_str(), rc));
                         break;
                 }
             }
@@ -681,8 +708,7 @@ int SessionTaskCopyFrom::Run(void)
 
                 for (;;)
                 {
-                    rc = pProcess->i_waitFor(ProcessWaitForFlag_StdOut,
-                                             30 * 1000 /* Timeout */, waitRes, &guestRc);
+                    rc = pProcess->i_waitFor(ProcessWaitForFlag_StdOut, msTimeout, waitRes, &guestRc);
                     if (RT_FAILURE(rc))
                     {
                         switch (rc)
@@ -712,7 +738,7 @@ int SessionTaskCopyFrom::Run(void)
 
                         uint32_t cbRead = 0; /* readData can return with VWRN_GSTCTL_OBJECTSTATE_CHANGED. */
                         rc = pProcess->i_readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
-                                                  30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
+                                                  msTimeout, byBuf, sizeof(byBuf),
                                                   &cbRead, &guestRc);
                         if (RT_FAILURE(rc))
                         {
@@ -725,7 +751,7 @@ int SessionTaskCopyFrom::Run(void)
 
                                 default:
                                     setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                                        Utf8StrFmt(GuestSession::tr("Reading from file \"%s\" (offset %RU64) failed: %Rrc"),
+                                                        Utf8StrFmt(GuestSession::tr("Reading from guest file \"%s\" (offset %RU64) failed: %Rrc"),
                                                                    mSource.c_str(), cbWrittenTotal, rc));
                                     break;
                             }
@@ -739,7 +765,7 @@ int SessionTaskCopyFrom::Run(void)
                             if (RT_FAILURE(rc))
                             {
                                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                                    Utf8StrFmt(GuestSession::tr("Error writing to file \"%s\" (%RU64 bytes left): %Rrc"),
+                                                    Utf8StrFmt(GuestSession::tr("Writing to host file \"%s\" (%RU64 bytes left) failed: %Rrc"),
                                                                 mDest.c_str(), cbToRead, rc));
                                 break;
                             }
@@ -772,50 +798,73 @@ int SessionTaskCopyFrom::Run(void)
                 LogFlowThisFunc(("rc=%Rrc, guestrc=%Rrc, waitRes=%ld, cbWrittenTotal=%RU64, cbSize=%RI64, cbToRead=%RU64\n",
                                  rc, guestRc, waitRes, cbWrittenTotal, objData.mObjectSize, cbToRead));
 
+                /*
+                 * Wait on termination of guest process until it completed all operations.
+                 */
                 if (   !fCanceled
                     || RT_SUCCESS(rc))
                 {
+                    rc = pProcess->i_waitFor(ProcessWaitForFlag_Terminate, msTimeout, waitRes, &guestRc);
+                    if (   RT_FAILURE(rc)
+                        || waitRes != ProcessWaitResult_Terminate)
+                    {
+                        if (RT_FAILURE(rc))
+                            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                                Utf8StrFmt(
+                                                GuestSession::tr("Waiting on termination for copying file \"%s\" from guest failed: %Rrc"),
+                                                mSource.c_str(), rc));
+                        else
+                        {
+                            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                                Utf8StrFmt(GuestSession::tr(
+                                                           "Waiting on termination for copying file \"%s\" from guest failed with wait result %ld"),
+                                                           mSource.c_str(), waitRes));
+                            rc = VERR_GENERAL_FAILURE; /* Fudge. */
+                        }
+                    }
+                }
+
+                if (RT_SUCCESS(rc))
+                {
+                    ProcessStatus_T procStatus;
+                    LONG exitCode;
+                    if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
+                            && procStatus != ProcessStatus_TerminatedNormally)
+                        || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
+                            && exitCode != 0)
+                       )
+                    {
+                        LogFlowThisFunc(("procStatus=%ld, exitCode=%ld\n", procStatus, exitCode));
+                        rc = GuestProcessTool::i_exitCodeToRc(procInfo, exitCode);
+                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                            Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to host failed: %Rrc"),
+                                                       mSource.c_str(), rc));
+                    }
                     /*
                      * Even if we succeeded until here make sure to check whether we really transfered
                      * everything.
                      */
-                    if (   objData.mObjectSize > 0
-                        && cbWrittenTotal == 0)
+                    else if (   objData.mObjectSize > 0
+                             && cbWrittenTotal == 0)
                     {
                         /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
                          * to the destination -> access denied. */
                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr("Unable to write \"%s\" to \"%s\": Access denied"),
-                                            mSource.c_str(), mDest.c_str()));
-                        rc = VERR_GENERAL_FAILURE; /* Fudge. */
+                                            Utf8StrFmt(GuestSession::tr("Writing guest file \"%s\" to host to \"%s\" failed: Access denied"),
+                                                       mSource.c_str(), mDest.c_str()));
+                        rc = VERR_ACCESS_DENIED;
                     }
                     else if (cbWrittenTotal < (uint64_t)objData.mObjectSize)
                     {
                         /* If we did not copy all let the user know. */
                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RI64 bytes transfered)"),
-                                                       mSource.c_str(), cbWrittenTotal, objData.mObjectSize));
-                        rc = VERR_GENERAL_FAILURE; /* Fudge. */
-                    }
-                    else
-                    {
-                        ProcessStatus_T procStatus;
-                        LONG exitCode;
-                        if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
-                                && procStatus != ProcessStatus_TerminatedNormally)
-                            || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
-                                && exitCode != 0)
-                           )
-                        {
-                            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                                Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %d"),
-                                                           mSource.c_str(), procStatus, exitCode)); /**@todo Add
-                                                                                                       stringify methods! */
-                            rc = VERR_GENERAL_FAILURE; /* Fudge. */
-                        }
-                        else /* Yay, success! */
-                            rc = setProgressSuccess();
+                                            Utf8StrFmt(GuestSession::tr("Copying guest file \"%s\" to host to \"%s\" failed (%RU64/%RI64 bytes transfered)"),
+                                                       mSource.c_str(), mDest.c_str(), cbWrittenTotal, objData.mObjectSize));
+                        rc = VERR_INTERRUPTED;
                     }
+
+                    if (RT_SUCCESS(rc))
+                        rc = setProgressSuccess();
                 }
             }
 
@@ -1026,7 +1075,6 @@ int SessionTaskUpdateAdditions::i_runFileOnGuest(GuestSession *pSession, GuestPr
 
     LogRel(("Running %s ...\n", procInfo.mName.c_str()));
 
-    LONG exitCode;
     GuestProcessTool procTool; int guestRc;
     int vrc = procTool.Init(pSession, procInfo, false /* Async */, &guestRc);
     if (RT_SUCCESS(vrc))
@@ -1034,17 +1082,17 @@ int SessionTaskUpdateAdditions::i_runFileOnGuest(GuestSession *pSession, GuestPr
         if (RT_SUCCESS(guestRc))
             vrc = procTool.i_wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
         if (RT_SUCCESS(vrc))
-            vrc = procTool.i_terminatedOk(&exitCode);
+            vrc = procTool.i_terminatedOk();
     }
 
     if (RT_FAILURE(vrc))
     {
         switch (vrc)
         {
-            case VERR_NOT_EQUAL: /** @todo Special guest control rc needed! */
+            case VWRN_GSTCTL_PROCESS_EXIT_CODE:
                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                    Utf8StrFmt(GuestSession::tr("Running update file \"%s\" on guest terminated with exit code %ld"),
-                                               procInfo.mExecutable.c_str(), exitCode));
+                                    Utf8StrFmt(GuestSession::tr("Running update file \"%s\" on guest failed: %Rrc"),
+                                               procInfo.mExecutable.c_str(), procTool.i_getRc()));
                 break;
 
             case VERR_GSTCTL_GUEST_ERROR:
diff --git a/src/VBox/Main/src-server/MachineImpl.cpp b/src/VBox/Main/src-server/MachineImpl.cpp
index 423554c..6781060 100644
--- a/src/VBox/Main/src-server/MachineImpl.cpp
+++ b/src/VBox/Main/src-server/MachineImpl.cpp
@@ -12069,7 +12069,15 @@ void Machine::i_copyFrom(Machine *aThat)
 
     mNetworkAdapters.resize(aThat->mNetworkAdapters.size());
     for (ULONG slot = 0; slot < mNetworkAdapters.size(); ++slot)
-        mNetworkAdapters[slot]->i_copyFrom(aThat->mNetworkAdapters[slot]);
+    {
+        if (mNetworkAdapters[slot].isNotNull())
+            mNetworkAdapters[slot]->i_copyFrom(aThat->mNetworkAdapters[slot]);
+        else
+        {
+            unconst(mNetworkAdapters[slot]).createObject();
+            mNetworkAdapters[slot]->initCopy(this, aThat->mNetworkAdapters[slot]);
+        }
+    }
     for (ULONG slot = 0; slot < RT_ELEMENTS(mSerialPorts); ++slot)
         mSerialPorts[slot]->i_copyFrom(aThat->mSerialPorts[slot]);
     for (ULONG slot = 0; slot < RT_ELEMENTS(mParallelPorts); ++slot)
diff --git a/src/VBox/NetworkServices/NAT/proxy.h b/src/VBox/NetworkServices/NAT/proxy.h
index e8bd49e..f2cc7ad 100644
--- a/src/VBox/NetworkServices/NAT/proxy.h
+++ b/src/VBox/NetworkServices/NAT/proxy.h
@@ -114,13 +114,4 @@ err_t pxping_init(struct netif *, SOCKET, SOCKET);
 #define DPRINTF1(a) Log2(a)
 #define DPRINTF2(a) Log3(a)
 
-#if 1 /* XXX: temporary enable it as optional verbose logging */
-#undef  DPRINTF0
-#define DPRINTF0(a) LogRel2(a)
-#undef  DPRINTF1
-#define DPRINTF1(a) LogRel3(a)
-#undef  DPRINTF2
-#define DPRINTF2(a) LogRel4(a)
-#endif
-
 #endif /* _nat_proxy_h_ */
diff --git a/src/VBox/NetworkServices/NAT/pxdns.c b/src/VBox/NetworkServices/NAT/pxdns.c
index add5a7e..0380c78 100644
--- a/src/VBox/NetworkServices/NAT/pxdns.c
+++ b/src/VBox/NetworkServices/NAT/pxdns.c
@@ -42,10 +42,13 @@
 
 #include "proxy.h"
 #include "proxy_pollmgr.h"
+#include "pxtcp.h"
 
 #include "lwip/sys.h"
 #include "lwip/tcpip.h"
+#include "lwip/ip_addr.h"
 #include "lwip/udp.h"
+#include "lwip/tcp.h"
 
 #ifndef RT_OS_WINDOWS
 #include <sys/poll.h>
@@ -83,6 +86,8 @@ struct pxdns {
     struct udp_pcb *pcb4;
     struct udp_pcb *pcb6;
 
+    struct tcp_pcb *ltcp;
+
     size_t generation;
     size_t nresolvers;
     union sockaddr_inet *resolvers;
@@ -177,6 +182,8 @@ struct request {
 static void pxdns_create_resolver_sockaddrs(struct pxdns *pxdns,
                                             const char **nameservers);
 
+static err_t pxdns_accept_syn(void *arg, struct tcp_pcb *newpcb, struct pbuf *syn);
+
 static void pxdns_recv4(void *arg, struct udp_pcb *pcb, struct pbuf *p,
                         ip_addr_t *addr, u16_t port);
 static void pxdns_recv6(void *arg, struct udp_pcb *pcb, struct pbuf *p,
@@ -210,6 +217,16 @@ pxdns_init(struct netif *proxy_netif)
 
     LWIP_UNUSED_ARG(proxy_netif);
 
+    pxdns->ltcp = tcp_new();
+    if (pxdns->ltcp != NULL) {
+        tcp_bind_ip6(pxdns->ltcp, IP6_ADDR_ANY, 53);
+        pxdns->ltcp = tcp_listen_dual(pxdns->ltcp);
+        if (pxdns->ltcp != NULL) {
+            tcp_arg(pxdns->ltcp, pxdns);
+            tcp_accept_syn(pxdns->ltcp, pxdns_accept_syn);
+        }
+    }
+
     pxdns->pmhdl4.callback = pxdns_pmgr_pump;
     pxdns->pmhdl4.data = (void *)pxdns;
     pxdns->pmhdl4.slot = -1;
@@ -862,3 +879,42 @@ pxdns_pcb_reply(void *ctx)
 
     pxdns_request_free(req);
 }
+
+
+/**
+ * TCP DNS proxy.  This kicks in for large replies that don't fit into
+ * 512 bytes of UDP payload.  Client will retry with TCP to get
+ * complete reply.
+ */
+static err_t
+pxdns_accept_syn(void *arg, struct tcp_pcb *newpcb, struct pbuf *syn)
+{
+    struct pxdns *pxdns = (struct pxdns *)arg;
+    union sockaddr_inet *si;
+    ipX_addr_t *dst;
+    u16_t dst_port;
+
+    tcp_accepted(pxdns->ltcp);
+
+    if (pxdns->nresolvers == 0) {
+        return ERR_CONN;
+    }
+
+    si = &pxdns->resolvers[0];
+
+    if (si->sa.sa_family == AF_INET6) {
+        dst = (ipX_addr_t *)&si->sin6.sin6_addr;
+        dst_port = ntohs(si->sin6.sin6_port);
+    }
+    else {
+        dst = (ipX_addr_t *)&si->sin.sin_addr;
+        dst_port = ntohs(si->sin.sin_port);
+    }
+
+    /*
+     * XXX: TODO: need to implement protocol hooks.  E.g. here if
+     * connect fails, we should try connecting to a different server.
+     */
+    return pxtcp_pcb_accept_outbound(newpcb, syn,
+               si->sa.sa_family == AF_INET6, dst, dst_port);
+}
diff --git a/src/VBox/NetworkServices/NAT/pxtcp.c b/src/VBox/NetworkServices/NAT/pxtcp.c
index 4b613ab..d1f5178 100644
--- a/src/VBox/NetworkServices/NAT/pxtcp.c
+++ b/src/VBox/NetworkServices/NAT/pxtcp.c
@@ -267,7 +267,7 @@ static void pxtcp_pcb_write_inbound(void *);
 static void pxtcp_pcb_pull_inbound(void *);
 
 /* tcp pcb callbacks */
-static err_t pxtcp_pcb_heard(void *, struct tcp_pcb *, err_t); /* global */
+static err_t pxtcp_pcb_heard(void *, struct tcp_pcb *, struct pbuf *); /* global */
 static err_t pxtcp_pcb_accept(void *, struct tcp_pcb *, err_t);
 static err_t pxtcp_pcb_connected(void *, struct tcp_pcb *, err_t);
 static err_t pxtcp_pcb_recv(void *, struct tcp_pcb *, struct pbuf *, err_t);
@@ -286,7 +286,7 @@ DECLINLINE(int) pxtcp_pcb_forward_inbound_done(const struct pxtcp *);
 static void pxtcp_pcb_schedule_poll(struct pxtcp *);
 static void pxtcp_pcb_cancel_poll(struct pxtcp *);
 
-static void pxtcp_pcb_reject(struct netif *, struct tcp_pcb *, struct pbuf *, int);
+static void pxtcp_pcb_reject(struct tcp_pcb *, int, struct netif *, struct pbuf *);
 DECLINLINE(void) pxtcp_pcb_maybe_deferred_delete(struct pxtcp *);
 
 /* poll manager handlers for pxtcp channels */
@@ -903,40 +903,45 @@ pxtcp_schedule_reset(struct pxtcp *pxtcp)
  * send TCP reset.
  */
 static void
-pxtcp_pcb_reject(struct netif *netif, struct tcp_pcb *pcb,
-                 struct pbuf *p, int sockerr)
+pxtcp_pcb_reject(struct tcp_pcb *pcb, int sockerr,
+                 struct netif *netif,  struct pbuf *p)
 {
-    struct netif *oif;
     int reset = 0;
 
-    oif = ip_current_netif();
-    ip_current_netif() = netif;
-
     if (sockerr == ECONNREFUSED) {
         reset = 1;
     }
-    else if (PCB_ISIPV6(pcb)) {
-        if (sockerr == EHOSTDOWN) {
-            icmp6_dest_unreach(p, ICMP6_DUR_ADDRESS); /* XXX: ??? */
-        }
-        else if (sockerr == EHOSTUNREACH
-                 || sockerr == ENETDOWN
-                 || sockerr == ENETUNREACH)
-        {
-            icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE);
+    else if (p != NULL) {
+        struct netif *oif;
+
+        LWIP_ASSERT1(netif != NULL);
+
+        oif = ip_current_netif();
+        ip_current_netif() = netif;
+
+        if (PCB_ISIPV6(pcb)) {
+            if (sockerr == EHOSTDOWN) {
+                icmp6_dest_unreach(p, ICMP6_DUR_ADDRESS); /* XXX: ??? */
+            }
+            else if (sockerr == EHOSTUNREACH
+                     || sockerr == ENETDOWN
+                     || sockerr == ENETUNREACH)
+            {
+                icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE);
+            }
         }
-    }
-    else {
-        if (sockerr == EHOSTDOWN
-            || sockerr == EHOSTUNREACH
-            || sockerr == ENETDOWN
-            || sockerr == ENETUNREACH)
-        {
-            icmp_dest_unreach(p, ICMP_DUR_HOST);
+        else {
+            if (sockerr == EHOSTDOWN
+                || sockerr == EHOSTUNREACH
+                || sockerr == ENETDOWN
+                || sockerr == ENETUNREACH)
+            {
+                icmp_dest_unreach(p, ICMP_DUR_HOST);
+            }
         }
-    }
 
-    ip_current_netif() = oif;
+        ip_current_netif() = oif;
+    }
 
     tcp_abandon(pcb, reset);
 }
@@ -965,7 +970,7 @@ pxtcp_pcb_accept_refuse(void *ctx)
     if (pxtcp->pcb != NULL) {
         struct tcp_pcb *pcb = pxtcp->pcb;
         pxtcp_pcb_dissociate(pxtcp);
-        pxtcp_pcb_reject(pxtcp->netif, pcb, pxtcp->unsent, pxtcp->sockerr);
+        pxtcp_pcb_reject(pcb,  pxtcp->sockerr, pxtcp->netif, pxtcp->unsent);
     }
 
     pollmgr_refptr_unref(pxtcp->rp);
@@ -995,18 +1000,26 @@ pxtcp_schedule_reject(struct pxtcp *pxtcp)
  * connections from guest(s).
  */
 static err_t
-pxtcp_pcb_heard(void *arg, struct tcp_pcb *newpcb, err_t error)
+pxtcp_pcb_heard(void *arg, struct tcp_pcb *newpcb, struct pbuf *syn)
+{
+    LWIP_UNUSED_ARG(arg);
+
+    return pxtcp_pcb_accept_outbound(newpcb, syn,
+               PCB_ISIPV6(newpcb), &newpcb->local_ip, newpcb->local_port);
+}
+
+
+err_t
+pxtcp_pcb_accept_outbound(struct tcp_pcb *newpcb, struct pbuf *p,
+                          int is_ipv6, ipX_addr_t *dst_addr, u16_t dst_port)
 {
-    struct pbuf *p = (struct pbuf *)arg;
     struct pxtcp *pxtcp;
-    ipX_addr_t dst_addr;
+    ipX_addr_t mapped_dst_addr;
     int sdom;
     SOCKET sock;
     ssize_t nsent;
     int sockerr = 0;
 
-    LWIP_UNUSED_ARG(error);     /* always ERR_OK */
-
     /*
      * TCP first calls accept callback when it receives the first SYN
      * and "tentatively accepts" new proxied connection attempt.  When
@@ -1020,11 +1033,11 @@ pxtcp_pcb_heard(void *arg, struct tcp_pcb *newpcb, err_t error)
 
     tcp_setprio(newpcb, TCP_PRIO_MAX);
 
-    pxremap_outbound_ipX(PCB_ISIPV6(newpcb), &dst_addr, &newpcb->local_ip);
+    pxremap_outbound_ipX(is_ipv6, &mapped_dst_addr, dst_addr);
 
-    sdom = PCB_ISIPV6(newpcb) ? PF_INET6 : PF_INET;
+    sdom = is_ipv6 ? PF_INET6 : PF_INET;
     sock = proxy_connected_socket(sdom, SOCK_STREAM,
-                                  &dst_addr, newpcb->local_port);
+                                  &mapped_dst_addr, dst_port);
     if (sock == INVALID_SOCKET) {
         sockerr = SOCKERRNO();
         goto abort;
@@ -1037,9 +1050,11 @@ pxtcp_pcb_heard(void *arg, struct tcp_pcb *newpcb, err_t error)
     }
 
     /* save initial datagram in case we need to reply with ICMP */
-    pbuf_ref(p);
-    pxtcp->unsent = p;
-    pxtcp->netif = ip_current_netif();
+    if (p != NULL) {
+        pbuf_ref(p);
+        pxtcp->unsent = p;
+        pxtcp->netif = ip_current_netif();
+    }
 
     pxtcp_pcb_associate(pxtcp, newpcb);
     pxtcp->sock = sock;
@@ -1060,7 +1075,7 @@ pxtcp_pcb_heard(void *arg, struct tcp_pcb *newpcb, err_t error)
   abort:
     DPRINTF0(("%s: pcb %p, sock %d: %R[sockerr]\n",
               __func__, (void *)newpcb, sock, sockerr));
-    pxtcp_pcb_reject(ip_current_netif(), newpcb, p, sockerr);
+    pxtcp_pcb_reject(newpcb, sockerr, ip_current_netif(), p);
     return ERR_ABRT;
 }
 
@@ -1207,9 +1222,10 @@ pxtcp_pcb_accept_confirm(void *ctx)
     }
 
     /* we are not going to reply with ICMP, so we can drop initial pbuf */
-    LWIP_ASSERT1(pxtcp->unsent != NULL);
-    pbuf_free(pxtcp->unsent);
-    pxtcp->unsent = NULL;
+    if (pxtcp->unsent != NULL) {
+        pbuf_free(pxtcp->unsent);
+        pxtcp->unsent = NULL;
+    }
 
     error = tcp_proxy_accept_confirm(pxtcp->pcb);
 
diff --git a/src/VBox/NetworkServices/NAT/pxtcp.h b/src/VBox/NetworkServices/NAT/pxtcp.h
index fb8e5ca..b776e53 100644
--- a/src/VBox/NetworkServices/NAT/pxtcp.h
+++ b/src/VBox/NetworkServices/NAT/pxtcp.h
@@ -18,9 +18,16 @@
 #ifndef _pxtcp_h_
 #define _pxtcp_h_
 
+#include "lwip/err.h"
+#include "lwip/ip_addr.h"
+
+struct pbuf;
+struct tcp_pcb;
 struct pxtcp;
 struct fwspec;
 
+err_t pxtcp_pcb_accept_outbound(struct tcp_pcb *, struct pbuf *, int, ipX_addr_t *, u16_t);
+
 struct pxtcp *pxtcp_create_forwarded(SOCKET);
 void pxtcp_cancel_forwarded(struct pxtcp *);
 
diff --git a/src/VBox/Runtime/common/ldr/ldrPE.cpp b/src/VBox/Runtime/common/ldr/ldrPE.cpp
index d07df96..04a6147 100644
--- a/src/VBox/Runtime/common/ldr/ldrPE.cpp
+++ b/src/VBox/Runtime/common/ldr/ldrPE.cpp
@@ -3432,6 +3432,7 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
     union /* combine stuff we're reading to help reduce stack usage. */
     {
         IMAGE_LOAD_CONFIG_DIRECTORY64   Cfg64;
+        uint8_t                         abZeros[sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V5) * 4];
     } u;
 
     /*
@@ -3458,26 +3459,45 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
                                 ? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V1)
                                 : sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V2) /*No V1*/;
 
+        bool fNewerStructureHack = false;
         if (   Dir.Size != cbExpectV5
             && Dir.Size != cbExpectV4
             && Dir.Size != cbExpectV3
             && Dir.Size != cbExpectV2
             && Dir.Size != cbExpectV1)
         {
-            Log(("rtldrPEOpen: %s: load cfg dir: unexpected dir size of %u bytes, expected %zu, %zu, %zu, %zu, or %zu.\n",
-                 pszLogName, Dir.Size, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1));
-            return RTErrInfoSetF(pErrInfo, VERR_LDRPE_LOAD_CONFIG_SIZE,
-                                 "Unexpected load config dir size of %u bytes; supported sized: %zu, %zu, %zu, %zu, or %zu",
-                                 Dir.Size, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
+            fNewerStructureHack = Dir.Size > cbExpectV5  /* These structure changes are slowly getting to us! More futher down. */
+                               && Dir.Size <= sizeof(u);
+            Log(("rtldrPEOpen: %s: load cfg dir: unexpected dir size of %u bytes, expected %zu, %zu, %zu, %zu, or %zu.%s\n",
+                 pszLogName, Dir.Size, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1,
+                 fNewerStructureHack ? " Will try ignore extra bytes if all zero." : ""));
+            if (!fNewerStructureHack)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRPE_LOAD_CONFIG_SIZE,
+                                     "Unexpected load config dir size of %u bytes; supported sized: %zu, %zu, %zu, %zu, or %zu",
+                                     Dir.Size, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
         }
 
         /*
-         * Read and convert to 64-bit.
+         * Read, check new stuff and convert to 64-bit.
+         *
+         * If we accepted a newer structure, we check whether the new bits are
+         * all zero.  This PRAYING/ASSUMING that the nothing new weird stuff is
+         * activated by a zero value and that it'll mostly be unused in areas
+         * we care about (which has been the case till now).
          */
         RT_ZERO(u.Cfg64);
         int rc = rtldrPEReadRVA(pModPe, &u.Cfg64, Dir.Size, Dir.VirtualAddress);
         if (RT_FAILURE(rc))
             return rc;
+        if (   fNewerStructureHack
+            && !ASMMemIsZero(&u.abZeros[cbExpectV5], Dir.Size - cbExpectV5))
+        {
+            Log(("rtldrPEOpen: %s: load cfg dir: Unexpected bytes are non-zero (%u bytes of which %u expected to be zero): %.*Rhxs\n",
+                 pszLogName, Dir.Size, Dir.Size - cbExpectV5, Dir.Size - cbExpectV5, &u.abZeros[cbExpectV5]));
+            return RTErrInfoSetF(pErrInfo, VERR_LDRPE_LOAD_CONFIG_SIZE,
+                                 "Grown load config (%u to %u bytes) includes non-zero bytes: %.*Rhxs",
+                                 cbExpectV5, Dir.Size, Dir.Size - cbExpectV5, &u.abZeros[cbExpectV5]);
+        }
         rtldrPEConvert32BitLoadConfigTo64Bit(&u.Cfg64);
 
         if (u.Cfg64.Size != Dir.Size)
@@ -3490,20 +3510,32 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
                 u.Cfg64.Size = Dir.Size;
             }
             /* Kludge #2: This happens a lot. Structure changes, but the linker doesn't get
-               it updated and stores some old size in the directory.  Use the header size. */
+               updated and stores some old size in the directory.  Use the header size. */
             else if (   u.Cfg64.Size == cbExpectV5
                      || u.Cfg64.Size == cbExpectV4
                      || u.Cfg64.Size == cbExpectV3
                      || u.Cfg64.Size == cbExpectV2
-                     || u.Cfg64.Size == cbExpectV1)
+                     || u.Cfg64.Size == cbExpectV1
+                     || (fNewerStructureHack = (u.Cfg64.Size > cbExpectV5 && u.Cfg64.Size <= sizeof(u))) )
             {
                 Log(("rtldrPEOpen: %s: load cfg dir: Header (%d) and directory (%d) size mismatch, applying the old linker kludge.\n",
                      pszLogName, u.Cfg64.Size, Dir.Size));
+
                 Dir.Size = u.Cfg64.Size;
+                uint32_t const uOrgDir = Dir.Size;
                 RT_ZERO(u.Cfg64);
                 rc = rtldrPEReadRVA(pModPe, &u.Cfg64, Dir.Size, Dir.VirtualAddress);
                 if (RT_FAILURE(rc))
                     return rc;
+                if (   fNewerStructureHack
+                    && !ASMMemIsZero(&u.abZeros[cbExpectV5], Dir.Size - cbExpectV5))
+                {
+                    Log(("rtldrPEOpen: %s: load cfg dir: Unknown bytes are non-zero (%u bytes of which %u expected to be zero): %.*Rhxs\n",
+                         pszLogName, Dir.Size, Dir.Size - cbExpectV5, Dir.Size - cbExpectV5, &u.abZeros[cbExpectV5]));
+                    return RTErrInfoSetF(pErrInfo, VERR_LDRPE_LOAD_CONFIG_SIZE,
+                                         "Grown load config (%u to %u bytes, dir %u) includes non-zero bytes: %.*Rhxs",
+                                         cbExpectV5, Dir.Size, uOrgDir, Dir.Size - cbExpectV5, &u.abZeros[cbExpectV5]);
+                }
                 rtldrPEConvert32BitLoadConfigTo64Bit(&u.Cfg64);
                 AssertReturn(u.Cfg64.Size == Dir.Size,
                              RTErrInfoSetF(pErrInfo, VERR_LDRPE_LOAD_CONFIG_SIZE, "Data changed while reading! (%d vs %d)\n",
@@ -3514,7 +3546,7 @@ static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const
                 Log(("rtldrPEOpen: %s: load cfg hdr: unexpected hdr size of %u bytes (dir %u), expected %zu, %zu, %zu, %zu, or %zu.\n",
                      pszLogName, u.Cfg64.Size, Dir.Size, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1));
                 return RTErrInfoSetF(pErrInfo, VERR_LDRPE_LOAD_CONFIG_SIZE,
-                                     "Unexpected load config dir size of %u bytes (dir %u); supported sized: %zu, %zu, %zu, %zu, or %zu",
+                                     "Unexpected load config header size of %u bytes (dir %u); supported sized: %zu, %zu, %zu, %zu, or %zu",
                                      u.Cfg64.Size, Dir.Size, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
             }
         }
diff --git a/src/VBox/Runtime/common/math/bignum-amd64-x86.asm b/src/VBox/Runtime/common/math/bignum-amd64-x86.asm
index a77e4a9..06421b1 100644
--- a/src/VBox/Runtime/common/math/bignum-amd64-x86.asm
+++ b/src/VBox/Runtime/common/math/bignum-amd64-x86.asm
@@ -25,11 +25,27 @@
 ;
 
 
+;*********************************************************************************************************************************
+;*  Header Files                                                                                                                 *
+;*********************************************************************************************************************************
 %define RT_ASM_WITH_SEH64
 %include "iprt/asmdefs.mac"
 %include "internal/bignum.mac"
 
 
+;*********************************************************************************************************************************
+;*  Defined Constants And Macros                                                                                                 *
+;*********************************************************************************************************************************
+%ifdef RT_ARCH_AMD64
+ %macro sahf 0
+  %error "SAHF not supported on ancient AMD64"
+ %endmacro
+ %macro lahf 0
+  %error "LAHF not supported on ancient AMD64"
+ %endmacro
+%endif
+
+
 BEGINCODE
 
 ;;
@@ -66,10 +82,10 @@ SEH64_END_PROLOGUE
  %endif
         xor     r11d, r11d              ; index register.
 
-%if RTBIGNUM_ELEMENT_SIZE == 4
+ %if RTBIGNUM_ELEMENT_SIZE == 4
         add     cUsed, 1                ; cUsed = RT_ALIGN(cUsed, 2) / 2
         shr     cUsed, 1
-%endif
+ %endif
         cmp     cUsed, 8                ; Skip the big loop if small number.
         jb      .small_job
 
@@ -105,12 +121,22 @@ SEH64_END_PROLOGUE
         dec     r10d                    ; Does not change CF.
         jnz     .big_loop
 
+ %if 0 ; Ancient AMD CPUs does have lahf/sahf, thus the mess in the %else.
         lahf                            ; Save CF
         and     cUsed, 7                ; Up to seven odd rounds.
         jz      .done
         sahf                            ; Restore CF.
         jmp     .small_loop             ; Skip CF=1 (clc).
-
+ %else
+        jnc     .no_carry
+        and     cUsed, 7                ; Up to seven odd rounds.
+        jz      .done
+        stc
+        jmp     .small_loop             ; Skip CF=1 (clc).
+.no_carry:
+        and     cUsed, 7                ; Up to seven odd rounds.
+        jz      .done
+ %endif
 .small_job:
         clc
 .small_loop:
@@ -246,10 +272,10 @@ SEH64_END_PROLOGUE
  %endif
         xor     r11d, r11d              ; index register.
 
-%if RTBIGNUM_ELEMENT_SIZE == 4
+ %if RTBIGNUM_ELEMENT_SIZE == 4
         add     cUsed, 1                ; cUsed = RT_ALIGN(cUsed, 2) / 2
         shr     cUsed, 1
-%endif
+ %endif
         cmp     cUsed, 8                ; Skip the big loop if small number.
         jb      .small_job
 
@@ -277,12 +303,22 @@ SEH64_END_PROLOGUE
         dec     r10d                    ; Does not change CF.
         jnz     .big_loop
 
+ %if 0 ; Ancient AMD CPUs does have lahf/sahf, thus the mess in the %else.
         lahf                            ; Save CF
         and     cUsed, 7                ; Up to seven odd rounds.
         jz      .done
         sahf                            ; Restore CF.
         jmp     .small_loop             ; Skip CF=1 (clc).
-
+ %else
+        jnc     .no_carry
+        and     cUsed, 7                ; Up to seven odd rounds.
+        jz      .done
+        stc
+        jmp     .small_loop             ; Skip CF=1 (clc).
+.no_carry:
+        and     cUsed, 7                ; Up to seven odd rounds.
+        jz      .done
+ %endif
 .small_job:
         clc
 .small_loop:
@@ -450,7 +486,7 @@ SEH64_END_PROLOGUE
         jnz     .big_loop
 
         ; More to do?
-        lahf                            ; save carry flag (uCarry no longer used on x86).
+        pushf                           ; save carry flag (uCarry no longer used on x86).
 %ifdef RT_ARCH_AMD64
         mov     cUsed, r11d
 %else
@@ -458,10 +494,10 @@ SEH64_END_PROLOGUE
 %endif
         and     cUsed, 7
         jz      .restore_cf_and_return  ; Jump if we're good and done.
-        sahf                            ; Restore CF.
+        popf                            ; Restore CF.
         jmp     .small_loop             ; Deal with the odd rounds.
 .restore_cf_and_return:
-        sahf
+        popf
         jmp     .carry_to_eax
 
         ; Small loop - One round at the time.

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-virtualbox/virtualbox.git



More information about the Pkg-virtualbox-commits mailing list