}
-std::string Option::toText(int indent /* =0 */ ) {
- std::stringstream tmp;
-
- for (int i = 0; i < indent; i++)
- tmp << " ";
-
- tmp << "type=" << type_ << ", len=" << len()-getHeaderLen() << ": ";
+std::string Option::toText(int indent) {
+ std::stringstream output;
+ output << headerToText(indent) << ": ";
for (unsigned int i = 0; i < data_.size(); i++) {
if (i) {
- tmp << ":";
+ output << ":";
}
- tmp << setfill('0') << setw(2) << hex
+ output << setfill('0') << setw(2) << hex
<< static_cast<unsigned short>(data_[i]);
}
- // print suboptions
- for (OptionCollection::const_iterator opt = options_.begin();
- opt != options_.end();
- ++opt) {
- tmp << (*opt).second->toText(indent+2);
+ // Append suboptions.
+ output << suboptionsToText(indent + 2);
+
+ return (output.str());
+}
+
+std::string
+Option::headerToText(const int indent) {
+ std::stringstream output;
+ for (int i = 0; i < indent; i++)
+ output << " ";
+
+ int field_len = (getUniverse() == V4 ? 3 : 5);
+ output << "type=" << std::setw(field_len) << std::setfill('0')
+ << type_ << ", len=" << std::setw(field_len) << std::setfill('0')
+ << len()-getHeaderLen();
+ return (output.str());
+}
+
+std::string
+Option::suboptionsToText(const int indent) const {
+ std::stringstream output;
+
+ if (!options_.empty()) {
+ output << "," << std::endl << "options:";
+ for (OptionCollection::const_iterator opt = options_.begin();
+ opt != options_.end(); ++opt) {
+ output << std::endl << (*opt).second->toText(indent);
+ }
}
- return tmp.str();
+
+ return (output.str());
}
uint16_t
-// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
/// those into one exception which can be documented here.
void unpackOptions(const OptionBuffer& buf);
- /// @brief A private method used for option correctness.
+ /// @brief Returns option header in the textual format.
+ ///
+ /// This protected method should be called by the derived classes in
+ /// their respective @c toText implementations.
+ ///
+ /// @param indent Number of spaces to insert before the text.
+ ///
+ /// @return Option header in the textual format.
+ std::string headerToText(const int indent = 0);
+
+ /// @brief Returns collection of suboptions in the textual format.
+ ///
+ /// This protected method should be called by the derived classes
+ /// in their respective @c toText implementations to append the
+ /// suboptions held by this option. Note that there are some
+ /// option types which don't have suboptions because they contain
+ /// variable length fields. For such options this method is not
+ /// called.
+ ///
+ /// @param indent Number of spaces to insert before the text.
+ ///
+ //// @return Suboptions in the textual format.
+ std::string suboptionsToText(const int indent = 0) const;
+
+ /// @brief A protected method used for option correctness.
///
/// It is used in constructors. In there are any problems detected
/// (like specifying type > 255 for DHCPv4 option), it will throw
-// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
return (getHeaderLen() + addrs_.size() * V4ADDRESS_LEN);
}
-std::string Option4AddrLst::toText(int indent /* =0 */ ) {
- std::stringstream tmp;
-
- for (int i = 0; i < indent; i++) {
- tmp << " ";
- }
-
- tmp << "type=" << type_ << ", len=" << len()-getHeaderLen() << ":";
+std::string Option4AddrLst::toText(int indent) {
+ std::stringstream output;
+ output << headerToText(indent) << ":";
for (AddressContainer::const_iterator addr = addrs_.begin();
addr != addrs_.end(); ++addr) {
- tmp << " " << (*addr);
+ output << " " << (*addr);
}
- return tmp.str();
+ return (output.str());
}
} // end of isc::dhcp namespace
-// Copyright (C) 2011-2012, 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
}
}
-std::string Option6AddrLst::toText(int indent /* =0 */) {
- stringstream tmp;
- for (int i = 0; i < indent; i++)
- tmp << " ";
-
- tmp << "type=" << type_ << " " << addrs_.size() << "addr(s): ";
+std::string Option6AddrLst::toText(int indent) {
+ stringstream output;
+ output << headerToText(indent) << ":";
for (AddressContainer::const_iterator addr = addrs_.begin();
addr != addrs_.end(); ++addr) {
- tmp << *addr << " ";
+ output << " " << *addr;
}
- return tmp.str();
+ return (output.str());
}
uint16_t Option6AddrLst::len() {
-// Copyright (C) 2012-2013, 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
text << readAddress(index);
break;
case OPT_FQDN_TYPE:
- text << readFqdn(index);
+ text << "\"" << readFqdn(index) << "\"";
break;
case OPT_STRING_TYPE:
- text << readString(index);
+ text << "\"" << readString(index) << "\"";
break;
default:
;
}
// Append data field type in brackets.
- text << " ( " << OptionDataTypeUtil::getDataTypeName(data_type) << " ) ";
+ text << " (" << OptionDataTypeUtil::getDataTypeName(data_type) << ")";
return (text.str());
}
}
std::string OptionCustom::toText(int indent) {
- std::stringstream tmp;
+ std::stringstream output;
- for (int i = 0; i < indent; ++i)
- tmp << " ";
-
- tmp << "type=" << type_ << ", len=" << len()-getHeaderLen()
- << ", data fields:" << std::endl;
+ output << headerToText(indent) << ":";
OptionDataType data_type = definition_.getType();
if (data_type == OPT_RECORD_TYPE) {
// with them.
for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
field != fields.end(); ++field) {
- for (int j = 0; j < indent + 2; ++j) {
- tmp << " ";
- }
- tmp << "#" << std::distance(fields.begin(), field) << " "
- << dataFieldToText(*field, std::distance(fields.begin(),
- field))
- << std::endl;
+ output << " " << dataFieldToText(*field, std::distance(fields.begin(),
+ field));
}
} else {
// For non-record types we iterate over all buffers
// and non-arrays as they only differ in such a way that
// non-arrays have just single data field.
for (unsigned int i = 0; i < getDataFieldsNum(); ++i) {
- for (int j = 0; j < indent + 2; ++j) {
- tmp << " ";
- }
- tmp << "#" << i << " "
- << dataFieldToText(definition_.getType(), i)
- << std::endl;
+ output << " " << dataFieldToText(definition_.getType(), i);
}
}
- // print suboptions
- for (OptionCollection::const_iterator opt = options_.begin();
- opt != options_.end();
- ++opt) {
- tmp << (*opt).second->toText(indent+2);
- }
- return tmp.str();
+ // Append suboptions.
+ output << suboptionsToText(indent + 2);
+
+ return (output.str());
}
} // end of isc::dhcp namespace
#include <util/io_utilities.h>
#include <stdint.h>
+#include <sstream>
namespace isc {
namespace dhcp {
return (length);
}
+ /// @brief Returns option carrying an integer value in the textual
+ /// format.
+ ///
+ /// The returned value also includes the suboptions if present.
+ ///
+ /// @param indent Number of spaces to be inserted before the text.
+ virtual std::string toText(int indent = 0) {
+ std::stringstream output;
+ output << headerToText(indent) << ": ";
+
+ // For 1 byte long data types we need to cast to the integer
+ // because they are usually implemented as "char" types, in
+ // which case the character rather than number would be printed.
+ if (OptionDataTypeTraits<T>::len == 1) {
+ output << static_cast<int>(getValue());
+ } else {
+ output << getValue();
+ }
+
+ // Append data type name.
+ output << " ("
+ << OptionDataTypeUtil::getDataTypeName(OptionDataTypeTraits<T>::type)
+ << ")";
+
+ // Append suboptions.
+ output << suboptionsToText(indent + 2);
+
+ return (output.str());
+ }
+
private:
T value_; ///< Value conveyed by the option.
-// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#include <dhcp/option.h>
#include <dhcp/option_data_types.h>
#include <util/io_utilities.h>
-
+#include <sstream>
#include <stdint.h>
namespace isc {
return (length);
}
+ /// @brief Returns textual representation of the option.
+ ///
+ /// @param indent Number of space characters to be inserted before
+ /// the text.
+ ///
+ /// @return textual representation of the option.
+ virtual std::string toText(int indent = 0) {
+ std::stringstream output;
+ output << headerToText(indent) << ":";
+
+ std::string data_type = OptionDataTypeUtil::getDataTypeName(OptionDataTypeTraits<T>::type);
+ for (typename std::vector<T>::const_iterator value = values_.begin();
+ value != values_.end(); ++value) {
+ output << " " << *value << " (" << data_type << ")";
+ }
+
+ return (output.str());
+ }
+
private:
std::vector<T> values_;
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// PERFORMANCE OF THIS SOFTWARE.
#include <dhcp/option_string.h>
+#include <sstream>
namespace isc {
namespace dhcp {
setData(begin, end);
}
+std::string
+OptionString::toText(int indent) {
+ std::ostringstream output;
+ output << headerToText(indent) << ": "
+ << "\"" << getValue() << "\" (string)";
+
+ return (output.str());
+}
+
} // end of isc::dhcp namespace
} // end of isc namespace
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
/// @throw isc::OutOfRange if provided buffer is truncated.
virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end);
+ /// @brief Returns option information in the textual format.
+ ///
+ /// @param indent Number of space characters to be inserted before
+ /// the text.
+ ///
+ /// @return Option information in the textual format.
+ virtual std::string toText(int indent = 0);
};
/// Pointer to the OptionString object.
-// Copyright (C) 2013, 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#include <dhcp/dhcp4.h>
#include <dhcp/dhcp6.h>
#include <dhcp/option_vendor.h>
+#include <sstream>
using namespace isc::dhcp;
// Calculate and store data-len as follows:
// data-len = total option length - header length
// - enterprise id field length - data-len field size
- buf.writeUint8(len() - getHeaderLen() -
- sizeof(uint32_t) - sizeof(uint8_t));
+ buf.writeUint8(dataLen());
}
packOptions(buf);
}
return (length);
}
+
+uint8_t
+OptionVendor::dataLen() {
+ // Calculate and store data-len as follows:
+ // data-len = total option length - header length
+ // - enterprise id field length - data-len field size
+ return (len() - getHeaderLen() - sizeof(uint32_t) - sizeof(uint8_t));
+}
+
+std::string
+OptionVendor::toText(int indent) {
+ std::stringstream output;
+ output << headerToText(indent) << ": "
+ << getVendorId() << " (uint32)";
+
+ // For the DHCPv4 there is one more field.
+ if (getUniverse() == Option::V4) {
+ output << " " << static_cast<int>(dataLen()) << " (uint8)";
+ }
+
+ // Append suboptions.
+ output << suboptionsToText(indent + 2);
+
+ return (output.str());
+}
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
/// @return length of this option
virtual uint16_t len();
+ /// @brief Returns the option in the textual format.
+ ///
+ /// @param indent Number of spaces to be inserted before the text.
+ ///
+ /// @return Vendor option in the textual format.
+ virtual std::string toText(int indent = 0);
+
private:
+ /// @brief Calculates the data-len value for DHCPv4.
+ ///
+ /// The data-len field is only present in DHCPv4 space. It follows
+ /// the vendor-id field. This method is called from the
+ /// @c OptionVendor::pack and @c OptionVendor::toText to calculate
+ /// this value.
+ ///
+ /// @return Returns calculated data-len value.
+ uint8_t dataLen();
+
uint32_t vendor_id_; ///< Enterprise-id
};
/// implementations of this method.
///
/// @return string with text representation
- virtual std::string toText() = 0;
+ virtual std::string toText() const = 0;
/// @brief Returns packet size in binary format.
///
std::string
-Pkt4::toText() {
- stringstream tmp;
- tmp << "localAddr=" << local_addr_ << ":" << local_port_
- << " remoteAddr=" << remote_addr_
- << ":" << remote_port_ << ", msgtype=" << static_cast<int>(getType())
- << ", transid=0x" << hex << transid_ << dec << endl;
-
- for (isc::dhcp::OptionCollection::iterator opt=options_.begin();
- opt != options_.end();
- ++opt) {
- tmp << " " << opt->second->toText();
+Pkt4::toText() const {
+ stringstream output;
+ output << "local_address=" << local_addr_ << ":" << local_port_
+ << ", remote_adress=" << remote_addr_
+ << ":" << remote_port_ << ", msg_type=" << static_cast<int>(getType())
+ << ", transid=0x" << hex << transid_ << dec;
+
+ if (!options_.empty()) {
+ output << "," << std::endl << "options:";
+ for (isc::dhcp::OptionCollection::const_iterator opt = options_.begin();
+ opt != options_.end(); ++opt) {
+ output << std::endl << opt->second->toText(2);
+ }
}
-
- return tmp.str();
+ return (output.str());
}
void
/// This function is useful mainly for debugging.
///
/// @return string with text representation
- std::string toText();
+ std::string toText() const;
/// @brief Returns the size of the required buffer to build the packet.
///
}
std::string
-Pkt6::toText() {
+Pkt6::toText() const {
stringstream tmp;
tmp << "localAddr=[" << local_addr_ << "]:" << local_port_
<< " remoteAddr=[" << remote_addr_
<< "]:" << remote_port_ << endl;
tmp << "msgtype=" << static_cast<int>(msg_type_) << ", transid=0x" <<
hex << transid_ << dec << endl;
- for (isc::dhcp::OptionCollection::iterator opt=options_.begin();
+ for (isc::dhcp::OptionCollection::const_iterator opt=options_.begin();
opt != options_.end();
++opt) {
tmp << opt->second->toText() << std::endl;
/// This function is useful mainly for debugging.
///
/// @return string with text representation
- virtual std::string toText();
+ virtual std::string toText() const;
/// @brief Returns length of the packet.
///
-// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
EXPECT_THROW(option->readInteger<uint32_t>(11), isc::OutOfRange);
}
+// This test checks that the custom option holding a record of data
+// fields can be presented in the textual format.
+TEST_F(OptionCustomTest, toTextRecord) {
+ OptionDefinition opt_def("foo", 123, "record");
+ opt_def.addRecordField("uint32");
+ opt_def.addRecordField("string");
+
+ OptionCustom option(opt_def, Option::V4);
+ option.writeInteger<uint32_t>(10);
+ option.writeString("lorem ipsum", 1);
+
+ EXPECT_EQ("type=123, len=015: 10 (uint32) \"lorem ipsum\" (string)",
+ option.toText());
+}
+
+// This test checks that the custom option holding other data type
+// than "record" be presented in the textual format.
+TEST_F(OptionCustomTest, toTextNoRecord) {
+ OptionDefinition opt_def("foo", 234, "uint32");
+
+ OptionCustom option(opt_def, Option::V6);
+ option.writeInteger<uint32_t>(123456);
+
+ OptionDefinition sub_opt_def("bar", 333, "fqdn");
+ OptionCustomPtr sub_opt(new OptionCustom(sub_opt_def, Option::V6));
+ sub_opt->writeFqdn("myhost.example.org.");
+ option.addOption(sub_opt);
+
+ EXPECT_EQ("type=00234, len=00028: 123456 (uint32),\n"
+ "options:\n"
+ " type=00333, len=00020: \"myhost.example.org.\" (fqdn)",
+ option.toText());
+}
+
} // anonymous namespace
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
addValuesTest<int16_t>();
}
+TEST_F(OptionIntArrayTest, toText) {
+ OptionUint32Array option(Option::V4, 128);
+ option.addValue(1);
+ option.addValue(32);
+ option.addValue(324);
+
+ EXPECT_EQ("type=128, len=012: 1 (uint32) 32 (uint32) 324 (uint32)",
+ option.toText());
+}
+
} // anonymous namespace
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
ASSERT_FALSE(subopt);
}
+// This test checks that the toText function returns the option in the
+// textual format correctly.
+TEST_F(OptionIntTest, toText) {
+ OptionUint32 option(Option::V4, 128, 345678);
+ EXPECT_EQ("type=128, len=004: 345678 (uint32)", option.toText());
+
+ option.addOption(OptionPtr(new OptionUint16(Option::V4, 1, 234)));
+ option.addOption(OptionPtr(new OptionUint8(Option::V4, 3, 22)));
+ EXPECT_EQ("type=128, len=011: 345678 (uint32),\n"
+ "options:\n"
+ " type=001, len=002: 234 (uint16)\n"
+ " type=003, len=001: 22 (uint8)",
+ option.toText());
+}
+
} // anonymous namespace
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
EXPECT_TRUE(option_value == test_string);
}
+// This test checks that the DHCP option holding a single string is
+// correctly returned in the textual format.
+TEST_F(OptionStringTest, toText) {
+ // V4 option
+ std::string option_value("lorem ipsum");
+ OptionString optv4(Option::V4, 122, option_value);
+ EXPECT_EQ("type=122, len=011: \"lorem ipsum\" (string)", optv4.toText());
+
+ // V6 option
+ option_value = "is a filler text";
+ OptionString optv6(Option::V6, 512, option_value);
+ EXPECT_EQ("type=00512, len=00016: \"is a filler text\" (string)", optv6.toText());
+}
+
} // anonymous namespace
-// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
Option opt(Option::V4, 253, buf);
- EXPECT_EQ("type=253, len=3: 00:0f:ff", opt.toText());
+ EXPECT_EQ("type=253, len=003: 00:0f:ff", opt.toText());
}
// Tests simple constructor
buf_[2] = 0xff;
OptionPtr opt(new Option(Option::V6, 258, buf_.begin(), buf_.begin() + 3 ));
- EXPECT_EQ("type=258, len=3: 00:0f:ff", opt->toText());
+ EXPECT_EQ("type=00258, len=00003: 00:0f:ff", opt->toText());
}
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#include <dhcp/docsis3_option_defs.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/option_vendor.h>
+#include <dhcp/option_int.h>
#include <dhcp/option_int_array.h>
#include <exceptions/exceptions.h>
#include <util/buffer.h>
EXPECT_FALSE(memcmp(&binary[0], output.getData(), output.getLength()));
}
+// Tests that the vendor option is correctly returned in the textual
+// format for DHCPv4 case.
+TEST_F(OptionVendorTest, toText4) {
+ OptionVendor option(Option::V4, 1024);
+ option.addOption(OptionPtr(new OptionUint32(Option::V4, 1, 100)));
+
+ EXPECT_EQ("type=125, len=011: 1024 (uint32) 6 (uint8),\n"
+ "options:\n"
+ " type=001, len=004: 100 (uint32)",
+ option.toText());
+}
+
+// Tests that the vendor option is correctly returned in the textual
+// format for DHCPv6 case.
+TEST_F(OptionVendorTest, toText6) {
+ OptionVendor option(Option::V6, 2048);
+ option.addOption(OptionPtr(new OptionUint16(Option::V6, 1, 100)));
+
+ EXPECT_EQ("type=00017, len=00010: 2048 (uint32),\n"
+ "options:\n"
+ " type=00001, len=00002: 100 (uint16)",
+ option.toText());
+}
+
}
#include <dhcp/dhcp4.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/docsis3_option_defs.h>
+#include <dhcp/option_int.h>
#include <dhcp/option_string.h>
+#include <dhcp/option4_addrlst.h>
#include <dhcp/pkt4.h>
#include <exceptions/exceptions.h>
#include <util/buffer.h>
}
}
+// This test checks that the packet data are correctly converted to the
+// textual format.
+TEST_F(Pkt4Test, toText) {
+ Pkt4 pkt(DHCPDISCOVER, 2543);
+ pkt.setLocalAddr(IOAddress("192.0.2.34"));
+ pkt.setRemoteAddr(IOAddress("192.10.33.4"));
+
+ pkt.addOption(OptionPtr(new Option4AddrLst(123, IOAddress("192.0.2.3"))));
+ pkt.addOption(OptionPtr(new OptionUint32(Option::V4, 156, 123456)));
+ pkt.addOption(OptionPtr(new OptionString(Option::V4, 87, "lorem ipsum")));
+
+ EXPECT_EQ("local_address=192.0.2.34:67, remote_adress=192.10.33.4:68, "
+ "msg_type=1, transid=0x9ef,\n"
+ "options:\n"
+ " type=053, len=001: 01\n"
+ " type=087, len=011: \"lorem ipsum\" (string)\n"
+ " type=123, len=004: 192.0.2.3\n"
+ " type=156, len=004: 123456 (uint32)",
+ pkt.toText());
+}
+
} // end of anonymous namespace