Index: /trunk/src/VBox/NetworkServices/DHCP/Config.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/DHCP/Config.cpp	(revision 49734)
+++ /trunk/src/VBox/NetworkServices/DHCP/Config.cpp	(revision 49735)
@@ -6,4 +6,5 @@
 
 #include <iprt/asm.h>
+#include <iprt/getopt.h>
 #include <iprt/net.h>
 #include <iprt/time.h>
@@ -19,4 +20,6 @@
 #include <iprt/cpp/xml.h>
 
+#define BASE_SERVICES_ONLY
+#include "../NetLib/VBoxNetBaseService.h"
 #include "../NetLib/VBoxNetLib.h"
 #include "../NetLib/shared_ptr.h"
@@ -666,6 +669,4 @@
         cbBooPReplyMsg = 0;
         
-        m_pSession = NIL_RTR0PTR;
-        m_pIfBuf = NULL;
         m_OurAddress.u = 0;
         m_OurNetmask.u = 0;
@@ -679,12 +680,8 @@
     int cbBooPReplyMsg;
 
-    /* XXX: artifacts should be hidden or removed from here. */
-    PSUPDRVSESSION m_pSession;
-    INTNETIFHANDLE m_hIf;
-    PINTNETBUF m_pIfBuf;
-
     RTNETADDRIPV4 m_OurAddress;
     RTNETADDRIPV4 m_OurNetmask;
     RTMAC m_OurMac;
+    const VBoxNetHlpUDPService *m_service;
 };
 
@@ -748,20 +745,9 @@
 
 
-void NetworkManager::setSession(PSUPDRVSESSION aSession)
-{
-    m->m_pSession = aSession;
-}
-
-
-void NetworkManager::setInterface(INTNETIFHANDLE aIf)
-{
-    m->m_hIf = aIf;
-}
-
-
-void NetworkManager::setRingBuffer(PINTNETBUF aBuf)
-{
-    m->m_pIfBuf = aBuf;
-}
+void NetworkManager::setService(const VBoxNetHlpUDPService *srv)
+{
+    m->m_service = srv;
+}
+
 /**
  * Network manager creates DHCPOFFER datagramm
@@ -982,12 +968,8 @@
     else
 #endif
-        rc = VBoxNetUDPBroadcast(m->m_pSession,
-                                 m->m_hIf,
-                                 m->m_pIfBuf,
-                                 m->m_OurAddress,
-                                 &m->m_OurMac,
-                                 RTNETIPV4_PORT_BOOTPS,               /* sender */
-                                 RTNETIPV4_PORT_BOOTPC,
-                                 &m->BootPReplyMsg, RTNET_DHCP_NORMAL_SIZE);
+        rc = m->m_service->hlpUDPBroadcast(RTNETIPV4_PORT_BOOTPS,               /* sender */
+                                           RTNETIPV4_PORT_BOOTPC,
+                                           &m->BootPReplyMsg, 
+                                           RTNET_DHCP_NORMAL_SIZE);
 
     AssertRCReturn(rc,rc);
Index: /trunk/src/VBox/NetworkServices/DHCP/Config.h
===================================================================
--- /trunk/src/VBox/NetworkServices/DHCP/Config.h	(revision 49734)
+++ /trunk/src/VBox/NetworkServices/DHCP/Config.h	(revision 49735)
@@ -503,12 +503,10 @@
     void setOurMac(const RTMAC& aMac);
 
-    void setSession(PSUPDRVSESSION);
-    void setInterface(INTNETIFHANDLE);
-    void setRingBuffer(PINTNETBUF);
-
     bool handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb);
     bool handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb);
     bool handleDhcpReqDecline(PCRTNETBOOTP pDhcpMsg, size_t cb);
     bool handleDhcpReqRelease(PCRTNETBOOTP pDhcpMsg, size_t cb);
+
+    void setService(const VBoxNetHlpUDPService *);
 private:
     NetworkManager();
Index: /trunk/src/VBox/NetworkServices/DHCP/NetworkManagerDhcp.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/DHCP/NetworkManagerDhcp.cpp	(revision 49734)
+++ /trunk/src/VBox/NetworkServices/DHCP/NetworkManagerDhcp.cpp	(revision 49735)
@@ -21,4 +21,5 @@
 #include <iprt/asm.h>
 #include <iprt/cdefs.h>
+#include <iprt/getopt.h>
 #include <iprt/net.h>
 #include <iprt/param.h>
@@ -38,4 +39,6 @@
 #include <VBox/intnet.h>
 
+#define BASE_SERVICES_ONLY
+#include "../NetLib/VBoxNetBaseService.h"
 #include "Config.h"
 #include "ClientDataInt.h"
Index: /trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp	(revision 49734)
+++ /trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp	(revision 49735)
@@ -95,4 +95,8 @@
     void                usage(void) { /* XXX: document options */ };
     int                 parseOpt(int rc, const RTGETOPTUNION& getOptVal);
+    int                 processFrame(void *, size_t) {return VERR_IGNORED; };
+    int                 processGSO(PCPDMNETWORKGSO, size_t) {return VERR_IGNORED; };
+    int                 processUDP(void *, size_t);
+
 
 protected:
@@ -169,25 +173,23 @@
  * Construct a DHCP server with a default configuration.
  */
-VBoxNetDhcp::VBoxNetDhcp()
-{
-    m_Name                  = "VBoxNetDhcp";
-    m_Network               = "VBoxNetDhcp";
-    m_TrunkName             = "";
-    m_enmTrunkType          = kIntNetTrunkType_WhateverNone;
-    m_MacAddress.au8[0]     = 0x08;
-    m_MacAddress.au8[1]     = 0x00;
-    m_MacAddress.au8[2]     = 0x27;
-    m_MacAddress.au8[3]     = 0x40;
-    m_MacAddress.au8[4]     = 0x41;
-    m_MacAddress.au8[5]     = 0x42;
-    m_Ipv4Address.u         = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,  5)));
-
-    m_pSession              = NIL_RTR0PTR;
-    m_cbSendBuf             =  8192;
-    m_cbRecvBuf             = 51200; /** @todo tune to 64 KB with help from SrvIntR0 */
-    m_hIf                   = INTNET_HANDLE_INVALID;
-    m_pIfBuf                = NULL;
-
-    m_cVerbosity            = 0;
+VBoxNetDhcp::VBoxNetDhcp():VBoxNetBaseService("VBoxNetDhcp", "VBoxNetDhcp")
+{
+    /*   m_enmTrunkType          = kIntNetTrunkType_WhateverNone; */
+    RTMAC mac;
+    mac.au8[0]     = 0x08;
+    mac.au8[1]     = 0x00;
+    mac.au8[2]     = 0x27;
+    mac.au8[3]     = 0x40;
+    mac.au8[4]     = 0x41;
+    mac.au8[5]     = 0x42;
+    setMacAddress(mac);
+
+    RTNETADDRIPV4 address;
+    address.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,  5)));
+    setIpv4Address(address);
+
+    setSendBufSize(8 * _1K);
+    setRecvBufSize(50 * _1K);
+
     m_uCurMsgType           = UINT8_MAX;
     m_cbCurMsg              = 0;
@@ -198,25 +200,5 @@
 
     for(unsigned int i = 0; i < RT_ELEMENTS(g_aOptionDefs); ++i)
-        m_vecOptionDefs.push_back(&g_aOptionDefs[i]);
-
-#if 0 /* enable to hack the code without a mile long argument list. */
-    VBoxNetDhcpCfg *pDefCfg = new VBoxNetDhcpCfg();
-    pDefCfg->m_LowerAddr.u    = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,100)));
-    pDefCfg->m_UpperAddr.u    = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,250)));
-    pDefCfg->m_SubnetMask.u   = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8(255,255,255,  0)));
-    RTNETADDRIPV4 Addr;
-    Addr.u                    = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,  1)));
-    pDefCfg->m_Routers.push_back(Addr);
-    Addr.u                    = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10,  0,  2,  2)));
-    pDefCfg->m_DNSes.push_back(Addr);
-    pDefCfg->m_DomainName     = "vboxnetdhcp.org";
-# if 0
-    pDefCfg->m_cSecLease      = 60*60; /* 1 hour */
-# else
-    pDefCfg->m_cSecLease      = 30; /* sec */
-# endif
-    pDefCfg->m_TftpServer     = "10.0.2.3"; //??
-    this->addConfig(pDefCfg);
-#endif
+        addCommandLineOption(&g_aOptionDefs[i]);
 }
 
@@ -282,7 +264,8 @@
     NetworkManager *netManager = NetworkManager::getNetworkManager();
 
-    netManager->setOurAddress(m_Ipv4Address);
-    netManager->setOurNetmask(m_Ipv4Netmask);
-    netManager->setOurMac(m_MacAddress);
+    netManager->setOurAddress(getIpv4Address());
+    netManager->setOurNetmask(getIpv4Netmask());
+    netManager->setOurMac(getMacAddress());
+    netManager->setService(this);
     
     if (isMainNeeded())
@@ -304,75 +287,29 @@
 int VBoxNetDhcp::run(void)
 {
-
-    /* XXX: shortcut should be hidden from network manager */
-    NetworkManager *netManager = NetworkManager::getNetworkManager();
-    netManager->setSession(m_pSession);
-    netManager->setInterface(m_hIf);
-    netManager->setRingBuffer(m_pIfBuf);
-
-    /*
-     * The loop.
-     */
-    PINTNETRINGBUF  pRingBuf = &m_pIfBuf->Recv;
-    for (;;)
-    {
-        /*
-         * Wait for a packet to become available.
-         */
-        INTNETIFWAITREQ WaitReq;
-        WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
-        WaitReq.Hdr.cbReq = sizeof(WaitReq);
-        WaitReq.pSession = m_pSession;
-        WaitReq.hIf = m_hIf;
-        WaitReq.cMillies = 2000; /* 2 secs - the sleep is for some reason uninterruptible... */  /** @todo fix interruptability in SrvIntNet! */
-        int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
-        if (RT_FAILURE(rc))
-        {
-            if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
-                continue;
-            RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: VMMR0_DO_INTNET_IF_WAIT returned %Rrc\n", rc);
-            return 1;
-        }
-
-        /*
-         * Process the receive buffer.
-         */
-        while (IntNetRingHasMoreToRead(pRingBuf))
-        {
-            size_t  cb;
-            void   *pv = VBoxNetUDPMatch(m_pIfBuf, RTNETIPV4_PORT_BOOTPS, &m_MacAddress,
-                                         VBOXNETUDP_MATCH_UNICAST | VBOXNETUDP_MATCH_BROADCAST | VBOXNETUDP_MATCH_CHECKSUM
-                                         | (m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0),
-                                         &m_CurHdrs, &cb);
-            if (pv && cb)
-            {
-                PCRTNETBOOTP pDhcpMsg = (PCRTNETBOOTP)pv;
-                m_pCurMsg  = pDhcpMsg;
-                m_cbCurMsg = cb;
-
-                uint8_t uMsgType;
-                if (RTNetIPv4IsDHCPValid(NULL /* why is this here? */, pDhcpMsg, cb, &uMsgType))
-                {
-                    m_uCurMsgType = uMsgType;
-                    handleDhcpMsg(uMsgType, pDhcpMsg, cb);
-                    m_uCurMsgType = UINT8_MAX;
-                }
-                else
-                    debugPrint(1, true, "VBoxNetDHCP: Skipping invalid DHCP packet.\n"); /** @todo handle pure bootp clients too? */
-
-                m_pCurMsg = NULL;
-                m_cbCurMsg = 0;
-            }
-            else if (VBoxNetArpHandleIt(m_pSession, m_hIf, m_pIfBuf, &m_MacAddress, m_Ipv4Address))
-            {
-                /* nothing */
-            }
-
-            /* Advance to the next frame. */
-            IntNetRingSkipFrame(pRingBuf);
-        }
-    }
-
+    doReceiveLoop();
     return 0;
+}
+
+
+int  VBoxNetDhcp::processUDP(void *pv, size_t cbPv)
+{
+    PCRTNETBOOTP pDhcpMsg = (PCRTNETBOOTP)pv;
+    m_pCurMsg  = pDhcpMsg;
+    m_cbCurMsg = cbPv;
+
+    uint8_t uMsgType;
+    if (RTNetIPv4IsDHCPValid(NULL /* why is this here? */, pDhcpMsg, cbPv, &uMsgType))
+    {
+        m_uCurMsgType = uMsgType;
+        handleDhcpMsg(uMsgType, pDhcpMsg, cbPv);
+        m_uCurMsgType = UINT8_MAX;
+    }
+    else
+        debugPrint(1, true, "VBoxNetDHCP: Skipping invalid DHCP packet.\n"); /** @todo handle pure bootp clients too? */
+
+    m_pCurMsg = NULL;
+    m_cbCurMsg = 0;
+
+    return VINF_SUCCESS;
 }
 
@@ -495,7 +432,8 @@
     CmdParameterIterator it;
 
+    RTNETADDRIPV4 address = getIpv4Address();
+    RTNETADDRIPV4 netmask = getIpv4Netmask();
     RTNETADDRIPV4 networkId;
-    networkId.u = m_Ipv4Address.u & m_Ipv4Netmask.u;
-    RTNETADDRIPV4 netmask = m_Ipv4Netmask;
+    networkId.u = address.u & netmask.u;
 
     RTNETADDRIPV4 UpperAddress;
@@ -524,5 +462,5 @@
     confManager->addNetwork(unconst(g_RootConfig),
                             networkId,
-                            m_Ipv4Netmask,
+                            netmask,
                             LowerAddress,
                             UpperAddress);
@@ -538,10 +476,11 @@
      */
     AssertRCReturn(virtualbox.isNull(), VERR_INTERNAL_ERROR);
-
-    HRESULT hrc = virtualbox->FindDHCPServerByNetworkName(com::Bstr(m_Network.c_str()).raw(),
-                                                  m_DhcpServer.asOutParam());
+    std::string networkName = getNetwork();
+
+    HRESULT hrc = virtualbox->FindDHCPServerByNetworkName(com::Bstr(networkName.c_str()).raw(),
+                                                          m_DhcpServer.asOutParam());
     AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
 
-    hrc = virtualbox->FindNATNetworkByName(com::Bstr(m_Network.c_str()).raw(),
+    hrc = virtualbox->FindNATNetworkByName(com::Bstr(networkName.c_str()).raw(),
                                            m_NATNetwork.asOutParam());
 
@@ -602,4 +541,7 @@
     }
 
+
+    RTNETADDRIPV4 address = getIpv4Address();
+    RTNETADDRIPV4 netmask = getIpv4Netmask();
     strs.setNull();
     ComPtr<IHost> host;
@@ -621,5 +563,5 @@
                         if (MapIp4Addr2Off[addr] != 0)
                         {
-                            addr.u = RT_H2N_U32(RT_N2H_U32(m_Ipv4Address.u & m_Ipv4Netmask.u)
+                            addr.u = RT_H2N_U32(RT_N2H_U32(address.u & netmask.u)
                                                 + MapIp4Addr2Off[addr]);
                         }
@@ -661,10 +603,10 @@
 
     RTNETADDRIPV4 networkId;
-    networkId.u = m_Ipv4Address.u & m_Ipv4Netmask.u;
+    networkId.u = address.u & netmask.u;
     std::string name = std::string("default");
 
     confManager->addNetwork(unconst(g_RootConfig),
                             networkId,
-                            m_Ipv4Netmask,
+                            netmask,
                             LowerAddress,
                             UpperAddress);
@@ -673,5 +615,5 @@
     hrc = virtualbox->COMGETTER(HomeFolder)(bstr.asOutParam());
     std::string strXmlLeaseFile(com::Utf8StrFmt("%ls%c%s.leases",
-                                                bstr.raw(), RTPATH_DELIMITER, m_Network.c_str()).c_str());
+                                                bstr.raw(), RTPATH_DELIMITER, networkName.c_str()).c_str());
     confManager->loadFromFile(strXmlLeaseFile);
 
Index: /trunk/src/VBox/NetworkServices/NAT/Makefile.kmk
===================================================================
--- /trunk/src/VBox/NetworkServices/NAT/Makefile.kmk	(revision 49734)
+++ /trunk/src/VBox/NetworkServices/NAT/Makefile.kmk	(revision 49735)
@@ -45,5 +45,9 @@
 VBoxNetLwipNAT_SOURCES += VBoxNetLwipNAT.cpp	\
 	../NetLib/VBoxNetBaseService.cpp \
-	../NetLib/VBoxNetPortForwardString.cpp
+	../NetLib/VBoxNetPortForwardString.cpp \
+	../NetLib/VBoxNetIntIf.cpp \
+	../NetLib/VBoxNetUDP.cpp \
+	../NetLib/VBoxNetARP.cpp
+
 VBoxNetLwipNAT_LIBS = \
 	$(LIB_RUNTIME)
Index: /trunk/src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp	(revision 49734)
+++ /trunk/src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp	(revision 49735)
@@ -164,4 +164,8 @@
     /* VBoxNetNAT always needs Main */
     virtual bool isMainNeeded() const { return true; }
+    virtual int processFrame(void *, size_t);
+    virtual int processGSO(PCPDMNETWORKGSO, size_t);
+    virtual int processUDP(void *, size_t) { return VERR_IGNORED; }
+
    private:
     struct proxy_options m_ProxyOptions;
@@ -187,4 +191,5 @@
     ComPtr<IHost> m_host;
     ComObjPtr<NATNetworkListenerImpl> m_vboxListener;
+    static INTNETSEG aXmitSeg[64];
 
     STDMETHOD(HandleEvent)(VBoxEventType_T aEventType, IEvent *pEvent);
@@ -202,5 +207,4 @@
     static err_t netifLinkoutput(netif *pNetif, pbuf *pBuf);
     static int intNetThreadRecv(RTTHREAD, void *);
-    static void vboxNetLwipNATProcessXmit(void);
 
     VECNATSERVICEPF m_vecPortForwardRule4;
@@ -213,4 +217,5 @@
 
 static VBoxNetLwipNAT *g_pLwipNat;
+INTNETSEG VBoxNetLwipNAT::aXmitSeg[64];
 
 STDMETHODIMP NATNetworkListener::HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent)
@@ -411,12 +416,14 @@
 
     /* lwip thread */
-    RTNETADDRIPV4 IpNetwork;
-    IpNetwork.u = g_pLwipNat->m_Ipv4Address.u & g_pLwipNat->m_Ipv4Netmask.u;
+    RTNETADDRIPV4 network;
+    RTNETADDRIPV4 address = g_pLwipNat->getIpv4Address();
+    RTNETADDRIPV4 netmask = g_pLwipNat->getIpv4Netmask();
+    network.u = address.u & netmask.u;
 
     ip_addr LwipIpAddr, LwipIpNetMask, LwipIpNetwork;
 
-    memcpy(&LwipIpAddr, &g_pLwipNat->m_Ipv4Address, sizeof(ip_addr));
-    memcpy(&LwipIpNetMask, &g_pLwipNat->m_Ipv4Netmask, sizeof(ip_addr));
-    memcpy(&LwipIpNetwork, &IpNetwork, sizeof(ip_addr));
+    memcpy(&LwipIpAddr, &address, sizeof(ip_addr));
+    memcpy(&LwipIpNetMask, &netmask, sizeof(ip_addr));
+    memcpy(&LwipIpNetwork, &network, sizeof(ip_addr));
 
     netif *pNetif = netif_add(&g_pLwipNat->m_LwipNetIf /* Lwip Interface */,
@@ -504,5 +511,6 @@
 
     pNetif->hwaddr_len = sizeof(RTMAC);
-    memcpy(pNetif->hwaddr, &pNat->m_MacAddress, sizeof(RTMAC));
+    RTMAC mac = g_pLwipNat->getMacAddress();
+    memcpy(pNetif->hwaddr, &mac, sizeof(RTMAC));
 
     pNat->m_u16Mtu = 1500; // XXX: FIXME
@@ -561,111 +569,5 @@
         return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to initialize COM!");
 
-    /* Well we're ready */
-    PINTNETRINGBUF  pRingBuf = &g_pLwipNat->m_pIfBuf->Recv;
-
-    for (;;)
-    {
-        /*
-         * Wait for a packet to become available.
-         */
-        /* 2. waiting for request for */
-        rc = g_pLwipNat->waitForIntNetEvent(2000);
-        if (RT_FAILURE(rc))
-        {
-            if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
-            {
-                /* do we want interrupt anyone ??? */
-                continue;
-            }
-            LogRel(("VBoxNetNAT: waitForIntNetEvent returned %Rrc\n", rc));
-            AssertRCReturn(rc,ERR_IF);
-        }
-
-        /*
-         * Process the receive buffer.
-         */
-        PCINTNETHDR pHdr;
-
-        while ((pHdr = IntNetRingGetNextFrameToRead(pRingBuf)) != NULL)
-        {
-            uint8_t const u8Type = pHdr->u8Type;
-            size_t         cbFrame = pHdr->cbFrame;
-            uint8_t        *pu8Frame = NULL;
-            pbuf           *pPbufHdr = NULL;
-            pbuf           *pPbuf = NULL;
-            switch (u8Type)
-            {
-
-                case INTNETHDR_TYPE_FRAME:
-                    /* @todo:should it be really here?
-                     * Well well well, we're accessing lwip code here
-                     */
-                    pPbufHdr = pPbuf = pbuf_alloc(PBUF_RAW, pHdr->cbFrame, PBUF_POOL);
-                    if (!pPbuf)
-                    {
-                        LogRel(("NAT: Can't allocate send buffer cbFrame=%u\n", cbFrame));
-                        break;
-                    }
-                    Assert(pPbufHdr->tot_len == cbFrame);
-                    pu8Frame = (uint8_t *)IntNetHdrGetFramePtr(pHdr, g_pLwipNat->m_pIfBuf);
-                    while(pPbuf)
-                    {
-                        memcpy(pPbuf->payload, pu8Frame, pPbuf->len);
-                        pu8Frame += pPbuf->len;
-                        pPbuf = pPbuf->next;
-                    }
-
-                    g_pLwipNat->m_LwipNetIf.input(pPbufHdr, &g_pLwipNat->m_LwipNetIf);
-
-                    AssertReleaseRC(rc);
-                    break;
-                case INTNETHDR_TYPE_GSO:
-                  {
-                      PCPDMNETWORKGSO pGso = IntNetHdrGetGsoContext(pHdr,
-                                                                    g_pLwipNat->m_pIfBuf);
-                      if (!PDMNetGsoIsValid(pGso, cbFrame,
-                                            cbFrame - sizeof(PDMNETWORKGSO)))
-                          break;
-                      cbFrame -= sizeof(PDMNETWORKGSO);
-                      uint8_t         abHdrScratch[256];
-                      uint32_t const  cSegs = PDMNetGsoCalcSegmentCount(pGso,
-                                                                        cbFrame);
-                      for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
-                      {
-                          uint32_t cbSegFrame;
-                          void    *pvSegFrame =
-                            PDMNetGsoCarveSegmentQD(pGso,
-                                                    (uint8_t *)(pGso + 1),
-                                                    cbFrame,
-                                                    abHdrScratch,
-                                                    iSeg,
-                                                    cSegs,
-                                                    &cbSegFrame);
-
-                          pPbuf = pbuf_alloc(PBUF_RAW, cbSegFrame, PBUF_POOL);
-                          if (!pPbuf)
-                          {
-                              LogRel(("NAT: Can't allocate send buffer cbFrame=%u\n", cbSegFrame));
-                              break;
-                          }
-                          Assert(   !pPbuf->next
-                                 && pPbuf->len == cbSegFrame);
-                          memcpy(pPbuf->payload, pvSegFrame, cbSegFrame);
-                          g_pLwipNat->m_LwipNetIf.input(pPbuf, &g_pLwipNat->m_LwipNetIf);
-
-                      }
-
-                  }
-                  break;
-                case INTNETHDR_TYPE_PADDING:
-                    break;
-                default:
-                    STAM_REL_COUNTER_INC(&g_pLwipNat->m_pIfBuf->cStatBadFrames);
-                    break;
-            }
-            IntNetRingSkipFrame(&g_pLwipNat->m_pIfBuf->Recv);
-
-        } /* loop */
-    }
+    g_pLwipNat->doReceiveLoop();
     /* 3. deinitilization and termination */
     LogFlowFuncLeaveRC(rc);
@@ -674,27 +576,10 @@
 
 
-/**
- *
- */
-void VBoxNetLwipNAT::vboxNetLwipNATProcessXmit()
-{
-    int rc = VINF_SUCCESS;
-    INTNETIFSENDREQ SendReq;
-    SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
-    SendReq.Hdr.cbReq    = sizeof(SendReq);
-    SendReq.pSession     = g_pLwipNat->m_pSession;
-    SendReq.hIf          = g_pLwipNat->m_hIf;
-    rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
-    AssertRC(rc);
-}
-
-
 err_t VBoxNetLwipNAT::netifLinkoutput(netif *pNetif, pbuf *pPBuf)
 {
-    int rc = VINF_SUCCESS;
-    err_t rcLwip = ERR_OK;
     AssertPtrReturn(pNetif, ERR_ARG);
     AssertPtrReturn(pPBuf, ERR_ARG);
     AssertReturn((void *)g_pLwipNat == pNetif->state, ERR_ARG);
+
     LogFlowFunc(("ENTER: pNetif[%c%c%d], pPbuf:%p\n",
                  pNetif->name[0],
@@ -703,64 +588,27 @@
                  pPBuf));
 
-    /*
-     * We're on the lwip thread ...
-     * try accure Xmit lock (actually we DO accure the lock ... )
-     * 1. we've entered csXmit so we should create frame
-     *   1.a. Frame creation success see 2.
-     *   1.b. (hm ... what about queue processing in place)
-     *   1.c. 2nd attempt create frame
-     *   1.d. Unlock the Xmit
-     *   1.e. goto BUSY.1
-     * 2. Copy pbuf to the frame
-     * 3. Send
-     * 4. leave csXmit & return.
-     *
-     * @todo: perhaps we can use it for optimization,
-     * e.g. drop UDP and reoccure lock on TCP NOTE: now BUSY is unachievable!
-     * Otherwise (BUSY)
-     * 1. Unbuffered (drop)
-     * (buffered)
-     * 1. Copy pbuf to entermediate buffer.
-     * 2. Add call buffer to the queue
-     * 3. return.
-     */
-    /* see p.1 */
-    rc = VINF_SUCCESS;
-    PINTNETHDR pHdr = NULL;
-    uint8_t *pu8Frame = NULL;
-    int offFrame = 0;
-    int idxSg = 0;
-    struct pbuf *pPBufPtr = pPBuf;
-    /* Allocate frame, and pad it if required. */
-    rc = IntNetRingAllocateFrame(&g_pLwipNat->m_pIfBuf->Send, pPBuf->tot_len, &pHdr, (void **)&pu8Frame);
-    if (RT_SUCCESS(rc))
-    {
-        /* see p. 2 */
-        while (pPBufPtr)
-        {
-            memcpy(&pu8Frame[offFrame], pPBufPtr->payload, pPBufPtr->len);
-            offFrame += pPBufPtr->len;
-            pPBufPtr = pPBufPtr->next;
-        }
-    }
-    if (RT_FAILURE(rc))
-    {
-        /* Could it be that some frames are still in the ring buffer */
-        /* 1.c */
-        AssertMsgFailed(("Debug Me!"));
-    }
-
-    /* Commit - what really this function do  */
-    IntNetRingCommitFrameEx(&g_pLwipNat->m_pIfBuf->Send, pHdr, pPBuf->tot_len);
-
-    g_pLwipNat->vboxNetLwipNATProcessXmit();
-
+    RT_ZERO(VBoxNetLwipNAT::aXmitSeg);
+    
+    unsigned idx = 0;
+    for( struct pbuf *pPBufPtr = pPBuf;
+         pPBufPtr;
+         pPBufPtr = pPBufPtr->next, ++idx) 
+    {
+        AssertReturn(idx < RT_ELEMENTS(VBoxNetLwipNAT::aXmitSeg), ERR_MEM);
+        VBoxNetLwipNAT::aXmitSeg[idx].pv = pPBufPtr->payload; 
+        VBoxNetLwipNAT::aXmitSeg[idx].cb = pPBufPtr->len;
+    }
+
+    int rc = g_pLwipNat->sendBufferOnWire(VBoxNetLwipNAT::aXmitSeg, idx, pPBuf->tot_len);
     AssertRCReturn(rc, ERR_IF);
-    LogFlowFunc(("LEAVE: %d\n", rcLwip));
-    return rcLwip;
-}
-
-
-VBoxNetLwipNAT::VBoxNetLwipNAT(SOCKET icmpsock4, SOCKET icmpsock6)
+
+    g_pLwipNat->flushWire();
+
+    LogFlowFunc(("LEAVE: %d\n", ERR_OK));
+    return ERR_OK;
+}
+
+
+VBoxNetLwipNAT::VBoxNetLwipNAT(SOCKET icmpsock4, SOCKET icmpsock6) : VBoxNetBaseService("VBoxNetNAT", "nat-network")
 {
     LogFlowFuncEnter();
@@ -785,19 +633,25 @@
     m_LwipNetIf.name[0] = 'N';
     m_LwipNetIf.name[1] = 'T';
-    m_MacAddress.au8[0] = 0x52;
-    m_MacAddress.au8[1] = 0x54;
-    m_MacAddress.au8[2] = 0;
-    m_MacAddress.au8[3] = 0x12;
-    m_MacAddress.au8[4] = 0x35;
-    m_MacAddress.au8[5] = 0;
-    m_Ipv4Address.u     = RT_MAKE_U32_FROM_U8( 10,  0,  2,  2); // NB: big-endian
-    m_Ipv4Netmask.u     = RT_H2N_U32_C(0xffffff00);
+
+    RTMAC mac;
+    mac.au8[0] = 0x52;
+    mac.au8[1] = 0x54;
+    mac.au8[2] = 0;
+    mac.au8[3] = 0x12;
+    mac.au8[4] = 0x35;
+    mac.au8[5] = 0;
+    setMacAddress(mac);
+
+    RTNETADDRIPV4 address;
+    address.u     = RT_MAKE_U32_FROM_U8( 10,  0,  2,  2); // NB: big-endian
+    setIpv4Address(address);
+    
+    address.u     = RT_H2N_U32_C(0xffffff00);
+    setIpv4Netmask(address);
 
     fDontLoadRulesOnStartup = false;
 
     for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i)
-        m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
-
-    m_enmTrunkType = kIntNetTrunkType_SrvNat;
+        addCommandLineOption(&g_aGetOptDef[i]);
 
     LogFlowFuncLeave();
@@ -898,5 +752,6 @@
     AssertRCReturn(rc, rc);
 
-    hrc = virtualbox->FindNATNetworkByName(com::Bstr(m_Network.c_str()).raw(),
+    std::string networkName = getNetwork();
+    hrc = virtualbox->FindNATNetworkByName(com::Bstr(networkName.c_str()).raw(),
                                                   m_net.asOutParam());
     AssertComRCReturn(hrc, VERR_NOT_FOUND);
@@ -955,5 +810,5 @@
 
 
-    com::Bstr bstrSourceIp4Key = com::BstrFmt("NAT/%s/SourceIp4",m_Network.c_str());
+    com::Bstr bstrSourceIp4Key = com::BstrFmt("NAT/%s/SourceIp4", networkName.c_str());
     com::Bstr bstrSourceIpX;
     hrc = virtualbox->GetExtraData(bstrSourceIp4Key.raw(), bstrSourceIpX.asOutParam());
@@ -1169,4 +1024,63 @@
     }
     return VERR_NOT_FOUND;
+}
+
+
+int VBoxNetLwipNAT::processFrame(void *pvFrame, size_t cbFrame)
+{
+    AssertReturn(pvFrame && cbFrame, VERR_INVALID_PARAMETER);
+
+    struct  pbuf *pPbufHdr, *pPbuf;
+    pPbufHdr = pPbuf = pbuf_alloc(PBUF_RAW, cbFrame, PBUF_POOL);
+
+    AssertMsgReturn(pPbuf, ("NAT: Can't allocate send buffer cbFrame=%u\n", cbFrame), VERR_INTERNAL_ERROR);
+    AssertReturn(pPbufHdr->tot_len == cbFrame, VERR_INTERNAL_ERROR);
+                    
+    uint8_t *pu8Frame = (uint8_t *)pvFrame;
+    while(pPbuf)
+    {
+        memcpy(pPbuf->payload, pu8Frame, pPbuf->len);
+        pu8Frame += pPbuf->len;
+        pPbuf = pPbuf->next;
+    }
+
+    m_LwipNetIf.input(pPbufHdr, &m_LwipNetIf);
+    
+    return VINF_SUCCESS;
+}
+
+
+int VBoxNetLwipNAT::processGSO(PCPDMNETWORKGSO pGso, size_t cbFrame)
+{
+    if (!PDMNetGsoIsValid(pGso, cbFrame,
+                          cbFrame - sizeof(PDMNETWORKGSO)))
+        return VERR_INVALID_PARAMETER;
+    
+    cbFrame -= sizeof(PDMNETWORKGSO);
+    uint8_t         abHdrScratch[256];
+    uint32_t const  cSegs = PDMNetGsoCalcSegmentCount(pGso,
+                                                      cbFrame);
+    for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
+    {
+        uint32_t cbSegFrame;
+        void    *pvSegFrame =
+          PDMNetGsoCarveSegmentQD(pGso,
+                                  (uint8_t *)(pGso + 1),
+                                  cbFrame,
+                                  abHdrScratch,
+                                  iSeg,
+                                  cSegs,
+                                  &cbSegFrame);
+
+        struct pbuf *pPbuf = pbuf_alloc(PBUF_RAW, cbSegFrame, PBUF_POOL);
+
+        AssertMsgReturn(pPbuf, ("NAT: Can't allocate send buffer cbFrame=%u\n", cbSegFrame), VERR_INTERNAL_ERROR);
+        AssertReturn(!pPbuf->next && pPbuf->len == cbSegFrame, VERR_INTERNAL_ERROR);
+
+        memcpy(pPbuf->payload, pvSegFrame, cbSegFrame);
+        m_LwipNetIf.input(pPbuf, &g_pLwipNat->m_LwipNetIf);
+    }
+
+    return VINF_SUCCESS;
 }
 
Index: /trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp	(revision 49734)
+++ /trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp	(revision 49735)
@@ -71,4 +71,47 @@
 *   Structures and Typedefs                                                    *
 *******************************************************************************/
+struct VBoxNetBaseService::Data
+{
+    Data(const std::string& aName, const std::string& aNetworkName):
+      m_Name(aName),
+      m_Network(aNetworkName),
+      m_enmTrunkType(kIntNetTrunkType_WhateverNone),
+      m_pSession(NIL_RTR0PTR),
+      m_cbSendBuf(128 * _1K),
+      m_cbRecvBuf(256 * _1K),
+      m_hIf(INTNET_HANDLE_INVALID),
+      m_pIfBuf(NULL),
+      m_cVerbosity(0),
+      m_fNeedMain(false)
+    {
+        int rc = RTCritSectInit(&m_csThis);
+        AssertRC(rc);
+    };
+
+    std::string         m_Name;
+    std::string         m_Network;
+    std::string         m_TrunkName;
+    INTNETTRUNKTYPE     m_enmTrunkType;
+
+    RTMAC               m_MacAddress;
+    RTNETADDRIPV4       m_Ipv4Address;
+    RTNETADDRIPV4       m_Ipv4Netmask;
+
+    PSUPDRVSESSION      m_pSession;
+    uint32_t            m_cbSendBuf;
+    uint32_t            m_cbRecvBuf;
+    INTNETIFHANDLE      m_hIf;          /**< The handle to the network interface. */
+    PINTNETBUF          m_pIfBuf;       /**< Interface buffer. */
+
+    std::vector<PRTGETOPTDEF> m_vecOptionDefs;
+
+    int32_t             m_cVerbosity;
+
+    /* cs for syncing */
+    RTCRITSECT          m_csThis;
+
+    /* Controls whether service will connect SVC for runtime needs */
+    bool                m_fNeedMain;
+};
 
 /*******************************************************************************
@@ -90,21 +133,10 @@
 
 
-VBoxNetBaseService::VBoxNetBaseService()
-{
-    int rc = RTCritSectInit(&m_csThis);
-    AssertRC(rc);
-    /* numbers from DrvIntNet */
-    m_cbSendBuf             = 128 * _1K;
-    m_cbRecvBuf             = 256 * _1K;
-    m_hIf                   = INTNET_HANDLE_INVALID;
-    m_pIfBuf                = NULL;
-
-    m_cVerbosity            = 0;
-    m_Name                  = "VBoxNetNAT";
-    m_Network               = "intnet";
-    m_fNeedMain             = false;
+VBoxNetBaseService::VBoxNetBaseService(const std::string& aName, const std::string& aNetworkName):m(NULL)
+{
+    m = new VBoxNetBaseService::Data(aName, aNetworkName);
 
     for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i)
-        m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
+        m->m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
 }
 
@@ -115,22 +147,29 @@
      * Close the interface connection.
      */
-    if (m_hIf != INTNET_HANDLE_INVALID)
-    {
-        INTNETIFCLOSEREQ CloseReq;
-        CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
-        CloseReq.Hdr.cbReq = sizeof(CloseReq);
-        CloseReq.pSession = m_pSession;
-        CloseReq.hIf = m_hIf;
-        m_hIf = INTNET_HANDLE_INVALID;
-        int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_RTCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
-        AssertRC(rc);
-    }
-
-    if (m_pSession)
-    {
-        SUPR3Term(false /*fForced*/);
-        m_pSession = NIL_RTR0PTR;
-    }
-    RTCritSectDelete(&m_csThis);
+    if (m != NULL) 
+    {
+        if (m->m_hIf != INTNET_HANDLE_INVALID)
+        {
+            INTNETIFCLOSEREQ CloseReq;
+            CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+            CloseReq.Hdr.cbReq = sizeof(CloseReq);
+            CloseReq.pSession = m->m_pSession;
+            CloseReq.hIf = m->m_hIf;
+            m->m_hIf = INTNET_HANDLE_INVALID;
+            int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_RTCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
+            AssertRC(rc);
+        }
+
+        if (m->m_pSession != NIL_RTR0PTR)
+        {
+            SUPR3Term(false /*fForced*/);
+            m->m_pSession = NIL_RTR0PTR;
+        }
+
+        RTCritSectDelete(&m->m_csThis);
+        
+        delete m;
+        m = NULL;
+    }       
 }
 
@@ -150,4 +189,9 @@
 }
 
+
+bool VBoxNetBaseService::isMainNeeded() const
+{
+    return m->m_fNeedMain;
+}
 
 /**
@@ -164,5 +208,5 @@
     RTGETOPTSTATE State;
     PRTGETOPTDEF paOptionArray = getOptionsPtr();
-    int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m_vecOptionDefs.size(), 0, 0 /*fFlags*/);
+    int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m->m_vecOptionDefs.size(), 0, 0 /*fFlags*/);
     AssertRCReturn(rc, 49);
 #if 0
@@ -181,26 +225,26 @@
         {
             case 'N': // --name
-                m_Name = Val.psz;
+                m->m_Name = Val.psz;
                 break;
 
             case 'n': // --network
-                m_Network = Val.psz;
+                m->m_Network = Val.psz;
                 break;
 
             case 't': //--trunk-name
-                m_TrunkName = Val.psz;
+                m->m_TrunkName = Val.psz;
                 break;
 
             case 'T': //--trunk-type
                 if (!strcmp(Val.psz, "none"))
-                    m_enmTrunkType = kIntNetTrunkType_None;
+                    m->m_enmTrunkType = kIntNetTrunkType_None;
                 else if (!strcmp(Val.psz, "whatever"))
-                    m_enmTrunkType = kIntNetTrunkType_WhateverNone;
+                    m->m_enmTrunkType = kIntNetTrunkType_WhateverNone;
                 else if (!strcmp(Val.psz, "netflt"))
-                    m_enmTrunkType = kIntNetTrunkType_NetFlt;
+                    m->m_enmTrunkType = kIntNetTrunkType_NetFlt;
                 else if (!strcmp(Val.psz, "netadp"))
-                    m_enmTrunkType = kIntNetTrunkType_NetAdp;
+                    m->m_enmTrunkType = kIntNetTrunkType_NetAdp;
                 else if (!strcmp(Val.psz, "srvnat"))
-                    m_enmTrunkType = kIntNetTrunkType_SrvNat;
+                    m->m_enmTrunkType = kIntNetTrunkType_SrvNat;
                 else
                 {
@@ -211,17 +255,17 @@
 
             case 'a': // --mac-address
-                m_MacAddress = Val.MacAddr;
+                m->m_MacAddress = Val.MacAddr;
                 break;
 
             case 'i': // --ip-address
-                m_Ipv4Address = Val.IPv4Addr;
+                m->m_Ipv4Address = Val.IPv4Addr;
                 break;
 
             case 'm': // --netmask 
-                m_Ipv4Netmask = Val.IPv4Addr;
+                m->m_Ipv4Netmask = Val.IPv4Addr;
                 break;
 
             case 'v': // --verbose
-                m_cVerbosity++;
+                m->m_cVerbosity++;
                 break;
 
@@ -231,5 +275,5 @@
 
             case 'M': // --need-main
-                m_fNeedMain = true;
+                m->m_fNeedMain = true;
                 break;
 
@@ -246,6 +290,6 @@
                          RTBldCfgRevision(),
                          RTProcShortName());
-                for (unsigned int i = 0; i < m_vecOptionDefs.size(); i++)
-                    RTPrintf("    -%c, %s\n", m_vecOptionDefs[i]->iShort, m_vecOptionDefs[i]->pszLong);
+                for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); i++)
+                    RTPrintf("    -%c, %s\n", m->m_vecOptionDefs[i]->iShort, m->m_vecOptionDefs[i]->pszLong);
                 usage(); /* to print Service Specific usage */
                 return 1;
@@ -272,8 +316,8 @@
      * Open the session, load ring-0 and issue the request.
      */
-    int rc = SUPR3Init(&m_pSession);
+    int rc = SUPR3Init(&m->m_pSession);
     if (RT_FAILURE(rc))
     {
-        m_pSession = NIL_RTR0PTR;
+        m->m_pSession = NIL_RTR0PTR;
         LogRel(("VBoxNetBaseService: SUPR3Init -> %Rrc\n", rc));
         return rc;
@@ -302,13 +346,13 @@
     OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     OpenReq.Hdr.cbReq = sizeof(OpenReq);
-    OpenReq.pSession = m_pSession;
-    strncpy(OpenReq.szNetwork, m_Network.c_str(), sizeof(OpenReq.szNetwork));
+    OpenReq.pSession = m->m_pSession;
+    strncpy(OpenReq.szNetwork, m->m_Network.c_str(), sizeof(OpenReq.szNetwork));
     OpenReq.szNetwork[sizeof(OpenReq.szNetwork) - 1] = '\0';
-    strncpy(OpenReq.szTrunk, m_TrunkName.c_str(), sizeof(OpenReq.szTrunk));
+    strncpy(OpenReq.szTrunk, m->m_TrunkName.c_str(), sizeof(OpenReq.szTrunk));
     OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0';
-    OpenReq.enmTrunkType = m_enmTrunkType;
+    OpenReq.enmTrunkType = m->m_enmTrunkType;
     OpenReq.fFlags = 0; /** @todo check this */
-    OpenReq.cbSend = m_cbSendBuf;
-    OpenReq.cbRecv = m_cbRecvBuf;
+    OpenReq.cbSend = m->m_cbSendBuf;
+    OpenReq.cbRecv = m->m_cbRecvBuf;
     OpenReq.hIf = INTNET_HANDLE_INVALID;
 
@@ -323,6 +367,6 @@
         return rc;
     }
-    m_hIf = OpenReq.hIf;
-    Log2(("successfully opened/created \"%s\" - hIf=%#x\n", OpenReq.szNetwork, m_hIf));
+    m->m_hIf = OpenReq.hIf;
+    Log2(("successfully opened/created \"%s\" - hIf=%#x\n", OpenReq.szNetwork, m->m_hIf));
 
     /*
@@ -332,6 +376,6 @@
     GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
-    GetBufferPtrsReq.pSession = m_pSession;
-    GetBufferPtrsReq.hIf = m_hIf;
+    GetBufferPtrsReq.pSession = m->m_pSession;
+    GetBufferPtrsReq.hIf = m->m_hIf;
     GetBufferPtrsReq.pRing3Buf = NULL;
     GetBufferPtrsReq.pRing0Buf = NIL_RTR0PTR;
@@ -345,5 +389,5 @@
     Log2(("pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d\n",
                pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv));
-    m_pIfBuf = pBuf;
+    m->m_pIfBuf = pBuf;
 
     /*
@@ -353,6 +397,6 @@
     ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     ActiveReq.Hdr.cbReq = sizeof(ActiveReq);
-    ActiveReq.pSession = m_pSession;
-    ActiveReq.hIf = m_hIf;
+    ActiveReq.pSession = m->m_pSession;
+    ActiveReq.hIf = m->m_hIf;
     ActiveReq.fActive = true;
     rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
@@ -370,4 +414,16 @@
 void VBoxNetBaseService::shutdown(void)
 {
+}
+
+
+int VBoxNetBaseService::syncEnter()
+{
+    return RTCritSectEnter(&m->m_csThis);
+}
+
+
+int VBoxNetBaseService::syncLeave()
+{
+    return RTCritSectLeave(&m->m_csThis);
 }
 
@@ -380,6 +436,6 @@
     WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     WaitReq.Hdr.cbReq = sizeof(WaitReq);
-    WaitReq.pSession = m_pSession;
-    WaitReq.hIf = m_hIf;
+    WaitReq.pSession = m->m_pSession;
+    WaitReq.hIf = m->m_hIf;
     WaitReq.cMillies = cMillis;
 
@@ -392,24 +448,26 @@
 int VBoxNetBaseService::sendBufferOnWire(PCINTNETSEG pcSg, int cSg, size_t cbFrame)
 {
-    int rc = VINF_SUCCESS;
     PINTNETHDR pHdr = NULL;
     uint8_t *pu8Frame = NULL;
+
+    /* Allocate frame */
+    int rc = IntNetRingAllocateFrame(&m->m_pIfBuf->Send, cbFrame, &pHdr, (void **)&pu8Frame);
+    AssertRCReturn(rc, rc);
+
+    /* Now we fill pvFrame with S/G above */
     int offFrame = 0;
-    int idxSg = 0;
-    /* Allocate frame */
-    rc = IntNetRingAllocateFrame(&m_pIfBuf->Send, cbFrame, &pHdr, (void **)&pu8Frame);
-    AssertRCReturn(rc, rc);
-    /* Now we fill pvFrame with S/G above */
-    for (idxSg = 0; idxSg < cSg; ++idxSg)
+    for (int idxSg = 0; idxSg < cSg; ++idxSg)
     {
         memcpy(&pu8Frame[offFrame], pcSg[idxSg].pv, pcSg[idxSg].cb);
         offFrame+=pcSg[idxSg].cb;
     }
+
     /* Commit */
-    IntNetRingCommitFrame(&m_pIfBuf->Send, pHdr);
+    IntNetRingCommitFrameEx(&m->m_pIfBuf->Send, pHdr, cbFrame);
 
     LogFlowFuncLeaveRC(rc);
     return rc;
 }
+
 /**
  * forcible ask for send packet on the "wire"
@@ -421,10 +479,212 @@
     SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     SendReq.Hdr.cbReq    = sizeof(SendReq);
-    SendReq.pSession     = m_pSession;
-    SendReq.hIf          = m_hIf;
+    SendReq.pSession     = m->m_pSession;
+    SendReq.hIf          = m->m_hIf;
     rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
     AssertRCReturnVoid(rc);
     LogFlowFuncLeave();
 
+}
+
+
+int VBoxNetBaseService::hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
+                                         void const *pvData, size_t cbData) const
+{
+    return VBoxNetUDPBroadcast(m->m_pSession, m->m_hIf, m->m_pIfBuf,
+                        m->m_Ipv4Address, &m->m_MacAddress, uSrcPort,
+                        uDstPort, pvData, cbData);
+
+}
+
+
+const std::string VBoxNetBaseService::getName() const
+{
+    return m->m_Name;
+}
+
+
+void VBoxNetBaseService::setName(const std::string& aName)
+{
+    m->m_Name = aName;
+}
+
+
+const std::string VBoxNetBaseService::getNetwork() const
+{
+    return m->m_Network;
+}
+
+
+void VBoxNetBaseService::setNetwork(const std::string& aNetwork)
+{
+    m->m_Network = aNetwork;
+}
+
+
+const RTMAC VBoxNetBaseService::getMacAddress() const
+{
+    return m->m_MacAddress;
+}
+
+
+void VBoxNetBaseService::setMacAddress(const RTMAC& aMac)
+{
+    m->m_MacAddress = aMac;
+}
+
+
+const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Address() const
+{
+    return m->m_Ipv4Address;
+}
+
+
+void VBoxNetBaseService::setIpv4Address(const RTNETADDRIPV4& aAddress)
+{
+    m->m_Ipv4Address = aAddress;
+}
+
+
+const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Netmask() const
+{
+    return m->m_Ipv4Netmask;
+}
+
+
+void VBoxNetBaseService::setIpv4Netmask(const RTNETADDRIPV4& aNetmask)
+{
+    m->m_Ipv4Netmask = aNetmask;
+}
+
+
+uint32_t VBoxNetBaseService::getSendBufSize() const
+{
+    return m->m_cbSendBuf;
+}
+
+
+void VBoxNetBaseService::setSendBufSize(uint32_t cbBuf)
+{
+    m->m_cbSendBuf = cbBuf;
+}
+
+
+uint32_t VBoxNetBaseService::getRecvBufSize() const
+{
+    return m->m_cbRecvBuf;
+}
+
+
+void VBoxNetBaseService::setRecvBufSize(uint32_t cbBuf)
+{
+    m->m_cbRecvBuf = cbBuf;
+}
+
+
+int32_t VBoxNetBaseService::getVerbosityLevel() const
+{
+    return m->m_cVerbosity;
+}
+
+
+void VBoxNetBaseService::setVerbosityLevel(int32_t aVerbosity)
+{
+    m->m_cVerbosity = aVerbosity;
+}
+
+
+void VBoxNetBaseService::addCommandLineOption(const PRTGETOPTDEF optDef)
+{
+    m->m_vecOptionDefs.push_back(optDef);
+}
+
+
+void VBoxNetBaseService::doReceiveLoop()
+{
+    int rc;
+    /* Well we're ready */
+    PINTNETRINGBUF  pRingBuf = &m->m_pIfBuf->Recv;
+
+    for (;;)
+    {
+        /*
+         * Wait for a packet to become available.
+         */
+        /* 2. waiting for request for */
+        rc = waitForIntNetEvent(2000);
+        if (RT_FAILURE(rc))
+        {
+            if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
+            {
+                /* do we want interrupt anyone ??? */
+                continue;
+            }
+            LogRel(("VBoxNetNAT: waitForIntNetEvent returned %Rrc\n", rc));
+            AssertRCReturnVoid(rc);
+        }
+
+        /*
+         * Process the receive buffer.
+         */
+        PCINTNETHDR pHdr;
+
+        while ((pHdr = IntNetRingGetNextFrameToRead(pRingBuf)) != NULL)
+        {
+            uint8_t const u8Type = pHdr->u8Type;
+            size_t         cbFrame = pHdr->cbFrame;
+            switch (u8Type)
+            {
+
+                case INTNETHDR_TYPE_FRAME:
+                    {
+                        void *pvFrame = IntNetHdrGetFramePtr(pHdr, m->m_pIfBuf);
+                        rc = processFrame(pvFrame, cbFrame);
+                        if (RT_FAILURE(rc) && rc == VERR_IGNORED)
+                        {
+                            /* XXX: UDP + ARP for DHCP */
+                            VBOXNETUDPHDRS Hdrs;
+                            size_t  cb;
+                            void   *pv = VBoxNetUDPMatch(m->m_pIfBuf, RTNETIPV4_PORT_BOOTPS, &m->m_MacAddress,
+                                                         VBOXNETUDP_MATCH_UNICAST | VBOXNETUDP_MATCH_BROADCAST 
+                                                         | VBOXNETUDP_MATCH_CHECKSUM
+                                                         | (m->m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0),
+                                                         &Hdrs, &cb);
+                            if (pv && cb)
+                                processUDP(pv, cb);
+                            else 
+                                VBoxNetArpHandleIt(m->m_pSession, m->m_hIf, m->m_pIfBuf, &m->m_MacAddress, m->m_Ipv4Address);
+                        }
+                    }
+                    break;
+                case INTNETHDR_TYPE_GSO:
+                  {
+                      PCPDMNETWORKGSO pGso = IntNetHdrGetGsoContext(pHdr, m->m_pIfBuf);
+                      rc = processGSO(pGso, cbFrame);
+                      if (RT_FAILURE(rc) && rc == VERR_IGNORED)
+                          break;
+                  }
+                  break;
+                case INTNETHDR_TYPE_PADDING:
+                    break;
+                default:
+                    break;
+            }
+            IntNetRingSkipFrame(&m->m_pIfBuf->Recv);
+
+        } /* loop */
+    }
+
+}
+
+
+void VBoxNetBaseService::debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const
+{
+    if (iMinLevel <= m->m_cVerbosity)
+    {
+        va_list va;
+        va_start(va, pszFmt);
+        debugPrintV(iMinLevel, fMsg, pszFmt, va);
+        va_end(va);
+    }
 }
 
@@ -440,5 +700,5 @@
 void VBoxNetBaseService::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
 {
-    if (iMinLevel <= m_cVerbosity)
+    if (iMinLevel <= m->m_cVerbosity)
     {
         va_list vaCopy;                 /* This dude is *very* special, thus the copy. */
@@ -458,11 +718,11 @@
 {
     PRTGETOPTDEF pOptArray = NULL;
-    pOptArray = (PRTGETOPTDEF)RTMemAlloc(sizeof(RTGETOPTDEF) * m_vecOptionDefs.size());
+    pOptArray = (PRTGETOPTDEF)RTMemAlloc(sizeof(RTGETOPTDEF) * m->m_vecOptionDefs.size());
     if (!pOptArray)
         return NULL;
-    for (unsigned int i = 0; i < m_vecOptionDefs.size(); ++i)
-    {
-        PRTGETOPTDEF pOpt = m_vecOptionDefs[i];
-        memcpy(&pOptArray[i], m_vecOptionDefs[i], sizeof(RTGETOPTDEF));
+    for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); ++i)
+    {
+        PRTGETOPTDEF pOpt = m->m_vecOptionDefs[i];
+        memcpy(&pOptArray[i], m->m_vecOptionDefs[i], sizeof(RTGETOPTDEF));
     }
     return pOptArray;
Index: /trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h
===================================================================
--- /trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h	(revision 49734)
+++ /trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h	(revision 49735)
@@ -20,28 +20,69 @@
 
 #include <iprt/critsect.h>
-class VBoxNetBaseService
+
+
+class VBoxNetHlpUDPService
 {
 public:
-    VBoxNetBaseService();
+virtual int                 hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
+                                        void const *pvData, size_t cbData) const = 0;
+};
+
+
+# ifndef BASE_SERVICES_ONLY 
+class VBoxNetBaseService: public VBoxNetHlpUDPService
+{
+public:
+    VBoxNetBaseService(const std::string& aName, const std::string& aNetworkName);
     virtual ~VBoxNetBaseService();
     int                 parseArgs(int argc, char **argv);
     int                 tryGoOnline(void);
     void                shutdown(void);
-    int                 syncEnter() { return RTCritSectEnter(&this->m_csThis);}
-    int                 syncLeave() { return RTCritSectLeave(&this->m_csThis);}
+    int                 syncEnter();
+    int                 syncLeave();
     int                 waitForIntNetEvent(int cMillis);
     int                 sendBufferOnWire(PCINTNETSEG pSg, int cSg, size_t cbBuffer);
     void                flushWire();
 
+    virtual int         hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
+                                        void const *pvData, size_t cbData) const;
     virtual void        usage(void) = 0;
     virtual int         run(void) = 0;
     virtual int         parseOpt(int rc, const RTGETOPTUNION& getOptVal) = 0;
+    virtual int         processFrame(void *, size_t) = 0;
+    virtual int         processGSO(PCPDMNETWORKGSO, size_t) = 0;
+    virtual int         processUDP(void *, size_t) = 0;
+
 
     virtual int         init(void);
-    virtual bool        isMainNeeded() const { return m_fNeedMain; }
-    /* VirtualBox instance */
-    ComPtr<IVirtualBox> virtualbox;
+    virtual bool        isMainNeeded() const;
 
 protected:
+    const std::string getName() const;
+    void setName(const std::string&);
+
+    const std::string getNetwork() const;
+    void setNetwork(const std::string&);
+
+    const RTMAC getMacAddress() const;
+    void setMacAddress(const RTMAC&);
+
+    const RTNETADDRIPV4 getIpv4Address() const;
+    void setIpv4Address(const RTNETADDRIPV4&);
+
+    const RTNETADDRIPV4 getIpv4Netmask() const;
+    void setIpv4Netmask(const RTNETADDRIPV4&);
+
+    uint32_t getSendBufSize() const;
+    void setSendBufSize(uint32_t);
+
+    uint32_t getRecvBufSize() const;
+    void setRecvBufSize(uint32_t);
+
+    int32_t getVerbosityLevel() const;
+    void setVerbosityLevel(int32_t);
+
+    void addCommandLineOption(const PRTGETOPTDEF);
+
     /**
      * Print debug message depending on the m_cVerbosity level.
@@ -52,48 +93,21 @@
      * @param   ...             Optional arguments.
      */
-    void debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const
-    {
-        if (iMinLevel <= m_cVerbosity)
-        {
-            va_list va;
-            va_start(va, pszFmt);
-            debugPrintV(iMinLevel, fMsg, pszFmt, va);
-            va_end(va);
-        }
-    }
-
+    void debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const;
     virtual void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const;
 
-    /** @name The server configuration data members.
-     * @{ */
-    std::string         m_Name;
-    std::string         m_Network;
-    std::string         m_TrunkName;
-    INTNETTRUNKTYPE     m_enmTrunkType;
-    RTMAC               m_MacAddress;
-    RTNETADDRIPV4       m_Ipv4Address;
-    RTNETADDRIPV4       m_Ipv4Netmask;
-    /** @} */
-    /** @name The network interface
-     * @{ */
-    PSUPDRVSESSION      m_pSession;
-    uint32_t            m_cbSendBuf;
-    uint32_t            m_cbRecvBuf;
-    INTNETIFHANDLE      m_hIf;          /**< The handle to the network interface. */
-    PINTNETBUF          m_pIfBuf;       /**< Interface buffer. */
-    std::vector<PRTGETOPTDEF> m_vecOptionDefs;
-    /** @} */
-    /** @name Debug stuff
-     * @{  */
-    int32_t             m_cVerbosity;
+    void doReceiveLoop();
+    
+
+protected:
+    /* VirtualBox instance */
+    ComPtr<IVirtualBox> virtualbox;
+
+private:
+    struct Data;
+    Data *m;
+
 private:
     PRTGETOPTDEF getOptionsPtr();
-
-    /* cs for syncing */
-    RTCRITSECT          m_csThis;
-    /* Controls whether service will connect SVC for runtime needs */
-    bool                m_fNeedMain;
-
-    /** @} */
 };
+# endif
 #endif
