Config.cpp revision e96c3345fd904eb75ce43234d620daba5e3aa639
/* $Id$ */
/**
* XXX: license.
*/
#include <VBox/intnetinline.h>
#include "../NetLib/VBoxNetLib.h"
#include "../NetLib/shared_ptr.h"
#include <list>
#include <vector>
#include <map>
#include <string>
#include "Config.h"
#include "ClientDataInt.h"
{
}
{
}
{
}
/* consts */
static ConfigurationManager *g_ConfigurationManager = ConfigurationManager::getConfigurationManager();
{
}
{
if (m_children.empty())
{
if (iMatch > 0)
{
*cfg = this;
return iMatch;
}
}
else
{
*cfg = this;
/* XXX: hack */
BaseConfigEntity *matching = this;
int matchingLevel = m_MatchLevel;
++it)
{
if (iMatch > matchingLevel)
{
}
}
return matchingLevel;
}
return iMatch;
}
/* Client */
/* Configs
NetworkConfigEntity(std::string name,
ConfigEntity* pCfg,
ClientMatchCriteria* criteria,
RTNETADDRIPV4& networkID,
RTNETADDRIPV4& networkMask)
*/
static const RTNETADDRIPV4 g_AnyIpv4 = {0};
{
m_MatchLevel = 2;
}
/* Configuration Manager */
struct ConfigurationManager::Data
{
Data():fFileExists(false){}
bool fFileExists;
};
{
if (!g_ConfigurationManager)
{
}
return g_ConfigurationManager;
}
/**
* <Leases version="1.0">
* <Lease mac="" network=""/>
* <Address value=""/>
* <Time issued="" expiration=""/>
* <options>
* <option name="" type=""/>
* </option>
* </options>
* </Lease>
* </Leases>
*/
{
try {
}
catch (...)
{
return VINF_SUCCESS;
}
/* XML parsing */
{
m->fFileExists = false;
return VERR_NOT_FOUND;
}
if (root)
/* XXX: version check */
bool valueExists;
{
continue;
{
}
}
return VINF_SUCCESS;
}
int ConfigurationManager::saveToFile()
{
if (m->m_leaseStorageFilename.empty())
return VINF_SUCCESS;
if (!root)
return VERR_INTERNAL_ERROR;
{
{
/* XXX: todo logging + error handling */
}
}
try {
} catch(...){}
return VINF_SUCCESS;
}
int ConfigurationManager::extractRequestList(PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& rawOpt)
{
return ConfigurationManager::findOption(RTNET_DHCP_OPT_PARAM_REQ_LIST, pDhcpMsg, cbDhcpMsg, rawOpt);
}
{
bool fDhcpValid = false;
/* 1st. client IDs */
++it)
{
{
/* check timestamp that request wasn't expired. */
return (*it);
}
}
{
/* We hasn't got any session for this client */
Client c;
}
return Client::NullClient;
}
/**
* 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.
* that this is adjusted if the option length is larger
* than the message buffer.
*/
int
ConfigurationManager::findOption(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& opt)
{
/*
* Validate the DHCP bits and figure the max size of the options in the vendor field.
*/
return VERR_INVALID_PARAMETER;
return VERR_INVALID_PARAMETER;
if (cbLeft > RTNET_DHCP_OPT_SIZE)
/*
* Search the vendor field.
*/
bool fExtended = false;
{
if (uCur == RTNET_DHCP_OPT_PAD)
{
cbLeft--;
pb++;
}
else if (cbLeft <= 1)
break;
else
{
{
return VINF_SUCCESS;
}
}
}
/** @todo search extended dhcp option field(s) when present */
return VERR_NOT_FOUND;
}
/**
* We bind lease for client till it continue with it on DHCPREQUEST.
*/
Lease ConfigurationManager::allocateLease4Client(const Client& client, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg)
{
{
/**
* This mean that client has already bound or commited lease.
* If we've it happens it means that we received DHCPDISCOVER twice.
*/
{
/* Here we should take lease from the m_allocation which was feed with leases
* on start
*/
if (l.isExpired())
{
if (!l.isExpired())
return l;
}
else
{
return l;
}
}
}
/* DHCPDISCOVER MAY contain request address */
hintAddress.u = 0;
if (RT_SUCCESS(rc))
{
hintAddress.u = 0; /* clear hint */
}
if ( hintAddress.u
&& !isAddressTaken(hintAddress))
{
return l;
}
++u32)
{
if (!isAddressTaken(address))
{
l.setAddress(address);
return l;
}
}
}
{
l.bindingPhase(false);
l.phaseStart(RTTimeMilliTS());
saveToFile();
return VINF_SUCCESS;
}
{
if (l.isInBindingPhase())
{
/*
* XXX: perhaps it better to keep this allocation ????
*/
l.expire();
return VINF_SUCCESS;
}
return VINF_SUCCESS;
}
{
++it)
{
{
return true;
}
}
return false;
}
{
}
const RTNETADDRIPV4& networkId,
const RTNETADDRIPV4& netmask,
{
static int id;
char name[64];
id++;
if (!LowerAddress.u)
if (!UpperAddress.u)
return new NetworkConfigEntity(strname,
5,
}
const RTNETADDRIPV4& address,
{
static int id;
char name[64];
id++;
}
{
switch(u8OptId)
{
case RTNET_DHCP_OPT_DNS:
break;
case RTNET_DHCP_OPT_ROUTERS:
break;
default:
}
return VINF_SUCCESS;
}
{
switch(u8OptId)
{
case RTNET_DHCP_OPT_DNS:
m->m_nameservers.clear();
break;
case RTNET_DHCP_OPT_ROUTERS:
break;
default:
}
return VINF_SUCCESS;
}
{
switch(u8OptId)
{
case RTNET_DHCP_OPT_DNS:
return m->m_nameservers;
case RTNET_DHCP_OPT_ROUTERS:
return m->m_routers;
}
/* XXX: Grrr !!! */
return m_empty;
}
{
switch (u8OptId)
{
m->m_domainName = str;
break;
default:
break;
}
return VINF_SUCCESS;
}
{
switch (u8OptId)
{
if (m->m_domainName.length())
return m->m_domainName;
else
return m_noString;
default:
break;
}
return m_noString;
}
void ConfigurationManager::init()
{
m = new ConfigurationManager::Data();
}
ConfigurationManager::~ConfigurationManager() { if (m) delete m; }
/**
* Network manager
*/
struct NetworkManager::Data
{
Data()
{
cbBooPReplyMsg = 0;
m_OurAddress.u = 0;
m_OurNetmask.u = 0;
}
union {
int cbBooPReplyMsg;
/* XXX: artifacts should be hidden or removed from here. */
};
{
m = new NetworkManager::Data();
}
{
delete m;
m = NULL;
}
{
if (!g_NetworkManager)
g_NetworkManager = new NetworkManager();
return g_NetworkManager;
}
{
return m->m_OurAddress;
}
{
return m->m_OurNetmask;
}
{
return m->m_OurMac;
}
{
m->m_OurAddress = aAddress;
}
{
m->m_OurNetmask = aNetmask;
}
{
}
{
m->m_pSession = aSession;
}
{
}
{
}
/**
* Network manager creates DHCPOFFER datagramm
*/
{
/* Ubuntu ???*/
/* options:
* - IP lease time
* - message type
* - server identifier
*/
}
/**
* Network manager creates DHCPACK
*/
{
address = l.getAddress();
/* rfc2131 4.3.1 is about DHCPDISCOVER and this value is equal to ciaddr from
* DHCPREQUEST or 0 ...
* XXX: Using addressHint is not correct way to initialize [cy]iaddress...
*/
/* options:
* - IP address lease time (if DHCPREQUEST)
* - message type
* - server identifier
*/
/*
* XXX: lease time should be conditional. If on dhcprequest then tim should be provided,
* else on dhcpinform it mustn't.
*/
}
/**
* Network manager creates DHCPNAK
*/
{
return VERR_INTERNAL_ERROR;
/* this field filed in prepareReplyPacket4Session, and
* RFC 2131 require to have it zero fo NAK.
*/
/* options:
* - message type (if DHCPREQUEST)
* - server identifier
*/
}
/**
*
*/
{
RT_ZERO(m->BootPReplyMsg);
/* XXX: bp_flags should be processed specially */
'\0',
return VINF_SUCCESS;
}
{
int rc;
/*
Options....
*/
/* The basics */
{
break;
}
{
break;
}
/*
*/
#if 0
/** @todo need to see someone set this flag to check that it's correct. */
{
&m_OurMac,
RTNETIPV4_PORT_BOOTPS, /* sender */
RTNETIPV4_PORT_BOOTPC, /* receiver */
}
else
#endif
m->m_hIf,
m->m_pIfBuf,
m->m_OurAddress,
&m->m_OurMac,
RTNETIPV4_PORT_BOOTPS, /* sender */
return VINF_SUCCESS;
}
int NetworkManager::processParameterReqList(const Client& client, uint8_t *pu8ReqList, int cReqList)
{
/* request parameter list */
int idxParam = 0;
{
bool fIgnore = false;
{
break;
case RTNET_DHCP_OPT_ROUTERS:
case RTNET_DHCP_OPT_DNS:
{
const Ipv4AddressContainer lst =
++it)
{
*pAddresses = (*it);
pAddresses++;
}
fIgnore = true;
}
break;
{
{
fIgnore = true;
break;
}
}
break;
default:
fIgnore = true;
break;
}
if (!fIgnore)
}
return VINF_SUCCESS;
}
/* Utility */
{
}
/* Client */
{
m = SharedPtr<ClientData>();
}
{
}
{
}
{
return m->m_mac;
}
{
if (m->fHasLease)
return Lease(*this);
else
}
{
}
/* Lease */
{
m = SharedPtr<ClientData>();
}
{
m = SharedPtr<ClientData>(c.m);
if ( !m->fHasLease
|| ( isExpired()
&& !isInBindingPhase()))
{
m->fHasLease = true;
m->fBinding = true;
}
}
{
AssertPtrReturn(m.get(), false);
if (!m->fBinding)
> m->u32LeaseExpirationPeriod);
else
> m->u32BindExpirationPeriod);
}
{
/* XXX: TODO */
}
{
if (m->fBinding)
else
}
{
}
bool Lease::isInBindingPhase() const
{
return m->fBinding;
}
{
return m->u64TimestampLeasingStarted;
}
{
if (m->fBinding)
m->u32BindExpirationPeriod = exp;
else
m->u32LeaseExpirationPeriod = exp;
}
{
if (m->fBinding)
return m->u32BindExpirationPeriod;
else
return m->u32LeaseExpirationPeriod;
}
{
return m->m_address;
}
{
}
{
return m->pCfg;
}
{
}
{
return m->options;
}
{
return m->options;
}
{
bool valueAddition = node->setAttribute(tagXMLLeaseAttributeMac.c_str(), com::Utf8StrFmt("%RTmac", &m->m_mac));
if (!valueAddition) return false;
valueAddition = node->setAttribute(tagXMLLeaseAttributeNetwork.c_str(), com::Utf8StrFmt("%RTnaipv4", m->m_network));
if (!valueAddition) return false;
if (!address) return false;
valueAddition = address->setAttribute(tagXMLAddressAttributeValue.c_str(), com::Utf8StrFmt("%RTnaipv4", m->m_address));
if (!valueAddition) return false;
if (!time) return false;
if (!valueAddition) return false;
if (!valueAddition) return false;
return true;
}
{
if (!valueExists) return false;
if (RT_FAILURE(rc)) return false;
if (!valueExists) return false;
if (RT_FAILURE(rc)) return false;
/* Address */
if (!address) return false;
if (!valueExists) return false;
/* Time */
if (!time) return false;
if (!valueExists) return false;
m->fBinding = false;
&m->u32LeaseExpirationPeriod);
if (!valueExists) return false;
m->fHasLease = true;
return true;
}