summaryrefslogtreecommitdiff
path: root/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-03-26 19:21:20 +0000
committer <>2014-05-08 15:03:54 +0000
commitfb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch)
treec2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
parent58ed4748338f9466599adfc8a9171280ed99e23f (diff)
downloadVirtualBox-master.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp')
-rw-r--r--src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp2080
1 files changed, 344 insertions, 1736 deletions
diff --git a/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp b/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
index 2ea54b66..6496b8ac 100644
--- a/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
+++ b/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -24,6 +24,16 @@
/*******************************************************************************
* 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>
@@ -43,383 +53,102 @@
#include <VBox/vmm/vmm.h>
#include <VBox/version.h>
+
#include "../NetLib/VBoxNetLib.h"
+#include "../NetLib/shared_ptr.h"
#include <vector>
+#include <list>
#include <string>
+#include <map>
+
+#include "../NetLib/VBoxNetBaseService.h"
+#include "../NetLib/utils.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 "Config.h"
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
-
-/**
- * DHCP configuration item.
- *
- * This is all public data because I'm too lazy to do it properly right now.
- */
-class VBoxNetDhcpCfg
-{
-public:
- /** The etheret addresses this matches config applies to.
- * An empty vector means 'ANY'. */
- std::vector<RTMAC> m_MacAddresses;
- /** The upper address in the range. */
- RTNETADDRIPV4 m_UpperAddr;
- /** The lower address in the range. */
- RTNETADDRIPV4 m_LowerAddr;
-
- /** Option 1: The net mask. */
- RTNETADDRIPV4 m_SubnetMask;
- /* * Option 2: The time offset. */
- /** Option 3: Routers for the subnet. */
- std::vector<RTNETADDRIPV4> m_Routers;
- /* * Option 4: Time server. */
- /* * Option 5: Name server. */
- /** Option 6: Domain Name Server (DNS) */
- std::vector<RTNETADDRIPV4> m_DNSes;
- /* * Option 7: Log server. */
- /* * Option 8: Cookie server. */
- /* * Option 9: LPR server. */
- /* * Option 10: Impress server. */
- /* * Option 11: Resource location server. */
- /* * Option 12: Host name. */
- std::string m_HostName;
- /* * Option 13: Boot file size option. */
- /* * Option 14: Merit dump file. */
- /** Option 15: Domain name. */
- std::string m_DomainName;
- /* * Option 16: Swap server. */
- /* * Option 17: Root path. */
- /* * Option 18: Extension path. */
- /* * Option 19: IP forwarding enable/disable. */
- /* * Option 20: Non-local routing enable/disable. */
- /* * Option 21: Policy filter. */
- /* * Option 22: Maximum datagram reassembly size (MRS). */
- /* * Option 23: Default IP time-to-live. */
- /* * Option 24: Path MTU aging timeout. */
- /* * Option 25: Path MTU plateau table. */
- /* * Option 26: Interface MTU. */
- /* * Option 27: All subnets are local. */
- /* * Option 28: Broadcast address. */
- /* * Option 29: Perform maximum discovery. */
- /* * Option 30: Mask supplier. */
- /* * Option 31: Perform route discovery. */
- /* * Option 32: Router solicitation address. */
- /* * Option 33: Static route. */
- /* * Option 34: Trailer encapsulation. */
- /* * Option 35: ARP cache timeout. */
- /* * Option 36: Ethernet encapsulation. */
- /* * Option 37: TCP Default TTL. */
- /* * Option 38: TCP Keepalive Interval. */
- /* * Option 39: TCP Keepalive Garbage. */
- /* * Option 40: Network Information Service (NIS) Domain. */
- /* * Option 41: Network Information Servers. */
- /* * Option 42: Network Time Protocol Servers. */
- /* * Option 43: Vendor Specific Information. */
- /* * Option 44: NetBIOS over TCP/IP Name Server (NBNS). */
- /* * Option 45: NetBIOS over TCP/IP Datagram distribution Server (NBDD). */
- /* * Option 46: NetBIOS over TCP/IP Node Type. */
- /* * Option 47: NetBIOS over TCP/IP Scope. */
- /* * Option 48: X Window System Font Server. */
- /* * Option 49: X Window System Display Manager. */
-
- /** Option 51: IP Address Lease Time. */
- uint32_t m_cSecLease;
-
- /* * Option 64: Network Information Service+ Domain. */
- /* * Option 65: Network Information Service+ Servers. */
- /** Option 66: TFTP server name. */
- std::string m_TftpServer;
- /** Address for the bp_siaddr field corresponding to m_TftpServer. */
- RTNETADDRIPV4 m_TftpServerAddr;
- /** Option 67: Bootfile name. */
- std::string m_BootfileName;
-
- /* * Option 68: Mobile IP Home Agent. */
- /* * Option 69: Simple Mail Transport Protocol (SMPT) Server. */
- /* * Option 70: Post Office Protocol (POP3) Server. */
- /* * Option 71: Network News Transport Protocol (NNTP) Server. */
- /* * Option 72: Default World Wide Web (WWW) Server. */
- /* * Option 73: Default Finger Server. */
- /* * Option 74: Default Internet Relay Chat (IRC) Server. */
- /* * Option 75: StreetTalk Server. */
-
- /* * Option 119: Domain Search. */
-
-
- VBoxNetDhcpCfg()
- {
- m_UpperAddr.u = UINT32_MAX;
- m_LowerAddr.u = UINT32_MAX;
- m_SubnetMask.u = UINT32_MAX;
- m_cSecLease = 60*60; /* 1 hour */
- }
-
- /** Validates the configuration.
- * @returns 0 on success, exit code + error message to stderr on failure. */
- int validate(void)
- {
- if ( m_UpperAddr.u == UINT32_MAX
- || m_LowerAddr.u == UINT32_MAX
- || m_SubnetMask.u == UINT32_MAX)
- {
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: Config is missing:");
- if (m_UpperAddr.u == UINT32_MAX)
- RTStrmPrintf(g_pStdErr, " --upper-ip");
- if (m_LowerAddr.u == UINT32_MAX)
- RTStrmPrintf(g_pStdErr, " --lower-ip");
- if (m_SubnetMask.u == UINT32_MAX)
- RTStrmPrintf(g_pStdErr, " --netmask");
- return 2;
- }
-
- if (RT_N2H_U32(m_UpperAddr.u) < RT_N2H_U32(m_LowerAddr.u))
- {
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: The --upper-ip value is lower than the --lower-ip one!\n"
- " %d.%d.%d.%d < %d.%d.%d.%d\n",
- m_UpperAddr.au8[0], m_UpperAddr.au8[1], m_UpperAddr.au8[2], m_UpperAddr.au8[3],
- m_LowerAddr.au8[0], m_LowerAddr.au8[1], m_LowerAddr.au8[2], m_LowerAddr.au8[3]);
- return 3;
- }
-
- /* the code goes insane if we have too many atm. lazy bird */
- uint32_t cIPs = RT_N2H_U32(m_UpperAddr.u) - RT_N2H_U32(m_LowerAddr.u);
- if (cIPs > 1024)
- {
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: Too many IPs between --upper-ip and --lower-ip! %d (max 1024)\n"
- " %d.%d.%d.%d < %d.%d.%d.%d\n",
- cIPs,
- m_UpperAddr.au8[0], m_UpperAddr.au8[1], m_UpperAddr.au8[2], m_UpperAddr.au8[3],
- m_LowerAddr.au8[0], m_LowerAddr.au8[1], m_LowerAddr.au8[2], m_LowerAddr.au8[3]);
- return 3;
- }
- return 0;
- }
-
- /**
- * Is this config for one specific client?
- *
- * @return true / false.
- */
- bool isOneSpecificClient(void) const
- {
- return m_LowerAddr.u == m_UpperAddr.u
- && m_MacAddresses.size() > 0;
- }
-
- /**
- * Checks if this config matches the specified MAC address.
- *
- * @returns true / false.
- *
- * @param pMac The MAC address to match.
- */
- bool matchesMacAddress(PCRTMAC pMac) const
- {
- size_t i = m_MacAddresses.size();
- if (RT_LIKELY(i < 1))
- return true; /* no entries == ALL wildcard match */
-
- while (i--)
- {
- PCRTMAC pCur = &m_MacAddresses[i];
- if ( pCur->au16[0] == pMac->au16[0]
- && pCur->au16[1] == pMac->au16[1]
- && pCur->au16[2] == pMac->au16[2])
- return true;
- }
- return false;
- }
-
-};
-
-/**
- * DHCP lease.
- */
-class VBoxNetDhcpLease
-{
-public:
- typedef enum State
- {
- /** Invalid. */
- kState_Invalid = 0,
- /** The lease is free / released. */
- kState_Free,
- /** An offer has been made.
- * Expire time indicates when the offer expires. */
- kState_Offer,
- /** The lease is active.
- * Expire time indicates when the lease expires. */
- kState_Active
- } State;
-
- /** The client MAC address. */
- RTMAC m_MacAddress;
- /** The IPv4 address. */
- RTNETADDRIPV4 m_IPv4Address;
-
- /** The current lease state. */
- State m_enmState;
- /** The lease expiration time. */
- RTTIMESPEC m_ExpireTime;
- /** Transaction ID. */
- uint32_t m_xid;
- /** The configuration for this lease. */
- VBoxNetDhcpCfg *m_pCfg;
-
-public:
- /** Constructor taking an IPv4 address and a Config. */
- VBoxNetDhcpLease(RTNETADDRIPV4 IPv4Addr, VBoxNetDhcpCfg *pCfg)
- {
- m_pCfg = pCfg;
- m_IPv4Address = IPv4Addr;
-
- m_MacAddress.au16[0] = m_MacAddress.au16[1] = m_MacAddress.au16[2] = 0xff;
- m_enmState = kState_Free;
- RTTimeSpecSetSeconds(&m_ExpireTime, 0);
- m_xid = UINT32_MAX;
- }
-
- /** Destructor. */
- ~VBoxNetDhcpLease()
- {
- m_IPv4Address.u = UINT32_MAX;
- m_pCfg = NULL;
- m_MacAddress.au16[0] = m_MacAddress.au16[1] = m_MacAddress.au16[2] = 0xff;
- m_enmState = kState_Free;
- m_xid = UINT32_MAX;
- }
-
- void offer(uint32_t xid);
- void activate(void);
- void activate(uint32_t xid);
- void release(void);
- bool hasExpired(void) const;
-
- /**
- * Checks if the lease is in use or not.
- *
- * @returns true if active, false if free or expired.
- *
- * @param pNow The current time to use. Optional.
- */
- bool isInUse(PCRTTIMESPEC pNow = NULL) const
- {
- if ( m_enmState == kState_Offer
- || m_enmState == kState_Active)
- {
- RTTIMESPEC Now;
- if (!pNow)
- pNow = RTTimeNow(&Now);
- return RTTimeSpecGetSeconds(&m_ExpireTime) > RTTimeSpecGetSeconds(pNow);
- }
- return false;
- }
-
- /**
- * Is this lease for one specific client?
- *
- * @return true/false.
- */
- bool isOneSpecificClient(void) const
- {
- return m_pCfg
- && m_pCfg->isOneSpecificClient();
- }
-
- /**
- * Is this lease currently being offered to a client.
- *
- * @returns true / false.
- */
- bool isBeingOffered(void) const
- {
- return m_enmState == kState_Offer
- && isInUse();
- }
-
- /**
- * Is the lease in the current config or not.
- *
- * When updating the config we might leave active leases behind which aren't
- * included in the new config. These will have m_pCfg set to NULL and should be
- * freed up when they expired.
- *
- * @returns true / false.
- */
- bool isInCurrentConfig(void) const
- {
- return m_pCfg != NULL;
- }
-};
-
/**
* DHCP server instance.
*/
-class VBoxNetDhcp
+class VBoxNetDhcp: public VBoxNetBaseService, public NATNetworkEventAdapter
{
public:
VBoxNetDhcp();
virtual ~VBoxNetDhcp();
- int parseArgs(int argc, char **argv);
- int tryGoOnline(void);
- int run(void);
+ int init();
+ 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:
- int addConfig(VBoxNetDhcpCfg *pCfg);
- void explodeConfig(void);
-
bool handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb);
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 makeDhcpReply(uint8_t uMsgType, VBoxNetDhcpLease *pLease, PCRTNETBOOTP pDhcpMsg, size_t cb);
- VBoxNetDhcpLease *findLeaseByMacAddress(PCRTMAC pMacAddress, bool fAnyState);
- VBoxNetDhcpLease *findLeaseByIpv4AndMacAddresses(RTNETADDRIPV4 IPv4Addr, PCRTMAC pMacAddress, bool fAnyState);
- VBoxNetDhcpLease *newLease(PCRTNETBOOTP pDhcpMsg, size_t cb);
-
- static uint8_t const *findOption(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cb, size_t *pcbMaxOpt);
- static bool findOptionIPv4Addr(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cb, PRTNETADDRIPV4 pIPv4Addr);
-
- inline void debugPrint( int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const;
void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const;
static const char *debugDhcpName(uint8_t uMsgType);
+private:
+ int initNoMain();
+ int initWithMain();
+ HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent);
+ int fetchAndUpdateDnsInfo();
+
protected:
- /** @name The server configuration data members.
+ /** @name The DHCP server specific configuration data members.
* @{ */
- std::string m_Name;
- std::string m_Network;
- std::string m_TrunkName;
- INTNETTRUNKTYPE m_enmTrunkType;
- RTMAC m_MacAddress;
- RTNETADDRIPV4 m_Ipv4Address;
+ /*
+ * XXX: what was the plan? SQL3 or plain text file?
+ * How it will coexists with managment from VBoxManagement, who should manage db
+ * in that case (VBoxManage, VBoxSVC ???)
+ */
std::string m_LeaseDBName;
+
/** @} */
- /** The current configs. */
- std::vector<VBoxNetDhcpCfg *> m_Cfgs;
+ /* corresponding dhcp server description in Main */
+ ComPtr<IDHCPServer> m_DhcpServer;
- /** The current leases. */
- std::vector<VBoxNetDhcpLease> m_Leases;
+ ComPtr<INATNetwork> m_NATNetwork;
- /** @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. */
- /** @} */
+ /** Listener for Host DNS changes */
+ ComPtr<NATNetworkListenerImpl> m_vboxListener;
+ /*
+ * We will ignore cmd line parameters IFF there will be some DHCP specific arguments
+ * otherwise all paramters will come from Main.
+ */
+ bool m_fIgnoreCmdLineParameters;
+
+ /*
+ * -b -n 10.0.1.2 -m 255.255.255.0 -> to the list processing in
+ */
+ typedef struct
+ {
+ char Key;
+ std::string strValue;
+ } CMDLNPRM;
+ std::list<CMDLNPRM> CmdParameterll;
+ typedef std::list<CMDLNPRM>::iterator CmdParameterIterator;
/** @name Debug stuff
* @{ */
@@ -432,130 +161,68 @@ protected:
};
-/*******************************************************************************
-* Global Variables *
-*******************************************************************************/
-/** Pointer to the DHCP server. */
-static VBoxNetDhcp *g_pDhcp;
-
-
-/**
- * Offer this lease to a client.
- *
- * @param xid The transaction ID.
- */
-void VBoxNetDhcpLease::offer(uint32_t xid)
+static inline int configGetBoundryAddress(const ComDhcpServerPtr& dhcp, bool fUpperBoundry, RTNETADDRIPV4& boundryAddress)
{
- m_enmState = kState_Offer;
- m_xid = xid;
- RTTimeNow(&m_ExpireTime);
- RTTimeSpecAddSeconds(&m_ExpireTime, 60);
-}
+ boundryAddress.u = INADDR_ANY;
+ HRESULT hrc;
+ com::Bstr strAddress;
+ if (fUpperBoundry)
+ hrc = dhcp->COMGETTER(UpperIP)(strAddress.asOutParam());
+ else
+ hrc = dhcp->COMGETTER(LowerIP)(strAddress.asOutParam());
+ AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
-/**
- * Activate this lease (i.e. a client is now using it).
- */
-void VBoxNetDhcpLease::activate(void)
-{
- m_enmState = kState_Active;
- RTTimeNow(&m_ExpireTime);
- RTTimeSpecAddSeconds(&m_ExpireTime, m_pCfg ? m_pCfg->m_cSecLease : 60); /* m_pCfg can be NULL right now... */
+ return RTNetStrToIPv4Addr(com::Utf8Str(strAddress).c_str(), &boundryAddress);
}
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
+/** Pointer to the DHCP server. */
+static VBoxNetDhcp *g_pDhcp;
-/**
- * Activate this lease with a new transaction ID.
- *
- * @param xid The transaction ID.
- * @todo check if this is really necessary.
- */
-void VBoxNetDhcpLease::activate(uint32_t xid)
+/* DHCP server specific options */
+static RTGETOPTDEF g_aOptionDefs[] =
{
- activate();
- m_xid = xid;
-}
-
-
-/**
- * Release a lease either upon client request or because it didn't quite match a
- * DHCP_REQUEST.
- */
-void VBoxNetDhcpLease::release(void)
-{
- m_enmState = kState_Free;
- RTTimeNow(&m_ExpireTime);
- RTTimeSpecAddSeconds(&m_ExpireTime, 5);
-}
-
+ { "--lease-db", 'D', RTGETOPT_REQ_STRING },
+ { "--begin-config", 'b', RTGETOPT_REQ_NOTHING },
+ { "--gateway", 'g', RTGETOPT_REQ_IPV4ADDR },
+ { "--lower-ip", 'l', RTGETOPT_REQ_IPV4ADDR },
+ { "--upper-ip", 'u', RTGETOPT_REQ_IPV4ADDR },
+};
/**
- * Checks if the lease has expired or not.
- *
- * This just checks the expiration time not the state. This is so that this
- * method will work for reusing RELEASEd leases when the client comes back after
- * a reboot or ipconfig /renew. Callers not interested in info on released
- * leases should check the state first.
- *
- * @returns true if expired, false if not.
+ * Construct a DHCP server with a default configuration.
*/
-bool VBoxNetDhcpLease::hasExpired() const
+VBoxNetDhcp::VBoxNetDhcp():VBoxNetBaseService("VBoxNetDhcp", "VBoxNetDhcp")
{
- RTTIMESPEC Now;
- return RTTimeSpecGetSeconds(&m_ExpireTime) > RTTimeSpecGetSeconds(RTTimeNow(&Now));
-}
-
+ /* 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);
-/**
- * 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;
m_uCurMsgType = UINT8_MAX;
m_cbCurMsg = 0;
m_pCurMsg = NULL;
memset(&m_CurHdrs, '\0', sizeof(m_CurHdrs));
-#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
+ m_fIgnoreCmdLineParameters = true;
+
+ for(unsigned int i = 0; i < RT_ELEMENTS(g_aOptionDefs); ++i)
+ addCommandLineOption(&g_aOptionDefs[i]);
}
@@ -564,463 +231,101 @@ VBoxNetDhcp::VBoxNetDhcp()
*/
VBoxNetDhcp::~VBoxNetDhcp()
{
- /*
- * 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_VMCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
- AssertRC(rc);
- }
-
- if (m_pSession)
- {
- SUPR3Term(false /*fForced*/);
- m_pSession = NIL_RTR0PTR;
- }
}
-/**
- * Adds a config to the tail.
- *
- * @returns See VBoxNetDHCP::validate().
- * @param pCfg The config too add.
- * This object will be consumed by this call!
- */
-int VBoxNetDhcp::addConfig(VBoxNetDhcpCfg *pCfg)
-{
- int rc = 0;
- if (pCfg)
- {
- rc = pCfg->validate();
- if (!rc)
- m_Cfgs.push_back(pCfg);
- else
- delete pCfg;
- }
- return rc;
-}
/**
- * Explodes the config into leases.
- *
- * @remarks This code is brute force and not very fast nor memory efficient.
- * We will have to revisit this later.
+ * Parse the DHCP specific arguments.
*
- * @remarks If an IP has been reconfigured for a fixed mac address and it's
- * already leased to a client, we it won't be available until the
- * client releases its lease or it expires.
+ * This callback caled for each paramenter so
+ * ....
+ * we nee post analisys of the parameters, at least
+ * for -b, -g, -l, -u, -m
*/
-void VBoxNetDhcp::explodeConfig(void)
+int VBoxNetDhcp::parseOpt(int rc, const RTGETOPTUNION& Val)
{
- RTTIMESPEC Now;
- RTTimeNow(&Now);
+ CMDLNPRM prm;
- /*
- * Remove all non-active leases from the vector and zapping the
- * config pointers of the once left behind.
- */
- std::vector<VBoxNetDhcpLease>::iterator Itr = m_Leases.begin();
- while (Itr != m_Leases.end())
- {
- if (!Itr->isInUse(&Now))
- Itr = m_Leases.erase(Itr);
- else
- {
- Itr->m_pCfg = NULL;
- Itr++;
- }
- }
+ /* Ok, we've entered here, thus we can't ignore cmd line parameters anymore */
+ m_fIgnoreCmdLineParameters = false;
- /*
- * Loop thru the configurations in reverse order, giving the last
- * configs priority of the newer ones.
- */
- size_t iCfg = m_Cfgs.size();
- while (iCfg-- > 0)
- {
- VBoxNetDhcpCfg *pCfg = m_Cfgs[iCfg];
+ prm.Key = rc;
- /* Expand the IP lease range. */
- uint32_t const uLast = RT_N2H_U32(pCfg->m_UpperAddr.u);
- for (uint32_t i = RT_N2H_U32(pCfg->m_LowerAddr.u); i <= uLast; i++)
+ switch (rc)
+ {
+ case 'l':
+ case 'u':
+ case 'g':
{
- RTNETADDRIPV4 IPv4Addr;
- IPv4Addr.u = RT_H2N_U32(i);
-
- /* Check if it exists and is configured. */
- VBoxNetDhcpLease *pLease = NULL;
- for (size_t j = 0; j < m_Leases.size(); j++)
- if (m_Leases[j].m_IPv4Address.u == IPv4Addr.u)
- {
- pLease = &m_Leases[j];
- break;
- }
- if (pLease)
- {
- if (!pLease->m_pCfg)
- pLease->m_pCfg = pCfg;
- }
- else
- {
- /* add it. */
- VBoxNetDhcpLease NewLease(IPv4Addr, pCfg);
- m_Leases.push_back(NewLease);
- debugPrint(10, false, "exploseConfig: new lease %d.%d.%d.%d",
- IPv4Addr.au8[0], IPv4Addr.au8[1], IPv4Addr.au8[2], IPv4Addr.au8[3]);
- }
+ char buf[17];
+ RTStrPrintf(buf, 17, "%RTnaipv4", Val.IPv4Addr.u);
+ prm.strValue = buf;
+ CmdParameterll.push_back(prm);
}
- }
-}
+ break;
-
-/**
- * Parse the arguments.
- *
- * @returns 0 on success, fully bitched exit code on failure.
- *
- * @param argc Argument count.
- * @param argv Argument vector.
- */
-int VBoxNetDhcp::parseArgs(int argc, char **argv)
-{
- static const RTGETOPTDEF s_aOptionDefs[] =
- {
- { "--name", 'N', RTGETOPT_REQ_STRING },
- { "--network", 'n', RTGETOPT_REQ_STRING },
- { "--trunk-name", 't', RTGETOPT_REQ_STRING },
- { "--trunk-type", 'T', RTGETOPT_REQ_STRING },
- { "--mac-address", 'a', RTGETOPT_REQ_MACADDR },
- { "--ip-address", 'i', RTGETOPT_REQ_IPV4ADDR },
- { "--lease-db", 'D', RTGETOPT_REQ_STRING },
- { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
-
- { "--begin-config", 'b', RTGETOPT_REQ_NOTHING },
- { "--gateway", 'g', RTGETOPT_REQ_IPV4ADDR },
- { "--lower-ip", 'l', RTGETOPT_REQ_IPV4ADDR },
- { "--upper-ip", 'u', RTGETOPT_REQ_IPV4ADDR },
- { "--netmask", 'm', RTGETOPT_REQ_IPV4ADDR },
- };
-
- RTGETOPTSTATE State;
- int rc = RTGetOptInit(&State, argc, argv, &s_aOptionDefs[0], RT_ELEMENTS(s_aOptionDefs), 0, 0 /*fFlags*/);
- AssertRCReturn(rc, 49);
-
- VBoxNetDhcpCfg *pCurCfg = NULL;
- for (;;)
- {
- RTGETOPTUNION Val;
- rc = RTGetOpt(&State, &Val);
- if (!rc)
+ case 'b': // ignore
+ case 'D': // ignore
break;
- switch (rc)
- {
- case 'N':
- m_Name = Val.psz;
- break;
- case 'n':
- m_Network = Val.psz;
- break;
- case 't':
- m_TrunkName = Val.psz;
- break;
- case 'T':
- if (!strcmp(Val.psz, "none"))
- m_enmTrunkType = kIntNetTrunkType_None;
- else if (!strcmp(Val.psz, "whatever"))
- m_enmTrunkType = kIntNetTrunkType_WhateverNone;
- else if (!strcmp(Val.psz, "netflt"))
- m_enmTrunkType = kIntNetTrunkType_NetFlt;
- else if (!strcmp(Val.psz, "netadp"))
- m_enmTrunkType = kIntNetTrunkType_NetAdp;
- else if (!strcmp(Val.psz, "srvnat"))
- m_enmTrunkType = kIntNetTrunkType_SrvNat;
- else
- {
- RTStrmPrintf(g_pStdErr, "Invalid trunk type '%s'\n", Val.psz);
- return 1;
- }
- break;
- case 'a':
- m_MacAddress = Val.MacAddr;
- break;
- case 'i':
- m_Ipv4Address = Val.IPv4Addr;
- break;
- case 'd':
- m_LeaseDBName = Val.psz;
- break;
- case 'v':
- m_cVerbosity++;
- break;
-
- /* Begin config. */
- case 'b':
- rc = addConfig(pCurCfg);
- if (rc)
- break;
- pCurCfg = NULL;
- /* fall thru */
-
- /* config specific ones. */
- case 'g':
- case 'l':
- case 'u':
- case 'm':
- if (!pCurCfg)
- {
- pCurCfg = new VBoxNetDhcpCfg();
- if (!pCurCfg)
- {
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: new VBoxDhcpCfg failed\n");
- return 1;
- }
- }
-
- switch (rc)
- {
- case 'g':
- pCurCfg->m_Routers.push_back(Val.IPv4Addr);
- break;
-
- case 'l':
- pCurCfg->m_LowerAddr = Val.IPv4Addr;
- break;
-
- case 'u':
- pCurCfg->m_UpperAddr = Val.IPv4Addr;
- break;
-
- case 'm':
- pCurCfg->m_SubnetMask = Val.IPv4Addr;
- break;
-
- case 0: /* ignore */ break;
- default:
- AssertMsgFailed(("%d", rc));
- return 1;
- }
- break;
-
- case 'V':
- RTPrintf("%sr%u\n", RTBldCfgVersion(), RTBldCfgRevision());
- return 1;
-
- case 'h':
- RTPrintf("VBoxNetDHCP Version %s\n"
- "(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
- "All rights reserved.\n"
- "\n"
- "Usage: VBoxNetDHCP <options>\n"
- "\n"
- "Options:\n",
- RTBldCfgVersion());
- for (size_t i = 0; i < RT_ELEMENTS(s_aOptionDefs); i++)
- RTPrintf(" -%c, %s\n", s_aOptionDefs[i].iShort, s_aOptionDefs[i].pszLong);
- return 1;
-
- default:
- rc = RTGetOptPrintError(rc, &Val);
- RTPrintf("Use --help for more information.\n");
- return rc;
- }
+ default:
+ rc = RTGetOptPrintError(rc, &Val);
+ RTPrintf("Use --help for more information.\n");
+ return rc;
}
- /*
- * Do the reconfig. (move this later)
- */
- if (!rc)
- explodeConfig();
-
- return rc;
+ return VINF_SUCCESS;
}
-
-/**
- * Tries to connect to the internal network.
- *
- * @returns 0 on success, exit code + error message to stderr on failure.
- */
-int VBoxNetDhcp::tryGoOnline(void)
+int VBoxNetDhcp::init()
{
- /*
- * Open the session, load ring-0 and issue the request.
- */
- int rc = SUPR3Init(&m_pSession);
- if (RT_FAILURE(rc))
- {
- m_pSession = NIL_RTR0PTR;
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3Init -> %Rrc", rc);
- return 1;
- }
-
- char szPath[RTPATH_MAX];
- rc = RTPathExecDir(szPath, sizeof(szPath) - sizeof("/VMMR0.r0"));
- if (RT_FAILURE(rc))
- {
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: RTPathProgram -> %Rrc", rc);
- return 1;
- }
-
- rc = SUPR3LoadVMM(strcat(szPath, "/VMMR0.r0"));
- if (RT_FAILURE(rc))
- {
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3LoadVMM(\"%s\") -> %Rrc", szPath, rc);
- return 1;
- }
+ int rc = this->VBoxNetBaseService::init();
+ AssertRCReturn(rc, rc);
- /*
- * Create the open request.
- */
- INTNETOPENREQ OpenReq;
- 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.szNetwork[sizeof(OpenReq.szNetwork) - 1] = '\0';
- strncpy(OpenReq.szTrunk, m_TrunkName.c_str(), sizeof(OpenReq.szTrunk));
- OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0';
- OpenReq.enmTrunkType = m_enmTrunkType;
- OpenReq.fFlags = 0; /** @todo check this */
- OpenReq.cbSend = m_cbSendBuf;
- OpenReq.cbRecv = m_cbRecvBuf;
- OpenReq.hIf = INTNET_HANDLE_INVALID;
+ NetworkManager *netManager = NetworkManager::getNetworkManager();
- /*
- * Issue the request.
- */
- debugPrint(2, false, "attempting to open/create network \"%s\"...", OpenReq.szNetwork);
- rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr);
- if (RT_SUCCESS(rc))
- {
- m_hIf = OpenReq.hIf;
- debugPrint(1, false, "successfully opened/created \"%s\" - hIf=%#x", OpenReq.szNetwork, m_hIf);
-
- /*
- * Get the ring-3 address of the shared interface buffer.
- */
- INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
- GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
- GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
- GetBufferPtrsReq.pSession = m_pSession;
- GetBufferPtrsReq.hIf = m_hIf;
- GetBufferPtrsReq.pRing3Buf = NULL;
- GetBufferPtrsReq.pRing0Buf = NIL_RTR0PTR;
- rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr);
- if (RT_SUCCESS(rc))
- {
- PINTNETBUF pBuf = GetBufferPtrsReq.pRing3Buf;
- debugPrint(1, false, "pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d",
- pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv);
- m_pIfBuf = pBuf;
+ netManager->setOurAddress(getIpv4Address());
+ netManager->setOurNetmask(getIpv4Netmask());
+ netManager->setOurMac(getMacAddress());
+ netManager->setService(this);
- /*
- * Activate the interface.
- */
- INTNETIFSETACTIVEREQ ActiveReq;
- ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
- ActiveReq.Hdr.cbReq = sizeof(ActiveReq);
- ActiveReq.pSession = m_pSession;
- ActiveReq.hIf = m_hIf;
- ActiveReq.fActive = true;
- rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
- if (RT_SUCCESS(rc))
- return 0;
-
- /* bail out */
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,) failed, rc=%Rrc\n", rc);
- }
- else
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,) failed, rc=%Rrc\n", rc);
- }
+ if (isMainNeeded())
+ rc = initWithMain();
else
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_OPEN,) failed, rc=%Rrc\n", rc);
+ rc = initNoMain();
+
+ AssertRCReturn(rc, rc);
- return RT_SUCCESS(rc) ? 0 : 1;
+ return VINF_SUCCESS;
}
-/**
- * Runs the DHCP server.
- *
- * @returns exit code + error message to stderr on failure, won't return on
- * success (you must kill this process).
- */
-int VBoxNetDhcp::run(void)
+int VBoxNetDhcp::processUDP(void *pv, size_t cbPv)
{
- /*
- * 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;
- }
+ PCRTNETBOOTP pDhcpMsg = (PCRTNETBOOTP)pv;
+ m_pCurMsg = pDhcpMsg;
+ m_cbCurMsg = cbPv;
- /*
- * Process the receive buffer.
- */
- while (IntNetRingHasMoreToRead(pRingBuf))
+ uint8_t uMsgType;
+ if (RTNetIPv4IsDHCPValid(NULL /* why is this here? */, pDhcpMsg, cbPv, &uMsgType))
+ {
+ m_uCurMsgType = uMsgType;
{
- 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);
+ /* To avoid fight with event processing thread */
+ VBoxNetALock(this);
+ handleDhcpMsg(uMsgType, pDhcpMsg, cbPv);
}
+ m_uCurMsgType = UINT8_MAX;
}
+ else
+ debugPrint(1, true, "VBoxNetDHCP: Skipping invalid DHCP packet.\n"); /** @todo handle pure bootp clients too? */
- return 0;
+ m_pCurMsg = NULL;
+ m_cbCurMsg = 0;
+
+ return VINF_SUCCESS;
}
@@ -1036,19 +341,21 @@ bool VBoxNetDhcp::handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t
{
if (pDhcpMsg->bp_op == RTNETBOOTP_OP_REQUEST)
{
+ NetworkManager *networkManager = NetworkManager::getNetworkManager();
+
switch (uMsgType)
{
case RTNET_DHCP_MT_DISCOVER:
- return handleDhcpReqDiscover(pDhcpMsg, cb);
+ return networkManager->handleDhcpReqDiscover(pDhcpMsg, cb);
case RTNET_DHCP_MT_REQUEST:
- return handleDhcpReqRequest(pDhcpMsg, cb);
+ return networkManager->handleDhcpReqRequest(pDhcpMsg, cb);
case RTNET_DHCP_MT_DECLINE:
- return handleDhcpReqDecline(pDhcpMsg, cb);
+ return networkManager->handleDhcpReqDecline(pDhcpMsg, cb);
case RTNET_DHCP_MT_RELEASE:
- return handleDhcpReqRelease(pDhcpMsg, cb);
+ return networkManager->handleDhcpReqRelease(pDhcpMsg, cb);
case RTNET_DHCP_MT_INFORM:
debugPrint(0, true, "Should we handle this?");
@@ -1062,946 +369,245 @@ bool VBoxNetDhcp::handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t
return false;
}
-
/**
- * The client is requesting an offer.
- *
- * @returns true.
- *
- * @param pDhcpMsg The message.
- * @param cb The message size.
- */
-bool VBoxNetDhcp::handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb)
-{
- /*
- * The newLease() method contains logic for finding current leases
- * and reusing them in case the client is forgetful.
- */
- VBoxNetDhcpLease *pLease = newLease(pDhcpMsg, cb);
- if (!pLease)
- return false;
- debugPrint(1, true, "Offering %d.%d.%d.%d to %.6Rhxs xid=%#x",
- pLease->m_IPv4Address.au8[0],
- pLease->m_IPv4Address.au8[1],
- pLease->m_IPv4Address.au8[2],
- pLease->m_IPv4Address.au8[3],
- &pDhcpMsg->bp_chaddr.Mac,
- pDhcpMsg->bp_xid);
- pLease->offer(pDhcpMsg->bp_xid);
-
- makeDhcpReply(RTNET_DHCP_MT_OFFER, pLease, pDhcpMsg, cb);
- return true;
-}
-
-
-/**
- * The client is requesting an offer.
- *
- * @returns true.
+ * Print debug message depending on the m_cVerbosity level.
*
- * @param pDhcpMsg The message.
- * @param cb The message size.
+ * @param iMinLevel The minimum m_cVerbosity level for this message.
+ * @param fMsg Whether to dump parts for the current DHCP message.
+ * @param pszFmt The message format string.
+ * @param va Optional arguments.
*/
-bool VBoxNetDhcp::handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb)
+void VBoxNetDhcp::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
{
- /** @todo Probably need to match the server IP here to work correctly with
- * other servers. */
- /** @todo This code isn't entirely correct and quite a bit of a hack, but it
- * will have to do for now as the right thing (tm) is very complex.
- * Part of the fun is verifying that the request is something we can
- * and should handle. */
-
- /*
- * Try find the lease by the requested address + client MAC address.
- */
- VBoxNetDhcpLease *pLease = NULL;
- RTNETADDRIPV4 IPv4Addr;
- bool fReqAddr = findOptionIPv4Addr(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cb, &IPv4Addr);
- if (fReqAddr)
- {
- fReqAddr = true;
- pLease = findLeaseByIpv4AndMacAddresses(IPv4Addr, &pDhcpMsg->bp_chaddr.Mac, true /* fAnyState */);
- }
-
- /*
- * Try find the lease by the client IP address + client MAC address.
- */
- if ( !pLease
- && pDhcpMsg->bp_ciaddr.u)
- pLease = findLeaseByIpv4AndMacAddresses(pDhcpMsg->bp_ciaddr, &pDhcpMsg->bp_chaddr.Mac, true /* fAnyState */);
-
-#if 0 /** @todo client id stuff - it doesn't make sense here imho, we need IP + MAC. What would make sense
- though is to compare the client id with what we've got in the lease and use it to root out
- bad requests. */
- /*
- * Try find the lease by using the client id.
- */
- if (!pLease)
+ if (iMinLevel <= m_cVerbosity)
{
- size_t cbClientID = 0;
- uint8_t const *pbClientID = findOption(RTNET_DHCP_OPT_CLIENT_ID, pDhcpMsg, cb, &cbClientID);
- if ( pbClientID
- && cbClientID == sizeof(RTMAC) + 1
- && pbClientID[0] == RTNET_ARP_ETHER
- &&
- )
- {
- pLease = findLeaseByIpv4AndMacAddresses(pDhcpMsg->bp_ciaddr, &pDhcpMsg->bp_chaddr.Mac, true /* fAnyState */);
- }
- }
-#endif
+ va_list vaCopy; /* This dude is *very* special, thus the copy. */
+ va_copy(vaCopy, va);
+ RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: %s: %N\n", iMinLevel >= 2 ? "debug" : "info", pszFmt, &vaCopy);
+ va_end(vaCopy);
- /*
- * Validate the lease that's requested.
- * We've already check the MAC and IP addresses.
- */
- bool fAckIt = false;
- if (pLease)
- {
- if (pLease->isBeingOffered())
- {
- if (pLease->m_xid == pDhcpMsg->bp_xid)
- debugPrint(2, true, "REQUEST for offered lease.");
- else
- debugPrint(2, true, "REQUEST for offered lease, xid mismatch. Expected %#x, got %#x.",
- pLease->m_xid, pDhcpMsg->bp_xid);
- pLease->activate(pDhcpMsg->bp_xid);
- fAckIt = true;
- }
- else if (!pLease->isInCurrentConfig())
- debugPrint(1, true, "REQUEST for obsolete lease -> NAK");
- else if (fReqAddr != (pDhcpMsg->bp_ciaddr.u != 0)) // ???
+ if ( fMsg
+ && m_cVerbosity >= 2
+ && m_pCurMsg)
{
- /** @todo this ain't safe. */
- debugPrint(1, true, "REQUEST for lease not on offer, assuming renewal. lease_xid=%#x bp_xid=%#x",
- pLease->m_xid, pDhcpMsg->bp_xid);
- fAckIt = true;
- pLease->activate(pDhcpMsg->bp_xid);
+ /* XXX: export this to debugPrinfDhcpMsg or variant and other method export
+ * to base class
+ */
+ const char *pszMsg = m_uCurMsgType != UINT8_MAX ? debugDhcpName(m_uCurMsgType) : "";
+ RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: debug: %8s chaddr=%.6Rhxs ciaddr=%d.%d.%d.%d yiaddr=%d.%d.%d.%d siaddr=%d.%d.%d.%d xid=%#x\n",
+ pszMsg,
+ &m_pCurMsg->bp_chaddr,
+ m_pCurMsg->bp_ciaddr.au8[0], m_pCurMsg->bp_ciaddr.au8[1], m_pCurMsg->bp_ciaddr.au8[2], m_pCurMsg->bp_ciaddr.au8[3],
+ m_pCurMsg->bp_yiaddr.au8[0], m_pCurMsg->bp_yiaddr.au8[1], m_pCurMsg->bp_yiaddr.au8[2], m_pCurMsg->bp_yiaddr.au8[3],
+ m_pCurMsg->bp_siaddr.au8[0], m_pCurMsg->bp_siaddr.au8[1], m_pCurMsg->bp_siaddr.au8[2], m_pCurMsg->bp_siaddr.au8[3],
+ m_pCurMsg->bp_xid);
}
- else
- debugPrint(1, true, "REQUEST for lease not on offer, NAK it.");
- }
-
- /*
- * NAK if if no lease was found.
- */
- if (fAckIt)
- {
- debugPrint(1, false, "ACK'ing DHCP_REQUEST");
- makeDhcpReply(RTNET_DHCP_MT_ACK, pLease, pDhcpMsg, cb);
- }
- else
- {
- debugPrint(1, false, "NAK'ing DHCP_REQUEST");
- makeDhcpReply(RTNET_DHCP_MT_NAC, NULL, pDhcpMsg, cb);
}
-
- return true;
}
/**
- * The client is declining an offer we've made.
- *
- * @returns true.
- *
- * @param pDhcpMsg The message.
- * @param cb The message size.
- */
-bool VBoxNetDhcp::handleDhcpReqDecline(PCRTNETBOOTP pDhcpMsg, size_t cb)
-{
- /** @todo Probably need to match the server IP here to work correctly with
- * other servers. */
-
- /*
- * The client is supposed to pass us option 50, requested address,
- * from the offer. We also match the lease state. Apparently the
- * MAC address is not supposed to be checked here.
- */
-
- /** @todo this is not required in the initial implementation, do it later. */
- debugPrint(1, true, "DECLINE is not implemented");
- return true;
-}
-
-
-/**
- * The client is releasing its lease - good boy.
- *
- * @returns true.
+ * Gets the name of given DHCP message type.
*
- * @param pDhcpMsg The message.
- * @param cb The message size.
- */
-bool VBoxNetDhcp::handleDhcpReqRelease(PCRTNETBOOTP pDhcpMsg, size_t cb)
-{
- /** @todo Probably need to match the server IP here to work correctly with
- * other servers. */
-
- /*
- * The client may pass us option 61, client identifier, which we should
- * use to find the lease by.
- *
- * We're matching MAC address and lease state as well.
- */
-
- /*
- * If no client identifier or if we couldn't find a lease by using it,
- * we will try look it up by the client IP address.
- */
-
-
- /*
- * If found, release it.
- */
-
-
- /** @todo this is not required in the initial implementation, do it later. */
- debugPrint(1, true, "RELEASE is not implemented");
- return true;
-}
-
-
-/**
- * Helper class for stuffing DHCP options into a reply packet.
+ * @returns Readonly name.
+ * @param uMsgType The message number.
*/
-class VBoxNetDhcpWriteCursor
+/* static */ const char *VBoxNetDhcp::debugDhcpName(uint8_t uMsgType)
{
-private:
- uint8_t *m_pbCur; /**< The current cursor position. */
- uint8_t *m_pbEnd; /**< The end the current option space. */
- uint8_t *m_pfOverload; /**< Pointer to the flags of the overload option. */
- uint8_t m_fUsed; /**< Overload fields that have been used. */
- PRTNETDHCPOPT m_pOpt; /**< The current option. */
- PRTNETBOOTP m_pDhcp; /**< The DHCP packet. */
- bool m_fOverflowed; /**< Set if we've overflowed, otherwise false. */
-
-public:
- /** Instantiate an option cursor for the specified DHCP message. */
- VBoxNetDhcpWriteCursor(PRTNETBOOTP pDhcp, size_t cbDhcp) :
- m_pbCur(&pDhcp->bp_vend.Dhcp.dhcp_opts[0]),
- m_pbEnd((uint8_t *)pDhcp + cbDhcp),
- m_pfOverload(NULL),
- m_fUsed(0),
- m_pOpt(NULL),
- m_pDhcp(pDhcp),
- m_fOverflowed(false)
- {
- AssertPtr(pDhcp);
- Assert(cbDhcp > RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts[10]));
- }
-
- /** Destructor. */
- ~VBoxNetDhcpWriteCursor()
- {
- m_pbCur = m_pbEnd = m_pfOverload = NULL;
- m_pOpt = NULL;
- m_pDhcp = NULL;
- }
-
- /**
- * Try use the bp_file field.
- * @returns true if not overloaded, false otherwise.
- */
- bool useBpFile(void)
+ switch (uMsgType)
{
- if ( m_pfOverload
- && (*m_pfOverload & 1))
- return false;
- m_fUsed |= 1 /* bp_file flag*/;
- return true;
+ case 0: return "MT_00";
+ case RTNET_DHCP_MT_DISCOVER: return "DISCOVER";
+ case RTNET_DHCP_MT_OFFER: return "OFFER";
+ case RTNET_DHCP_MT_REQUEST: return "REQUEST";
+ case RTNET_DHCP_MT_DECLINE: return "DECLINE";
+ case RTNET_DHCP_MT_ACK: return "ACK";
+ case RTNET_DHCP_MT_NAC: return "NAC";
+ case RTNET_DHCP_MT_RELEASE: return "RELEASE";
+ case RTNET_DHCP_MT_INFORM: return "INFORM";
+ case 9: return "MT_09";
+ case 10: return "MT_0a";
+ case 11: return "MT_0b";
+ case 12: return "MT_0c";
+ case 13: return "MT_0d";
+ case 14: return "MT_0e";
+ case 15: return "MT_0f";
+ case 16: return "MT_10";
+ case 17: return "MT_11";
+ case 18: return "MT_12";
+ case 19: return "MT_13";
+ case UINT8_MAX: return "MT_ff";
+ default: return "UNKNOWN";
}
+}
- /**
- * Try overload more BOOTP fields
- */
- bool overloadMore(void)
- {
- /* switch option area. */
- uint8_t *pbNew;
- uint8_t *pbNewEnd;
- uint8_t fField;
- if (!(m_fUsed & 1))
- {
- fField = 1;
- pbNew = &m_pDhcp->bp_file[0];
- pbNewEnd = &m_pDhcp->bp_file[sizeof(m_pDhcp->bp_file)];
- }
- else if (!(m_fUsed & 2))
- {
- fField = 2;
- pbNew = &m_pDhcp->bp_sname[0];
- pbNewEnd = &m_pDhcp->bp_sname[sizeof(m_pDhcp->bp_sname)];
- }
- else
- return false;
+int VBoxNetDhcp::initNoMain()
+{
+ CmdParameterIterator it;
- if (!m_pfOverload)
- {
- /* Add an overload option. */
- *m_pbCur++ = RTNET_DHCP_OPT_OPTION_OVERLOAD;
- *m_pbCur++ = fField;
- m_pfOverload = m_pbCur;
- *m_pbCur++ = 1; /* bp_file flag */
- }
- else
- *m_pfOverload |= fField;
+ RTNETADDRIPV4 address = getIpv4Address();
+ RTNETADDRIPV4 netmask = getIpv4Netmask();
+ RTNETADDRIPV4 networkId;
+ networkId.u = address.u & netmask.u;
- /* pad current option field */
- while (m_pbCur != m_pbEnd)
- *m_pbCur++ = RTNET_DHCP_OPT_PAD; /** @todo not sure if this stuff is at all correct... */
+ RTNETADDRIPV4 UpperAddress;
+ RTNETADDRIPV4 LowerAddress = networkId;
+ UpperAddress.u = RT_H2N_U32(RT_N2H_U32(LowerAddress.u) | RT_N2H_U32(netmask.u));
- /* switch */
- m_pbCur = pbNew;
- m_pbEnd = pbNewEnd;
- return true;
- }
-
- /**
- * Begin an option.
- *
- * @returns true on success, false if we're out of space.
- *
- * @param uOption The option number.
- * @param cb The amount of data.
- */
- bool begin(uint8_t uOption, size_t cb)
+ for (it = CmdParameterll.begin(); it != CmdParameterll.end(); ++it)
{
- /* Check that the data of the previous option has all been written. */
- Assert( !m_pOpt
- || (m_pbCur - m_pOpt->dhcp_len == (uint8_t *)(m_pOpt + 1)));
- AssertMsg(cb <= 255, ("%#x\n", cb));
-
- /* Check if we need to overload more stuff. */
- if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + (m_pfOverload ? 1 : 3))
+ switch(it->Key)
{
- m_pOpt = NULL;
- if (!overloadMore())
- {
- m_fOverflowed = true;
- AssertMsgFailedReturn(("%u %#x\n", uOption, cb), false);
- }
- if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + 1)
- {
- m_fOverflowed = true;
- AssertMsgFailedReturn(("%u %#x\n", uOption, cb), false);
- }
- }
+ case 'l':
+ RTNetStrToIPv4Addr(it->strValue.c_str(), &LowerAddress);
+ break;
- /* Emit the option header. */
- m_pOpt = (PRTNETDHCPOPT)m_pbCur;
- m_pOpt->dhcp_opt = uOption;
- m_pOpt->dhcp_len = (uint8_t)cb;
- m_pbCur += 2;
- return true;
- }
+ case 'u':
+ RTNetStrToIPv4Addr(it->strValue.c_str(), &UpperAddress);
+ break;
+ case 'b':
+ break;
- /**
- * Puts option data.
- *
- * @param pvData The data.
- * @param cb The amount to put.
- */
- void put(void const *pvData, size_t cb)
- {
- Assert(m_pOpt || m_fOverflowed);
- if (RT_LIKELY(m_pOpt))
- {
- Assert((uintptr_t)m_pbCur - (uintptr_t)(m_pOpt + 1) + cb <= (size_t)m_pOpt->dhcp_len);
- memcpy(m_pbCur, pvData, cb);
- m_pbCur += cb;
}
}
- /**
- * Puts an IPv4 Address.
- *
- * @param IPv4Addr The address.
- */
- void putIPv4Addr(RTNETADDRIPV4 IPv4Addr)
- {
- put(&IPv4Addr, 4);
- }
+ ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
+ AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);
+ confManager->addNetwork(unconst(g_RootConfig),
+ networkId,
+ netmask,
+ LowerAddress,
+ UpperAddress);
- /**
- * Adds an IPv4 address option.
- *
- * @returns true/false just like begin().
- *
- * @param uOption The option number.
- * @param IPv4Addr The address.
- */
- bool optIPv4Addr(uint8_t uOption, RTNETADDRIPV4 IPv4Addr)
- {
- if (!begin(uOption, 4))
- return false;
- putIPv4Addr(IPv4Addr);
- return true;
- }
+ return VINF_SUCCESS;
+}
- /**
- * Adds an option taking 1 or more IPv4 address.
- *
- * If the vector contains no addresses, the option will not be added.
- *
- * @returns true/false just like begin().
- *
- * @param uOption The option number.
- * @param rIPv4Addrs Reference to the address vector.
- */
- bool optIPv4Addrs(uint8_t uOption, std::vector<RTNETADDRIPV4> const &rIPv4Addrs)
- {
- size_t const c = rIPv4Addrs.size();
- if (!c)
- return true;
-
- if (!begin(uOption, 4*c))
- return false;
- for (size_t i = 0; i < c; i++)
- putIPv4Addr(rIPv4Addrs[i]);
- return true;
- }
- /**
- * Puts an 8-bit integer.
- *
- * @param u8 The integer.
+int VBoxNetDhcp::initWithMain()
+{
+ /* ok, here we should initiate instance of dhcp server
+ * and listener for Dhcp configuration events
*/
- void putU8(uint8_t u8)
- {
- put(&u8, 1);
- }
+ AssertRCReturn(virtualbox.isNull(), VERR_INTERNAL_ERROR);
+ std::string networkName = getNetwork();
- /**
- * Adds an 8-bit integer option.
- *
- * @returns true/false just like begin().
- *
- * @param uOption The option number.
- * @param u8 The integer
- */
- bool optU8(uint8_t uOption, uint8_t u8)
- {
- if (!begin(uOption, 1))
- return false;
- putU8(u8);
- return true;
- }
+ int rc = findDhcpServer(virtualbox, networkName, m_DhcpServer);
+ AssertRCReturn(rc, rc);
- /**
- * Puts an 32-bit integer (network endian).
- *
- * @param u32Network The integer.
- */
- void putU32(uint32_t u32)
- {
- put(&u32, 4);
- }
+ rc = findNatNetwork(virtualbox, networkName, m_NATNetwork);
+ AssertRCReturn(rc, rc);
- /**
- * Adds an 32-bit integer (network endian) option.
- *
- * @returns true/false just like begin().
- *
- * @param uOption The option number.
- * @param u32Network The integer.
- */
- bool optU32(uint8_t uOption, uint32_t u32)
- {
- if (!begin(uOption, 4))
- return false;
- putU32(u32);
- return true;
- }
+ BOOL fNeedDhcpServer = isDhcpRequired(m_NATNetwork);
+ if (!fNeedDhcpServer)
+ return VERR_CANCELLED;
- /**
- * Puts a std::string.
- *
- * @param rStr Reference to the string.
- */
- void putStr(std::string const &rStr)
- {
- put(rStr.c_str(), rStr.size());
- }
+ RTNETADDRIPV4 gateway;
+ com::Bstr strGateway;
+ HRESULT hrc = m_NATNetwork->COMGETTER(Gateway)(strGateway.asOutParam());
+ AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
+ RTNetStrToIPv4Addr(com::Utf8Str(strGateway).c_str(), &gateway);
- /**
- * Adds an std::string option if the string isn't empty.
- *
- * @returns true/false just like begin().
- *
- * @param uOption The option number.
- * @param rStr Reference to the string.
- */
- bool optStr(uint8_t uOption, std::string const &rStr)
- {
- const size_t cch = rStr.size();
- if (!cch)
- return true;
-
- if (!begin(uOption, cch))
- return false;
- put(rStr.c_str(), cch);
- return true;
- }
+ ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
+ AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);
+ confManager->addToAddressList(RTNET_DHCP_OPT_ROUTERS, gateway);
- /**
- * Whether we've overflowed.
- *
- * @returns true on overflow, false otherwise.
- */
- bool hasOverflowed(void) const
- {
- return m_fOverflowed;
- }
+ rc = fetchAndUpdateDnsInfo();
+ AssertMsgRCReturn(rc, ("Wasn't able to fetch Dns info"), rc);
- /**
- * Adds the terminating END option.
- *
- * The END will always be added as we're reserving room for it, however, we
- * might have dropped previous options due to overflows and that is what the
- * return status indicates.
- *
- * @returns true on success, false on a (previous) overflow.
- */
- bool optEnd(void)
- {
- Assert((uintptr_t)(m_pbEnd - m_pbCur) < 4096);
- *m_pbCur++ = RTNET_DHCP_OPT_END;
- return !hasOverflowed();
- }
-};
+ ComEventTypeArray aVBoxEvents;
+ aVBoxEvents.push_back(VBoxEventType_OnHostNameResolutionConfigurationChange);
+ rc = createNatListener(m_vboxListener, virtualbox, this, aVBoxEvents);
+ AssertRCReturn(rc, rc);
+ RTNETADDRIPV4 LowerAddress;
+ rc = configGetBoundryAddress(m_DhcpServer, false, LowerAddress);
+ AssertMsgRCReturn(rc, ("can't get lower boundrary adderss'"),rc);
-/**
- * Constructs and sends a reply to a client.
- *
- * @returns
- * @param uMsgType The DHCP message type.
- * @param pLease The lease. This can be NULL for some replies.
- * @param pDhcpMsg The client message. We will dig out the MAC address,
- * transaction ID, and requested options from this.
- * @param cb The size of the client message.
- */
-void VBoxNetDhcp::makeDhcpReply(uint8_t uMsgType, VBoxNetDhcpLease *pLease, PCRTNETBOOTP pDhcpMsg, size_t cb)
-{
- size_t cbReply = RTNET_DHCP_NORMAL_SIZE; /** @todo respect the RTNET_DHCP_OPT_MAX_DHCP_MSG_SIZE option */
- PRTNETBOOTP pReply = (PRTNETBOOTP)alloca(cbReply);
+ RTNETADDRIPV4 UpperAddress;
+ rc = configGetBoundryAddress(m_DhcpServer, true, UpperAddress);
+ AssertMsgRCReturn(rc, ("can't get upper boundrary adderss'"),rc);
- /*
- * The fixed bits stuff.
- */
- pReply->bp_op = RTNETBOOTP_OP_REPLY;
- pReply->bp_htype = RTNET_ARP_ETHER;
- pReply->bp_hlen = sizeof(RTMAC);
- pReply->bp_hops = 0;
- pReply->bp_xid = pDhcpMsg->bp_xid;
- pReply->bp_secs = 0;
- pReply->bp_flags = 0; // (pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST); ??
- pReply->bp_ciaddr.u = 0;
- pReply->bp_yiaddr.u = pLease ? pLease->m_IPv4Address.u : 0xffffffff;
- pReply->bp_siaddr.u = pLease && pLease->m_pCfg ? pLease->m_pCfg->m_TftpServerAddr.u : 0; /* (next server == TFTP)*/
- pReply->bp_giaddr.u = 0;
- memset(&pReply->bp_chaddr, '\0', sizeof(pReply->bp_chaddr));
- pReply->bp_chaddr.Mac = pDhcpMsg->bp_chaddr.Mac;
- memset(&pReply->bp_sname[0], '\0', sizeof(pReply->bp_sname));
- memset(&pReply->bp_file[0], '\0', sizeof(pReply->bp_file));
- pReply->bp_vend.Dhcp.dhcp_cookie = RT_H2N_U32_C(RTNET_DHCP_COOKIE);
- memset(&pReply->bp_vend.Dhcp.dhcp_opts[0], '\0', RTNET_DHCP_OPT_SIZE);
+ RTNETADDRIPV4 address = getIpv4Address();
+ RTNETADDRIPV4 netmask = getIpv4Netmask();
+ RTNETADDRIPV4 networkId = networkid(address, netmask);
+ std::string name = std::string("default");
- /*
- * The options - use a cursor class for dealing with the ugly stuff.
- */
- VBoxNetDhcpWriteCursor Cursor(pReply, cbReply);
+ confManager->addNetwork(unconst(g_RootConfig),
+ networkId,
+ netmask,
+ LowerAddress,
+ UpperAddress);
- /* The basics */
- Cursor.optU8(RTNET_DHCP_OPT_MSG_TYPE, uMsgType);
- Cursor.optIPv4Addr(RTNET_DHCP_OPT_SERVER_ID, m_Ipv4Address);
+ com::Bstr bstr;
+ hrc = virtualbox->COMGETTER(HomeFolder)(bstr.asOutParam());
+ com::Utf8StrFmt strXmlLeaseFile("%ls%c%s.leases",
+ bstr.raw(), RTPATH_DELIMITER, networkName.c_str());
+ confManager->loadFromFile(strXmlLeaseFile);
- if (uMsgType != RTNET_DHCP_MT_NAC)
- {
- AssertReturnVoid(pLease && pLease->m_pCfg);
- const VBoxNetDhcpCfg *pCfg = pLease->m_pCfg; /* no need to retain it. */
-
- /* The IP config. */
- Cursor.optU32(RTNET_DHCP_OPT_LEASE_TIME, RT_H2N_U32(pCfg->m_cSecLease));
- Cursor.optIPv4Addr(RTNET_DHCP_OPT_SUBNET_MASK, pCfg->m_SubnetMask);
- Cursor.optIPv4Addrs(RTNET_DHCP_OPT_ROUTERS, pCfg->m_Routers);
- Cursor.optIPv4Addrs(RTNET_DHCP_OPT_ROUTERS, pCfg->m_DNSes);
- Cursor.optStr(RTNET_DHCP_OPT_HOST_NAME, pCfg->m_HostName);
- Cursor.optStr(RTNET_DHCP_OPT_DOMAIN_NAME, pCfg->m_DomainName);
-
- /* The PXE config. */
- if (pCfg->m_BootfileName.size())
- {
- if (Cursor.useBpFile())
- RTStrPrintf((char *)&pReply->bp_file[0], sizeof(pReply->bp_file), "%s", pCfg->m_BootfileName.c_str());
- else
- Cursor.optStr(RTNET_DHCP_OPT_BOOTFILE_NAME, pCfg->m_BootfileName);
- }
- }
-
- /* Terminate the options. */
- if (!Cursor.optEnd())
- debugPrint(0, true, "option overflow\n");
-
- /*
- * Send it.
- */
- int rc;
-#if 0
- if (!(pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST)) /** @todo need to see someone set this flag to check that it's correct. */
- {
- RTNETADDRIPV4 IPv4AddrBrdCast;
- IPv4AddrBrdCast.u = UINT32_C(0xffffffff); /* broadcast IP */
- rc = VBoxNetUDPUnicast(m_pSession, m_hIf, m_pIfBuf,
- m_Ipv4Address, &m_MacAddress, RTNETIPV4_PORT_BOOTPS, /* sender */
- IPv4AddrBrdCast, &pDhcpMsg->bp_chaddr.Mac, RTNETIPV4_PORT_BOOTPC, /* receiver */
- pReply, cbReply);
- }
- else
-#endif
- rc = VBoxNetUDPBroadcast(m_pSession, m_hIf, m_pIfBuf,
- m_Ipv4Address, &m_MacAddress, RTNETIPV4_PORT_BOOTPS, /* sender */
- RTNETIPV4_PORT_BOOTPC, /* receiver port */
- pReply, cbReply);
- if (RT_FAILURE(rc))
- debugPrint(0, true, "error %Rrc when sending the reply", rc);
+ return VINF_SUCCESS;
}
-/**
- * Look up a lease by MAC address.
- *
- * @returns Pointer to the lease if found, NULL if not found.
- * @param pMacAddress The mac address.
- * @param fAnyState Any state.
- */
-VBoxNetDhcpLease *VBoxNetDhcp::findLeaseByMacAddress(PCRTMAC pMacAddress, bool fAnyState)
+int VBoxNetDhcp::fetchAndUpdateDnsInfo()
{
- size_t iLease = m_Leases.size();
- while (iLease-- > 0)
+ ComHostPtr host;
+ if (SUCCEEDED(virtualbox->COMGETTER(Host)(host.asOutParam())))
{
- VBoxNetDhcpLease *pLease = &m_Leases[iLease];
- if ( pLease
- && pLease->m_MacAddress.au16[0] == pMacAddress->au16[0]
- && pLease->m_MacAddress.au16[1] == pMacAddress->au16[1]
- && pLease->m_MacAddress.au16[2] == pMacAddress->au16[2]
- && ( fAnyState
- || (pLease->m_enmState != VBoxNetDhcpLease::kState_Free)) )
- return pLease;
- }
+ AddressToOffsetMapping mapIp4Addr2Off;
+ int rc = localMappings(m_NATNetwork, mapIp4Addr2Off);
+ /* XXX: here could be several cases: 1. COM error, 2. not found (empty) 3. ? */
+ AssertMsgRCReturn(rc, ("Can't fetch local mappings"), rc);
- return NULL;
-}
+ RTNETADDRIPV4 address = getIpv4Address();
+ RTNETADDRIPV4 netmask = getIpv4Netmask();
+ AddressList nameservers;
+ rc = hostDnsServers(host, networkid(address, netmask), mapIp4Addr2Off, nameservers);
+ AssertMsgRCReturn(rc, ("Debug me!!!"), rc);
+ /* XXX: Search strings */
-/**
- * Look up a lease by IPv4 and MAC addresses.
- *
- * @returns Pointer to the lease if found, NULL if not found.
- * @param IPv4Addr The IPv4 address.
- * @param pMacAddress The mac address.
- * @param fAnyState Any state.
- */
-VBoxNetDhcpLease *VBoxNetDhcp::findLeaseByIpv4AndMacAddresses(RTNETADDRIPV4 IPv4Addr, PCRTMAC pMacAddress, bool fAnyState)
-{
- size_t iLease = m_Leases.size();
- while (iLease-- > 0)
- {
- VBoxNetDhcpLease *pLease = &m_Leases[iLease];
- if ( pLease
- && pLease->m_IPv4Address.u == IPv4Addr.u
- && pLease->m_MacAddress.au16[0] == pMacAddress->au16[0]
- && pLease->m_MacAddress.au16[1] == pMacAddress->au16[1]
- && pLease->m_MacAddress.au16[2] == pMacAddress->au16[2]
- && ( fAnyState
- || (pLease->m_enmState != VBoxNetDhcpLease::kState_Free)) )
- return pLease;
- }
-
- return NULL;
-}
-
+ std::string domain;
+ rc = hostDnsDomain(host, domain);
+ AssertMsgRCReturn(rc, ("Debug me!!"), rc);
-/**
- * Creates a new lease for the client specified in the DHCP message.
- *
- * The caller has already made sure it doesn't already have a lease.
- *
- * @returns Pointer to the lease if found, NULL+log if not found.
- * @param IPv4Addr The IPv4 address.
- * @param pMacAddress The MAC address.
- */
-VBoxNetDhcpLease *VBoxNetDhcp::newLease(PCRTNETBOOTP pDhcpMsg, size_t cb)
-{
- RTMAC const MacAddr = pDhcpMsg->bp_chaddr.Mac;
- RTTIMESPEC Now;
- RTTimeNow(&Now);
-
- /*
- * Search the possible leases.
- *
- * We'll try do all the searches in one pass, that is to say, perfect
- * match, old lease, and next free/expired lease.
- */
- VBoxNetDhcpLease *pBest = NULL;
- VBoxNetDhcpLease *pOld = NULL;
- VBoxNetDhcpLease *pFree = NULL;
-
- size_t cLeases = m_Leases.size();
- for (size_t i = 0; i < cLeases; i++)
- {
- VBoxNetDhcpLease *pCur = &m_Leases[i];
-
- /* Skip it if no configuration, that means its not in the current config. */
- if (!pCur->m_pCfg)
- continue;
-
- /* best */
- if ( pCur->isOneSpecificClient()
- && pCur->m_pCfg->matchesMacAddress(&MacAddr))
{
- if ( !pBest
- || pBest->m_pCfg->m_MacAddresses.size() < pCur->m_pCfg->m_MacAddresses.size())
- pBest = pCur;
- }
+ VBoxNetALock(this);
+ ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
+ confManager->flushAddressList(RTNET_DHCP_OPT_DNS);
- /* old lease */
- if ( pCur->m_MacAddress.au16[0] == MacAddr.au16[0]
- && pCur->m_MacAddress.au16[1] == MacAddr.au16[1]
- && pCur->m_MacAddress.au16[2] == MacAddr.au16[2])
- {
- if ( !pOld
- || RTTimeSpecGetSeconds(&pCur->m_ExpireTime) > RTTimeSpecGetSeconds(&pFree->m_ExpireTime))
- pOld = pCur;
- }
+ for (AddressList::iterator it = nameservers.begin(); it != nameservers.end(); ++it)
+ confManager->addToAddressList(RTNET_DHCP_OPT_DNS, *it);
- /* expired lease */
- if (!pCur->isInUse(&Now))
- {
- if ( !pFree
- || RTTimeSpecGetSeconds(&pCur->m_ExpireTime) < RTTimeSpecGetSeconds(&pFree->m_ExpireTime))
- pFree = pCur;
+ confManager->setString(RTNET_DHCP_OPT_DOMAIN_NAME, domain);
}
}
- VBoxNetDhcpLease *pNew = pBest;
- if (!pNew)
- pNew = pOld;
- if (!pNew)
- pNew = pFree;
- if (!pNew)
- {
- debugPrint(0, true, "No more leases.");
- return NULL;
- }
-
- /*
- * Init the lease.
- */
- pNew->m_MacAddress = MacAddr;
- pNew->m_xid = pDhcpMsg->bp_xid;
- /** @todo extract the client id. */
-
- return pNew;
+ return VINF_SUCCESS;
}
-/**
- * Finds an option.
- *
- * @returns On success, a pointer to the first byte in the option data (no none
- * then it'll be the byte following the 0 size field) and *pcbOpt set
- * to the option length.
- * On failure, NULL is returned and *pcbOpt unchanged.
- *
- * @param uOption The option to search for.
- * @param pDhcpMsg The DHCP message.
- * @param cb The size of the message.
- * @param pcbOpt Where to store the option size size. Optional. Note
- * that this is adjusted if the option length is larger
- * than the message buffer.
- */
-/* static */ const uint8_t *
-VBoxNetDhcp::findOption(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cb, size_t *pcbOpt)
+HRESULT VBoxNetDhcp::HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent)
{
- Assert(uOption != RTNET_DHCP_OPT_PAD);
-
- /*
- * Validate the DHCP bits and figure the max size of the options in the vendor field.
- */
- if (cb <= RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts))
- return NULL;
- if (pDhcpMsg->bp_vend.Dhcp.dhcp_cookie != RT_H2N_U32_C(RTNET_DHCP_COOKIE))
- return NULL;
- size_t cbLeft = cb - RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts);
- if (cbLeft > RTNET_DHCP_OPT_SIZE)
- cbLeft = RTNET_DHCP_OPT_SIZE;
-
- /*
- * Search the vendor field.
- */
- bool fExtended = false;
- uint8_t const *pb = &pDhcpMsg->bp_vend.Dhcp.dhcp_opts[0];
- while (pb && cbLeft > 0)
+ switch(aEventType)
{
- uint8_t uCur = *pb;
- if (uCur == RTNET_DHCP_OPT_PAD)
- {
- cbLeft--;
- pb++;
- }
- else if (cbLeft <= 1)
+ case VBoxEventType_OnHostNameResolutionConfigurationChange:
+ fetchAndUpdateDnsInfo();
break;
- else
- {
- size_t cbCur = pb[1];
- if (cbCur > cbLeft - 2)
- cbCur = cbLeft - 2;
- if (uCur == uOption)
- {
- if (pcbOpt)
- *pcbOpt = cbCur;
- return pb+2;
- }
- pb += cbCur + 2;
- cbLeft -= cbCur - 2;
- }
- }
-
- /** @todo search extended dhcp option field(s) when present */
-
- return NULL;
-}
-
-
-/**
- * Locates an option with an IPv4 address in the DHCP message.
- *
- * @returns true and *pIpv4Addr if found, false if not.
- *
- * @param uOption The option to find.
- * @param pDhcpMsg The DHCP message.
- * @param cb The size of the message.
- * @param pIPv4Addr Where to put the address.
- */
-/* static */ bool
-VBoxNetDhcp::findOptionIPv4Addr(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cb, PRTNETADDRIPV4 pIPv4Addr)
-{
- size_t cbOpt;
- uint8_t const *pbOpt = findOption(uOption, pDhcpMsg, cb, &cbOpt);
- if (pbOpt)
- {
- if (cbOpt >= sizeof(RTNETADDRIPV4))
- {
- *pIPv4Addr = *(PCRTNETADDRIPV4)pbOpt;
- return true;
- }
- }
- return false;
-}
-
-
-/**
- * Print debug message depending on the m_cVerbosity level.
- *
- * @param iMinLevel The minimum m_cVerbosity level for this message.
- * @param fMsg Whether to dump parts for the current DHCP message.
- * @param pszFmt The message format string.
- * @param ... Optional arguments.
- */
-inline void VBoxNetDhcp::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);
- }
-}
-
-
-/**
- * Print debug message depending on the m_cVerbosity level.
- *
- * @param iMinLevel The minimum m_cVerbosity level for this message.
- * @param fMsg Whether to dump parts for the current DHCP message.
- * @param pszFmt The message format string.
- * @param va Optional arguments.
- */
-void VBoxNetDhcp::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
-{
- if (iMinLevel <= m_cVerbosity)
- {
- va_list vaCopy; /* This dude is *very* special, thus the copy. */
- va_copy(vaCopy, va);
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: %s: %N\n", iMinLevel >= 2 ? "debug" : "info", pszFmt, &vaCopy);
- va_end(vaCopy);
-
- if ( fMsg
- && m_cVerbosity >= 2
- && m_pCurMsg)
- {
- const char *pszMsg = m_uCurMsgType != UINT8_MAX ? debugDhcpName(m_uCurMsgType) : "";
- RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: debug: %8s chaddr=%.6Rhxs ciaddr=%d.%d.%d.%d yiaddr=%d.%d.%d.%d siaddr=%d.%d.%d.%d xid=%#x\n",
- pszMsg,
- &m_pCurMsg->bp_chaddr,
- m_pCurMsg->bp_ciaddr.au8[0], m_pCurMsg->bp_ciaddr.au8[1], m_pCurMsg->bp_ciaddr.au8[2], m_pCurMsg->bp_ciaddr.au8[3],
- m_pCurMsg->bp_yiaddr.au8[0], m_pCurMsg->bp_yiaddr.au8[1], m_pCurMsg->bp_yiaddr.au8[2], m_pCurMsg->bp_yiaddr.au8[3],
- m_pCurMsg->bp_siaddr.au8[0], m_pCurMsg->bp_siaddr.au8[1], m_pCurMsg->bp_siaddr.au8[2], m_pCurMsg->bp_siaddr.au8[3],
- m_pCurMsg->bp_xid);
- }
}
-}
-
-/**
- * Gets the name of given DHCP message type.
- *
- * @returns Readonly name.
- * @param uMsgType The message number.
- */
-/* static */ const char *VBoxNetDhcp::debugDhcpName(uint8_t uMsgType)
-{
- switch (uMsgType)
- {
- case 0: return "MT_00";
- case RTNET_DHCP_MT_DISCOVER: return "DISCOVER";
- case RTNET_DHCP_MT_OFFER: return "OFFER";
- case RTNET_DHCP_MT_REQUEST: return "REQUEST";
- case RTNET_DHCP_MT_DECLINE: return "DECLINE";
- case RTNET_DHCP_MT_ACK: return "ACK";
- case RTNET_DHCP_MT_NAC: return "NAC";
- case RTNET_DHCP_MT_RELEASE: return "RELEASE";
- case RTNET_DHCP_MT_INFORM: return "INFORM";
- case 9: return "MT_09";
- case 10: return "MT_0a";
- case 11: return "MT_0b";
- case 12: return "MT_0c";
- case 13: return "MT_0d";
- case 14: return "MT_0e";
- case 15: return "MT_0f";
- case 16: return "MT_10";
- case 17: return "MT_11";
- case 18: return "MT_12";
- case 19: return "MT_13";
- case UINT8_MAX: return "MT_ff";
- default: return "UNKNOWN";
- }
+ return S_OK;
}
-
-
/**
* Entry point.
*/
-extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
+extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv)
{
/*
* Instantiate the DHCP server and hand it the options.
*/
+
VBoxNetDhcp *pDhcp = new VBoxNetDhcp();
if (!pDhcp)
{
@@ -2012,14 +618,16 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
if (rc)
return rc;
+ pDhcp->init();
+
/*
* Try connect the server to the network.
*/
rc = pDhcp->tryGoOnline();
- if (rc)
+ if (RT_FAILURE(rc))
{
delete pDhcp;
- return rc;
+ return 1;
}
/*
@@ -2030,19 +638,19 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
g_pDhcp = NULL;
delete pDhcp;
- return rc;
+ return 0;
}
#ifndef VBOX_WITH_HARDENING
-int main(int argc, char **argv, char **envp)
+int main(int argc, char **argv)
{
int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);
if (RT_FAILURE(rc))
return RTMsgInitFailure(rc);
- return TrustedMain(argc, argv, envp);
+ return TrustedMain(argc, argv);
}
# ifdef RT_OS_WINDOWS
@@ -2061,7 +669,7 @@ static LRESULT CALLBACK WindowProc(HWND hwnd,
return DefWindowProc (hwnd, uMsg, wParam, lParam);
}
-static LPCSTR g_WndClassName = "VBoxNetDHCPClass";
+static LPCWSTR g_WndClassName = L"VBoxNetDHCPClass";
static DWORD WINAPI MsgThreadProc(__in LPVOID lpParameter)
{
@@ -2139,7 +747,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
if(hThread != NULL)
CloseHandle(hThread);
- return main(__argc, __argv, environ);
+ return main(__argc, __argv);
}
# endif /* RT_OS_WINDOWS */