Commit c6fd1d3c authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[1230] DHCPv4 server managed to configure its first client!

- processDiscover(), processRequest(), copyDefaultFields(),
  appendDefaultOptions() implemented in dhcpv4_srv class

- setUint8(), setUint16(), setUint32() added to Option class.

- Pkt4 class now properly sets packet type after parsing.
parent 7bf0432c
......@@ -24,12 +24,18 @@ using namespace isc;
using namespace isc::dhcp;
using namespace isc::asiolink;
// This is the hardcoded lease. Currently this is a skeleton server that only
// grants this option.
#define HARDCODED_LEASE "10.3.2.222"
// #define ECHO_SERVER
// These are hardcoded parameters. Currently this is a skeleton server that only
// grants those options and a single, fixed, hardcoded lease.
const std::string HARDCODED_LEASE = "10.3.2.222"; // assigned lease
const std::string HARDCODED_NETMASK = "255.255.255.0";
const uint32_t HARDCODED_LEASE_TIME = 60; // in seconds
const std::string HARDCODED_GATEWAY = "10.3.2.2";
const std::string HARDCODED_DNS_SERVER = "8.8.8.8";
const std::string HARDCODED_DOMAIN_NAME = "isc.example.org";
const std::string HARDCODED_SERVER_ID = "10.3.1.1";
Dhcpv4Srv::Dhcpv4Srv(uint16_t port) {
cout << "Initialization: opening sockets on port " << port << endl;
......@@ -152,65 +158,91 @@ Dhcpv4Srv::setServerID() {
#endif
}
boost::shared_ptr<Pkt4>
Dhcpv4Srv::processDiscover(boost::shared_ptr<Pkt4>& discover) {
boost::shared_ptr<Pkt4> offer = boost::shared_ptr<Pkt4>(new Pkt4(DHCPOFFER, discover->getTransid()));
offer->setIface(discover->getIface());
offer->setIndex(discover->getIndex());
offer->setCiaddr(discover->getCiaddr());
offer->setSiaddr(IOAddress("0.0.0.0")); // explictly set this to 0
void Dhcpv4Srv::copyDefaultFields(const boost::shared_ptr<Pkt4>& question,
boost::shared_ptr<Pkt4>& answer) {
answer->setIface(question->getIface());
answer->setIndex(question->getIndex());
answer->setCiaddr(question->getCiaddr());
offer->setHops(discover->getHops());
answer->setSiaddr(IOAddress("0.0.0.0")); // explictly set this to 0
answer->setHops(question->getHops());
// copy MAC address
vector<uint8_t> mac;
mac.resize(Pkt4::MAX_CHADDR_LEN);
memcpy(&mac[0], discover->getChaddr(), Pkt4::MAX_CHADDR_LEN);
offer->setHWAddr(discover->getHtype(),
discover->getHlen(),
mac);
memcpy(&mac[0], question->getChaddr(), Pkt4::MAX_CHADDR_LEN);
answer->setHWAddr(question->getHtype(), question->getHlen(), mac);
// relay address
offer->setGiaddr(discover->getGiaddr());
if (discover->getGiaddr().toText() != "0.0.0.0") {
answer->setGiaddr(question->getGiaddr());
if (question->getGiaddr().toText() != "0.0.0.0") {
// relayed traffic
offer->setRemoteAddr(discover->getGiaddr());
answer->setRemoteAddr(question->getGiaddr());
} else {
// direct traffic
offer->setRemoteAddr(discover->getRemoteAddr());
answer->setRemoteAddr(question->getRemoteAddr());
}
// TODO: Implement actual lease assignment here
offer->setYiaddr(IOAddress(HARDCODED_LEASE));
}
void Dhcpv4Srv::appendDefaultOptions(boost::shared_ptr<Pkt4>& msg, uint8_t msg_type) {
// add Message Type Option (type 53)
boost::shared_ptr<Option> opt;
std::vector<uint8_t> tmp;
tmp.push_back(static_cast<int>(DHCPOFFER));
tmp.push_back(static_cast<uint8_t>(msg_type));
opt = boost::shared_ptr<Option>(new Option(Option::V4, DHO_DHCP_MESSAGE_TYPE, tmp));
offer->addOption(opt);
msg->addOption(opt);
// more options will be added here later
}
boost::shared_ptr<Pkt4>
Dhcpv4Srv::processDiscover(boost::shared_ptr<Pkt4>& discover) {
boost::shared_ptr<Pkt4> offer = boost::shared_ptr<Pkt4>
(new Pkt4(DHCPOFFER, discover->getTransid()));
boost::shared_ptr<Option> opt;
copyDefaultFields(discover, offer);
appendDefaultOptions(offer, DHCPOFFER);
// TODO: Implement actual lease assignment here
offer->setYiaddr(IOAddress(HARDCODED_LEASE));
// DHCP Server Identifier (type 54)
opt = boost::shared_ptr<Option>(new Option4AddrLst(54, IOAddress("10.3.1.1")));
opt = boost::shared_ptr<Option>
(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER, IOAddress(HARDCODED_SERVER_ID)));
offer->addOption(opt);
// IP Address Lease time (type 51)
opt = boost::shared_ptr<Option>(new Option(Option::V4, DHO_DHCP_LEASE_TIME));
opt->setUint32(HARDCODED_LEASE_TIME);
offer->addOption(opt);
// Subnet mask (type 1)
opt = boost::shared_ptr<Option>(new Option4AddrLst(1, IOAddress("255.255.255.0")));
opt = boost::shared_ptr<Option>
(new Option4AddrLst(DHO_SUBNET_MASK, IOAddress(HARDCODED_NETMASK)));
offer->addOption(opt);
// Router (type 3)
opt = boost::shared_ptr<Option>(new Option4AddrLst(3, IOAddress("10.3.2.2")));
opt = boost::shared_ptr<Option>
(new Option4AddrLst(DHO_ROUTERS, IOAddress(HARDCODED_GATEWAY)));
offer->addOption(opt);
// Domain name (type 15)
vector<uint8_t> domain(HARDCODED_DOMAIN_NAME.begin(), HARDCODED_DOMAIN_NAME.end());
opt = boost::shared_ptr<Option>(new Option(Option::V4, DHO_DOMAIN_NAME, domain));
offer->addOption(opt);
// TODO: Add Option_String class
// DNS servers (type 6)
opt = boost::shared_ptr<Option>(new Option4AddrLst(6, IOAddress("8.8.8.8")));
opt = boost::shared_ptr<Option>
(new Option4AddrLst(DHO_DOMAIN_NAME_SERVERS, IOAddress(HARDCODED_DNS_SERVER)));
offer->addOption(opt);
return (offer);
......@@ -218,8 +250,50 @@ Dhcpv4Srv::processDiscover(boost::shared_ptr<Pkt4>& discover) {
boost::shared_ptr<Pkt4>
Dhcpv4Srv::processRequest(boost::shared_ptr<Pkt4>& request) {
/// TODO: Currently implemented echo mode. Implement this for real
return (request);
boost::shared_ptr<Pkt4> ack = boost::shared_ptr<Pkt4>
(new Pkt4(DHCPACK, request->getTransid()));
boost::shared_ptr<Option> opt;
copyDefaultFields(request, ack);
appendDefaultOptions(ack, DHCPACK);
// TODO: Implement actual lease assignment here
ack->setYiaddr(IOAddress(HARDCODED_LEASE));
// DHCP Server Identifier (type 54)
opt = boost::shared_ptr<Option>
(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER, IOAddress(HARDCODED_SERVER_ID)));
ack->addOption(opt);
// IP Address Lease time (type 51)
opt = boost::shared_ptr<Option>(new Option(Option::V4, DHO_DHCP_LEASE_TIME));
opt->setUint32(HARDCODED_LEASE_TIME);
ack->addOption(opt);
// TODO: create Option_IntArray that holds list of integers, similar to Option4_AddrLst
// Subnet mask (type 1)
opt = boost::shared_ptr<Option>
(new Option4AddrLst(DHO_SUBNET_MASK, IOAddress(HARDCODED_NETMASK)));
ack->addOption(opt);
// Router (type 3)
opt = boost::shared_ptr<Option>(new Option4AddrLst(DHO_ROUTERS, IOAddress(HARDCODED_GATEWAY)));
ack->addOption(opt);
// Domain name (type 15)
vector<uint8_t> domain(HARDCODED_DOMAIN_NAME.begin(), HARDCODED_DOMAIN_NAME.end());
opt = boost::shared_ptr<Option>(new Option(Option::V4, DHO_DOMAIN_NAME, domain));
ack->addOption(opt);
// TODO: Add Option_String class
// DNS servers (type 6)
opt = boost::shared_ptr<Option>
(new Option4AddrLst(DHO_DOMAIN_NAME_SERVERS, IOAddress(HARDCODED_DNS_SERVER)));
ack->addOption(opt);
return (ack);
}
void Dhcpv4Srv::processRelease(boost::shared_ptr<Pkt4>& release) {
......
......@@ -106,6 +106,22 @@ protected:
/// @param infRequest message received from client
boost::shared_ptr<Pkt4> processInform(boost::shared_ptr<Pkt4>& inform);
/// @brief Copies default parameters from client's to server's message
///
/// Some fields are copied from client's message into server's response,
/// e.g. client HW address, number of hops, transaction-id etc.
///
/// @param question any message sent by client
/// @param answer any message server is going to send as response
void copyDefaultFields(const boost::shared_ptr<Pkt4>& question,
boost::shared_ptr<Pkt4>& answer);
/// @brief Appends default options to a message
///
/// @param msg message object (options will be added to it)
/// @param msg_type specifies message type
void appendDefaultOptions(boost::shared_ptr<Pkt4>& msg, uint8_t msg_type);
/// @brief Returns server-intentifier option
///
/// @return server-id option
......
......@@ -326,6 +326,21 @@ uint32_t Option::getUint32() {
return ( readUint32(&data_[0]) );
}
void Option::setUint8(uint8_t value) {
data_.resize(1);
data_[0] = value;
}
void Option::setUint16(uint16_t value) {
data_.resize(2);
writeUint16(value, &data_[0]);
}
void Option::setUint32(uint32_t value) {
data_.resize(4);
writeUint32(value, &data_[0]);
}
Option::~Option() {
}
......@@ -257,6 +257,27 @@ public:
/// @return uint32_t value stored on first four bytes
uint32_t getUint32();
/// @brief Sets content of this option to singe uint8 value.
///
/// Option it resized appropriately (to length of 1 octet).
///
/// @param value value to be set
void setUint8(uint8_t value);
/// @brief Sets content of this option to singe uint16 value.
///
/// Option it resized appropriately (to length of 2 octets).
///
/// @param value value to be set
void setUint16(uint16_t value);
/// @brief Sets content of this option to singe uint32 value.
///
/// Option it resized appropriately (to length of 4 octets).
///
/// @param value value to be set
void setUint32(uint32_t value);
/// just to force that every option has virtual dtor
virtual ~Option();
......
......@@ -176,6 +176,8 @@ Pkt4::unpack() {
bufferIn.readVector(optsBuffer, opts_len);
LibDHCP::unpackOptions4(optsBuffer, options_);
check();
return (true);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment