VirtualBox

Changeset 47501 in vbox


Ignore:
Timestamp:
Aug 1, 2013 6:24:41 AM (11 years ago)
Author:
vboxsync
Message:

VBoxNetDHCP: removes session handling. binding and lease expiration control was added.

Location:
trunk/src/VBox/NetworkServices/DHCP
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/NetworkServices/DHCP/Config.cpp

    r47129 r47501  
    3636
    3737const NullConfigEntity *g_NullConfig = new NullConfigEntity();
    38 const RootConfigEntity *g_RootConfig = new RootConfigEntity(std::string("ROOT"));
     38RootConfigEntity *g_RootConfig = new RootConfigEntity(std::string("ROOT"), 1200 /* 20 min. */);
    3939const ClientMatchCriteria *g_AnyClient = new AnyClientMatchCriteria();
    4040
    41 static SessionManager *g_SessionManager = SessionManager::getSessionManager();
    4241static ConfigurationManager *g_ConfigurationManager = ConfigurationManager::getConfigurationManager();
    4342
    4443static NetworkManager *g_NetworkManager = NetworkManager::getNetworkManager();
    4544
     45
     46
    4647/* Client */
    4748
    48 Client::Client(const RTMAC& mac, uint32_t xid)
     49Client::Client(const RTMAC& mac)
    4950{
    5051    m_mac = mac;
    51     //    m_sessions.insert(Map2ClientSessionType(xid, Session(this, xid)));
    52 }
    53 
    54 /* Session */
    55 
    56 bool Session::operator < (const Session& s) const
    57 {
    58     return (m_u32Xid < s.m_u32Xid);
    59 }
    60 
    61 int Session::switchTo(CLIENTSESSIONSTATE enmState)
    62 {
    63     m_state = enmState;
    64     return VINF_SUCCESS;
     52    m_lease = NULL;
    6553}
    6654
     
    7462static const RTNETADDRIPV4 g_AnyIpv4 = {0};
    7563static const RTNETADDRIPV4 g_AllIpv4 = {0xffffffff};
    76 RootConfigEntity::RootConfigEntity(std::string name):
     64RootConfigEntity::RootConfigEntity(std::string name, uint32_t expPeriod):
    7765  NetworkConfigEntity(name, g_NullConfig, g_AnyClient, g_AnyIpv4, g_AllIpv4)
    7866{
    7967    m_MatchLevel = 2;
    80 }
    81 
    82 /* Session Manager */
    83 SessionManager *SessionManager::getSessionManager()
    84 {
    85     if (!g_SessionManager)
    86         g_SessionManager = new SessionManager();
    87     return g_SessionManager;
    88 }
    89 
    90 /*
    91  *  XXX: it sounds like a hack, we use packet descriptor to get the session,
    92  * instead use corresponding functions in NetworkManager to fetch client identification
    93  * (note: it isn't only mac driven) and XID for the session.
    94  */
    95 
    96 /**
    97  * XXX: what about leases ... Lease is a committed Session....
    98  */
    99 Session& SessionManager::getClientSessionByDhcpPacket(const RTNETBOOTP *pDhcpMsg, size_t cbDhcpMsg)
     68    m_u32ExpirationPeriod = expPeriod;
     69}
     70
     71
     72/* Configuration Manager */
     73ConfigurationManager *ConfigurationManager::getConfigurationManager()
     74{
     75    if (!g_ConfigurationManager)
     76        g_ConfigurationManager = new ConfigurationManager();
     77
     78    return g_ConfigurationManager;
     79}
     80
     81
     82int ConfigurationManager::extractRequestList(PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& rawOpt)
     83{
     84    return ConfigurationManager::findOption(RTNET_DHCP_OPT_PARAM_REQ_LIST, pDhcpMsg, cbDhcpMsg, rawOpt);
     85}
     86
     87
     88Client *ConfigurationManager::getClientByDhcpPacket(const RTNETBOOTP *pDhcpMsg, size_t cbDhcpMsg)
    10089{
    10190
     
    10392    bool fDhcpValid = false;
    10493    uint8_t uMsgType = 0;
    105 
     94   
    10695    fDhcpValid = RTNetIPv4IsDHCPValid(NULL, pDhcpMsg, cbDhcpMsg, &uMsgType);
    107     Assert(fDhcpValid);
    108 
     96    AssertReturn(fDhcpValid, NULL);
     97
     98    LogFlowFunc(("dhcp:mac:%RTmac\n", &pDhcpMsg->bp_chaddr.Mac));
    10999    /* 1st. client IDs */
    110100    for ( it = m_clients.begin();
     
    112102         ++it)
    113103    {
    114         /* OK. */
    115         if ((*it) == pDhcpMsg->bp_chaddr.Mac)
    116             break;
    117     }
    118 
    119     const uint32_t xid = pDhcpMsg->bp_xid;
     104        if (*(*it) == pDhcpMsg->bp_chaddr.Mac)
     105        {
     106            LogFlowFunc(("client:mac:%RTmac\n",  &(*it)->m_mac));
     107            /* check timestamp that request wasn't expired. */
     108            return (*it);
     109        }
     110    }
     111
    120112    if (it == m_clients.end())
    121113    {
    122114        /* We hasn't got any session for this client */
    123         m_clients.push_back(Client(pDhcpMsg->bp_chaddr.Mac,
    124                                    pDhcpMsg->bp_xid));
    125         Client& client = m_clients.back();
    126         client.m_sessions.insert(Map2ClientSessionType(xid, Session(&client, xid)));
    127         Assert(client.m_sessions[xid].m_pClient);
    128         return client.m_sessions[xid];
    129     }
    130 
    131     Session& session = it->m_sessions[xid];
    132     session.m_pClient = &(*it);
    133     session.m_u32Xid = xid;
    134 
    135     RawOption opt;
    136     int rc;
    137 
    138     switch(uMsgType)
    139     {
    140         case RTNET_DHCP_MT_DISCOVER:
    141             session.switchTo(DHCPDISCOVERRECEIEVED);
    142             /* MAY */
    143             rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cbDhcpMsg, opt);
    144             if (RT_SUCCESS(rc))
    145             {
    146                 /* hint for address allocation here */
    147                 session.addressHint = *(PRTNETADDRIPV4)opt.au8RawOpt;
    148             }
    149             /* MAY: todo */
    150             rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_LEASE_TIME, pDhcpMsg, cbDhcpMsg, opt);
    151 
    152             /* MAY: not now  */
    153             rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_CLIENT_ID, pDhcpMsg, cbDhcpMsg, opt);
    154             /* XXX: MAY
    155             ConfigurationManager::findOption(RTNET_DHCP_OPT_VENDOR_CLASS_IDENTIFIER, pDhcpMsg, opt);
    156             */
    157             /* MAY: well */
    158             rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_PARAM_REQ_LIST, pDhcpMsg, cbDhcpMsg, opt);
    159             if (RT_SUCCESS(rc))
    160                 memcpy(&session.reqParamList, &opt, sizeof(RawOption));
    161 
    162             /* MAY: todo */
    163             rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_MAX_DHCP_MSG_SIZE, pDhcpMsg, cbDhcpMsg, opt);
    164 
    165             break;
    166 
    167         case RTNET_DHCP_MT_REQUEST:
    168             session.switchTo(DHCPREQUESTRECEIVED);
    169             /* MUST in (SELECTING. INIT-REBOOT) MUST NOT BOUND. RENEW MAY  */
    170             rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cbDhcpMsg, opt);
    171             if (RT_SUCCESS(rc))
    172             {
    173                 /* hint for address allocation here */
    174                 session.addressHint = *(PRTNETADDRIPV4)opt.au8RawOpt;
    175             }
    176 
    177             /* MAY */
    178             ConfigurationManager::findOption(RTNET_DHCP_OPT_LEASE_TIME, pDhcpMsg, cbDhcpMsg, opt);
    179             /* MAY */
    180             ConfigurationManager::findOption(RTNET_DHCP_OPT_CLIENT_ID, pDhcpMsg, cbDhcpMsg, opt);
    181             /* XXX: MAY
    182             ConfigurationManager::findOption(RTNET_DHCP_OPT_VENDOR_CLASS_IDENTIFIER, pDhcpMsg, opt);
    183             */
    184             /* MAY */
    185             rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_PARAM_REQ_LIST, pDhcpMsg, cbDhcpMsg, opt);
    186             if (RT_SUCCESS(rc))
    187                 memcpy(&session.reqParamList, &opt, sizeof(RawOption));
    188 
    189             /* MAY */
    190             ConfigurationManager::findOption(RTNET_DHCP_OPT_MAX_DHCP_MSG_SIZE, pDhcpMsg, cbDhcpMsg, opt);
    191 
    192             break;
    193 
    194         case RTNET_DHCP_MT_DECLINE:
    195         case RTNET_DHCP_MT_OFFER:
    196         case RTNET_DHCP_MT_ACK:
    197         case RTNET_DHCP_MT_NAC:
    198         case RTNET_DHCP_MT_RELEASE:
    199         case RTNET_DHCP_MT_INFORM:
    200             AssertMsgFailed(("unimplemented"));
    201     }
    202 
    203     Assert(session.m_pClient);
    204     return session;
    205 }
    206 
    207 void SessionManager::releaseClientSession(Session& session)
    208 {
    209 }
    210 
    211 void SessionManager::releaseClient(Client& client)
    212 {
    213 }
    214 
    215 
    216 /* Configuration Manager */
    217 ConfigurationManager *ConfigurationManager::getConfigurationManager()
    218 {
    219     if (!g_ConfigurationManager)
    220         g_ConfigurationManager = new ConfigurationManager();
    221 
    222     return g_ConfigurationManager;
    223 }
    224 
     115        m_clients.push_back(new Client(pDhcpMsg->bp_chaddr.Mac));
     116        return m_clients.back();
     117    }
     118
     119    return NULL;
     120}
    225121
    226122/**
     
    272168        else
    273169        {
    274             size_t  cbCur = pb[1];
     170            size_t cbCur = pb[1];
    275171            if (cbCur > cbLeft - 2)
    276172                cbCur = cbLeft - 2;
     
    294190
    295191/**
    296  * We've find the config for session ...
    297  * XXX: using Session's private members
    298  */
    299 int ConfigurationManager::findConfiguration4Session(Session& session)
    300 {
    301     /* XXX: state switching broken?
    302      * XXX: DHCPDECLINE and DHCPINFO should we support them.
    303      */
    304     AssertReturn(   session.m_state == DHCPDISCOVERRECEIEVED
    305                  || session.m_state == DHCPREQUESTRECEIVED, VERR_INTERNAL_ERROR);
    306 
    307     if (session.m_pCfg)
    308         return VINF_SUCCESS;
    309 
    310     Assert(session.m_pClient);
    311     if (g_RootConfig->match(*session.m_pClient, &session.m_pCfg) > 0)
    312         return VINF_SUCCESS;
    313     else
    314         return VERR_INTERNAL_ERROR; /* XXX: is it really *internal* error? Perhaps some misconfiguration */
    315 
    316 }
    317 
    318 /**
    319  * What we are archieveing here is non commited lease ()
    320  */
    321 int ConfigurationManager::allocateConfiguration4Session(Session& session)
     192 * We bind lease for client till it continue with it on DHCPREQUEST.
     193 */
     194Lease *ConfigurationManager::allocateLease4Client(Client *client, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg)
    322195{
    323196    /**
    324197     * Well, session hasn't get the config.
    325198     */
    326     AssertPtrReturn(session.m_pCfg, VERR_INTERNAL_ERROR);
    327 
    328     bool fWithAddressHint = (session.addressHint.u != 0);
    329 
    330     if (fWithAddressHint)
    331     {
    332         if (m_allocations[session].u == session.addressHint.u)
     199    AssertPtrReturn(client, NULL);
     200   
     201    /**
     202     * This mean that client has already bound or commited lease.
     203     * If we've it happens it means that we received DHCPDISCOVER twice.
     204     */
     205    if (client->m_lease)
     206    {
     207        if (client->m_lease->isExpired())
     208            expireLease4Client(client);
     209        else
    333210        {
    334             /* Good, our hint matches allocation  */
    335             return VINF_SUCCESS;
     211            AssertReturn(client->m_lease->m_address.u != 0,NULL);
     212            return client->m_lease;
    336213        }
    337         /**
    338          * This definetly depends on client state ...
    339          * AssertMsgFailed(("Debug Me"));
    340          * Workaround #1
    341          * clear and ignore.
    342          */
    343         fWithAddressHint = false;
    344         session.addressHint.u = 0;
    345     }
    346 
    347     /*
    348      * We've received DHCPDISCOVER
    349      */
    350     AssertReturn(session.m_state == DHCPDISCOVERRECEIEVED, VERR_INTERNAL_ERROR);
    351 
    352     /**
    353      * XXX: this is wrong allocation check...
    354      * session initilized by client shouldn't be equal to lease in STL terms.
    355      */
    356     MapSession2Ip4AddressIterator it = m_allocations.find(session);
    357 
    358     if (it == m_allocations.end())
    359     {
    360         /* XXX: not optimal allocation */
    361         const NetworkConfigEntity *pNetCfg = dynamic_cast<const NetworkConfigEntity *>(session.m_pCfg);
    362 
    363         /**
    364          * Check config class.
    365          */
    366         AssertPtrReturn(pNetCfg, VERR_INTERNAL_ERROR);
    367 
    368         uint32_t u32Address = RT_N2H_U32(pNetCfg->lowerIp().u);
    369         while (u32Address < RT_N2H_U32(pNetCfg->upperIp().u))
     214    }
     215
     216    RTNETADDRIPV4 hintAddress;
     217    RawOption opt;
     218    Lease *please = NULL;
     219
     220    NetworkConfigEntity *pNetCfg;
     221
     222    AssertReturn(g_RootConfig->match(*client, (BaseConfigEntity **)&pNetCfg) > 0, NULL);
     223
     224    /* DHCPDISCOVER MAY contain request address */
     225    hintAddress.u = 0;
     226    int rc = findOption(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cbDhcpMsg, opt);
     227    if (RT_SUCCESS(rc))
     228    {
     229        hintAddress.u = *(uint32_t *)opt.au8RawOpt;
     230        if (   !RT_H2N_U32(hintAddress.u) < RT_H2N_U32(pNetCfg->lowerIp().u)
     231            || !RT_H2N_U32(hintAddress.u) > RT_H2N_U32(pNetCfg->upperIp().u))
     232            hintAddress.u = 0; /* clear hint */
     233    }
     234
     235    if (   hintAddress.u
     236        && !isAddressTaken(hintAddress, NULL))
     237    {
     238        please = new Lease();
     239        please->pCfg = pNetCfg;
     240        please->m_client = client;
     241        client->m_lease = please;
     242        client->m_lease->m_address = hintAddress;
     243        m_allocations[please] = hintAddress;
     244        return please;
     245    }
     246
     247    uint32_t u32 = 0;
     248    for(u32 = RT_H2N_U32(pNetCfg->lowerIp().u);
     249        u32 <= RT_H2N_U32(pNetCfg->upperIp().u);
     250        ++u32)
     251    {
     252        RTNETADDRIPV4 address;
     253        address.u = RT_H2N_U32(u32);
     254        if (!isAddressTaken(address, NULL))
    370255        {
    371 
    372             /* u32Address in host format */
    373             MapSession2Ip4AddressIterator addressIterator;
    374             bool fFound = false;
    375 
    376             for (addressIterator = m_allocations.begin();
    377                  addressIterator != m_allocations.end();
    378                  ++addressIterator)
    379             {
    380                 if (RT_N2H_U32(addressIterator->second.u) == u32Address)
    381                 {
    382                     /*
    383                      * This address is taken
    384                      * XXX: check if session isn't expired... if expired we can
    385                      * reuse it for this request
    386                      */
    387                     /* XXX: fTakeAddress = true; owning session is expired */
    388                     fFound = true;
    389                     break;
    390                 }
    391             } /* end of for over allocations */
    392 
    393             if (!fFound)
    394             {
    395                 RTNETADDRIPV4 address = { RT_H2N_U32_C(u32Address)};
    396                 m_allocations.insert(MapSession2Ip4AddressPair(session, address));
    397                 session.switchTo(DHCPOFFERPREPARED);
    398                 return VINF_SUCCESS;
    399             }
    400 
    401             u32Address ++;
    402         } /* end of while over candidates */
    403 
    404     }
    405 
    406     /* XXX: really??? */
    407     session.switchTo(DHCPOFFERPREPARED);
     256            please = new Lease();
     257            please->pCfg = pNetCfg;
     258            please->m_client = client;
     259            client->m_lease = please;
     260            client->m_lease->m_address = address;
     261            m_allocations[please] = client->m_lease->m_address;
     262            return please;
     263        }
     264    }
     265   
     266    return NULL;
     267}
     268
     269
     270int ConfigurationManager::commitLease4Client(Client *client)
     271{
     272    client->m_lease->u64TimestampBindingStarted = 0;
     273    client->m_lease->u32LeaseExpirationPeriod = client->m_lease->pCfg->expirationPeriod();
     274    client->m_lease->u64TimestampLeasingStarted = RTTimeMilliTS();
     275    client->m_lease->fBinding = false;
    408276    return VINF_SUCCESS;
    409277}
    410278
    411 
    412 int ConfigurationManager::commitConfiguration4ClientSession(Session& session)
    413 {
    414     /**/
    415     session.switchTo(DHCPACKNAKPREPARED);
    416 
    417     /* XXX: clean up the rest of the session, now this session LEASE!!! */
     279int ConfigurationManager::expireLease4Client(Client *client)
     280{
     281    MapLease2Ip4AddressIterator it = m_allocations.find(client->m_lease);
     282    AssertReturn(it != m_allocations.end(), VERR_NOT_FOUND);
     283
     284    m_allocations.erase(it);
     285
     286    delete client->m_lease;
     287    client->m_lease = NULL;
     288   
    418289    return VINF_SUCCESS;
    419290}
    420291
    421 RTNETADDRIPV4 ConfigurationManager::getSessionAddress(const Session& session)
    422 {
    423     return m_allocations[session];
    424 }
    425 
     292bool ConfigurationManager::isAddressTaken(const RTNETADDRIPV4& addr, Lease** ppLease)
     293{
     294    MapLease2Ip4AddressIterator it;
     295   
     296    for (it = m_allocations.begin();
     297         it != m_allocations.end();
     298         ++it)
     299    {
     300        if (it->second.u == addr.u)
     301        {
     302            if (ppLease)
     303                *ppLease = it->first;
     304           
     305            return true;
     306        }
     307    }
     308    return false;
     309}
    426310
    427311NetworkConfigEntity *ConfigurationManager::addNetwork(NetworkConfigEntity *pCfg,
     
    484368 * Network manager creates DHCPOFFER datagramm
    485369 */
    486 int NetworkManager::offer4Session(Session& session)
    487 {
    488     AssertReturn(session.m_state == DHCPOFFERPREPARED, VERR_INTERNAL_ERROR);
    489 
    490     prepareReplyPacket4Session(session);
    491 
    492     RTNETADDRIPV4 address = ConfigurationManager::getConfigurationManager()->getSessionAddress(session);
     370int NetworkManager::offer4Client(Client *client, uint32_t u32Xid,
     371                                 uint8_t *pu8ReqList, int cReqList)
     372{
     373    AssertPtrReturn(client, VERR_INTERNAL_ERROR);
     374    AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
     375
     376    prepareReplyPacket4Client(client, u32Xid);
     377
     378   
     379    RTNETADDRIPV4 address = client->m_lease->m_address;
    493380    BootPReplyMsg.BootPHeader.bp_yiaddr =  address;
    494381
     
    505392
    506393    /* XXX: can't store options per session */
    507     Client *client = unconst(session.m_pClient);
    508394    AssertPtr(client);
    509395
     
    514400
    515401    opt.u8OptId = RTNET_DHCP_OPT_LEASE_TIME;
    516     *(uint32_t *)opt.au8RawOpt = RT_H2N_U32(ConfigurationManager::getConfigurationManager()->getLeaseTime());
     402    *(uint32_t *)opt.au8RawOpt = RT_H2N_U32(client->m_lease->pCfg->expirationPeriod());
    517403    opt.cbRawOpt = sizeof(RTNETADDRIPV4);
    518404    client->rawOptions.push_back(opt);
    519405
    520     processParameterReqList(session);
    521 
    522     return doReply(session);
     406    processParameterReqList(client, pu8ReqList, cReqList);
     407
     408    return doReply(client);
    523409}
    524410
     
    527413 * Network manager creates DHCPACK
    528414 */
    529 int NetworkManager::ack(Session& session)
    530 {
     415int NetworkManager::ack(Client *client, uint32_t u32Xid,
     416                        uint8_t *pu8ReqList, int cReqList)
     417{
     418    AssertPtrReturn(client, VERR_INTERNAL_ERROR);
     419    AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
     420
    531421    RTNETADDRIPV4 address;
    532422
    533     AssertReturn(session.m_state == DHCPACKNAKPREPARED, VERR_INTERNAL_ERROR);
    534     prepareReplyPacket4Session(session);
    535 
    536     address = ConfigurationManager::getConfigurationManager()->getSessionAddress(session);
     423    prepareReplyPacket4Client(client, u32Xid);
     424
     425    address = client->m_lease->m_address;
    537426    BootPReplyMsg.BootPHeader.bp_ciaddr =  address;
    538427
     
    542431     * XXX: Using addressHint is not correct way to initialize [cy]iaddress...
    543432     */
    544     BootPReplyMsg.BootPHeader.bp_ciaddr = session.addressHint;
    545     BootPReplyMsg.BootPHeader.bp_yiaddr = session.addressHint;
     433    BootPReplyMsg.BootPHeader.bp_ciaddr = client->m_lease->m_address;
     434    BootPReplyMsg.BootPHeader.bp_yiaddr = client->m_lease->m_address;
    546435
    547436    Assert(BootPReplyMsg.BootPHeader.bp_yiaddr.u);
     
    555444    RT_ZERO(opt);
    556445
    557     /* XXX: can't store options per session */
    558     Client *client = unconst(session.m_pClient);
    559     AssertPtr(client);
    560 
    561446    opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
    562447    opt.au8RawOpt[0] = RTNET_DHCP_MT_ACK;
     
    569454     */
    570455    opt.u8OptId = RTNET_DHCP_OPT_LEASE_TIME;
    571     *(uint32_t *)opt.au8RawOpt =
    572       RT_H2N_U32(ConfigurationManager::getConfigurationManager()->getLeaseTime());
     456    *(uint32_t *)opt.au8RawOpt = RT_H2N_U32(client->m_lease->u32LeaseExpirationPeriod);
    573457    opt.cbRawOpt = sizeof(RTNETADDRIPV4);
    574458    client->rawOptions.push_back(opt);
    575459
    576     processParameterReqList(session);
    577 
    578     return doReply(session);
    579 
     460    processParameterReqList(client, pu8ReqList, cReqList);
     461
     462    return doReply(client);
    580463}
    581464
     
    584467 * Network manager creates DHCPNAK
    585468 */
    586 int NetworkManager::nak(Session& session)
    587 {
    588     AssertReturn(session.m_state == DHCPACKNAKPREPARED, VERR_INTERNAL_ERROR);
    589 
    590     prepareReplyPacket4Session(session);
     469int NetworkManager::nak(Client* client, uint32_t u32Xid)
     470{
     471    AssertPtrReturn(client, VERR_INTERNAL_ERROR);
     472    AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
     473
     474    prepareReplyPacket4Client(client, u32Xid);
    591475
    592476    /* this field filed in prepareReplyPacket4Session, and
     
    601485    RawOption opt;
    602486    RT_ZERO(opt);
    603 
    604     /* XXX: can't store options per session */
    605     Client *client = unconst(session.m_pClient);
    606     AssertPtr(client);
    607487
    608488    opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
     
    611491    client->rawOptions.push_back(opt);
    612492
    613     return doReply(session);
     493    return doReply(client);
    614494}
    615495
     
    618498 *
    619499 */
    620 int NetworkManager::prepareReplyPacket4Session(const Session& session)
    621 {
     500int NetworkManager::prepareReplyPacket4Client(Client *client, uint32_t u32Xid)
     501{
     502    AssertPtrReturn(client, VERR_INTERNAL_ERROR);
     503    AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
     504
    622505    memset(&BootPReplyMsg, 0, sizeof(BootPReplyMsg));
    623506
     
    626509    BootPReplyMsg.BootPHeader.bp_hlen   = sizeof(RTMAC);
    627510    BootPReplyMsg.BootPHeader.bp_hops   = 0;
    628     BootPReplyMsg.BootPHeader.bp_xid    = session.m_u32Xid;
     511    BootPReplyMsg.BootPHeader.bp_xid    = u32Xid;
    629512    BootPReplyMsg.BootPHeader.bp_secs   = 0;
    630513    /* XXX: bp_flags should be processed specially */
     
    633516    BootPReplyMsg.BootPHeader.bp_giaddr.u = 0;
    634517
    635     Assert(session.m_pClient);
    636     BootPReplyMsg.BootPHeader.bp_chaddr.Mac = session.m_pClient->m_mac;
    637 
    638     BootPReplyMsg.BootPHeader.bp_yiaddr =
    639       ConfigurationManager::getConfigurationManager()->getSessionAddress(session);
    640 
     518    BootPReplyMsg.BootPHeader.bp_chaddr.Mac = client->m_mac;
     519
     520    BootPReplyMsg.BootPHeader.bp_yiaddr = client->m_lease->m_address;
    641521    BootPReplyMsg.BootPHeader.bp_siaddr.u = 0;
    642522
     
    652532
    653533
    654 int NetworkManager::doReply(const Session& session)
     534int NetworkManager::doReply(Client *client)
    655535{
    656536    int rc;
     537
     538    AssertPtrReturn(client, VERR_INTERNAL_ERROR);
     539    AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
    657540
    658541    /*
     
    661544    VBoxNetDhcpWriteCursor Cursor(&BootPReplyMsg.BootPHeader, RTNET_DHCP_NORMAL_SIZE);
    662545
    663     /* XXX: unconst */
    664     Client *cl = unconst(session.m_pClient);
    665     AssertPtrReturn(cl, VERR_INTERNAL_ERROR);
    666 
    667546    /* The basics */
    668547
    669548    Cursor.optIPv4Addr(RTNET_DHCP_OPT_SERVER_ID, m_OurAddress);
    670549
    671     while(!cl->rawOptions.empty())
    672     {
    673         RawOption opt = cl->rawOptions.back();
     550    while(!client->rawOptions.empty())
     551    {
     552        RawOption opt = client->rawOptions.back();
    674553        if (!Cursor.begin(opt.u8OptId, opt.cbRawOpt))
    675554            break;
    676555        Cursor.put(opt.au8RawOpt, opt.cbRawOpt);
    677556
    678         cl->rawOptions.pop_back();
    679     }
    680 
    681 
    682     if (!cl->rawOptions.empty())
     557        client->rawOptions.pop_back();
     558    }
     559
     560
     561    if (!client->rawOptions.empty())
    683562    {
    684563        Log(("Wasn't able to put all options\n"));
    685564        /* force clean up */
    686         cl->rawOptions.clear();
     565        client->rawOptions.clear();
    687566    }
    688567
    689568    Cursor.optEnd();
    690 
    691     switch (session.m_state)
    692     {
    693         case DHCPOFFERPREPARED:
    694             break;
    695         case DHCPACKNAKPREPARED:
    696             break;
    697         default:
    698             AssertMsgFailedReturn(("Unsupported state(%d)\n", session.m_state), VERR_INTERNAL_ERROR);
    699     }
    700569
    701570    /*
     
    732601
    733602
    734 int NetworkManager::processParameterReqList(Session& session)
     603int NetworkManager::processParameterReqList(Client* client, uint8_t *pu8ReqList, int cReqList)
    735604{
    736605    /* request parameter list */
     
    738607    int idxParam = 0;
    739608
    740     uint8_t *pReqList = session.reqParamList.au8RawOpt;
    741 
    742     const NetworkConfigEntity *pNetCfg = dynamic_cast<const NetworkConfigEntity *>(session.m_pCfg);
    743 
    744     /* XXX: can't store options per session */
    745     Client *client = unconst(session.m_pClient);
    746     AssertPtr(client);
    747 
    748 
    749     for (idxParam = 0; idxParam < session.reqParamList.cbRawOpt; ++idxParam)
     609    AssertPtrReturn(client, VERR_INTERNAL_ERROR);
     610
     611    uint8_t *pReqList = pu8ReqList;
     612
     613    const NetworkConfigEntity *pNetCfg = client->m_lease->pCfg;
     614
     615    for (idxParam = 0; idxParam < cReqList; ++idxParam)
    750616    {
    751617
     
    762628            case RTNET_DHCP_OPT_ROUTERS:
    763629                {
    764                     const Ipv4AddressContainer lst = g_ConfigurationManager->getAddressList(RTNET_DHCP_OPT_ROUTERS);
     630                    const Ipv4AddressContainer lst =
     631                      g_ConfigurationManager->getAddressList(
     632                        RTNET_DHCP_OPT_ROUTERS);
    765633                    PRTNETADDRIPV4 pAddresses = (PRTNETADDRIPV4)&opt.au8RawOpt[0];
    766634
  • trunk/src/VBox/NetworkServices/DHCP/Config.h

    r47020 r47501  
    77# define _CONFIG_H_
    88
     9#include <iprt/asm-math.h>
    910#include <iprt/cpp/utils.h>
    1011
     
    2526    return (b < a);
    2627}
    27 
    28 
    29 typedef enum CLIENTSESSIONSTATE
    30 {
    31   /**
    32    * defult state, session isn't operable, not initialized an so on.
    33    */
    34   DHCPNONSENSE,
    35   /** We've received dhcp discover =>
    36    * we're starting new client and/or session.
    37    * Using XID (we record session)
    38    * and response with DHCPOFFER
    39    */
    40   DHCPDISCOVERRECEIEVED,
    41   /**
    42    * We're ready to send DHCPOFFER
    43    */
    44   DHCPOFFERPREPARED,
    45   /**
    46    * This more, session state, we responsed, to
    47    * client with DHCPOFFER using session's XID
    48    */
    49   DHCPOFFERSENT,
    50   /**
    51    * this is session's state, client's done DHCPREQUEST with (XID)
    52    */
    53   DHCPREQUESTRECEIVED,
    54   /**
    55    * We're ready to send DHCPACK or DHCPNAK
    56    */
    57   DHCPACKNAKPREPARED,
    58   /**
    59    * We've been able to furfill client's request for (XID) session, erased others Client
    60    * 's sessions ... and send DHCPACK (should be Lease bind at this point?)
    61    */
    62   DHCPACKSENT,
    63   /**
    64    * We couldn't furfill client's request -> destroy session.
    65    */
    66   DHCPNACKSENT,
    67   /**
    68    * real client, don't want our DHCPOFFER, we're delating our client representation,
    69    * and sessions objects.
    70    */
    71   DHCPDECLINERECEIVED,
    72   /**
    73    * nice to have, but not mandatory.
    74    */
    75   DHCPINFORMRECEIVED
    76 } CLIENTSESSIONSTATE;
    7728
    7829
     
    8738
    8839class Client;
     40class Lease;
    8941class BaseConfigEntity;
    9042
    91 /**
    92  * This class joins client and the lease ...
    93  * at the begining client might request several address assignments...
    94  *
    95  * So session here is descriptor joining client to each of it's requests.
    96  * When client finalizes its selection ... only single assignment is chosen,
    97  * others are released.
    98  */
    99 class Session
    100 {
    101 public:
    102     Session(const Client *client = NULL,
    103             uint32_t xid = 0,
    104             CLIENTSESSIONSTATE enmState = DHCPNONSENSE):
    105       m_pClient(client),
    106       m_state(enmState),
    107       m_u32Xid(xid),
    108       m_pCfg(NULL)
    109     {
    110         /* XXX: state ? Which is acceptable on initialization ?! */
    111         addressHint.u = 0;
    112         RT_ZERO(reqParamList);
    113     }
    114 
    115     bool operator < (const Session& s) const;
    116 
    117     int switchTo(CLIENTSESSIONSTATE);
    118     /* XXX private: */
    119 
    120     /**/
    121     const Client* m_pClient;
    122     /* We don't store the state in the client, because client might initiate several
    123      * sessions.
    124      */
    125     CLIENTSESSIONSTATE m_state;
    126     /**
    127      * uniq identificator of session
    128      */
    129     uint32_t m_u32Xid;
    130 
    131     /* dhcp-opts: request address */
    132     RTNETADDRIPV4 addressHint;
    133 
    134     /* dhcp-opts: request parameter list */
    135     RawOption reqParamList;
    136     /* Config for this session */
    137     const BaseConfigEntity *m_pCfg;
    138 
    139     /**
    140      * times used for evaluating wherther Session/Lease could be expired.
    141      */
    142 
    143     RTTIMESPEC creation;
    144     RTTIMESPEC expiration;
    145 };
    146 
    147 typedef std::map<uint32_t, Session>   Map2ClientSession;
    148 typedef Map2ClientSession::value_type Map2ClientSessionType;
    149 typedef Map2ClientSession::iterator   Map2ClientSessionIterator;
    150 
    151 class Lease
    152 {
    153 public:
    154     Lease(const Session& session):m_pClient(session.m_pClient){}
    155     virtual ~Lease(){}
    156 private:
    157     const Client *m_pClient;
    158 
    159     bool operator == (const Session& session) const
    160     {
    161         /* XXX: pointer comparison, perhaps not we really need */
    162         return (session.m_pClient == m_pClient);
    163     }
    164 };
    165 
    166 typedef std::map<Lease, RTNETADDRIPV4> MapLease2Ip4Address;
     43
     44class NetworkConfigEntity;
     45class HostConfigEntity;
     46class ClientMatchCriteria;
     47
     48typedef std::map<Lease *, RTNETADDRIPV4> MapLease2Ip4Address;
     49typedef MapLease2Ip4Address::iterator MapLease2Ip4AddressIterator;
    16750typedef MapLease2Ip4Address::value_type MapLease2Ip4AddressPair;
    168 typedef MapLease2Ip4Address::iterator MapLease2Ip4AddressIterator;
    16951
    17052/*
     
    18264
    18365    /* XXX: Option 60 and 61 */
    184     Client(const RTMAC& mac, uint32_t xid = 0);
     66    Client(const RTMAC& mac);
    18567
    18668    bool operator== (const RTMAC& mac) const
     
    19678
    19779    RTMAC m_mac;
    198     Map2ClientSession m_sessions;
    199     /* XXX: it's logically per session object, but some client broke XIDness */
    200     /* XXX: we're using it as stack */
     80    Lease *m_lease;
     81
     82    /* XXX: should be in lease */
    20183    std::vector<RawOption> rawOptions;
    20284};
    20385
    20486
    205 typedef std::vector<Client> VecClient;
     87typedef std::vector<Client*> VecClient;
    20688typedef VecClient::iterator VecClientIterator;
    20789typedef VecClient::const_iterator VecClientConstIterator;
    20890
    209 
    210 class SessionManager
    211 {
    212     public:
    213 
    214     static SessionManager* getSessionManager();
    215 
    216     /**
    217      * This method we call on every DHCP packet we've received.
    218      * 1. it finds/creates Client/and Session Object.
    219      */
    220     Session& getClientSessionByDhcpPacket(const RTNETBOOTP* pDhcpMsg, size_t cbPacket);
    221 
    222     /* XXX: DHCPDECLINE */
    223     void releaseClientSession(Session& session);
    224     /* XXX: DHCPRELEASE */
    225     void releaseClient(Client& client);
    226 
    227     private:
    228 
    229     VecClient m_clients;
    230 
    231     SessionManager(){}
    232     virtual ~SessionManager(){}
    233 };
    234 
    235 
    236 typedef std::map<Session, RTNETADDRIPV4> MapSession2Ip4Address;
    237 typedef MapSession2Ip4Address::iterator MapSession2Ip4AddressIterator;
    238 typedef MapSession2Ip4Address::value_type MapSession2Ip4AddressPair;
    239 
    240 class NetworkConfigEntity;
    241 class HostConfigEntity;
    242 class ClientMatchCriteria;
    243 
    244 class ConfigurationManager
    245 {
    246     public:
    247     static ConfigurationManager* getConfigurationManager();
    248 
    249     /**
    250      * We call this on DHCPDISCOVER
    251      */
    252     int findConfiguration4Session(Session& session);
    253 
    254     /**
    255      * XXX: it's could be done on DHCPOFFER or on DHCPACK (rfc2131 gives freedom here
    256      * 3.1.2, what is strict that allocation should do address check before real
    257      * allocation)...
    258      */
    259     int allocateConfiguration4Session(Session& session);
    260 
    261     /*
    262      * We call this before DHCPACK sent and after DHCPREQUEST received ...
    263      * when requested configuration is acceptable.
    264      */
    265     int commitConfiguration4ClientSession(Session& sesion);
    266 
    267     static int findOption(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& opt);
    268 
    269     NetworkConfigEntity *addNetwork(NetworkConfigEntity *pCfg,
    270                                     const RTNETADDRIPV4& networkId,
    271                                     const RTNETADDRIPV4& netmask,
    272                                     RTNETADDRIPV4& UpperAddress,
    273                                     RTNETADDRIPV4& LowerAddress);
    274 
    275     HostConfigEntity *addHost(NetworkConfigEntity*, const RTNETADDRIPV4&, ClientMatchCriteria*);
    276 
    277     RTNETADDRIPV4  getSessionAddress(const Session& session);
    278 
    279     /* XXX: from config */
    280     uint32_t getLeaseTime() {return 600;}
    281 
    282     int addToAddressList(uint8_t u8OptId, RTNETADDRIPV4& address)
    283     {
    284         switch(u8OptId)
    285         {
    286             case RTNET_DHCP_OPT_DNS:
    287                 m_nameservers.push_back(address);
    288                 break;
    289             case RTNET_DHCP_OPT_ROUTERS:
    290                 m_routers.push_back(address);
    291                 break;
    292             default:
    293                 Log(("dhcp-opt: list (%d) unsupported\n", u8OptId));
    294         }
    295         return VINF_SUCCESS;
    296     }
    297 
    298     int flushAddressList(uint8_t u8OptId)
    299     {
    300        switch(u8OptId)
    301        {
    302            case RTNET_DHCP_OPT_DNS:
    303                 m_nameservers.clear();
    304                 break;
    305            case RTNET_DHCP_OPT_ROUTERS:
    306                m_routers.clear();
    307                break;
    308            default:
    309                Log(("dhcp-opt: list (%d) unsupported\n", u8OptId));
    310        }
    311        return VINF_SUCCESS;
    312     }
    313 
    314     const Ipv4AddressContainer& getAddressList(uint8_t u8OptId)
    315     {
    316        switch(u8OptId)
    317        {
    318            case RTNET_DHCP_OPT_DNS:
    319                return m_nameservers;
    320 
    321            case RTNET_DHCP_OPT_ROUTERS:
    322                return m_routers;
    323 
    324        }
    325        /* XXX: Grrr !!! */
    326        return m_empty;
    327     }
    328 
    329     private:
    330     ConfigurationManager(){}
    331     virtual ~ConfigurationManager(){}
    332     MapSession2Ip4Address m_allocations;
    333     /*
    334      *
    335      */
    336     Ipv4AddressContainer m_nameservers;
    337     Ipv4AddressContainer m_routers;
    338     Ipv4AddressContainer m_empty;
    339 
    340 };
    341 
    342 
    343 class NetworkManager
    344 {
    345     public:
    346     static NetworkManager *getNetworkManager();
    347 
    348     int offer4Session(Session& ses);
    349     int ack(Session& ses);
    350     int nak(Session& ses);
    351 
    352     const RTNETADDRIPV4& getOurAddress(){ return m_OurAddress;}
    353     const RTNETADDRIPV4& getOurNetmask(){ return m_OurNetmask;}
    354     const RTMAC& getOurMac() {return m_OurMac;}
    355 
    356     void setOurAddress(const RTNETADDRIPV4& aAddress){ m_OurAddress = aAddress;}
    357     void setOurNetmask(const RTNETADDRIPV4& aNetmask){ m_OurNetmask = aNetmask;}
    358     void setOurMac(const RTMAC& aMac) {m_OurMac = aMac;}
    359 
    360     /* XXX: artifacts should be hidden or removed from here. */
    361     PSUPDRVSESSION m_pSession;
    362     INTNETIFHANDLE m_hIf;
    363     PINTNETBUF m_pIfBuf;
    364 
    365     private:
    366     int prepareReplyPacket4Session(const Session& session);
    367     int doReply(const Session& session);
    368     int processParameterReqList(Session& session);
    369 
    370     union {
    371         RTNETBOOTP BootPHeader;
    372         uint8_t au8Storage[1024];
    373     } BootPReplyMsg;
    374     int cbBooPReplyMsg;
    375 
    376     RTNETADDRIPV4 m_OurAddress;
    377     RTNETADDRIPV4 m_OurNetmask;
    378     RTMAC m_OurMac;
    379 
    380     NetworkManager(){}
    381     virtual ~NetworkManager(){}
    382 };
    38391
    38492/**
     
    476184public:
    477185    BaseConfigEntity(const ClientMatchCriteria *criteria = NULL,
    478                      int matchingLevel = 0)
     186      int matchingLevel = 0)
    479187      : m_criteria(criteria),
    480188      m_MatchLevel(matchingLevel){};
     
    488196
    489197    /* Should return how strong matching */
    490     virtual int match(const Client& client, const BaseConfigEntity **cfg) const
     198    virtual int match(Client& client, BaseConfigEntity **cfg)
    491199    {
    492200        int iMatch = (m_criteria && m_criteria->check(client)? m_MatchLevel: 0);
     
    503211            *cfg = this;
    504212            /* XXX: hack */
    505             BaseConfigEntity const *matching = this;
     213            BaseConfigEntity *matching = this;
    506214            int matchingLevel = m_MatchLevel;
    507215
    508             for (std::vector<const BaseConfigEntity *>::const_iterator it = m_children.begin();
     216            for (std::vector<BaseConfigEntity *>::iterator it = m_children.begin();
    509217                 it != m_children.end();
    510218                 ++it)
     
    521229        return iMatch;
    522230    }
    523 
     231    virtual uint32_t expirationPeriod() const = 0;
    524232    protected:
    525233    const ClientMatchCriteria *m_criteria;
    526234    int m_MatchLevel;
    527     std::vector<const BaseConfigEntity *> m_children;
     235    std::vector<BaseConfigEntity *> m_children;
    528236};
    529237
     
    538246        return 0;
    539247    }
     248    virtual uint32_t expirationPeriod() const {return 0;}
    540249};
    541250
     
    560269    std::string m_name;
    561270    const BaseConfigEntity *m_parentCfg;
     271    virtual uint32_t expirationPeriod() const
     272    {
     273        if (!m_u32ExpirationPeriod)
     274            return m_parentCfg->expirationPeriod();
     275        else
     276            return m_u32ExpirationPeriod;
     277    }
     278
     279    /* XXX: private:*/
     280    uint32_t m_u32ExpirationPeriod;
    562281};
    563282
     
    646365{
    647366    public:
    648     RootConfigEntity(std::string name);
     367    RootConfigEntity(std::string name, uint32_t expirationPeriod);
    649368    virtual ~RootConfigEntity(){};
    650369};
     
    675394#endif
    676395
     396class ConfigurationManager
     397{
     398    public:
     399    static ConfigurationManager* getConfigurationManager();
     400    static int extractRequestList(PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& rawOpt);
     401
     402    /**
     403     *
     404     */
     405    Client* getClientByDhcpPacket(const RTNETBOOTP *pDhcpMsg, size_t cbDhcpMsg);
     406
     407    /**
     408     * XXX: it's could be done on DHCPOFFER or on DHCPACK (rfc2131 gives freedom here
     409     * 3.1.2, what is strict that allocation should do address check before real
     410     * allocation)...
     411     */
     412    Lease* allocateLease4Client(Client *client, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg);
     413
     414    /**
     415     * We call this before DHCPACK sent and after DHCPREQUEST received ...
     416     * when requested configuration is acceptable.
     417     */
     418    int commitLease4Client(Client *client);
     419   
     420    /**
     421     * Expires client lease.
     422     */
     423    int expireLease4Client(Client *client);
     424
     425    static int findOption(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& opt);
     426
     427    NetworkConfigEntity *addNetwork(NetworkConfigEntity *pCfg,
     428                                    const RTNETADDRIPV4& networkId,
     429                                    const RTNETADDRIPV4& netmask,
     430                                    RTNETADDRIPV4& UpperAddress,
     431                                    RTNETADDRIPV4& LowerAddress);
     432
     433    HostConfigEntity *addHost(NetworkConfigEntity*, const RTNETADDRIPV4&, ClientMatchCriteria*);
     434
     435    int addToAddressList(uint8_t u8OptId, RTNETADDRIPV4& address)
     436    {
     437        switch(u8OptId)
     438        {
     439            case RTNET_DHCP_OPT_DNS:
     440                m_nameservers.push_back(address);
     441                break;
     442            case RTNET_DHCP_OPT_ROUTERS:
     443                m_routers.push_back(address);
     444                break;
     445            default:
     446                Log(("dhcp-opt: list (%d) unsupported\n", u8OptId));
     447        }
     448        return VINF_SUCCESS;
     449    }
     450
     451    int flushAddressList(uint8_t u8OptId)
     452    {
     453       switch(u8OptId)
     454       {
     455           case RTNET_DHCP_OPT_DNS:
     456                m_nameservers.clear();
     457                break;
     458           case RTNET_DHCP_OPT_ROUTERS:
     459               m_routers.clear();
     460               break;
     461           default:
     462               Log(("dhcp-opt: list (%d) unsupported\n", u8OptId));
     463       }
     464       return VINF_SUCCESS;
     465    }
     466
     467    const Ipv4AddressContainer& getAddressList(uint8_t u8OptId)
     468    {
     469       switch(u8OptId)
     470       {
     471           case RTNET_DHCP_OPT_DNS:
     472               return m_nameservers;
     473
     474           case RTNET_DHCP_OPT_ROUTERS:
     475               return m_routers;
     476
     477       }
     478       /* XXX: Grrr !!! */
     479       return m_empty;
     480    }
     481
     482    private:
     483    ConfigurationManager(){}
     484    virtual ~ConfigurationManager(){}
     485
     486    bool isAddressTaken(const RTNETADDRIPV4& addr, Lease** ppLease = NULL);
     487    MapLease2Ip4Address m_allocations;
     488    /**
     489     * Here we can store expired Leases to do not re-allocate them latter.
     490     */
     491    /* XXX: MapLease2Ip4Address m_freed; */
     492    /*
     493     *
     494     */
     495    Ipv4AddressContainer m_nameservers;
     496    Ipv4AddressContainer m_routers;
     497    Ipv4AddressContainer m_empty;
     498    VecClient m_clients;
     499
     500};
     501
     502
     503class NetworkManager
     504{
     505    public:
     506    static NetworkManager *getNetworkManager();
     507
     508    int offer4Client(Client* lease, uint32_t u32Xid, uint8_t *pu8ReqList, int cReqList);
     509    int ack(Client *lease, uint32_t u32Xid, uint8_t *pu8ReqList, int cReqList);
     510    int nak(Client *lease, uint32_t u32Xid);
     511
     512    const RTNETADDRIPV4& getOurAddress(){ return m_OurAddress;}
     513    const RTNETADDRIPV4& getOurNetmask(){ return m_OurNetmask;}
     514    const RTMAC& getOurMac() {return m_OurMac;}
     515
     516    void setOurAddress(const RTNETADDRIPV4& aAddress){ m_OurAddress = aAddress;}
     517    void setOurNetmask(const RTNETADDRIPV4& aNetmask){ m_OurNetmask = aNetmask;}
     518    void setOurMac(const RTMAC& aMac) {m_OurMac = aMac;}
     519
     520    /* XXX: artifacts should be hidden or removed from here. */
     521    PSUPDRVSESSION m_pSession;
     522    INTNETIFHANDLE m_hIf;
     523    PINTNETBUF m_pIfBuf;
     524
     525    private:
     526    int prepareReplyPacket4Client(Client *client, uint32_t u32Xid);
     527    int doReply(Client *client);
     528    int processParameterReqList(Client *client, uint8_t *pu8ReqList, int cReqList);
     529
     530    union {
     531        RTNETBOOTP BootPHeader;
     532        uint8_t au8Storage[1024];
     533    } BootPReplyMsg;
     534    int cbBooPReplyMsg;
     535
     536    RTNETADDRIPV4 m_OurAddress;
     537    RTNETADDRIPV4 m_OurNetmask;
     538    RTMAC m_OurMac;
     539
     540    NetworkManager(){}
     541    virtual ~NetworkManager(){}
     542};
     543
     544
     545
     546class Lease
     547{
     548public:
     549    Lease()
     550    {
     551        m_address.u = 0;
     552        m_client = NULL;
     553        fBinding = false;
     554        u64TimestampBindingStarted = 0;
     555        u64TimestampLeasingStarted = 0;
     556        u32LeaseExpirationPeriod = 0;
     557        u32BindExpirationPeriod = 0;
     558        pCfg = NULL;
     559    }
     560    virtual ~Lease(){}
     561   
     562    bool isExpired()
     563    {
     564        if (!fBinding)
     565            return (ASMDivU64ByU32RetU32(RTTimeMilliTS() - u64TimestampLeasingStarted, 1000)
     566                    > u32LeaseExpirationPeriod);
     567        else
     568            return (ASMDivU64ByU32RetU32(RTTimeMilliTS() - u64TimestampBindingStarted, 1000)
     569                    > u32BindExpirationPeriod);
     570
     571    }
     572
     573    /* XXX private: */
     574    RTNETADDRIPV4 m_address;
     575   
     576    /** lease isn't commited */
     577    bool fBinding;
     578   
     579    /** Timestamp when lease commited. */
     580    uint64_t u64TimestampLeasingStarted;
     581    /** Period when lease is expired in secs. */
     582    uint32_t u32LeaseExpirationPeriod;
     583
     584    /** timestamp when lease was bound */
     585    uint64_t u64TimestampBindingStarted;
     586    /* Period when binding is expired in secs. */
     587    uint32_t u32BindExpirationPeriod;
     588
     589    NetworkConfigEntity *pCfg;
     590    Client *m_client;
     591};
     592
     593
     594
     595
    677596
    678597extern const ClientMatchCriteria *g_AnyClient;
    679 extern const RootConfigEntity *g_RootConfig;
     598extern RootConfigEntity *g_RootConfig;
    680599extern const NullConfigEntity *g_NullConfig;
    681600
  • trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp

    r47111 r47501  
    618618    if (!m_DhcpServer.isNull())
    619619    {
     620#if 0
    620621        HRESULT hrc;
    621622        com::SafeArray<BSTR> sf;
     
    632633            /* XXX: per-host configuration */
    633634        }
    634 
    635         SessionManager *sesionManager = SessionManager::getSessionManager();
    636         Session& session = sesionManager->getClientSessionByDhcpPacket(pDhcpMsg, cb);
    637         /* XXX: switch -> private */
    638         session.switchTo(DHCPDISCOVERRECEIEVED);
    639 
     635#endif
     636        RawOption opt;
     637        memset(&opt, 0, sizeof(RawOption));
     638        /* 1. Find client */
    640639        ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
    641         int rc = confManager->findConfiguration4Session(session);
    642         AssertRCReturn(rc, false);
    643 
    644         rc = confManager->allocateConfiguration4Session(session);
    645         AssertRCReturn(rc, false);
    646 
    647         NetworkManager *netManager = NetworkManager::getNetworkManager();
    648         rc = netManager->offer4Session(session);
    649         AssertRCReturn(rc, false);
    650 
    651 
     640        Client *client = confManager->getClientByDhcpPacket(pDhcpMsg, cb);
     641
     642        /* 2. Find/Bind lease for client */
     643        Lease *lease = confManager->allocateLease4Client(client, pDhcpMsg, cb);
     644        AssertPtrReturn(lease, VINF_SUCCESS);
     645
     646        int rc = ConfigurationManager::extractRequestList(pDhcpMsg, cb, opt);
     647       
     648        /* 3. Send of offer */
     649        NetworkManager *networkManager = NetworkManager::getNetworkManager();
     650       
     651        lease->fBinding = true;
     652        lease->u64TimestampBindingStarted = RTTimeMilliTS();
     653        lease->u32BindExpirationPeriod = 300; /* 3 min. */
     654        networkManager->offer4Client(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt);
    652655    } /* end of if(!m_DhcpServer.isNull()) */
    653656
     
    666669bool VBoxNetDhcp::handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb)
    667670{
    668     SessionManager *sesionManager = SessionManager::getSessionManager();
    669     Session& session = sesionManager->getClientSessionByDhcpPacket(pDhcpMsg, cb);
    670     /* XXX: switch -> private */
    671     session.switchTo(DHCPREQUESTRECEIVED);
    672 
    673671    ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
    674     int rc = confManager->findConfiguration4Session(session);
    675     AssertRCReturn(rc, false);
    676 
    677     rc = confManager->commitConfiguration4ClientSession(session);
    678 
    679     NetworkManager *netManager = NetworkManager::getNetworkManager();
    680     if (RT_SUCCESS(rc))
    681         rc = netManager->ack(session);
     672    NetworkManager *networkManager = NetworkManager::getNetworkManager();
     673
     674    /* 1. find client */
     675    Client *client = confManager->getClientByDhcpPacket(pDhcpMsg, cb);
     676
     677    /* 2. find bound lease */
     678    if (client->m_lease)
     679    {
     680
     681        if (client->m_lease->isExpired())
     682        {
     683            /* send client to INIT state */
     684            networkManager->nak(client, pDhcpMsg->bp_xid);
     685            confManager->expireLease4Client(client);
     686            return true;
     687        }
     688        /* XXX: Validate request */
     689        RawOption opt;
     690        memset((void *)&opt, 0, sizeof(RawOption));
     691
     692        int rc = confManager->commitLease4Client(client);
     693        AssertRCReturn(rc, false);
     694
     695        rc = ConfigurationManager::extractRequestList(pDhcpMsg, cb, opt);
     696        AssertRCReturn(rc, false);
     697
     698        networkManager->ack(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt);
     699    }
    682700    else
    683         rc = netManager->nak(session);
    684 
    685     AssertRCReturn(rc, false);
    686 
     701    {
     702        networkManager->nak(client, pDhcpMsg->bp_xid);
     703    }
    687704    return true;
    688705}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette