Commit 59a52758 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[1239] RX path improvements. Code is now able to parse incoming DISCOVER messages.

parent e9610929
......@@ -23,6 +23,8 @@ using namespace isc;
using namespace isc::dhcp;
using namespace isc::asiolink;
// #define ECHO_SERVER
Dhcpv4Srv::Dhcpv4Srv(uint16_t port) {
cout << "Initialization: opening sockets on port " << port << endl;
......@@ -52,17 +54,21 @@ Dhcpv4Srv::run() {
query = IfaceMgr::instance().receive4();
#if ECHO_SERVER
#if defined(ECHO_SERVER)
query->repack();
IfaceMgr::instance().send(query);
continue;
#endif
if (query) {
if (!query->unpack()) {
cout << "Failed to parse incoming packet" << endl;
try {
query->unpack();
} catch (const std::exception& e) {
/// TODO: Printout reasons of failed parsing
cout << "Failed to parse incoming packet " << endl;
continue;
}
switch (query->getType()) {
case DHCPDISCOVER:
rsp = processDiscover(query);
......@@ -84,8 +90,7 @@ Dhcpv4Srv::run() {
<< query->getType() << endl;
}
cout << "Received " << query->len() << " bytes packet type="
<< query->getType() << endl;
cout << "Received message type " << int(query->getType()) << endl;
// TODO: print out received packets only if verbose (or debug)
// mode is enabled
......@@ -99,7 +104,7 @@ Dhcpv4Srv::run() {
rsp->setIface(query->getIface());
rsp->setIndex(query->getIndex());
cout << "Replying with:" << rsp->getType() << endl;
cout << "Replying with message type " << (int)rsp->getType() << ":" << endl;
cout << rsp->toText();
cout << "----" << endl;
if (rsp->pack()) {
......
......@@ -157,7 +157,7 @@ static const uint16_t DHCP4_SERVER_PORT = 67;
/// Magic cookie validating dhcp options field (and bootp vendor
/// extensions field).
///static const char* DHCP_OPTIONS_COOKIE = "\143\202\123\143";
static const uint32_t DHCP_OPTIONS_COOKIE = 0x63825363;
// TODO: Following are leftovers from dhcp.h import from ISC DHCP
// They will be converted to C++-style defines once they will start
......
......@@ -353,8 +353,10 @@ IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, int port) {
memset(&addr4, 0, sizeof(sockaddr));
addr4.sin_family = AF_INET;
addr4.sin_port = htons(port);
memcpy(&addr4.sin_addr, addr.getAddress().to_v4().to_bytes().data(),
sizeof(addr4.sin_addr));
addr4.sin_addr.s_addr = htonl(addr);
//addr4.sin_addr.s_addr = 0; // anyaddr: this will receive 0.0.0.0 => 255.255.255.255 traffic
// addr4.sin_addr.s_addr = 0xffffffffu; // broadcast address. This will receive 0.0.0.0 => 255.255.255.255 as well
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
......@@ -627,6 +629,11 @@ IfaceMgr::send(boost::shared_ptr<Pkt4>& pkt)
pktinfo->ipi_ifindex = pkt->getIndex();
m.msg_controllen = cmsg->cmsg_len;
cout << "Trying to send " << pkt->getBuffer().getLength() << " bytes to "
<< pkt->getRemoteAddr().toText() << ":" << pkt->getRemotePort()
<< " over socket " << getSocket(*pkt) << " on interface "
<< getIface(pkt->getIface())->getFullName() << endl;
result = sendmsg(getSocket(*pkt), &m, 0);
if (result < 0) {
isc_throw(Unexpected, "Pkt4 send failed.");
......@@ -699,7 +706,7 @@ IfaceMgr::receive4() {
unsigned int ifindex = 0;
boost::shared_ptr<Pkt4> pkt;
const uint32_t RCVBUFSIZE = 1500;
uint8_t buf[RCVBUFSIZE];
uint8_t* buf = (uint8_t*) malloc(RCVBUFSIZE);
memset(&control_buf_[0], 0, control_buf_len_);
memset(&from_addr, 0, sizeof(from_addr));
......@@ -732,6 +739,7 @@ IfaceMgr::receive4() {
if (result < 0) {
cout << "Failed to receive UDP4 data." << endl;
delete buf;
return (boost::shared_ptr<Pkt4>()); // NULL
}
......@@ -744,6 +752,10 @@ IfaceMgr::receive4() {
ifindex = pktinfo->ipi_ifindex;
to_addr = pktinfo->ipi_addr;
// debug:
IOAddress tmp(htonl(pktinfo->ipi_spec_dst.s_addr));
cout << "The other addr is: " << tmp.toText() << endl;
// to_addr = pktinfo->ipi_spec_dst;
found_pktinfo = 1;
}
......@@ -751,6 +763,7 @@ IfaceMgr::receive4() {
}
if (!found_pktinfo) {
cout << "Unable to find pktinfo" << endl;
delete buf;
return (boost::shared_ptr<Pkt4>()); // NULL
}
......
......@@ -92,6 +92,15 @@ LibDHCP::unpackOptions4(const std::vector<uint8_t>& buf,
// 2 - header of DHCPv4 option
while (offset + 2 <= buf.size()) {
uint8_t opt_type = buf[offset++];
if (opt_type == DHO_END)
return; // just return. Don't need to add DHO_END option
if (offset + 1 >= buf.size()) {
isc_throw(OutOfRange, "Attempt to parse truncated option "
<< opt_type);
}
uint8_t opt_len = buf[offset++];
if (offset + opt_len > buf.size() ) {
isc_throw(OutOfRange, "Option parse failed. Tried to parse "
......
......@@ -328,6 +328,33 @@ Option::addOption(boost::shared_ptr<Option> opt) {
options_.insert(pair<int, boost::shared_ptr<Option> >(opt->getType(), opt));
}
uint8_t Option::getUint8() {
if (data_.size() < sizeof(uint8_t) ) {
isc_throw(OutOfRange, "Attempt to read uint8 from option " << type_
<< " that has size " << data_.size());
}
return (data_[0]);
}
uint16_t Option::getUint16() {
if (data_.size() < sizeof(uint16_t) ) {
isc_throw(OutOfRange, "Attempt to read uint16 from option " << type_
<< " that has size " << data_.size());
}
return ( ((uint16_t)data_[0]) << 8 ) + data_[1];
}
uint32_t Option::getUint32() {
if (data_.size() < sizeof(uint32_t) ) {
isc_throw(OutOfRange, "Attempt to read uint32 from option " << type_
<< " that has size " << data_.size());
}
return (((uint32_t)data_[0]) << 24)
+ (((uint32_t)data_[1]) << 16)
+ (((uint32_t)data_[2]) << 8)
+ (((uint32_t)data_[3]));
}
Option::~Option() {
}
......@@ -237,6 +237,12 @@ public:
bool
delOption(unsigned short type);
uint8_t getUint8();
uint16_t getUint16();
uint32_t getUint32();
/// just to force that every option has virtual dtor
virtual
~Option();
......
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