Browse Source

[3203] v6 vendor class is not intepreted as client class.

Tomek Mrugalski 11 years ago
parent
commit
71965bcfe5

+ 4 - 0
src/bin/dhcp6/dhcp6_messages.mes

@@ -27,6 +27,10 @@ successfully established a session with the BIND 10 control channel.
 This debug message is issued just before the IPv6 DHCP server attempts
 This debug message is issued just before the IPv6 DHCP server attempts
 to establish a session with the BIND 10 control channel.
 to establish a session with the BIND 10 control channel.
 
 
+% DHCP6_CLASS_ASSIGNED client packet has been assigned to the following class(es): %1
+This debug message informs that incoming packet has been assigned to specified
+class or classes. This is a norma
+
 % DHCP6_CLIENTID_MISSING mandatory client-id option is missing, message from %1 dropped
 % DHCP6_CLIENTID_MISSING mandatory client-id option is missing, message from %1 dropped
 This error message indicates that the received message is being dropped
 This error message indicates that the received message is being dropped
 because it does not include the mandatory client-id option necessary for
 because it does not include the mandatory client-id option necessary for

+ 34 - 0
src/bin/dhcp6/dhcp6_srv.cc

@@ -310,6 +310,9 @@ bool Dhcpv6Srv::run() {
             callout_handle->getArgument("query6", query);
             callout_handle->getArgument("query6", query);
         }
         }
 
 
+        // Assign this packet to a class, if possible
+        classifyPacket(query);
+
         try {
         try {
                 NameChangeRequestPtr ncr;
                 NameChangeRequestPtr ncr;
             switch (query->getType()) {
             switch (query->getType()) {
@@ -2409,6 +2412,37 @@ Dhcpv6Srv::unpackOptions(const OptionBuffer& buf,
     return (offset);
     return (offset);
 }
 }
 
 
+void Dhcpv6Srv::classifyPacket(const Pkt6Ptr& pkt) {
+
+    boost::shared_ptr<OptionCustom> vclass =
+        boost::dynamic_pointer_cast<OptionCustom>(pkt->getOption(D6O_VENDOR_CLASS));
+
+    if (!vclass) {
+        return;
+    }
+
+    string classes = "";
+
+    // DOCSIS specific section
+    if (vclass->readString(2).find("docsis3.0") != std::string::npos) {
+        pkt->addClass("docsis3.0");
+        classes += "docsis3.0 ";
+    } else
+    if (vclass->readString(2).find("eRouter1.0") != std::string::npos) {
+        pkt->addClass("eRouter1.0");
+        classes += "eRouter1.0 ";
+    }else
+    {
+        // Otherwise use the string as is
+        classes += vclass->readString(2);
+        pkt->addClass(vclass->readString(2));
+    }
+
+    if (!classes.empty()) {
+        LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASS_ASSIGNED)
+            .arg(classes);
+    }
+}
 
 
 };
 };
 };
 };

+ 10 - 0
src/bin/dhcp6/dhcp6_srv.h

@@ -533,6 +533,16 @@ protected:
                          size_t* relay_msg_offset,
                          size_t* relay_msg_offset,
                          size_t* relay_msg_len);
                          size_t* relay_msg_len);
 
 
+    /// @brief Assigns incoming packet to zero or more classes.
+    ///
+    /// @note For now, the client classification is very simple. It just uses
+    /// content of the vendor-class-identifier option as a class. The resulting
+    /// class will be stored in packet (see @ref isc::dhcp::Pkt6::classes_ and
+    /// @ref isc::dhcp::Pkt6::inClass).
+    ///
+    /// @param pkt packet to be classified
+    void classifyPacket(const Pkt6Ptr& pkt);
+
 private:
 private:
     /// @brief Allocation Engine.
     /// @brief Allocation Engine.
     /// Pointer to the allocation engine that we are currently using
     /// Pointer to the allocation engine that we are currently using

+ 29 - 0
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -1673,6 +1673,35 @@ TEST_F(Dhcpv6SrvTest, unpackOptions) {
     EXPECT_EQ(0x0, option_bar->getValue());
     EXPECT_EQ(0x0, option_bar->getValue());
 }
 }
 
 
+// Checks if client packets are classified properly
+TEST_F(Dhcpv6SrvTest, clientClassification) {
+
+    NakedDhcpv6Srv srv(0);
+
+    // Let's create a relayed SOLICIT. This particular relayed SOLICIT has
+    // vendor-class set to docsis3.0
+    Pkt6Ptr sol1;
+    ASSERT_NO_THROW(sol1 = captureDocsisRelayedSolicit());
+    ASSERT_NO_THROW(sol1->unpack());
+
+    srv.classifyPacket(sol1);
+
+    // It should belong to docsis3.0 class. It should not belong to eRouter1.0
+    EXPECT_TRUE(sol1->inClass("docsis3.0"));
+    EXPECT_FALSE(sol1->inClass("eRouter1.0"));
+
+    // Let's get a relayed SOLICIT. This particular relayed SOLICIT has
+    // vendor-class set to eRouter1.0
+    Pkt6Ptr sol2;
+    ASSERT_NO_THROW(sol2 = captureeRouterRelayedSolicit());
+    ASSERT_NO_THROW(sol2->unpack());
+
+    srv.classifyPacket(sol2);
+
+    EXPECT_TRUE(sol2->inClass("eRouter1.0"));
+    EXPECT_FALSE(sol2->inClass("docsis3.0"));
+}
+
 
 
 /// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
 /// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
 /// to call processX() methods.
 /// to call processX() methods.

+ 2 - 0
src/bin/dhcp6/tests/dhcp6_test_utils.h

@@ -112,6 +112,7 @@ public:
     using Dhcpv6Srv::createStatusCode;
     using Dhcpv6Srv::createStatusCode;
     using Dhcpv6Srv::selectSubnet;
     using Dhcpv6Srv::selectSubnet;
     using Dhcpv6Srv::sanityCheck;
     using Dhcpv6Srv::sanityCheck;
+    using Dhcpv6Srv::classifyPacket;
     using Dhcpv6Srv::loadServerID;
     using Dhcpv6Srv::loadServerID;
     using Dhcpv6Srv::writeServerID;
     using Dhcpv6Srv::writeServerID;
     using Dhcpv6Srv::unpackOptions;
     using Dhcpv6Srv::unpackOptions;
@@ -477,6 +478,7 @@ public:
     Pkt6Ptr captureSimpleSolicit();
     Pkt6Ptr captureSimpleSolicit();
     Pkt6Ptr captureRelayedSolicit();
     Pkt6Ptr captureRelayedSolicit();
     Pkt6Ptr captureDocsisRelayedSolicit();
     Pkt6Ptr captureDocsisRelayedSolicit();
+    Pkt6Ptr captureeRouterRelayedSolicit();
 
 
     /// @brief Auxiliary method that sets Pkt6 fields
     /// @brief Auxiliary method that sets Pkt6 fields
     ///
     ///

+ 145 - 5
src/bin/dhcp6/tests/wireshark.cc

@@ -17,9 +17,9 @@
 #include <string>
 #include <string>
 
 
 /// @file   wireshark.cc
 /// @file   wireshark.cc
-/// 
+///
 /// @brief  contains packet captures imported from Wireshark
 /// @brief  contains packet captures imported from Wireshark
-/// 
+///
 /// These are actual packets captured over wire. They are used in various
 /// These are actual packets captured over wire. They are used in various
 /// tests.
 /// tests.
 ///
 ///
@@ -33,6 +33,10 @@
 /// 6. Coding guidelines line restrictions apply, so wrap your code as necessary
 /// 6. Coding guidelines line restrictions apply, so wrap your code as necessary
 /// 7. Make sure you decribe the capture appropriately
 /// 7. Make sure you decribe the capture appropriately
 /// 8. Follow whatever rest of the methods are doing (set ports, ifaces etc.)
 /// 8. Follow whatever rest of the methods are doing (set ports, ifaces etc.)
+/// 9. To easily copy packet description, click File... -> Extract packet
+///    dissections -> as plain text file...
+///    (Make sure that the packet is expanded in the view. The text file will
+///    contain whatever expansion level you have in the graphical tree.)
 
 
 using namespace std;
 using namespace std;
 
 
@@ -81,7 +85,7 @@ Pkt6Ptr Dhcpv6SrvTest::captureRelayedSolicit() {
     //     - ORO (7)
     //     - ORO (7)
 
 
     // string exported from Wireshark
     // string exported from Wireshark
-    string hex_string = 
+    string hex_string =
         "0c0500000000000000000000000000000000fc00000000000000000000000000000900"
         "0c0500000000000000000000000000000000fc00000000000000000000000000000900"
         "12000231350009002c010517100001000e0001000151b5e46208002758f1e80003000c"
         "12000231350009002c010517100001000e0001000151b5e46208002758f1e80003000c"
         "000000010000000000000000000600020007";
         "000000010000000000000000000600020007";
@@ -102,7 +106,7 @@ Pkt6Ptr Dhcpv6SrvTest::captureRelayedSolicit() {
 Pkt6Ptr isc::test::Dhcpv6SrvTest::captureDocsisRelayedSolicit() {
 Pkt6Ptr isc::test::Dhcpv6SrvTest::captureDocsisRelayedSolicit() {
 
 
     // This is an actual DOCSIS packet
     // This is an actual DOCSIS packet
-    // RELAY-FORW (12) 
+    // RELAY-FORW (12)
     //  - Relay Message
     //  - Relay Message
     //    - SOLICIT (1)
     //    - SOLICIT (1)
     //      - client-id
     //      - client-id
@@ -132,7 +136,7 @@ Pkt6Ptr isc::test::Dhcpv6SrvTest::captureDocsisRelayedSolicit() {
     //    - Suboption 1026: Cable Modem MAC addr = 10:0d:7f:00:07:88
     //    - Suboption 1026: Cable Modem MAC addr = 10:0d:7f:00:07:88
 
 
     // string exported from Wireshark
     // string exported from Wireshark
-    string hex_string = 
+    string hex_string =
         "0c002a0288fe00fe00015a8d09fffe7af955fe80000000000000120d7ffffe00078800"
         "0c002a0288fe00fe00015a8d09fffe7af955fe80000000000000120d7ffffe00078800"
         "090189010d397f0001000a00030001100d7f000788000300287f000788000000000000"
         "090189010d397f0001000a00030001100d7f000788000300287f000788000000000000"
         "000000050018000000000000000000000000000000000000000000000000000e000000"
         "000000050018000000000000000000000000000000000000000000000000000e000000"
@@ -159,5 +163,141 @@ Pkt6Ptr isc::test::Dhcpv6SrvTest::captureDocsisRelayedSolicit() {
     return (pkt);
     return (pkt);
 }
 }
 
 
+/// returns a buffer with relayed SOLICIT (from DOCSIS3.0 eRouter)
+Pkt6Ptr isc::test::Dhcpv6SrvTest::captureeRouterRelayedSolicit() {
+
+/* Packet description exported from wireshark:
+DHCPv6
+    Message type: Relay-forw (12)
+    Hopcount: 0
+    Link address: 2001:558:ffa8::1 (2001:558:ffa8::1)
+    Peer address: fe80::22e5:2aff:feb8:1515 (fe80::22e5:2aff:feb8:1515)
+    Relay Message
+        Option: Relay Message (9)
+        Length: 241
+        Value: 01a90044000e000000140000000600080011001700180019...
+        DHCPv6
+            Message type: Solicit (1)
+            Transaction ID: 0xa90044
+            Rapid Commit
+                Option: Rapid Commit (14)
+                Length: 0
+            Reconfigure Accept
+                Option: Reconfigure Accept (20)
+                Length: 0
+            Option Request
+                Option: Option Request (6)
+                Length: 8
+                Value: 0011001700180019
+                Requested Option code: Vendor-specific Information (17)
+                Requested Option code: DNS recursive name server (23)
+                Requested Option code: Domain Search List (24)
+                Requested Option code: Identity Association for Prefix Delegation (25)
+            Vendor Class
+                Option: Vendor Class (16)
+                Length: 16
+                Value: 0000118b000a65526f75746572312e30
+                Enterprise ID: Cable Television Laboratories, Inc. (4491)
+                vendor-class-data: eRouter1.0
+            Vendor-specific Information
+                Option: Vendor-specific Information (17)
+                Length: 112
+                Value: 0000118b0002000745524f555445520003000b45434d3a45...
+                Enterprise ID: Cable Television Laboratories, Inc. (4491)
+                Suboption: Device Type =  (2)"EROUTER"
+                Suboption: Embedded Components =  (3)"ECM:EROUTER"
+                Suboption: Serial Number =  (4)"2BR229U40044C"
+                Suboption: Hardware Version =  (5)"1.04"
+                Suboption: Software Version =  (6)"V1.33.03"
+                Suboption: Boot ROM Version =  (7)"2.3.0R2"
+                Suboption: Organization Unique Identifier =  (8)"00095B"
+                Suboption: Model Number =  (9)"CG3000DCR"
+                Suboption: Vendor Name =  (10)"Netgear"
+            Client Identifier
+                Option: Client Identifier (1)
+                Length: 10
+                Value: 0003000120e52ab81515
+                DUID: 0003000120e52ab81515
+                DUID Type: link-layer address (3)
+                Hardware type: Ethernet (1)
+                Link-layer address: 20:e5:2a:b8:15:15
+            Identity Association for Prefix Delegation
+                Option: Identity Association for Prefix Delegation (25)
+                Length: 41
+                Value: 2ab815150000000000000000001a00190000000000000000...
+                IAID: 2ab81515
+                T1: 0
+                T2: 0
+                IA Prefix
+                    Option: IA Prefix (26)
+                    Length: 25
+                    Value: 000000000000000038000000000000000000000000000000...
+                    Preferred lifetime: 0
+                    Valid lifetime: 0
+                    Prefix length: 56
+                    Prefix address: :: (::)
+            Identity Association for Non-temporary Address
+                Option: Identity Association for Non-temporary Address (3)
+                Length: 12
+                Value: 2ab815150000000000000000
+                IAID: 2ab81515
+                T1: 0
+                T2: 0
+            Elapsed time
+                Option: Elapsed time (8)
+                Length: 2
+                Value: 0000
+                Elapsed time: 0 ms
+    Vendor-specific Information
+        Option: Vendor-specific Information (17)
+        Length: 22
+        Value: 0000118b0402000620e52ab815140401000401020300
+        Enterprise ID: Cable Television Laboratories, Inc. (4491)
+        Suboption: CM MAC Address Option =  (1026)20:e5:2a:b8:15:14
+        Suboption: CMTS Capabilities Option :  (1025)
+    Interface-Id
+        Option: Interface-Id (18)
+        Length: 4
+        Value: 00000022
+        Interface-ID:
+    Remote Identifier
+        Option: Remote Identifier (37)
+        Length: 14
+        Value: 0000101300015c228d4110000122
+        Enterprise ID: Arris Interactive LLC (4115)
+        Remote-ID: 00015c228d4110000122
+    DHCP option 53
+        Option: Unknown (53)
+        Length: 10
+        Value: 0003000100015c228d3d
+        DUID: 0003000100015c228d3d
+        DUID Type: link-layer address (3)
+        Hardware type: Ethernet (1)
+        Link-layer address: 00:01:5c:22:8d:3d */
+
+    // string exported from Wireshark
+    string hex_string =
+        "0c0020010558ffa800000000000000000001fe8000000000000022e52afffeb8151500"
+        "0900f101a90044000e000000140000000600080011001700180019001000100000118b"
+        "000a65526f75746572312e30001100700000118b0002000745524f555445520003000b"
+        "45434d3a45524f555445520004000d3242523232395534303034344300050004312e30"
+        "340006000856312e33332e303300070007322e332e3052320008000630303039354200"
+        "090009434733303030444352000a00074e6574676561720001000a0003000120e52ab8"
+        "1515001900292ab815150000000000000000001a001900000000000000003800000000"
+        "0000000000000000000000000003000c2ab81515000000000000000000080002000000"
+        "1100160000118b0402000620e52ab81514040100040102030000120004000000220025"
+        "000e0000101300015c228d41100001220035000a0003000100015c228d3d";
+
+    std::vector<uint8_t> bin;
+
+    // Decode the hex string and store it in bin (which happens
+    // to be OptionBuffer format)
+    isc::util::encode::decodeHex(hex_string, bin);
+
+    Pkt6Ptr pkt(new Pkt6(&bin[0], bin.size()));
+    captureSetDefaultFields(pkt);
+    return (pkt);
+}
+
 }; // end of isc::test namespace
 }; // end of isc::test namespace
 }; // end of isc namespace
 }; // end of isc namespace