Browse Source

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

Tomek Mrugalski 13 years ago
parent
commit
59a5275869

+ 11 - 6
src/bin/dhcp4/dhcp4_srv.cc

@@ -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()) {

+ 1 - 1
src/lib/dhcp/dhcp4.h

@@ -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

+ 16 - 3
src/lib/dhcp/iface_mgr.cc

@@ -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
     }
 

+ 9 - 0
src/lib/dhcp/libdhcp.cc

@@ -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 "

+ 27 - 0
src/lib/dhcp/option.cc

@@ -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() {
 
 }

+ 6 - 0
src/lib/dhcp/option.h

@@ -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();