Browse Source

[2902] Use default HW address if not specified.

Marcin Siodelski 12 years ago
parent
commit
882b1c68c7
2 changed files with 36 additions and 30 deletions
  1. 35 23
      src/lib/dhcp/protocol_util.cc
  2. 1 7
      src/lib/dhcp/tests/protocol_util_unittest.cc

+ 35 - 23
src/lib/dhcp/protocol_util.cc

@@ -112,33 +112,45 @@ decodeIpUdpHeader(InputBuffer& buf, Pkt4Ptr& pkt) {
 
 void
 writeEthernetHeader(const Pkt4Ptr& pkt, OutputBuffer& out_buf) {
+    // Set destination HW address.
     HWAddrPtr remote_addr = pkt->getRemoteHWAddr();
-    HWAddrPtr local_addr = pkt->getLocalHWAddr();
-    if (!remote_addr) {
-        isc_throw(BadValue, "remote HW address must be set to construct"
-                  " an ethernet frame header");
-
-    } else if (!local_addr) {
-        isc_throw(BadValue, "local HW address must be set to construct"
-                  " an ethernet frame header");
-
-    } else if (remote_addr->hwaddr_.size() != HWAddr::ETHERNET_HWADDR_LEN) {
-        isc_throw(BadValue, "invalid size of the remote HW address "
-                  << remote_addr->hwaddr_.size() << " when constructing"
-                  << " an ethernet frame header; expected size is"
-                  << " " << HWAddr::ETHERNET_HWADDR_LEN);
-
-    } else if (local_addr->hwaddr_.size() != HWAddr::ETHERNET_HWADDR_LEN) {
-        isc_throw(BadValue, "invalid size of the local HW address "
-                  << local_addr->hwaddr_.size() << " when constructing"
-                  << " an ethernet frame header; expected size is"
-                  << " " << HWAddr::ETHERNET_HWADDR_LEN);
+    if (remote_addr) {
+        if (remote_addr->hwaddr_.size() == HWAddr::ETHERNET_HWADDR_LEN) {
+            out_buf.writeData(&remote_addr->hwaddr_[0],
+                              HWAddr::ETHERNET_HWADDR_LEN);
+        } else {
+            isc_throw(BadValue, "invalid size of the remote HW address "
+                      << remote_addr->hwaddr_.size() << " when constructing"
+                      << " an ethernet frame header; expected size is"
+                      << " " << HWAddr::ETHERNET_HWADDR_LEN);
+        }
+    } else {
+        // HW address has not been specified. This is possible when receiving
+        // packet through a logical interface (e.g. lo). In such cases, we
+        // don't want to fail but rather provide a default HW address, which
+        // consists of zeros.
+        out_buf.writeData(&std::vector<uint8_t>(HWAddr::ETHERNET_HWADDR_LEN)[0],
+                          HWAddr::ETHERNET_HWADDR_LEN);
+    }
 
+    // Set source HW address.
+    HWAddrPtr local_addr = pkt->getLocalHWAddr();
+    if (local_addr) {
+        if (local_addr->hwaddr_.size() == HWAddr::ETHERNET_HWADDR_LEN) {
+            out_buf.writeData(&local_addr->hwaddr_[0],
+                              HWAddr::ETHERNET_HWADDR_LEN);
+        } else {
+            isc_throw(BadValue, "invalid size of the local HW address "
+                      << local_addr->hwaddr_.size() << " when constructing"
+                      << " an ethernet frame header; expected size is"
+                      << " " << HWAddr::ETHERNET_HWADDR_LEN);
+        }
+    } else {
+        // Provide default HW address.
+        out_buf.writeData(&std::vector<uint8_t>(HWAddr::ETHERNET_HWADDR_LEN)[0],
+                          HWAddr::ETHERNET_HWADDR_LEN);
     }
 
-    // Write destination and source address.
-    out_buf.writeData(&remote_addr->hwaddr_[0], HWAddr::ETHERNET_HWADDR_LEN);
-    out_buf.writeData(&local_addr->hwaddr_[0], HWAddr::ETHERNET_HWADDR_LEN);
     // Type IP.
     out_buf.writeUint16(0x0800);
 }

+ 1 - 7
src/lib/dhcp/tests/protocol_util_unittest.cc

@@ -215,19 +215,13 @@ TEST(ProtocolUtilTest, writeEthernetHeader) {
     OutputBuffer buf(1);
     Pkt4Ptr pkt(new Pkt4(DHCPDISCOVER, 0));
 
-    // HW addresses not set yet. It should fail.
-    EXPECT_THROW(writeEthernetHeader(pkt, buf), BadValue);
-
     HWAddrPtr local_hw_addr(new HWAddr(src_hw_addr, 6, 1));
     ASSERT_NO_THROW(pkt->setLocalHWAddr(local_hw_addr));
 
-    // Remote address still not set. It should fail again.
-    EXPECT_THROW(writeEthernetHeader(pkt, buf), BadValue);
-
     // Set invalid length (7) of the hw address.
     HWAddrPtr remote_hw_addr(new HWAddr(&std::vector<uint8_t>(1, 7)[0], 7, 1));
     ASSERT_NO_THROW(pkt->setRemoteHWAddr(remote_hw_addr));
-    // HW address is too long, so it should fail again.
+    // HW address is too long, so it should fail.
     EXPECT_THROW(writeEthernetHeader(pkt, buf), BadValue);
 
     // Finally, set a valid HW address.