Index: /trunk/include/VBox/pdmnetifs.h
===================================================================
--- /trunk/include/VBox/pdmnetifs.h	(revision 33824)
+++ /trunk/include/VBox/pdmnetifs.h	(revision 33825)
@@ -28,4 +28,5 @@
 
 #include <VBox/types.h>
+#include <iprt/net.h>
 
 RT_C_DECLS_BEGIN
@@ -407,4 +408,15 @@
 #define PDMINETWORKCONFIG_IID                   "d6d909e8-716d-415d-b109-534e4478ff4e"
 
+typedef struct PDMINETWORKNATCONFIG
+{
+    /**
+     * Inform NAT about the adding/removing redirection rule
+     */
+    DECLR3CALLBACKMEMBER(int, pfnRedirectRuleCommand ,(PDMINETWORKNATCONFIG *pInterface, bool fRemove, 
+                                                   const char *pNatRuleName, bool fUdp, const char *pHostIp,
+                                                   uint16_t u16HostPort, const char *pGuestIp, uint16_t u16GuestPort));
+
+} PDMINETWORKNATCONFIG, *PPDMINETWORKNATCONFIG;
+#define PDMINETWORKNATCONFIG_IID                "0f001d62-4d2f-11df-93b3-2fd0b3a36a6b" 
 /** @} */
 
Index: /trunk/src/VBox/Devices/Network/DrvNAT.cpp
===================================================================
--- /trunk/src/VBox/Devices/Network/DrvNAT.cpp	(revision 33824)
+++ /trunk/src/VBox/Devices/Network/DrvNAT.cpp	(revision 33825)
@@ -131,4 +131,6 @@
     /** The network interface. */
     PDMINETWORKUP           INetworkUp;
+    /** The network NAT Engine configureation. */
+    PDMINETWORKNATCONFIG    INetworkNATCfg;
     /** The port we're attached to. */
     PPDMINETWORKDOWN        pIAboveNet;
@@ -650,4 +652,53 @@
 }
 
+static void drvNATNotifyApplyPortForwardCommand(PDRVNAT pThis,bool fRemove, 
+                                                const char *pNatRuleName, 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 
+        || inet_aton(pHostIp, &hostIp) == 0)
+        hostIp.s_addr = INADDR_ANY;
+
+    if (   pGuestIp == NULL
+        || inet_aton(pGuestIp, &guestIp) == 0)
+        guestIp.s_addr = pThis->GuestIP;
+
+    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);
+}
+
+DECLCALLBACK(int) drvNATNetworkNatConfig_RedirectRuleCommand(PPDMINETWORKNATCONFIG pInterface, bool fRemove, 
+                                                   const char *pNatRuleName, bool fUdp, const char *pHostIp,
+                                                   uint16_t u16HostPort, const char *pGuestIp, uint16_t u16GuestPort)
+{
+    LogFlow(("drvNATNetworkNatConfig_ApplyNatCommand: cRules=%s\n", (pNatRuleName ? pNatRuleName: "")));
+    PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkNATCfg);
+    PRTREQ pReq;
+    int rc = RTReqCallEx(pThis->pSlirpReqQueue, &pReq, 0 /*cMillies*/, RTREQFLAGS_VOID,
+                         (PFNRT)drvNATNotifyApplyPortForwardCommand, 8, pThis, fRemove,
+                          pNatRuleName, fUdp, pHostIp, u16HostPort, pGuestIp, u16GuestPort);
+    if (RT_LIKELY(rc == VERR_TIMEOUT))
+    {
+        drvNATNotifyNATThread(pThis, "drvNATNetworkNatConfig_RedirectRuleCommand");
+        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);
+        AssertRC(rc);
+    }
+    else
+        AssertRC(rc);
+    
+    RTReqFree(pReq);
+    port_forwarding_done:
+    return rc;
+}
+
 /**
  * NAT thread handling the slirp stuff.
@@ -896,4 +947,5 @@
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKUP, &pThis->INetworkUp);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKNATCONFIG, &pThis->INetworkNATCfg);
     return NULL;
 }
@@ -1006,5 +1058,5 @@
         struct in_addr BindIP;
         GETIP_DEF(rc, pThis, pNode, BindIP, INADDR_ANY);
-        if (slirp_redir(pThis->pNATState, fUDP, BindIP, iHostPort, GuestIP, iGuestPort, Mac.au8) < 0)
+        if (slirp_add_redirect(pThis->pNATState, fUDP, BindIP, iHostPort, GuestIP, iGuestPort, Mac.au8) < 0)
             return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_NAT_REDIR_SETUP, RT_SRC_POS,
                                        N_("NAT#%d: configuration error: failed to set up "
@@ -1111,4 +1163,7 @@
     pThis->INetworkUp.pfnSetPromiscuousMode = drvNATNetworkUp_SetPromiscuousMode;
     pThis->INetworkUp.pfnNotifyLinkChanged  = drvNATNetworkUp_NotifyLinkChanged;
+
+    /* NAT engine configuration */
+    pThis->INetworkNATCfg.pfnRedirectRuleCommand = drvNATNetworkNatConfig_RedirectRuleCommand;
 
     /*
Index: /trunk/src/VBox/Devices/Network/slirp/libslirp.h
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/libslirp.h	(revision 33824)
+++ /trunk/src/VBox/Devices/Network/slirp/libslirp.h	(revision 33825)
@@ -72,7 +72,10 @@
 void slirp_post_sent(PNATState pData, void *pvArg);
 
-int slirp_redir(PNATState pData, int is_udp, struct in_addr host_addr,
+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 slirp_remove_redirect(PNATState pData, int is_udp, struct in_addr host_addr,
+                int host_port, struct in_addr guest_addr,
+                int guest_port);
 int slirp_add_exec(PNATState pData, int do_pty, const char *args, int addr_low_byte,
                    int guest_port);
Index: /trunk/src/VBox/Devices/Network/slirp/slirp.c
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 33824)
+++ /trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 33825)
@@ -1657,6 +1657,9 @@
 
 #if !defined(VBOX_WITH_NAT_SERVICE)
-        if (rule->guest_addr.s_addr != guest_addr)
+        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;
 #endif
 
@@ -1703,4 +1706,5 @@
         so->so_la = lib;
         rule->activated = 1;
+        rule->so = so;
         pData->cRedirectionsActive++;
         continue;
@@ -1727,9 +1731,21 @@
  * corresponding port-forwarding
  */
-int slirp_redir(PNATState pData, int is_udp, struct in_addr host_addr, int host_port,
+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 port_forward_rule *rule = NULL;
-    Assert(memcmp(ethaddr, zerro_ethaddr, ETH_ALEN) == 0);
+    Assert(ethaddr);
+    LIST_FOREACH(rule, &pData->port_forward_rule_head, list)
+    {
+        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
+#ifndef VBOX_WITH_NAT_SERVICE
+            && rule->guest_addr.s_addr == guest_addr.s_addr
+#endif
+            )
+                return 0; /* rule has been already registered */
+    }
 
     rule = RTMemAllocZ(sizeof(struct port_forward_rule));
@@ -1748,4 +1764,41 @@
     LIST_INSERT_HEAD(&pData->port_forward_rule_head, rule, list);
     pData->cRedirectionsStored++;
+    /* activate port-forwarding if guest has already got assigned IP */
+    if (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)
+    {
+        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
+#ifndef VBOX_WITH_NAT_SERVICE
+            && rule->guest_addr.s_addr == guest_addr.s_addr
+#endif
+            && rule->activated)
+        {
+            LibAliasUninit(rule->so->so_la);
+            if (is_udp)
+            {
+                udp_detach(pData, rule->so);
+            }
+            else
+            {
+                tcp_close(pData, sototcpcb(rule->so));
+            }
+            LIST_REMOVE(rule, list);
+            RTMemFree(rule);
+            pData->cRedirectionsStored--;
+            break;
+        }
+        
+    }
     return 0;
 }
@@ -2019,4 +2072,5 @@
         mtu = 1500;
     }
+    /* MTU is maximum transition unit on */
     if_mtu =
     if_mru = mtu;
Index: /trunk/src/VBox/Devices/Network/slirp/slirp_state.h
===================================================================
--- /trunk/src/VBox/Devices/Network/slirp/slirp_state.h	(revision 33824)
+++ /trunk/src/VBox/Devices/Network/slirp/slirp_state.h	(revision 33825)
@@ -85,4 +85,5 @@
     uint8_t mac_address[6]; /*need ETH_ALEN here */
     int activated;
+    struct socket *so;
     LIST_ENTRY(port_forward_rule) list;
 };
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp	(revision 33824)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp	(revision 33825)
@@ -394,4 +394,96 @@
             }
         }
+        else if(   a->argc > 2 
+                && !strncmp(a->argv[1], "natpf", 5))
+        {
+            /* Get the number of network adapters */
+            ULONG NetworkAdapterCount = 0;
+            ComPtr <ISystemProperties> info;
+            ComPtr<INATEngine> engine;
+            CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
+            CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
+            unsigned n = parseNum(&a->argv[1][5], NetworkAdapterCount, "NIC");
+            if (!n)
+            {
+                rc = E_FAIL;
+                break;
+            }
+            if (a->argc <= 2)
+            {
+                errorArgument("Missing argument to '%s'", a->argv[1]);
+                rc = E_FAIL;
+                break;
+            }
+
+            /* get the corresponding network adapter */
+            ComPtr<INetworkAdapter> adapter;
+            CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
+            if (!adapter)
+            {
+                rc = E_FAIL;
+                break;
+            }
+            CHECK_ERROR(adapter, COMGETTER(NatDriver)(engine.asOutParam()));
+            if (!engine)
+            {
+                rc = E_FAIL;
+                break;
+            }
+
+            if (!strcmp(a->argv[2], "delete"))
+            { 
+                if (a->argc >= 3)
+                    CHECK_ERROR(engine, RemoveRedirect(Bstr(a->argv[3]).raw()));
+            }
+            else
+            {
+#define ITERATE_TO_NEXT_TERM(ch)                                           \
+    do {                                                                   \
+        while (*ch != ',')                                                 \
+        {                                                                  \
+            if (*ch == 0)                                                  \
+            {                                                              \
+                return errorSyntax(USAGE_CONTROLVM,                         \
+                                   "Missing or Invalid argument to '%s'",  \
+                                    a->argv[1]);                           \
+            }                                                              \
+            ch++;                                                          \
+        }                                                                  \
+        *ch = '\0';                                                        \
+        ch++;                                                              \
+    } while(0)
+
+                char *strName;
+                char *strProto;
+                char *strHostIp;
+                char *strHostPort;
+                char *strGuestIp;
+                char *strGuestPort;
+                char *strRaw = RTStrDup(a->argv[2]);
+                char *ch = strRaw;
+                strName = RTStrStrip(ch);
+                ITERATE_TO_NEXT_TERM(ch);
+                strProto = RTStrStrip(ch);
+                ITERATE_TO_NEXT_TERM(ch);
+                strHostIp = RTStrStrip(ch);
+                ITERATE_TO_NEXT_TERM(ch);
+                strHostPort = RTStrStrip(ch);
+                ITERATE_TO_NEXT_TERM(ch);
+                strGuestIp = RTStrStrip(ch);
+                ITERATE_TO_NEXT_TERM(ch);
+                strGuestPort = RTStrStrip(ch);
+                NATProtocol_T proto;
+                if (RTStrICmp(strProto, "udp") == 0)
+                    proto = NATProtocol_UDP;
+                else if (RTStrICmp(strProto, "tcp") == 0)
+                    proto = NATProtocol_TCP;
+                CHECK_ERROR(engine, AddRedirect(Bstr(strName).raw(), proto, Bstr(strHostIp).raw(),
+                        RTStrToUInt16(strHostPort), Bstr(strGuestIp).raw(), RTStrToUInt16(strGuestPort)));
+#undef ITERATE_TO_NEXT_TERM
+            }
+            /* commit changes */
+            if (SUCCEEDED(rc))
+                CHECK_ERROR(sessionMachine, SaveSettings());
+        }
         else if (!strncmp(a->argv[1], "nic", 3))
         {
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 33824)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 33825)
@@ -391,4 +391,7 @@
                      "                            nictrace<1-N> on|off\n"
                      "                            nictracefile<1-N> <filename>\n"
+                     "                            natpf<1-N> [<rulename>],tcp|udp,[<hostip>],\n"
+                     "                                          <hostport>,[<guestip>],<guestport>\n"
+                     "                            natpf<1-N> delete <rulename>\n"
                      "                            guestmemoryballoon <balloonsize in MB>]\n"
                      "                            gueststatisticsinterval <seconds>]\n"
Index: /trunk/src/VBox/Main/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 33824)
+++ /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 33825)
@@ -1092,4 +1092,28 @@
 uint32_t Console::sSSMConsoleVer = 0x00010001;
 
+inline static const char *networkAdapterTypeToName(NetworkAdapterType_T adapterType)
+{
+    switch (adapterType)
+    {
+        case NetworkAdapterType_Am79C970A:
+        case NetworkAdapterType_Am79C973:
+            return "pcnet";
+#ifdef VBOX_WITH_E1000
+        case NetworkAdapterType_I82540EM:
+        case NetworkAdapterType_I82543GC:
+        case NetworkAdapterType_I82545EM:
+            return "e1000";
+#endif
+#ifdef VBOX_WITH_VIRTIO
+        case NetworkAdapterType_Virtio:
+            return "virtio-net";
+#endif
+        default:
+            AssertFailed();
+            return "unknown";
+    }
+    return NULL;
+}
+
 /**
  * Loads various console data stored in the saved state file.
@@ -3415,5 +3439,5 @@
             {
                 /*
-                 * Find the pcnet instance, get the config interface and update
+                 * Find the adapter instance, get the config interface and update
                  * the link state.
                  */
@@ -3421,29 +3445,5 @@
                 rc = aNetworkAdapter->COMGETTER(AdapterType)(&adapterType);
                 AssertComRC(rc);
-                const char *pszAdapterName = NULL;
-                switch (adapterType)
-                {
-                    case NetworkAdapterType_Am79C970A:
-                    case NetworkAdapterType_Am79C973:
-                        pszAdapterName = "pcnet";
-                        break;
-#ifdef VBOX_WITH_E1000
-                    case NetworkAdapterType_I82540EM:
-                    case NetworkAdapterType_I82543GC:
-                    case NetworkAdapterType_I82545EM:
-                        pszAdapterName = "e1000";
-                        break;
-#endif
-#ifdef VBOX_WITH_VIRTIO
-                    case NetworkAdapterType_Virtio:
-                        pszAdapterName = "virtio-net";
-                        break;
-#endif
-                    default:
-                        AssertFailed();
-                        pszAdapterName = "unknown";
-                        break;
-                }
-
+                const char *pszAdapterName = networkAdapterTypeToName(adapterType);
                 PPDMIBASE pBase;
                 int vrc = PDMR3QueryDeviceLun(mpVM, pszAdapterName, ulInstance, 0, &pBase);
@@ -3496,4 +3496,87 @@
         CONSOLE_DO_CALLBACKS1(OnNetworkAdapterChanged, aNetworkAdapter);
 
+    LogFlowThisFunc(("Leaving rc=%#x\n", rc));
+    return rc;
+}
+
+/**
+ * Called by IInternalSessionControl::OnNATEngineChange().
+ *
+ * @note Locks this object for writing.
+ */
+HRESULT Console::onNATRedirectRuleChange(INetworkAdapter *aNetworkAdapter, BOOL aNatRuleRemove, IN_BSTR aRuleName, 
+                                 NATProtocol_T aProto, IN_BSTR aHostIp, LONG aHostPort, IN_BSTR aGuestIp, LONG aGuestPort)
+{
+    LogFlowThisFunc(("\n"));
+
+    AutoCaller autoCaller(this);
+    AssertComRCReturnRC(autoCaller.rc());
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    HRESULT rc = S_OK;
+    int vrc = VINF_SUCCESS;
+    PPDMINETWORKNATCONFIG pNetNatCfg = NULL;
+    /* don't trigger nat engine change if the VM isn't running */
+    if (mpVM)
+    {
+        /* protect mpVM */
+        AutoVMCaller autoVMCaller(this);
+        if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
+        ULONG ulInstance;
+        rc = aNetworkAdapter->COMGETTER(Slot)(&ulInstance);
+        AssertComRC(rc);
+        if (FAILED(rc))
+            goto done;
+        /*
+         * Find the adapter instance, get the config interface and update
+         * the link state.
+         */
+        NetworkAdapterType_T adapterType;
+        rc = aNetworkAdapter->COMGETTER(AdapterType)(&adapterType);
+        AssertComRC(rc);
+        if (FAILED(rc))
+        {
+            rc = E_FAIL;
+            goto done;
+        }
+
+        const char *pszAdapterName = networkAdapterTypeToName(adapterType);
+        PPDMIBASE pBase;
+        vrc = PDMR3QueryLun(mpVM, pszAdapterName, ulInstance, 0, &pBase);
+        ComAssertRC(vrc);
+        if (RT_FAILURE(vrc))
+        {
+            rc = E_FAIL;
+            goto done;
+        }
+        NetworkAttachmentType_T attachmentType;
+        vrc = aNetworkAdapter->COMGETTER(AttachmentType)(&attachmentType);
+
+        if (   RT_FAILURE(vrc) 
+            || attachmentType != NetworkAttachmentType_NAT)
+        {
+            rc = (RT_FAILURE(vrc)) ? E_FAIL: rc;
+            goto done;
+        }
+        
+        /* look down for PDMINETWORKNATCONFIG interface */
+        while (pBase)
+        {
+            if ((pNetNatCfg = (PPDMINETWORKNATCONFIG)pBase->pfnQueryInterface(pBase, PDMINETWORKNATCONFIG_IID)))
+                break;
+            PPDMDRVINS drvins = PDMIBASE_2_PDMDRV(pBase);
+            pBase = drvins->pDownBase;
+        }
+        if (!pNetNatCfg)
+            goto done;
+        bool fUdp = (aProto == NATProtocol_UDP);
+        vrc = pNetNatCfg->pfnRedirectRuleCommand(pNetNatCfg, aNatRuleRemove, Utf8Str(aRuleName).c_str(), fUdp, 
+                                                 Utf8Str(aHostIp).c_str(), aHostPort, Utf8Str(aGuestIp).c_str(), 
+                                                 aGuestPort);
+        if (RT_FAILURE(vrc))
+            rc = E_FAIL;
+    }
+done:
     LogFlowThisFunc(("Leaving rc=%#x\n", rc));
     return rc;
Index: /trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MachineImpl.cpp	(revision 33824)
+++ /trunk/src/VBox/Main/MachineImpl.cpp	(revision 33825)
@@ -10926,4 +10926,28 @@
  *  @note Locks this object for reading.
  */
+HRESULT SessionMachine::onNATRedirectRuleChange(INetworkAdapter *networkAdapter, BOOL aNatRuleRemove, IN_BSTR aRuleName, 
+                                 NATProtocol_T aProto, IN_BSTR aHostIp, LONG aHostPort, IN_BSTR aGuestIp, LONG aGuestPort)
+{
+    LogFlowThisFunc(("\n"));
+
+    AutoCaller autoCaller(this);
+    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
+
+    ComPtr<IInternalSessionControl> directControl;
+    {
+        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+        directControl = mData->mSession.mDirectControl;
+    }
+
+    /* ignore notifications sent after #OnSessionEnd() is called */
+    if (!directControl)
+        return S_OK;
+
+    return directControl->OnNATRedirectRuleChange(networkAdapter, aNatRuleRemove, aRuleName, aProto, aHostIp, aHostPort, aGuestIp, aGuestPort);
+}
+
+/**
+ *  @note Locks this object for reading.
+ */
 HRESULT SessionMachine::onSerialPortChange(ISerialPort *serialPort)
 {
Index: /trunk/src/VBox/Main/NATEngineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/NATEngineImpl.cpp	(revision 33824)
+++ /trunk/src/VBox/Main/NATEngineImpl.cpp	(revision 33825)
@@ -32,5 +32,5 @@
 ////////////////////////////////////////////////////////////////////////////////
 
-NATEngine::NATEngine():mParent(NULL){}
+NATEngine::NATEngine():mParent(NULL), mAdapter(NULL){}
 NATEngine::~NATEngine(){}
 
@@ -40,5 +40,5 @@
 }
 
-HRESULT NATEngine::init(Machine *aParent)
+HRESULT NATEngine::init(Machine *aParent, INetworkAdapter *aAdapter)
 {
     AutoInitSpan autoInitSpan(this);
@@ -50,8 +50,9 @@
     mData->mBindIP.setNull();
     unconst(mParent) = aParent;
-    return S_OK;
-}
-
-HRESULT NATEngine::init(Machine *aParent, NATEngine *aThat)
+    unconst(mAdapter) = aAdapter;
+    return S_OK;
+}
+
+HRESULT NATEngine::init(Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat)
 {
     AutoInitSpan autoInitSpan(this);
@@ -72,4 +73,5 @@
     }
     unconst(mParent) = aParent;
+    unconst(mAdapter) = aAdapter;
     unconst(mPeer) = aThat;
     autoInitSpan.setSucceeded();
@@ -77,5 +79,5 @@
 }
 
-HRESULT NATEngine::initCopy (Machine *aParent, NATEngine *aThat)
+HRESULT NATEngine::initCopy (Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat)
 {
     AutoInitSpan autoInitSpan(this);
@@ -96,4 +98,5 @@
         mNATRules.insert(std::make_pair(it->first, it->second));
     }
+    unconst(mAdapter) = aAdapter;
     unconst(mParent) = aParent;
     autoInitSpan.setSucceeded();
@@ -265,20 +268,18 @@
     Utf8Str name = aName;
     settings::NATRule r;
+    const char *proto;
+    switch (aProto)
+    {
+        case NATProtocol_TCP:
+            proto = "tcp";
+            break;
+        case NATProtocol_UDP:
+            proto = "udp";
+            break;
+        default:
+            return E_INVALIDARG;
+    }
     if (name.isEmpty())
-    {
-        const char *proto;
-        switch (aProto)
-        {
-            case NATProtocol_TCP:
-                proto = "tcp";
-                break;
-            case NATProtocol_UDP:
-                proto = "udp";
-                break;
-            default:
-                return E_INVALIDARG;
-        }
         name = Utf8StrFmt("%s_%d_%d", proto, aHostPort, aGuestPort);
-    }
     r.strName = name.c_str();
     r.u32Proto = aProto;
@@ -290,4 +291,6 @@
     mParent->setModified(Machine::IsModified_NetworkAdapters);
     m_fModified = true;
+    alock.release();
+    mParent->onNATRedirectRuleChange(mAdapter, FALSE, Bstr(name).raw(), aProto, Bstr(r.strHostIP).raw(), r.u16HostPort, Bstr(r.strGuestIP).raw(), r.u16GuestPort);
     return S_OK;
 }
@@ -300,12 +303,20 @@
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-    Utf8Str rule;
     NATRuleMap::iterator it = mNATRules.find(aName);
     if (it == mNATRules.end())
         return E_INVALIDARG;
     mData.backup();
+    settings::NATRule r = it->second;
+    Utf8Str strHostIP = r.strHostIP;
+    Utf8Str strGuestIP = r.strGuestIP;
+    NATProtocol_T proto = r.u32Proto;
+    uint16_t u16HostPort = r.u16HostPort;
+    uint16_t u16GuestPort = r.u16GuestPort;
+                                                    
     mNATRules.erase(it);
     mParent->setModified(Machine::IsModified_NetworkAdapters);
     m_fModified = true;
+    alock.release();
+    mParent->onNATRedirectRuleChange(mAdapter, TRUE, aName, proto, Bstr(strHostIP).raw(), u16HostPort, Bstr(strGuestIP).raw(), u16GuestPort);
     return S_OK;
 }
Index: /trunk/src/VBox/Main/NetworkAdapterImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/NetworkAdapterImpl.cpp	(revision 33824)
+++ /trunk/src/VBox/Main/NetworkAdapterImpl.cpp	(revision 33825)
@@ -75,5 +75,5 @@
     unconst(mParent) = aParent;
     unconst(mNATEngine).createObject();
-    mNATEngine->init(aParent);
+    mNATEngine->init(aParent, this);
     /* mPeer is left null */
 
@@ -125,5 +125,5 @@
     unconst(mPeer) = aThat;
     unconst(mNATEngine).createObject();
-    mNATEngine->init(aParent, aThat->mNATEngine);
+    mNATEngine->init(aParent, this, aThat->mNATEngine);
 
     AutoCaller thatCaller (aThat);
@@ -160,5 +160,5 @@
 
     unconst(mNATEngine).createObject();
-    mNATEngine->initCopy(aParent, aThat->mNATEngine);
+    mNATEngine->initCopy(aParent, this, aThat->mNATEngine);
 
     AutoCaller thatCaller (aThat);
Index: /trunk/src/VBox/Main/SessionImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/SessionImpl.cpp	(revision 33824)
+++ /trunk/src/VBox/Main/SessionImpl.cpp	(revision 33825)
@@ -524,4 +524,19 @@
 
     return mConsole->onNetworkAdapterChange(networkAdapter, changeAdapter);
+}
+
+STDMETHODIMP Session::OnNATRedirectRuleChange(INetworkAdapter *networkAdapter, BOOL aNatRuleRemove, IN_BSTR aRuleName, 
+                                 NATProtocol_T aProto, IN_BSTR aHostIp, LONG aHostPort, IN_BSTR aGuestIp, LONG aGuestPort)
+{
+    LogFlowThisFunc(("\n"));
+
+    AutoCaller autoCaller(this);
+    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+
+    return mConsole->onNATRedirectRuleChange(networkAdapter, aNatRuleRemove, aRuleName, aProto, aHostIp, aHostPort, aGuestIp, aGuestPort);
 }
 
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 33824)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 33825)
@@ -12695,4 +12695,27 @@
     </method>
 
+    <method name="onNATRedirectRuleChange">
+      <desc>
+        Triggered on adding/removing of NAT Engine redirection rule of the
+        associated virtual machine.
+
+        <result name="VBOX_E_INVALID_VM_STATE">
+          Session state prevents operation.
+        </result>
+        <result name="VBOX_E_INVALID_OBJECT_STATE">
+          Session type prevents operation.
+        </result>
+
+      </desc>
+      <param name="networkAdapter" type="INetworkAdapter" dir="in"/>
+      <param name="natRedirectRemove" type="boolean" dir="in"/>
+      <param name="natRuleName" type="wstring" dir="in"/>
+      <param name="natProto" type="NATProtocol" dir="in"/>
+      <param name="natHostIp" type="wstring" dir="in"/>
+      <param name="natHostPort" type="long" dir="in"/>
+      <param name="natGuestIp" type="wstring" dir="in"/>
+      <param name="natGuestPort" type="long" dir="in"/>
+    </method>
+
     <method name="onSerialPortChange">
       <desc>
Index: /trunk/src/VBox/Main/include/ConsoleImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 33824)
+++ /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 33825)
@@ -180,4 +180,7 @@
     // events from IInternalSessionControl
     HRESULT onNetworkAdapterChange(INetworkAdapter *aNetworkAdapter, BOOL changeAdapter);
+    HRESULT onNATRedirectRuleChange(INetworkAdapter *networkAdapter, BOOL aNatRuleRemove, IN_BSTR aRuleName, 
+                                 NATProtocol_T aProto, IN_BSTR aHostIp, LONG aHostPort, IN_BSTR aGuestIp, LONG aGuestPort);
+    HRESULT onNATEngineChange(INetworkAdapter *aNetworkAdapter, BOOL aNatReset);
     HRESULT onSerialPortChange(ISerialPort *aSerialPort);
     HRESULT onParallelPortChange(IParallelPort *aParallelPort);
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 33824)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 33825)
@@ -613,4 +613,6 @@
     // callback handlers
     virtual HRESULT onNetworkAdapterChange(INetworkAdapter * /* networkAdapter */, BOOL /* changeAdapter */) { return S_OK; }
+    virtual HRESULT onNATRedirectRuleChange(INetworkAdapter * /* networkAdapter */, BOOL /* Remove */, IN_BSTR /* Rule name */, 
+                                 NATProtocol_T /* proto */, IN_BSTR /* host ip */, LONG /* host port */, IN_BSTR /* guest ip */, LONG /* guest port */) { return S_OK; }
     virtual HRESULT onSerialPortChange(ISerialPort * /* serialPort */) { return S_OK; }
     virtual HRESULT onParallelPortChange(IParallelPort * /* parallelPort */) { return S_OK; }
@@ -954,4 +956,6 @@
 
     HRESULT onNetworkAdapterChange(INetworkAdapter *networkAdapter, BOOL changeAdapter);
+    HRESULT onNATRedirectRuleChange(INetworkAdapter *networkAdapter, BOOL aNatRuleRemove, IN_BSTR aRuleName, 
+                                 NATProtocol_T aProto, IN_BSTR aHostIp, LONG aHostPort, IN_BSTR aGuestIp, LONG aGuestPort);
     HRESULT onStorageControllerChange();
     HRESULT onMediumChange(IMediumAttachment *aMediumAttachment, BOOL aForce);
Index: /trunk/src/VBox/Main/include/NATEngineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/NATEngineImpl.h	(revision 33824)
+++ /trunk/src/VBox/Main/include/NATEngineImpl.h	(revision 33825)
@@ -82,7 +82,7 @@
 
     HRESULT FinalConstruct();
-    HRESULT init(Machine *aParent);
-    HRESULT init(Machine *aParent, NATEngine *aThat);
-    HRESULT initCopy(Machine *aParent, NATEngine *aThat);
+    HRESULT init(Machine *aParent, INetworkAdapter *aAdapter);
+    HRESULT init(Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat);
+    HRESULT initCopy(Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat);
     bool isModified();
     bool isReallyModified();
@@ -130,4 +130,5 @@
     Machine * const mParent;
     NATRuleMap mNATRules;
+    INetworkAdapter * const mAdapter;
 };
 #endif
Index: /trunk/src/VBox/Main/include/SessionImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/SessionImpl.h	(revision 33824)
+++ /trunk/src/VBox/Main/include/SessionImpl.h	(revision 33825)
@@ -85,4 +85,6 @@
     STDMETHOD(Uninitialize)();
     STDMETHOD(OnNetworkAdapterChange)(INetworkAdapter *networkAdapter, BOOL changeAdapter);
+    STDMETHOD(OnNATRedirectRuleChange)(INetworkAdapter *networkAdapter, BOOL aNatRuleRemove, IN_BSTR aRuleName, 
+                                 NATProtocol_T aProto, IN_BSTR aHostIp, LONG aHostPort, IN_BSTR aGuestIp, LONG aGuestPort);
     STDMETHOD(OnSerialPortChange)(ISerialPort *serialPort);
     STDMETHOD(OnParallelPortChange)(IParallelPort *parallelPort);
