Browse Source

[3705] RSOO option support implemented.

Tomek Mrugalski 10 years ago
parent
commit
37036f7f24

+ 1 - 0
src/lib/dhcp/dhcp6.h

@@ -65,6 +65,7 @@
 #define D6O_CLT_TIME                            46 /* RFC5007 */
 #define D6O_LQ_RELAY_DATA                       47 /* RFC5007 */
 #define D6O_LQ_CLIENT_LINK                      48 /* RFC5007 */
+#define D6O_RSOO                                66 /* RFC6422 */
 #define D6O_CLIENT_LINKLAYER_ADDR               79 /* RFC6939 */
 
 /*

+ 1 - 0
src/lib/dhcp/std_option_defs.h

@@ -327,6 +327,7 @@ const OptionDefParams OPTION_DEF_PARAMS6[] = {
       RECORD_DEF(LQ_RELAY_DATA_RECORDS), "" },
     { "lq-client-link", D6O_LQ_CLIENT_LINK, OPT_IPV6_ADDRESS_TYPE, true,
       NO_RECORD_DEF, "" },
+    { "rsoo", D6O_RSOO, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "dhcp4" },
     { "client-linklayer-addr", D6O_CLIENT_LINKLAYER_ADDR, OPT_BINARY_TYPE, false,
         NO_RECORD_DEF, "" }
 

+ 39 - 0
src/lib/dhcp/tests/pkt6_unittest.cc

@@ -1294,4 +1294,43 @@ TEST_F(Pkt6Test, getMACFromRemoteIdRelayOption) {
     EXPECT_EQ(tmp.str(), mac->toText(true));
 }
 
+// This test verifies that a solicit that passed through two be parsed
+// properly. In particular the second relay (outer encapsulation) included RSOO
+// (Relay Supplied Options option). This test checks whether it was parsed
+// properly. See captureRelayed2xRSOO() description for details.
+TEST_F(Pkt6Test, rsoo) {
+    Pkt6Ptr msg = test::PktCaptures::captureRelayed2xRSOO();
+
+    EXPECT_NO_THROW(msg->unpack());
+
+    EXPECT_EQ(DHCPV6_SOLICIT, msg->getType());
+    EXPECT_EQ(217, msg->len());
+
+    ASSERT_EQ(2, msg->relay_info_.size());
+
+    OptionPtr opt;
+
+    Pkt6::RelayInfo& relay1 = msg->relay_info_[0];
+    Pkt6::RelayInfo& relay2 = msg->relay_info_[1];
+
+    // There should be an RSOO option in the outermost relay
+    opt = msg->getRelayOption(D6O_RSOO, 1);
+    ASSERT_TRUE(opt);
+
+    EXPECT_EQ(D6O_RSOO, opt->getType());
+    const OptionCollection& rsoo = opt->getOptions();
+    ASSERT_EQ(2, rsoo.size());
+
+    OptionPtr rsoo1 = opt->getOption(255);
+    OptionPtr rsoo2 = opt->getOption(256);
+
+    ASSERT_TRUE(rsoo1);
+    ASSERT_TRUE(rsoo2);
+
+    EXPECT_EQ(8, rsoo1->len()); // 4 bytes of data + header
+    EXPECT_EQ(13, rsoo2->len()); // 9 bytes of data + header
+
+}
+
+
 }

+ 1 - 0
src/lib/dhcp/tests/pkt_captures.h

@@ -45,6 +45,7 @@ public:
     static isc::dhcp::Pkt6Ptr captureDocsisRelayedSolicit();
     static isc::dhcp::Pkt6Ptr captureeRouterRelayedSolicit();
     static isc::dhcp::Pkt6Ptr captureCableLabsShortVendorClass();
+    static isc::dhcp::Pkt6Ptr captureRelayed2xRSOO();
 
 protected:
     /// @brief Auxiliary method that sets Pkt6 fields

+ 71 - 0
src/lib/dhcp/tests/pkt_captures6.cc

@@ -328,5 +328,76 @@ Pkt6Ptr isc::test::PktCaptures::captureCableLabsShortVendorClass() {
 
 }
 
+/// @brief creates doubly relayed solicit message
+///
+/// This is a traffic capture exported from wireshark and manually modified
+/// to include necessary options (RSOO). It includes a SOLICIT message
+/// that passed through two relays. It is especially interesting,
+/// because of the following properties:
+/// - double encapsulation
+/// - first relay inserts relay-msg before extra options
+/// - second relay inserts relay-msg after extra options
+/// - both relays are from different vendors
+/// - interface-id are different for each relay
+/// - first relay inserts valid remote-id
+/// - second relay inserts remote-id with empty vendor data
+/// - the solicit message requests for custom options in ORO
+/// - there are option types in RELAY-FORW that do not appear in SOLICIT
+/// - there are option types in SOLICT that do not appear in RELAY-FORW
+///
+/// RELAY-FORW
+///  - relay message option
+///      - RELAY-FORW
+///          - rsoo (66)
+///              - option 255 (len 4)
+///              - option 256 (len 9)
+///          - RELAY-FORW
+///             - SOLICIT
+///                  - client-id option
+///                  - ia_na option
+///                  - elapsed time
+///                  - ORO
+///      - interface-id option (18)
+///      - remote-id option (37)
+///
+/// The original capture was posted to dibbler users mailing list.
+///
+/// @return created double relayed SOLICIT message
+isc::dhcp::Pkt6Ptr isc::test::PktCaptures::captureRelayed2xRSOO() {
+
+    // string exported from Wireshark
+    string hex_string =
+        "0c01200108880db800010000000000000000fe80000000000000020021fffe5c18a9"
+        "0009007d0c0000000000000000000000000000000000fe80000000000000020021fffe5c18a9"
+        "00420015" // RSOO (includes ...
+        "00ff000401020304" // ... option 255, len 4, content 0x01020304
+        "01000009010203040506070809" // ... option 256, len 9, content 0x010203040506070809
+        "0025000400000de9" // remote-id
+        "00090036" // relay-msg, len 54
+        "016b4fe2" // solicit"
+        "0001000e0001000118b033410000215c18a9" // client-id
+        "0003000c00000001ffffffffffffffff" // ia-na
+        "000800020000"
+        "00060006001700f200f3"
+        "0012001c4953414d3134347c3239397c697076367c6e743a76703a313a" // vendor-class
+        "313130002500120000197f0001000118b033410000215c18a9";
+
+    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()));
+    pkt->setRemotePort(547);
+    pkt->setRemoteAddr(IOAddress("fe80::1234"));
+    pkt->setLocalPort(547);
+    pkt->setLocalAddr(IOAddress("ff05::1:3"));
+    pkt->setIndex(2);
+    pkt->setIface("eth0");
+    return (pkt);
+}
+
+
 }; // end of isc::test namespace
 }; // end of isc namespace