summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dhcp')
-rw-r--r--src/lib/dhcp/classify.cc15
-rw-r--r--src/lib/dhcp/classify.h9
-rw-r--r--src/lib/dhcp/pkt4.cc8
-rw-r--r--src/lib/dhcp/tests/classify_unittest.cc26
-rw-r--r--src/lib/dhcp/tests/iface_mgr_unittest.cc4
-rw-r--r--src/lib/dhcp/tests/option_definition_unittest.cc28
-rw-r--r--src/lib/dhcp/tests/pkt4_unittest.cc32
7 files changed, 105 insertions, 17 deletions
diff --git a/src/lib/dhcp/classify.cc b/src/lib/dhcp/classify.cc
index ed499266c0..95fc5dd08b 100644
--- a/src/lib/dhcp/classify.cc
+++ b/src/lib/dhcp/classify.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -10,6 +10,7 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/constants.hpp>
#include <boost/algorithm/string/split.hpp>
+#include <sstream>
#include <vector>
namespace isc {
@@ -28,6 +29,18 @@ ClientClasses::ClientClasses(const std::string& class_names)
}
}
}
+
+std::string
+ClientClasses::toText(const std::string& separator) const {
+ std::stringstream s;
+ for (const_iterator class_it = begin(); class_it != end(); ++class_it) {
+ if (class_it != begin()) {
+ s << separator;
+ }
+ s << *class_it;
+ }
+ return (s.str());
+}
} // end of namespace isc::dhcp
} // end of namespace isc
diff --git a/src/lib/dhcp/classify.h b/src/lib/dhcp/classify.h
index 61911f1047..174930c348 100644
--- a/src/lib/dhcp/classify.h
+++ b/src/lib/dhcp/classify.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -65,6 +65,13 @@ namespace dhcp {
contains(const ClientClass& x) const {
return (find(x) != end());
}
+
+ /// @brief Returns all class names as text
+ ///
+ /// @param separator Separator to be used between class names. The
+ /// default separator comprises comma sign followed by space
+ /// character.
+ std::string toText(const std::string& separator = ", ") const;
};
};
diff --git a/src/lib/dhcp/pkt4.cc b/src/lib/dhcp/pkt4.cc
index 706574b5b0..3c980b5205 100644
--- a/src/lib/dhcp/pkt4.cc
+++ b/src/lib/dhcp/pkt4.cc
@@ -482,7 +482,9 @@ Pkt4::setSname(const uint8_t* sname, size_t snameLen /*= MAX_SNAME_LEN*/) {
}
std::copy(sname, (sname + snameLen), sname_);
- std::fill((sname_ + snameLen), (sname_ + MAX_SNAME_LEN), 0);
+ if (snameLen < MAX_SNAME_LEN) {
+ std::fill((sname_ + snameLen), (sname_ + MAX_SNAME_LEN), 0);
+ }
// No need to store snameLen as any empty space is filled with 0s
}
@@ -498,7 +500,9 @@ Pkt4::setFile(const uint8_t* file, size_t fileLen /*= MAX_FILE_LEN*/) {
}
std::copy(file, (file + fileLen), file_);
- std::fill((file_ + fileLen), (file_ + MAX_FILE_LEN), 0);
+ if (fileLen < MAX_FILE_LEN) {
+ std::fill((file_ + fileLen), (file_ + MAX_FILE_LEN), 0);
+ }
// No need to store fileLen as any empty space is filled with 0s
}
diff --git a/src/lib/dhcp/tests/classify_unittest.cc b/src/lib/dhcp/tests/classify_unittest.cc
index 9de2e284c5..215551eb06 100644
--- a/src/lib/dhcp/tests/classify_unittest.cc
+++ b/src/lib/dhcp/tests/classify_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -107,3 +107,27 @@ TEST(ClassifyTest, ClientClassesIterator) {
EXPECT_TRUE(seengamma);
EXPECT_FALSE(seendelta);
}
+
+// Check that the ClientClasses::toText function returns
+// correct values.
+TEST(ClassifyTest, ClientClassesToText) {
+ // No classes.
+ ClientClasses classes;
+ EXPECT_TRUE(classes.toText().empty());
+
+ // Insert single class name and see if it doesn't include spurious
+ // comma after it.
+ classes.insert("alpha");
+ EXPECT_EQ("alpha", classes.toText());
+
+ // Insert next class name and see that both classes are present.
+ classes.insert("gamma");
+ EXPECT_EQ("alpha, gamma", classes.toText());
+
+ // Insert third class and make sure they get ordered alphabetically.
+ classes.insert("beta");
+ EXPECT_EQ("alpha, beta, gamma", classes.toText());
+
+ // Check non-standard separator.
+ EXPECT_EQ("alpha.beta.gamma", classes.toText("."));
+}
diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc
index 0d244b7c7f..efd21df6a5 100644
--- a/src/lib/dhcp/tests/iface_mgr_unittest.cc
+++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -883,7 +883,7 @@ TEST_F(IfaceMgrTest, multipleSockets) {
init_sockets_it != init_sockets.end(); ++init_sockets_it) {
// recv() must result in error when using invalid socket.
char buf;
- recv(*init_sockets_it, &buf, 1, MSG_PEEK);
+ static_cast<void>(recv(*init_sockets_it, &buf, 1, MSG_PEEK));
// EWOULDBLOCK would mean that socket is valid/open but
// simply no data is received so we have to check for
// other errors.
diff --git a/src/lib/dhcp/tests/option_definition_unittest.cc b/src/lib/dhcp/tests/option_definition_unittest.cc
index 399c62dcc7..ccf658b0d3 100644
--- a/src/lib/dhcp/tests/option_definition_unittest.cc
+++ b/src/lib/dhcp/tests/option_definition_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -362,6 +362,7 @@ TEST_F(OptionDefinitionTest, ipv6AddressArray) {
option_v6 = opt_def.optionFactory(Option::V6, D6O_NIS_SERVERS, buf);
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(Option6AddrLst));
boost::shared_ptr<Option6AddrLst> option_cast_v6 =
boost::static_pointer_cast<Option6AddrLst>(option_v6);
@@ -418,6 +419,7 @@ TEST_F(OptionDefinitionTest, ipv6AddressArrayTokenized) {
// should have Option6AddrLst type.
ASSERT_TRUE(option_v6);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(Option6AddrLst));
// Cast to the actual option type to get IPv6 addresses from it.
boost::shared_ptr<Option6AddrLst> option_cast_v6 =
@@ -462,6 +464,7 @@ TEST_F(OptionDefinitionTest, ipv4AddressArray) {
option_v4 = opt_def.optionFactory(Option::V4, DHO_NAME_SERVERS, buf)
);
const Option* optptr = option_v4.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(Option4AddrLst));
// Get the list of parsed addresses from the option object.
boost::shared_ptr<Option4AddrLst> option_cast_v4 =
@@ -515,6 +518,7 @@ TEST_F(OptionDefinitionTest, ipv4AddressArrayTokenized) {
// should have Option6AddrLst type.
ASSERT_TRUE(option_v4);
const Option* optptr = option_v4.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(Option4AddrLst));
// Cast to the actual option type to get IPv4 addresses from it.
boost::shared_ptr<Option4AddrLst> option_cast_v4 =
@@ -540,6 +544,7 @@ TEST_F(OptionDefinitionTest, empty) {
option_v6 = opt_def.optionFactory(Option::V6, D6O_RAPID_COMMIT, OptionBuffer())
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(Option));
// Expect 'empty' DHCPv6 option.
EXPECT_EQ(Option::V6, option_v6->getUniverse());
@@ -584,6 +589,7 @@ TEST_F(OptionDefinitionTest, emptyWithSuboptions) {
);
// Returned option should be of the OptionCustom type.
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom));
// Sanity-check length, universe etc.
EXPECT_EQ(Option::V6, option_v6->getUniverse());
@@ -623,6 +629,7 @@ TEST_F(OptionDefinitionTest, binary) {
);
// Expect base option type returned.
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(Option));
// Sanity check on universe, length and size. These are
// the basic parameters identifying any option.
@@ -671,6 +678,7 @@ TEST_F(OptionDefinitionTest, recordIA6) {
OptionPtr option_v6;
ASSERT_NO_THROW(option_v6 = opt_def.optionFactory(Option::V6, D6O_IA_NA, buf));
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(Option6IA));
boost::shared_ptr<Option6IA> option_cast_v6 =
boost::static_pointer_cast<Option6IA>(option_v6);
@@ -715,6 +723,7 @@ TEST_F(OptionDefinitionTest, recordIAAddr6) {
}
ASSERT_NO_THROW(option_v6 = opt_def.optionFactory(Option::V6, D6O_IAADDR, buf));
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(Option6IAAddr));
boost::shared_ptr<Option6IAAddr> option_cast_v6 =
boost::static_pointer_cast<Option6IAAddr>(option_v6);
@@ -753,6 +762,7 @@ TEST_F(OptionDefinitionTest, recordIAAddr6Tokenized) {
ASSERT_NO_THROW(option_v6 = opt_def.optionFactory(Option::V6, D6O_IAADDR,
data_field_values));
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(Option6IAAddr));
boost::shared_ptr<Option6IAAddr> option_cast_v6 =
boost::static_pointer_cast<Option6IAAddr>(option_v6);
@@ -776,6 +786,7 @@ TEST_F(OptionDefinitionTest, boolValue) {
OptionBuffer(1, 1));
);
const Option* optptr = option_v4.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom));
// Validate parsed value in the received option.
boost::shared_ptr<OptionCustom> option_cast_v4 =
@@ -816,6 +827,7 @@ TEST_F(OptionDefinitionTest, boolTokenized) {
values);
);
const Option* optptr = option_v4.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom));
// Validate the value.
OptionCustomPtr option_cast_v4 =
@@ -829,6 +841,7 @@ TEST_F(OptionDefinitionTest, boolTokenized) {
values);
);
optptr = option_v4.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom));
// Validate the value.
option_cast_v4 = boost::static_pointer_cast<OptionCustom>(option_v4);
@@ -841,6 +854,7 @@ TEST_F(OptionDefinitionTest, boolTokenized) {
values);
);
optptr = option_v4.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom));
// Validate the value.
option_cast_v4 = boost::static_pointer_cast<OptionCustom>(option_v4);
@@ -853,6 +867,7 @@ TEST_F(OptionDefinitionTest, boolTokenized) {
values);
);
optptr = option_v4.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom));
// Validate the value.
option_cast_v4 = boost::static_pointer_cast<OptionCustom>(option_v4);
@@ -885,6 +900,7 @@ TEST_F(OptionDefinitionTest, uint8) {
OptionBuffer(1, 1));
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint8_t>));
// Validate the value.
boost::shared_ptr<OptionInt<uint8_t> > option_cast_v6 =
@@ -914,6 +930,7 @@ TEST_F(OptionDefinitionTest, uint8Tokenized) {
option_v6 = opt_def.optionFactory(Option::V6, D6O_PREFERENCE, values);
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint8_t>));
// Validate the value.
boost::shared_ptr<OptionInt<uint8_t> > option_cast_v6 =
@@ -938,6 +955,7 @@ TEST_F(OptionDefinitionTest, uint16) {
option_v6 = opt_def.optionFactory(Option::V6, D6O_ELAPSED_TIME, buf);
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint16_t>));
// Validate the value.
boost::shared_ptr<OptionInt<uint16_t> > option_cast_v6 =
@@ -968,6 +986,7 @@ TEST_F(OptionDefinitionTest, uint16Tokenized) {
option_v6 = opt_def.optionFactory(Option::V6, D6O_ELAPSED_TIME, values);
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint16_t>));
// Validate the value.
boost::shared_ptr<OptionInt<uint16_t> > option_cast_v6 =
@@ -994,6 +1013,7 @@ TEST_F(OptionDefinitionTest, uint32) {
option_v6 = opt_def.optionFactory(Option::V6, D6O_CLT_TIME, buf);
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint32_t>));
// Validate the value.
boost::shared_ptr<OptionInt<uint32_t> > option_cast_v6 =
@@ -1023,6 +1043,7 @@ TEST_F(OptionDefinitionTest, uint32Tokenized) {
option_v6 = opt_def.optionFactory(Option::V6, D6O_CLT_TIME, values);
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint32_t>));
// Validate the value.
boost::shared_ptr<OptionInt<uint32_t> > option_cast_v6 =
@@ -1053,6 +1074,7 @@ TEST_F(OptionDefinitionTest, uint16Array) {
option_v6 = opt_def.optionFactory(Option::V6, opt_code, buf);
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionIntArray<uint16_t>));
boost::shared_ptr<OptionIntArray<uint16_t> > option_cast_v6 =
boost::static_pointer_cast<OptionIntArray<uint16_t> >(option_v6);
@@ -1096,6 +1118,7 @@ TEST_F(OptionDefinitionTest, uint16ArrayTokenized) {
option_v6 = opt_def.optionFactory(Option::V6, opt_code, str_values);
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionIntArray<uint16_t>));
boost::shared_ptr<OptionIntArray<uint16_t> > option_cast_v6 =
boost::static_pointer_cast<OptionIntArray<uint16_t> >(option_v6);
@@ -1128,6 +1151,7 @@ TEST_F(OptionDefinitionTest, uint32Array) {
option_v6 = opt_def.optionFactory(Option::V6, opt_code, buf);
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionIntArray<uint32_t>));
boost::shared_ptr<OptionIntArray<uint32_t> > option_cast_v6 =
boost::static_pointer_cast<OptionIntArray<uint32_t> >(option_v6);
@@ -1174,6 +1198,7 @@ TEST_F(OptionDefinitionTest, uint32ArrayTokenized) {
option_v6 = opt_def.optionFactory(Option::V6, opt_code, str_values);
);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionIntArray<uint32_t>));
boost::shared_ptr<OptionIntArray<uint32_t> > option_cast_v6 =
boost::static_pointer_cast<OptionIntArray<uint32_t> >(option_v6);
@@ -1201,6 +1226,7 @@ TEST_F(OptionDefinitionTest, utf8StringTokenized) {
);
ASSERT_TRUE(option_v6);
const Option* optptr = option_v6.get();
+ ASSERT_TRUE(optptr);
ASSERT_TRUE(typeid(*optptr) == typeid(OptionString));
OptionStringPtr option_v6_string =
boost::static_pointer_cast<OptionString>(option_v6);
diff --git a/src/lib/dhcp/tests/pkt4_unittest.cc b/src/lib/dhcp/tests/pkt4_unittest.cc
index ac3f1b66ef..1db3e61940 100644
--- a/src/lib/dhcp/tests/pkt4_unittest.cc
+++ b/src/lib/dhcp/tests/pkt4_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -485,13 +485,15 @@ TEST_F(Pkt4Test, sname) {
uint8_t sname[Pkt4::MAX_SNAME_LEN];
scoped_ptr<Pkt4> pkt;
- // Let's test each sname length, from 0 till 64
- for (size_t snameLen = 0; snameLen < Pkt4::MAX_SNAME_LEN; ++snameLen) {
+ // Let's test each sname length, from 0 till 64 (included)
+ for (size_t snameLen = 0; snameLen <= Pkt4::MAX_SNAME_LEN; ++snameLen) {
for (size_t i = 0; i < snameLen; ++i) {
sname[i] = i + 1;
}
- for (size_t i = snameLen; i < Pkt4::MAX_SNAME_LEN; ++i) {
- sname[i] = 0;
+ if (snameLen < Pkt4::MAX_SNAME_LEN) {
+ for (size_t i = snameLen; i < Pkt4::MAX_SNAME_LEN; ++i) {
+ sname[i] = 0;
+ }
}
// Type and transaction doesn't matter in this test
@@ -516,6 +518,11 @@ TEST_F(Pkt4Test, sname) {
Pkt4 pkt4(DHCPOFFER, 1234);
EXPECT_THROW(pkt4.setSname(NULL, Pkt4::MAX_SNAME_LEN), InvalidParameter);
EXPECT_THROW(pkt4.setSname(NULL, 0), InvalidParameter);
+
+ // Check that a too long argument generates an exception
+ // (the actual content doesn't matter).
+ uint8_t bigsname[Pkt4::MAX_SNAME_LEN + 1];
+ EXPECT_THROW(pkt4.setSname(bigsname, Pkt4::MAX_SNAME_LEN + 1), OutOfRange);
}
TEST_F(Pkt4Test, file) {
@@ -523,13 +530,15 @@ TEST_F(Pkt4Test, file) {
uint8_t file[Pkt4::MAX_FILE_LEN];
scoped_ptr<Pkt4> pkt;
- // Let's test each file length, from 0 till 128.
- for (size_t fileLen = 0; fileLen < Pkt4::MAX_FILE_LEN; ++fileLen) {
+ // Let's test each file length, from 0 till 128 (included).
+ for (size_t fileLen = 0; fileLen <= Pkt4::MAX_FILE_LEN; ++fileLen) {
for (size_t i = 0; i < fileLen; ++i) {
file[i] = i + 1;
}
- for (size_t i = fileLen; i < Pkt4::MAX_FILE_LEN; ++i) {
- file[i] = 0;
+ if (fileLen < Pkt4::MAX_FILE_LEN) {
+ for (size_t i = fileLen; i < Pkt4::MAX_FILE_LEN; ++i) {
+ file[i] = 0;
+ }
}
// Type and transaction doesn't matter in this test.
@@ -554,6 +563,11 @@ TEST_F(Pkt4Test, file) {
Pkt4 pkt4(DHCPOFFER, 1234);
EXPECT_THROW(pkt4.setFile(NULL, Pkt4::MAX_FILE_LEN), InvalidParameter);
EXPECT_THROW(pkt4.setFile(NULL, 0), InvalidParameter);
+
+ // Check that a too long argument generates an exception
+ // (the actual content doesn't matter).
+ uint8_t bigfile[Pkt4::MAX_FILE_LEN + 1];
+ EXPECT_THROW(pkt4.setFile(bigfile, Pkt4::MAX_FILE_LEN + 1), OutOfRange);
}
TEST_F(Pkt4Test, options) {