/** * The client is requesting an offer. * * @returns true. * * @param pDhcpMsg The message. * @param cb The message size. */ bool NetworkManager::handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb) { ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager(); /* 1. find client */ Client client = confManager->getClientByDhcpPacket(pDhcpMsg, cb); /* 2. find bound lease */ Lease l = client.lease(); if (l != Lease::NullLease) { if (l.isExpired()) { /* send client to INIT state */ Client c(client); nak(client, pDhcpMsg->bp_xid); confManager->expireLease4Client(c); return true; } else { /* XXX: Validate request */ RawOption opt; RT_ZERO(opt); Client c(client); int rc = confManager->commitLease4Client(c); AssertRCReturn(rc, false); rc = ConfigurationManager::extractRequestList(pDhcpMsg, cb, opt); AssertRCReturn(rc, false); ack(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt); } } else { nak(client, pDhcpMsg->bp_xid); } return true; }
/** * 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. */ const Lease l = client.lease(); if (l != Lease::NullLease) { /* Here we should take lease from the m_allocation which was feed with leases * on start */ if (l.isExpired()) { expireLease4Client(const_cast<Client&>(client)); if (!l.isExpired()) return l; } else { AssertReturn(l.getAddress().u != 0, Lease::NullLease); return l; } } } RTNETADDRIPV4 hintAddress; RawOption opt; NetworkConfigEntity *pNetCfg; Client cl(client); AssertReturn(g_RootConfig->match(cl, (BaseConfigEntity **)&pNetCfg) > 0, Lease::NullLease); /* DHCPDISCOVER MAY contain request address */ hintAddress.u = 0; int rc = findOption(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cbDhcpMsg, opt); if (RT_SUCCESS(rc)) { hintAddress.u = *(uint32_t *)opt.au8RawOpt; if ( RT_H2N_U32(hintAddress.u) < RT_H2N_U32(pNetCfg->lowerIp().u) || RT_H2N_U32(hintAddress.u) > RT_H2N_U32(pNetCfg->upperIp().u)) hintAddress.u = 0; /* clear hint */ } if ( hintAddress.u && !isAddressTaken(hintAddress)) { Lease l(cl); l.setConfig(pNetCfg); l.setAddress(hintAddress); m->m_allocations.insert(MapLease2Ip4AddressPair(l, hintAddress)); return l; } uint32_t u32 = 0; for(u32 = RT_H2N_U32(pNetCfg->lowerIp().u); u32 <= RT_H2N_U32(pNetCfg->upperIp().u); ++u32) { RTNETADDRIPV4 address; address.u = RT_H2N_U32(u32); if (!isAddressTaken(address)) { Lease l(cl); l.setConfig(pNetCfg); l.setAddress(address); m->m_allocations.insert(MapLease2Ip4AddressPair(l, address)); return l; } } return Lease::NullLease; }