From: Tomek Mrugalski Date: Tue, 30 Sep 2014 17:57:46 +0000 (+0200) Subject: [3546] Initial version of Pkt::getMAC() method implemented. X-Git-Tag: trac3489_base~2^2~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dd1ecaaa20749cb8b0d95bba1c72e4df1fd5835a;p=thirdparty%2Fkea.git [3546] Initial version of Pkt::getMAC() method implemented. --- diff --git a/src/lib/dhcp/pkt.cc b/src/lib/dhcp/pkt.cc index abfd64ad9a..6951d1b4cf 100644 --- a/src/lib/dhcp/pkt.cc +++ b/src/lib/dhcp/pkt.cc @@ -86,5 +86,22 @@ Pkt::setHWAddrMember(const uint8_t htype, const uint8_t, hw_addr.reset(new HWAddr(mac_addr, htype)); } +HWAddrPtr +Pkt::getMAC(MACSource from) { + HWAddrPtr mac; + if (from == MAC_SOURCE_RAW || from == MAC_SOURCE_ANY) { + mac = getRemoteHWAddr(); + if (mac) { + return (mac); + } + } + + /// @todo: add other MAC acquisition methods here + + + // Ok, none of the methods were suitable. Return NULL. + return (HWAddrPtr()); +} + }; }; diff --git a/src/lib/dhcp/pkt.h b/src/lib/dhcp/pkt.h index 1e7d4a4107..bb285b42fd 100644 --- a/src/lib/dhcp/pkt.h +++ b/src/lib/dhcp/pkt.h @@ -34,6 +34,49 @@ namespace dhcp { /// This class is purely virtual. Please instantiate Pkt4, Pkt6 or any /// other derived classes. class Pkt { +public: + + /// @brief specified where did we get this MAC address from? + /// + /// The list covers all possible MAC sources. The uncommented ones + /// are currently supported. When you implement a new method, please + /// uncomment appropriate line here. + enum MACSource { + + /// Not really a type, only used in getMAC() calls + MAC_SOURCE_ANY, + + /// obtained first hand from raw socket (100% reliable) + MAC_SOURCE_RAW, + + /// extracted from DUID-LL or DUID-LLT (not reliable as the client + /// can send fake DUID) + // MAC_SOURCE_DUID, + + /// extracted from IPv6 link-local address. Client can use different + /// IID other than EUI-64, e.g. Windows supports RFC4941 and uses + /// random values instead of EUI-64. + // MAC_SOURCE_IPV6_LINK_LOCAL, + + /// RFC6939 (a relay agent can insert client link layer address option) + /// Note that a skilled attacker can fake that by sending his request + /// relayed, so the legitimate relay will think it's a second relay. + // MAC_SOURCE_CLIENT_ADDR_RELAY_OPTION, + + /// A relay can insert remote-id. In some deployments it contains a MAC + /// address. + // MAC_SOURCE_REMOTE_ID, + + /// A relay can insert a subscriber-id option. In some deployments it + /// contains a MAC address. + // MAC_SOURCE_SUBSCRIBER_ID, + + /// A CMTS (acting as DHCP relay agent) that supports DOCSIS standard + /// can insert DOCSIS options that contain client's MAC address. + /// Client in this context would be a cable modem. + // MAC_SOURCE_DOCSIS_OPTIONS + }; + protected: Pkt(uint32_t transid, const isc::asiolink::IOAddress& local_addr, const isc::asiolink::IOAddress& remote_addr, uint16_t local_port, @@ -381,13 +424,22 @@ public: void setRemoteHWAddr(const uint8_t htype, const uint8_t hlen, const std::vector& mac_addr); - /// @brief Returns the remote HW address. + /// @brief Returns the remote HW address obtained from raw sockets. /// /// @return remote HW address. HWAddrPtr getRemoteHWAddr() const { return (remote_hwaddr_); } + /// @brief Returns MAC address. + /// + /// The difference between this method and getRemoteHWAddr() is that + /// getRemoteHWAddr() returns only what was obtained from raw sockets. + /// This method is more generic and can attempt to obtain MAC from + /// varied sources: raw sockets, client-id, link-local IPv6 address, + /// and various relay options. + HWAddrPtr getMAC(MACSource from); + /// @brief virtual desctructor /// /// There is nothing to clean up here, but since there are virtual methods, diff --git a/src/lib/dhcp/tests/pkt4_unittest.cc b/src/lib/dhcp/tests/pkt4_unittest.cc index 1f08137042..0c09b412c0 100644 --- a/src/lib/dhcp/tests/pkt4_unittest.cc +++ b/src/lib/dhcp/tests/pkt4_unittest.cc @@ -851,4 +851,30 @@ TEST_F(Pkt4Test, clientClasses) { EXPECT_TRUE(pkt.inClass("foo")); } +// Tests whether MAC can be obtained and that MAC sources are not +// confused. +TEST_F(Pkt4Test, getMAC) { + Pkt4 pkt(DHCPOFFER, 1234); + + // DHCPv6 packet by default doens't have MAC address specified. + EXPECT_FALSE(pkt.getMAC(Pkt::MAC_SOURCE_ANY)); + EXPECT_FALSE(pkt.getMAC(Pkt::MAC_SOURCE_RAW)); + + // Let's invent a MAC + const uint8_t hw[] = { 2, 4, 6, 8, 10, 12 }; // MAC + const uint8_t hw_type = 123; // hardware type + HWAddrPtr dummy_hwaddr(new HWAddr(hw, sizeof(hw), hw_type)); + + // Now let's pretend that we obtained it from raw sockets + pkt.setRemoteHWAddr(dummy_hwaddr); + + // Now we should be able to get something + ASSERT_TRUE(pkt.getMAC(Pkt::MAC_SOURCE_ANY)); + ASSERT_TRUE(pkt.getMAC(Pkt::MAC_SOURCE_RAW)); + + // Check that the returned MAC is indeed the expected one + ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(Pkt::MAC_SOURCE_ANY)); + ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(Pkt::MAC_SOURCE_RAW)); +} + } // end of anonymous namespace diff --git a/src/lib/dhcp/tests/pkt6_unittest.cc b/src/lib/dhcp/tests/pkt6_unittest.cc index 17cb629b2b..bf121f08ea 100644 --- a/src/lib/dhcp/tests/pkt6_unittest.cc +++ b/src/lib/dhcp/tests/pkt6_unittest.cc @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -810,4 +811,30 @@ TEST_F(Pkt6Test, clientClasses) { EXPECT_TRUE(pkt.inClass("foo")); } +// Tests whether MAC can be obtained and that MAC sources are not +// confused. +TEST_F(Pkt6Test, getMAC) { + Pkt6 pkt(DHCPV6_ADVERTISE, 1234); + + // DHCPv6 packet by default doens't have MAC address specified. + EXPECT_FALSE(pkt.getMAC(Pkt::MAC_SOURCE_ANY)); + EXPECT_FALSE(pkt.getMAC(Pkt::MAC_SOURCE_RAW)); + + // Let's invent a MAC + const uint8_t hw[] = { 2, 4, 6, 8, 10, 12 }; // MAC + const uint8_t hw_type = 123; // hardware type + HWAddrPtr dummy_hwaddr(new HWAddr(hw, sizeof(hw), hw_type)); + + // Now let's pretend that we obtained it from raw sockets + pkt.setRemoteHWAddr(dummy_hwaddr); + + // Now we should be able to get something + ASSERT_TRUE(pkt.getMAC(Pkt::MAC_SOURCE_ANY)); + ASSERT_TRUE(pkt.getMAC(Pkt::MAC_SOURCE_RAW)); + + // Check that the returned MAC is indeed the expected one + ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(Pkt::MAC_SOURCE_ANY)); + ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(Pkt::MAC_SOURCE_RAW)); +} + }