Index: /trunk/src/VBox/NetworkServices/NetLib/ComHostUtils.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/NetLib/ComHostUtils.cpp	(revision 49819)
+++ /trunk/src/VBox/NetworkServices/NetLib/ComHostUtils.cpp	(revision 49819)
@@ -0,0 +1,209 @@
+/* $Id$ */
+/** @file
+ * ComHostUtils.cpp
+ */
+
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <VBox/com/com.h>
+#include <VBox/com/listeners.h>
+#include <VBox/com/string.h>
+#include <VBox/com/Guid.h>
+#include <VBox/com/array.h>
+#include <VBox/com/ErrorInfo.h>
+#include <VBox/com/errorprint.h>
+#include <VBox/com/EventQueue.h>
+#include <VBox/com/VirtualBox.h>
+
+#include <iprt/alloca.h>
+#include <iprt/buildconfig.h>
+#include <iprt/err.h>
+#include <iprt/net.h>                   /* must come before getopt */
+#include <iprt/getopt.h>
+#include <iprt/initterm.h>
+#include <iprt/message.h>
+#include <iprt/param.h>
+#include <iprt/path.h>
+#include <iprt/stream.h>
+#include <iprt/time.h>
+#include <iprt/string.h>
+
+
+#include "../NetLib/VBoxNetLib.h"
+#include "../NetLib/shared_ptr.h"
+
+#include <vector>
+#include <list>
+#include <string>
+#include <map>
+
+#include "../NetLib/VBoxNetBaseService.h"
+
+#ifdef RT_OS_WINDOWS /* WinMain */
+# include <Windows.h>
+# include <stdlib.h>
+# ifdef INET_ADDRSTRLEN
+/* On Windows INET_ADDRSTRLEN defined as 22 Ws2ipdef.h, because it include port number */
+#  undef INET_ADDRSTRLEN
+# endif
+# define INET_ADDRSTRLEN 16
+#else
+# include <netinet/in.h>
+#endif
+
+#include "utils.h"
+
+
+VBOX_LISTENER_DECLARE(NATNetworkListenerImpl)
+
+
+int localMappings(const ComNatPtr& nat, AddressToOffsetMapping& mapping)
+{
+    mapping.clear();
+
+    ComBstrArray strs;
+    int cStrs;
+    HRESULT hrc = nat->COMGETTER(LocalMappings)(ComSafeArrayAsOutParam(strs));
+    if (   SUCCEEDED(hrc)
+        && (cStrs = strs.size()))
+    {
+        for (int i = 0; i < cStrs; ++i)
+        {
+            char szAddr[17];
+            RTNETADDRIPV4 ip4addr;
+            char *pszTerm;
+            uint32_t u32Off;
+            com::Utf8Str strLo2Off(strs[i]);
+            const char *pszLo2Off = strLo2Off.c_str();
+
+            RT_ZERO(szAddr);
+
+            pszTerm = RTStrStr(pszLo2Off, "=");
+
+            if (   pszTerm
+                   && (pszTerm - pszLo2Off) <= INET_ADDRSTRLEN)
+            {
+                memcpy(szAddr, pszLo2Off, (pszTerm - pszLo2Off));
+                int rc = RTNetStrToIPv4Addr(szAddr, &ip4addr);
+                if (RT_SUCCESS(rc))
+                {
+                    u32Off = RTStrToUInt32(pszTerm + 1);
+                    if (u32Off != 0)
+                        mapping.insert(
+                          AddressToOffsetMapping::value_type(ip4addr, u32Off));
+                }
+            }
+        }
+    }
+    else
+        return VERR_NOT_FOUND;
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * @note: const dropped here, because of map<K,V>::operator[] which isn't const, map<K,V>::at() has const
+ * variant but it's C++11.
+ */
+int hostDnsServers(const ComHostPtr& host, const RTNETADDRIPV4& networkid, 
+                   /*const*/ AddressToOffsetMapping& mapping, AddressList& servers)
+{
+    servers.clear();
+
+    ComBstrArray strs;
+    if (SUCCEEDED(host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(strs))))
+    {
+        RTNETADDRIPV4 addr;
+        int rc;
+
+        for (unsigned int i = 0; i < strs.size(); ++i)
+        {
+            rc = RTNetStrToIPv4Addr(com::Utf8Str(strs[i]).c_str(), &addr);
+            if (RT_SUCCESS(rc))
+            {
+                if (addr.au8[0] == 127)
+                {
+                    /* XXX: here we want map<K,V>::at(const K& k) const */
+                    if (mapping[addr] != 0)
+                    {
+                        addr.u = RT_H2N_U32(RT_N2H_U32(networkid.u)
+                                            + mapping[addr]);
+                    }
+                    else
+                        continue; /* XXX: Warning here (local mapping wasn't registered) */
+                }
+
+                servers.push_back(addr);
+            }
+        }
+    }
+    else
+        return VERR_NOT_FOUND;
+
+    return VINF_SUCCESS;
+}
+
+
+int hostDnsSearchList(const ComHostPtr& host, std::vector<std::string>& strings)
+{
+    strings.clear();
+
+    ComBstrArray strs;
+    if (SUCCEEDED(host->COMGETTER(SearchStrings)(ComSafeArrayAsOutParam(strs)))) 
+    {
+        for (unsigned int i = 0; i < strs.size(); ++i)
+        {
+            strings.push_back(com::Utf8Str(strs[i]).c_str());
+        }
+    }
+    else
+        return VERR_NOT_FOUND;
+
+    return VINF_SUCCESS;
+}
+
+
+int hostDnsDomain(const ComHostPtr& host, std::string& domainStr)
+{
+    com::Bstr domain;
+    if (SUCCEEDED(host->COMGETTER(DomainName)(domain.asOutParam())))
+    {
+        domainStr = com::Utf8Str(domain).c_str();
+        return VINF_SUCCESS;
+    }
+
+    return VERR_NOT_FOUND;
+}
+
+int createNatListener(ComNatListenerPtr& listener, const ComVirtualBoxPtr& vboxptr, 
+                             NATNetworkEventAdapter *adapter, const ComEventTypeArray& events)
+{
+    ComObjPtr<NATNetworkListenerImpl> obj;
+    HRESULT hrc = obj.createObject();
+    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+    hrc = obj->init(new NATNetworkListener(), adapter);
+    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+    ComPtr<IEventSource> esVBox;
+    hrc = vboxptr->COMGETTER(EventSource)(esVBox.asOutParam());
+    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+
+    listener = obj;
+
+    hrc = esVBox->RegisterListener(listener, ComSafeArrayAsInParam(events), true);
+    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+}
Index: /trunk/src/VBox/NetworkServices/NetLib/utils.h
===================================================================
--- /trunk/src/VBox/NetworkServices/NetLib/utils.h	(revision 49819)
+++ /trunk/src/VBox/NetworkServices/NetLib/utils.h	(revision 49819)
@@ -0,0 +1,131 @@
+/* $Id$ */
+/** @file
+ * ComHostUtils.cpp
+ */
+
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#ifndef _NETLIB_UTILS_H_
+#define _NETLIB_UTILS_H_
+
+#include "cpp/utils.h"
+
+typedef ComPtr<IVirtualBox> ComVirtualBoxPtr;
+typedef ComPtr<IDHCPServer> ComDhcpServerPtr;
+typedef ComPtr<IHost> ComHostPtr;
+typedef ComPtr<INATNetwork> ComNatPtr;
+typedef com::SafeArray<BSTR> ComBstrArray;
+
+typedef std::vector<RTNETADDRIPV4> AddressList;
+typedef std::map<RTNETADDRIPV4, int> AddressToOffsetMapping;
+
+  
+inline bool isDhcpRequired(const ComNatPtr& nat)
+{
+    BOOL fNeedDhcpServer = false;
+    if (FAILED(nat->COMGETTER(NeedDhcpServer)(&fNeedDhcpServer)))
+        return false;
+    
+    return fNeedDhcpServer;
+}
+
+
+inline int findDhcpServer(const ComVirtualBoxPtr& vbox, const std::string& name, ComDhcpServerPtr& dhcp)
+{
+    HRESULT hrc = vbox->FindDHCPServerByNetworkName(com::Bstr(name.c_str()).raw(),
+                                                          dhcp.asOutParam());
+    AssertComRCReturn(hrc, VERR_NOT_FOUND);
+    
+    return VINF_SUCCESS;
+}
+
+
+inline int findNatNetwork(const ComVirtualBoxPtr& vbox, const std::string& name, ComNatPtr& nat)
+{
+    HRESULT hrc = vbox->FindNATNetworkByName(com::Bstr(name.c_str()).raw(),
+                                                   nat.asOutParam());
+
+    AssertComRCReturn(hrc, VERR_NOT_FOUND);
+    
+    return VINF_SUCCESS;
+}
+
+
+inline RTNETADDRIPV4 networkid(const RTNETADDRIPV4& addr, const RTNETADDRIPV4& netmask)
+{
+    RTNETADDRIPV4 netid;
+    netid.u = addr.u & netmask.u;
+    return netid;
+}
+
+
+int localMappings(const ComNatPtr&, AddressToOffsetMapping&);
+int hostDnsServers(const ComHostPtr&, const RTNETADDRIPV4&,/* const */ AddressToOffsetMapping&, AddressList&);
+int hostDnsSearchList(const ComHostPtr&, std::vector<std::string>&);
+int hostDnsDomain(const ComHostPtr&, std::string& domainStr);
+
+
+class NATNetworkEventAdapter
+{
+    public:
+    virtual HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent) = 0;
+};
+
+
+class NATNetworkListener
+{
+    public:
+    NATNetworkListener():m_pNAT(NULL){}
+
+    HRESULT init(NATNetworkEventAdapter *pNAT)
+    {
+        AssertPtrReturn(pNAT, E_INVALIDARG);
+
+        m_pNAT = pNAT;
+        return S_OK;
+    }
+
+    HRESULT init()
+    {
+        m_pNAT = NULL;
+        return S_OK;
+    }
+
+    void uninit() { m_pNAT = NULL; }
+
+    HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent)
+    {
+        if (m_pNAT)
+            return m_pNAT->HandleEvent(aEventType, pEvent);
+        else
+            return E_FAIL;
+    }
+
+    private:
+    NATNetworkEventAdapter *m_pNAT;
+};
+typedef ListenerImpl<NATNetworkListener, NATNetworkEventAdapter*> NATNetworkListenerImpl;
+
+# if VBOX_WITH_XPCOM 
+class NS_CLASSINFO_NAME(NATNetworkListenerImpl);
+# endif
+
+typedef ComPtr<NATNetworkListenerImpl> ComNatListenerPtr;
+typedef com::SafeArray<VBoxEventType_T> ComEventTypeArray;
+
+int createNatListener(ComNatListenerPtr& listener, const ComVirtualBoxPtr& vboxptr, 
+                      NATNetworkEventAdapter *adapter, const ComEventTypeArray& events);
+#endif
