Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Adam Osuchowski
Kea
Commits
22a33dfd
Commit
22a33dfd
authored
Nov 29, 2012
by
Marcin Siodelski
Browse files
[2491] Added a function to write/read FQDN to/from buffer.
parent
c806c0c3
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/lib/dhcp/Makefile.am
View file @
22a33dfd
...
...
@@ -37,6 +37,7 @@ libb10_dhcp___la_SOURCES += pkt4.cc pkt4.h
libb10_dhcp___la_CXXFLAGS
=
$(AM_CXXFLAGS)
libb10_dhcp___la_CPPFLAGS
=
$(AM_CPPFLAGS)
$(LOG4CPLUS_INCLUDES)
libb10_dhcp___la_LIBADD
=
$(top_builddir)
/src/lib/asiolink/libb10-asiolink.la
libb10_dhcp___la_LIBADD
+=
$(top_builddir)
/src/lib/dns/libb10-dns++.la
libb10_dhcp___la_LIBADD
+=
$(top_builddir)
/src/lib/util/libb10-util.la
libb10_dhcp___la_LDFLAGS
=
-no-undefined
-version-info
2:0:0
...
...
src/lib/dhcp/option_data_types.cc
View file @
22a33dfd
...
...
@@ -13,6 +13,8 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <dhcp/option_data_types.h>
#include <dns/labelsequence.h>
#include <dns/name.h>
#include <util/encode/hex.h>
namespace
isc
{
...
...
@@ -206,6 +208,48 @@ OptionDataTypeUtil::writeBool(const bool value,
buf
.
push_back
(
static_cast
<
uint8_t
>
(
value
?
1
:
0
));
}
std
::
string
OptionDataTypeUtil
::
readFqdn
(
const
std
::
vector
<
uint8_t
>&
buf
)
{
// If buffer is empty emit an error.
if
(
buf
.
empty
())
{
isc_throw
(
BadDataTypeCast
,
"unable to read FQDN from a buffer."
<<
" The buffer is empty"
);
}
// Copy the data from a buffer to InputBuffer so as we can use
// isc::dns::Name object to get the FQDN. This is not the most
// efficient way to do it but currently there is no construtor
// in Name that would use std::vector directly.
isc
::
util
::
InputBuffer
in_buf
(
static_cast
<
const
void
*>
(
&
buf
[
0
]),
buf
.
size
());
try
{
// Try to create an object from the buffer. If exception is thrown
// it means that the buffer doesn't hold a valid domain name (invalid
// syntax).
isc
::
dns
::
Name
name
(
in_buf
);
return
(
name
.
toText
());
}
catch
(
const
isc
::
Exception
&
ex
)
{
// Unable to convert the data in the buffer into FQDN.
isc_throw
(
BadDataTypeCast
,
ex
.
what
());
}
}
void
OptionDataTypeUtil
::
writeFqdn
(
const
std
::
string
&
fqdn
,
std
::
vector
<
uint8_t
>&
buf
)
{
try
{
isc
::
dns
::
Name
name
(
fqdn
);
isc
::
dns
::
LabelSequence
labels
(
name
);
if
(
labels
.
getDataLength
()
>
0
)
{
buf
.
resize
(
buf
.
size
()
+
labels
.
getDataLength
());
size_t
read_len
=
0
;
const
uint8_t
*
data
=
labels
.
getData
(
&
read_len
);
memcpy
(
static_cast
<
void
*>
(
&
buf
[
buf
.
size
()
-
labels
.
getDataLength
()]),
data
,
read_len
);
}
}
catch
(
const
isc
::
Exception
&
ex
)
{
isc_throw
(
BadDataTypeCast
,
ex
.
what
());
}
}
std
::
string
OptionDataTypeUtil
::
readString
(
const
std
::
vector
<
uint8_t
>&
buf
)
{
std
::
string
value
;
...
...
src/lib/dhcp/option_data_types.h
View file @
22a33dfd
...
...
@@ -332,6 +332,33 @@ public:
}
}
/// @brief Read FQDN from a buffer as a string value.
///
/// The format of an FQDN within a buffer complies with RFC1035,
/// section 3.1.
///
/// @param buf input buffer holding a FQDN.
///
/// @throw BadDataTypeCast if a FQDN stored within a buffer is
/// invalid (e.g. empty, contains invalid characters, truncated).
/// @return fully qualified domain name in a text form.
static
std
::
string
readFqdn
(
const
std
::
vector
<
uint8_t
>&
buf
);
/// @brief Append FQDN into a buffer.
///
/// This method appends the Fully Qualified Domain Name (FQDN)
/// represented as string value into a buffer. The format of
/// the FQDN being stored into a buffer complies with RFC1035,
/// section 3.1.
///
/// @param fqdn fully qualified domain name to be written.
/// @param [out] buf output buffer.
///
/// @throw isc::dhcp::BadDataTypeCast if provided FQDN
/// is invalid.
static
void
writeFqdn
(
const
std
::
string
&
fqdn
,
std
::
vector
<
uint8_t
>&
buf
);
/// @brief Read string value from a buffer.
///
/// @param buf input buffer.
...
...
src/lib/dhcp/tests/Makefile.am
View file @
22a33dfd
...
...
@@ -35,6 +35,7 @@ libdhcp___unittests_SOURCES += option6_ia_unittest.cc
libdhcp___unittests_SOURCES
+=
option6_iaaddr_unittest.cc
libdhcp___unittests_SOURCES
+=
option6_int_array_unittest.cc
libdhcp___unittests_SOURCES
+=
option6_int_unittest.cc
libdhcp___unittests_SOURCES
+=
option_data_types_unittest.cc
libdhcp___unittests_SOURCES
+=
option_definition_unittest.cc
libdhcp___unittests_SOURCES
+=
option_custom_unittest.cc
libdhcp___unittests_SOURCES
+=
option_unittest.cc
...
...
src/lib/dhcp/tests/option_data_types_unittest.cc
0 → 100644
View file @
22a33dfd
// Copyright (C) 2012 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
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#include <dhcp/option_data_types.h>
#include <gtest/gtest.h>
using
namespace
isc
;
using
namespace
isc
::
dhcp
;
namespace
{
/// @brief Test class for option data type utilities.
class
OptionDataTypesTest
:
public
::
testing
::
Test
{
public:
/// @brief Constructor.
OptionDataTypesTest
()
{
}
};
// The purpose of this test is to verify that FQDN is read from
// a buffer and returned as a text. The representation of the FQDN
// in the buffer complies with RFC1035, section 3.1.
// This test also checks that if invalid (truncated) FQDN is stored
// in a buffer the appropriate exception is returned when trying to
// read it as a string.
TEST_F
(
OptionDataTypesTest
,
readFqdn
)
{
// The binary representation of the "mydomain.example.com".
// Values: 8, 7, 3 and 0 specify the lengths of subsequent
// labels within the FQDN.
const
char
data
[]
=
{
8
,
109
,
121
,
100
,
111
,
109
,
97
,
105
,
110
,
// "mydomain"
7
,
101
,
120
,
97
,
109
,
112
,
108
,
101
,
// "example"
3
,
99
,
111
,
109
,
// "com"
0
};
// Make a vector out of the data.
std
::
vector
<
uint8_t
>
buf
(
data
,
data
+
sizeof
(
data
));
// Read the buffer as FQDN and verify its correctness.
std
::
string
fqdn
;
EXPECT_NO_THROW
(
fqdn
=
OptionDataTypeUtil
::
readFqdn
(
buf
));
EXPECT_EQ
(
"mydomain.example.com."
,
fqdn
);
// By resizing the buffer we simulate truncation. The first
// length field (8) indicate that the first label's size is
// 8 but the actual buffer size is 5. Expect that conversion
// fails.
buf
.
resize
(
5
);
EXPECT_THROW
(
OptionDataTypeUtil
::
readFqdn
(
buf
),
isc
::
dhcp
::
BadDataTypeCast
);
// Another special case: provide an empty buffer.
buf
.
clear
();
EXPECT_THROW
(
OptionDataTypeUtil
::
readFqdn
(
buf
),
isc
::
dhcp
::
BadDataTypeCast
);
}
// The purpose of this test is to verify that FQDN's syntax is validated
// and that FQDN is correctly written to a buffer in a format described
// in RFC1035 section 3.1.
TEST_F
(
OptionDataTypesTest
,
writeFqdn
)
{
// Create empty buffer. The FQDN will be written to it.
OptionBuffer
buf
;
// Write a domain name into the buffer in the format described
// in RFC1035 section 3.1. This function should not throw
// exception because domain name is well formed.
EXPECT_NO_THROW
(
OptionDataTypeUtil
::
writeFqdn
(
"mydomain.example.com"
,
buf
)
);
// The length of the data is 22 (8 bytes for "mydomain" label,
// 7 bytes for "example" label, 3 bytes for "com" label and
// finally 4 bytes positions between labels where length
// information is stored.
ASSERT_EQ
(
22
,
buf
.
size
());
// Verify that length fields between labels hold valid values.
EXPECT_EQ
(
8
,
buf
[
0
]);
// length of "mydomain"
EXPECT_EQ
(
7
,
buf
[
9
]);
// length of "example"
EXPECT_EQ
(
3
,
buf
[
17
]);
// length of "com"
EXPECT_EQ
(
0
,
buf
[
21
]);
// zero byte at the end.
// Verify that labels are valid.
std
::
string
label0
(
buf
.
begin
()
+
1
,
buf
.
begin
()
+
9
);
EXPECT_EQ
(
"mydomain"
,
label0
);
std
::
string
label1
(
buf
.
begin
()
+
10
,
buf
.
begin
()
+
17
);
EXPECT_EQ
(
"example"
,
label1
);
std
::
string
label2
(
buf
.
begin
()
+
18
,
buf
.
begin
()
+
21
);
EXPECT_EQ
(
"com"
,
label2
);
// The tested function is supposed to append data to a buffer
// so let's check that it is a case by appending another domain.
OptionDataTypeUtil
::
writeFqdn
(
"hello.net"
,
buf
);
// The buffer length should be now longer.
ASSERT_EQ
(
33
,
buf
.
size
());
// Check the length fields for new labels being appended.
EXPECT_EQ
(
5
,
buf
[
22
]);
EXPECT_EQ
(
3
,
buf
[
28
]);
// And check that labels are ok.
std
::
string
label3
(
buf
.
begin
()
+
23
,
buf
.
begin
()
+
28
);
EXPECT_EQ
(
"hello"
,
label3
);
std
::
string
label4
(
buf
.
begin
()
+
29
,
buf
.
begin
()
+
32
);
EXPECT_EQ
(
"net"
,
label4
);
// Check that invalid (empty) FQDN is rejected and expected
// exception type is thrown.
buf
.
clear
();
EXPECT_THROW
(
OptionDataTypeUtil
::
writeFqdn
(
""
,
buf
),
isc
::
dhcp
::
BadDataTypeCast
);
// Check another invalid domain name (with repeated dot).
buf
.
clear
();
EXPECT_THROW
(
OptionDataTypeUtil
::
writeFqdn
(
"example..com"
,
buf
),
isc
::
dhcp
::
BadDataTypeCast
);
}
}
// anonymous namespace
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment