int ConfigurationManager::commitLease4Client(Client& client)
{
    Lease l = client.lease();
    AssertReturn(l != Lease::NullLease, VERR_INTERNAL_ERROR);

    l.bindingPhase(false);
    const NetworkConfigEntity *pCfg = l.getConfig();

    AssertPtr(pCfg);
    l.setExpiration(pCfg->expirationPeriod());
    l.phaseStart(RTTimeMilliTS());

    saveToFile();

    return VINF_SUCCESS;
}
int NetworkManager::processParameterReqList(const Client& client, const uint8_t *pu8ReqList,
                                            int cReqList, std::vector<RawOption>& extra)
{
    int rc;

    const Lease l = client.lease();

    const NetworkConfigEntity *pNetCfg = l.getConfig();

    /*
     * XXX: Brute-force.  Unfortunately, there's no notification event
     * for changes.  Should at least cache the options for a short
     * time, enough to last discover/offer/request/ack cycle.
     */
    typedef std::map< int, std::pair<std::string, int> > DhcpOptionMap;
    DhcpOptionMap OptMap;

    if (!m->m_DhcpServer.isNull())
    {
        com::SafeArray<BSTR> strings;
        com::Bstr str;
        HRESULT hrc;
        int OptCode, OptEncoding;
        char *pszOptText;

        strings.setNull();
        hrc = m->m_DhcpServer->COMGETTER(GlobalOptions)(ComSafeArrayAsOutParam(strings));
        AssertComRC(hrc);
        for (size_t i = 0; i < strings.size(); ++i)
        {
            com::Utf8Str encoded(strings[i]);
            rc = parseDhcpOptionText(encoded.c_str(),
                                     &OptCode, &pszOptText, &OptEncoding);
            if (!RT_SUCCESS(rc))
                continue;

            OptMap[OptCode] = std::make_pair(pszOptText, OptEncoding);
        }

        const RTMAC &mac = client.getMacAddress();
        char strMac[6*2+1] = "";
        RTStrPrintf(strMac, sizeof(strMac), "%02x%02x%02x%02x%02x%02x",
                    mac.au8[0], mac.au8[1], mac.au8[2],
                    mac.au8[3], mac.au8[4], mac.au8[5]);

        strings.setNull();
        hrc = m->m_DhcpServer->GetMacOptions(com::Bstr(strMac).raw(),
                                             ComSafeArrayAsOutParam(strings));
        AssertComRC(hrc);
        for (size_t i = 0; i < strings.size(); ++i)
        {
            com::Utf8Str text(strings[i]);
            rc = parseDhcpOptionText(text.c_str(),
                                     &OptCode, &pszOptText, &OptEncoding);
            if (!RT_SUCCESS(rc))
                continue;

            OptMap[OptCode] = std::make_pair(pszOptText, OptEncoding);
        }
    }

    /* request parameter list */
    RawOption opt;
    bool fIgnore;
    uint8_t u8Req;
    for (int idxParam = 0; idxParam < cReqList; ++idxParam)
    {
        fIgnore = false;
        RT_ZERO(opt);
        u8Req = opt.u8OptId = pu8ReqList[idxParam];

        switch(u8Req)
        {
            case RTNET_DHCP_OPT_SUBNET_MASK:
                ((PRTNETADDRIPV4)opt.au8RawOpt)->u = pNetCfg->netmask().u;
                opt.cbRawOpt = sizeof(RTNETADDRIPV4);

                break;

            case RTNET_DHCP_OPT_ROUTERS:
            case RTNET_DHCP_OPT_DNS:
                {
                    const Ipv4AddressContainer lst =
                      g_ConfigurationManager->getAddressList(u8Req);
                    PRTNETADDRIPV4 pAddresses = (PRTNETADDRIPV4)&opt.au8RawOpt[0];

                    for (Ipv4AddressConstIterator it = lst.begin();
                         it != lst.end();
                         ++it)
                    {
                        *pAddresses = (*it);
                        pAddresses++;
                        opt.cbRawOpt += sizeof(RTNETADDRIPV4);
                    }

                    if (lst.empty())
                        fIgnore = true;
                }
                break;
            case RTNET_DHCP_OPT_DOMAIN_NAME:
                {
                    std::string domainName = g_ConfigurationManager->getString(u8Req);
                    if (domainName == g_ConfigurationManager->m_noString)
                    {
                        fIgnore = true;
                        break;
                    }

                    char *pszDomainName = (char *)&opt.au8RawOpt[0];

                    strcpy(pszDomainName, domainName.c_str());
                    opt.cbRawOpt = domainName.length();
                }
                break;
            default:
                {
                    DhcpOptionMap::const_iterator it = OptMap.find((int)u8Req);
                    if (it == OptMap.end())
                    {
                        Log(("opt: %d is ignored\n", u8Req));
                        fIgnore = true;
                    }
                    else
                    {
                        std::string OptText((*it).second.first);
                        int OptEncoding((*it).second.second);

                        rc = fillDhcpOption(opt, OptText, OptEncoding);
                        if (!RT_SUCCESS(rc))
                        {
                            fIgnore = true;
                            break;
                        }
                    }
                }
                break;
        }

        if (!fIgnore)
            extra.push_back(opt);

    }

    return VINF_SUCCESS;
}