int NetworkManager::prepareReplyPacket4Client(const Client& client, uint32_t u32Xid) { RT_ZERO(m->BootPReplyMsg); m->BootPReplyMsg.BootPHeader.bp_op = RTNETBOOTP_OP_REPLY; m->BootPReplyMsg.BootPHeader.bp_htype = RTNET_ARP_ETHER; m->BootPReplyMsg.BootPHeader.bp_hlen = sizeof(RTMAC); m->BootPReplyMsg.BootPHeader.bp_hops = 0; m->BootPReplyMsg.BootPHeader.bp_xid = u32Xid; m->BootPReplyMsg.BootPHeader.bp_secs = 0; /* XXX: bp_flags should be processed specially */ m->BootPReplyMsg.BootPHeader.bp_flags = 0; m->BootPReplyMsg.BootPHeader.bp_ciaddr.u = 0; m->BootPReplyMsg.BootPHeader.bp_giaddr.u = 0; m->BootPReplyMsg.BootPHeader.bp_chaddr.Mac = client.getMacAddress(); const Lease l = client.lease(); m->BootPReplyMsg.BootPHeader.bp_yiaddr = l.getAddress(); m->BootPReplyMsg.BootPHeader.bp_siaddr.u = 0; m->BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_cookie = RT_H2N_U32_C(RTNET_DHCP_COOKIE); memset(&m->BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_opts[0], '\0', RTNET_DHCP_OPT_SIZE); return VINF_SUCCESS; }
/** * Network manager creates DHCPACK */ int NetworkManager::ack(const Client& client, uint32_t u32Xid, uint8_t *pu8ReqList, int cReqList) { RTNETADDRIPV4 address; prepareReplyPacket4Client(client, u32Xid); Lease l = client.lease(); address = l.getAddress(); m->BootPReplyMsg.BootPHeader.bp_ciaddr = address; /* 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... */ m->BootPReplyMsg.BootPHeader.bp_ciaddr = address; m->BootPReplyMsg.BootPHeader.bp_yiaddr = address; Assert(m->BootPReplyMsg.BootPHeader.bp_yiaddr.u); /* options: * - IP address lease time (if DHCPREQUEST) * - message type * - server identifier */ RawOption opt; RT_ZERO(opt); std::vector<RawOption> extra; opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE; opt.au8RawOpt[0] = RTNET_DHCP_MT_ACK; opt.cbRawOpt = 1; extra.push_back(opt); /* * XXX: lease time should be conditional. If on dhcprequest then tim should be provided, * else on dhcpinform it mustn't. */ opt.u8OptId = RTNET_DHCP_OPT_LEASE_TIME; *(uint32_t *)opt.au8RawOpt = RT_H2N_U32(l.getExpiration()); opt.cbRawOpt = sizeof(RTNETADDRIPV4); extra.push_back(opt); processParameterReqList(client, pu8ReqList, cReqList, extra); return doReply(client, extra); }
bool operator< (const Lease& lhs, const Lease& rhs) { return ( (lhs.getAddress() < rhs.getAddress()) || (lhs.issued() < rhs.issued())); }
/** * 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; }