Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
1039a942
Commit
1039a942
authored
Nov 11, 2015
by
Thomas Markwalder
Browse files
[master] Added client class storgae classes to libdhcpsrv
Merged in #4095.
parents
894bf2cf
d80ac51e
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/lib/dhcp/classify.h
View file @
1039a942
...
...
@@ -20,11 +20,14 @@
/// @file classify.h
///
/// @brief Defines
basic
elements of client class
ification.
/// @brief Defines elements
for storing the names
of client class
es
///
/// This file defines common elements used for client classification.
/// It is simple for now, but the complexity involved in client
/// classification is expected to grow significantly.
/// This file defines common elements used to track the client classes
/// that may be associated with a given packet. In order to minimize the
/// exposure of the DHCP library to server side concepts such as client
/// classification the classes herein provide a mechanism to maintain lists
/// of class names, rather than the classes they represent. It is the
/// upper layers' perogative to use these names as they see fit.
///
/// @todo This file should be moved to dhcpsrv eventually as the classification
/// is server side concept. Client has no notion of classifying incoming server
...
...
@@ -36,10 +39,10 @@ namespace isc {
namespace
dhcp
{
///
Definition of
a single class.
///
@brief Defines
a single class
name
.
typedef
std
::
string
ClientClass
;
/// @brief Container for storing client classes
/// @brief Container for storing client class
nam
es
///
/// Depending on how you look at it, this is either a little more than just
/// a set of strings or a client classifier that performs access control.
...
...
src/lib/dhcp/option.h
View file @
1039a942
...
...
@@ -47,6 +47,8 @@ typedef boost::shared_ptr<Option> OptionPtr;
/// A collection of DHCP (v4 or v6) options
typedef
std
::
multimap
<
unsigned
int
,
OptionPtr
>
OptionCollection
;
/// A pointer to an OptionCollection
typedef
boost
::
shared_ptr
<
OptionCollection
>
OptionCollectionPtr
;
/// @brief This type describes a callback function to parse options from buffer.
///
...
...
src/lib/dhcpsrv/Makefile.am
View file @
1039a942
...
...
@@ -88,6 +88,7 @@ libkea_dhcpsrv_la_SOURCES += cfg_subnets4.cc cfg_subnets4.h
libkea_dhcpsrv_la_SOURCES
+=
cfg_subnets6.cc cfg_subnets6.h
libkea_dhcpsrv_la_SOURCES
+=
cfg_mac_source.cc cfg_mac_source.h
libkea_dhcpsrv_la_SOURCES
+=
cfgmgr.cc cfgmgr.h
libkea_dhcpsrv_la_SOURCES
+=
client_class_def.cc client_class_def.h
libkea_dhcpsrv_la_SOURCES
+=
csv_lease_file4.cc csv_lease_file4.h
libkea_dhcpsrv_la_SOURCES
+=
csv_lease_file6.cc csv_lease_file6.h
libkea_dhcpsrv_la_SOURCES
+=
d2_client_cfg.cc d2_client_cfg.h
...
...
src/lib/dhcpsrv/client_class_def.cc
0 → 100644
View file @
1039a942
// Copyright (C) 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
// 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
"client_class_def.h"
namespace
isc
{
namespace
dhcp
{
//********** ClientClassDef ******************//
ClientClassDef
::
ClientClassDef
(
const
std
::
string
&
name
,
const
ExpressionPtr
&
match_expr
,
const
OptionCollectionPtr
&
options
)
:
name_
(
name
),
match_expr_
(
match_expr
),
options_
(
options
)
{
// Name can't be blank
if
(
name_
.
empty
())
{
isc_throw
(
BadValue
,
"ClientClassDef name cannot be empty"
);
}
// @todo Does it make sense for a class to NOT have match expression?
// For classes without options, make sure we have an empty collection
if
(
!
options_
)
{
options_
.
reset
(
new
OptionCollection
());
}
}
ClientClassDef
::~
ClientClassDef
()
{
}
std
::
string
ClientClassDef
::
getName
()
const
{
return
(
name_
);
}
void
ClientClassDef
::
setName
(
const
std
::
string
&
name
)
{
name_
=
name
;
}
const
ExpressionPtr
&
ClientClassDef
::
getMatchExpr
()
const
{
return
(
match_expr_
);
}
void
ClientClassDef
::
setMatchExpr
(
const
ExpressionPtr
&
match_expr
)
{
match_expr_
=
match_expr
;
}
const
OptionCollectionPtr
&
ClientClassDef
::
getOptions
()
const
{
return
(
options_
);
}
void
ClientClassDef
::
setOptions
(
const
OptionCollectionPtr
&
options
)
{
options_
=
options
;
}
OptionPtr
ClientClassDef
::
findOption
(
uint16_t
option_code
)
const
{
if
(
options_
)
{
isc
::
dhcp
::
OptionCollection
::
iterator
it
=
options_
->
find
(
option_code
);
if
(
it
!=
options_
->
end
())
{
return
((
*
it
).
second
);
}
}
return
(
OptionPtr
());
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
ClientClassDef
&
x
)
{
os
<<
"ClientClassDef:"
<<
x
.
getName
();
return
(
os
);
}
//********** ClientClassDictionary ******************//
ClientClassDictionary
::
ClientClassDictionary
()
:
classes_
(
new
ClientClassDefMap
())
{
}
ClientClassDictionary
::~
ClientClassDictionary
()
{
}
void
ClientClassDictionary
::
addClass
(
const
std
::
string
&
name
,
const
ExpressionPtr
&
match_expr
,
const
OptionCollectionPtr
&
options
)
{
ClientClassDefPtr
cclass
(
new
ClientClassDef
(
name
,
match_expr
,
options
));
addClass
(
cclass
);
}
void
ClientClassDictionary
::
addClass
(
ClientClassDefPtr
&
class_def
)
{
if
(
!
class_def
)
{
isc_throw
(
BadValue
,
"ClientClassDictionary::addClass "
" - class definition cannot be null"
);
}
if
(
findClass
(
class_def
->
getName
()))
{
isc_throw
(
DuplicateClientClassDef
,
"Client Class: "
<<
class_def
->
getName
()
<<
" has already been defined"
);
}
(
*
classes_
)[
class_def
->
getName
()]
=
class_def
;
}
ClientClassDefPtr
ClientClassDictionary
::
findClass
(
const
std
::
string
&
name
)
const
{
ClientClassDefMap
::
iterator
it
=
classes_
->
find
(
name
);
if
(
it
!=
classes_
->
end
())
{
return
(
*
it
).
second
;
}
return
(
ClientClassDefPtr
());
}
void
ClientClassDictionary
::
removeClass
(
const
std
::
string
&
name
)
{
classes_
->
erase
(
name
);
}
const
ClientClassDefMapPtr
&
ClientClassDictionary
::
getClasses
()
const
{
return
(
classes_
);
}
}
// namespace isc::dhcp
}
// namespace isc
src/lib/dhcpsrv/client_class_def.h
0 → 100644
View file @
1039a942
// Copyright (C) 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
// 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.
#ifndef CLIENT_CLASS_DEF_H
#define CLIENT_CLASS_DEF_H
#include
<dhcp/option.h>
#include
<eval/token.h>
#include
<exceptions/exceptions.h>
#include
<string>
/// @file client_class_def.h
///
/// @brief Defines classes for storing client class definitions
///
/// The file defines the class, ClientClassDef, which houses the
/// information for single client class such as the class name, the
/// logical expression used to identify members of the class, and options
/// that may be attributed to class members.
///
/// In addition it defines a container class, ClientClassDictionary, which
/// is houses class definitions keyed by class name.
///
namespace
isc
{
namespace
dhcp
{
/// @brief Error that occurs when an attempt is made to add a duplicate class
/// to a class dictionary.
class
DuplicateClientClassDef
:
public
isc
::
Exception
{
public:
DuplicateClientClassDef
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{}
};
/// @brief Embodies a single client class definition
class
ClientClassDef
{
public:
/// @brief Constructor
///
/// @param name Name to assign to this class
/// @param match_expr Expression the class will use to determine membership
/// @param options Collection of options members should be given
ClientClassDef
(
const
std
::
string
&
name
,
const
ExpressionPtr
&
match_expr
,
const
OptionCollectionPtr
&
options
=
OptionCollectionPtr
());
/// @brief Destructor
virtual
~
ClientClassDef
();
/// @brief Fetches the class's name
std
::
string
getName
()
const
;
/// @brief Sets the class's name
///
/// @param name the name to assign the class
void
setName
(
const
std
::
string
&
name
);
/// @brief Fetches the class's match expression
const
ExpressionPtr
&
getMatchExpr
()
const
;
/// @brief Sets the class's match expression
///
/// @param match_expr the expression to assign the class
void
setMatchExpr
(
const
ExpressionPtr
&
match_expr
);
/// @brief Fetches the class's option collection
const
OptionCollectionPtr
&
getOptions
()
const
;
/// @brief Sets the class's option collection
///
/// @param options the option collection to assign the class
void
setOptions
(
const
OptionCollectionPtr
&
options
);
/// @brief Fetches an option from the class's collection by code
///
/// @param option_code Option code value of the desired option
/// @return A pointer to the option if found, otherwise an
/// empty pointer
OptionPtr
findOption
(
uint16_t
option_code
)
const
;
/// @brief Provides a convenient text representation of the class
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
ClientClassDef
&
x
);
private:
/// @brief Unique text identifier by which this class is known.
std
::
string
name_
;
/// @brief The logical expression which deteremines membership in
/// this class.
ExpressionPtr
match_expr_
;
/// @brief The collection of options members should be given
/// Currently this is a multimap, not sure we need/want that complexity
OptionCollectionPtr
options_
;
};
/// @brief a pointer to an ClientClassDef
typedef
boost
::
shared_ptr
<
ClientClassDef
>
ClientClassDefPtr
;
/// @brief Defines a map of ClientClassDef's, keyed by the class name.
typedef
std
::
map
<
std
::
string
,
ClientClassDefPtr
>
ClientClassDefMap
;
/// @brief Defines a pointer to a ClientClassDictionary
typedef
boost
::
shared_ptr
<
ClientClassDefMap
>
ClientClassDefMapPtr
;
/// @brief Maintains a list of ClientClassDef's
class
ClientClassDictionary
{
public:
/// @brief Constructor
ClientClassDictionary
();
/// @brief Destructor
~
ClientClassDictionary
();
/// @brief Adds a new class to the list
///
/// @param name Name to assign to this class
/// @param match_expr Expression the class will use to determine membership
/// @param options Collection of options members should be given
///
/// @throw DuplicateClientClassDef if class already exists within the
/// dictionary. See @ref dhcp::ClientClassDef::ClientClassDef() for
/// others.
void
addClass
(
const
std
::
string
&
name
,
const
ExpressionPtr
&
match_expr
,
const
OptionCollectionPtr
&
options
);
/// @brief Adds a new class to the list
///
/// @param class_def pointer to class definition to add
///
/// @throw DuplicateClientClassDef if class already exists within the
/// dictionary, BadValue if the pointer is empty.
void
addClass
(
ClientClassDefPtr
&
class_def
);
/// @brief Fetches the class definition for a given class name
///
/// @param name the name of the desired class
///
/// @return ClientClassDefPtr to the desired class if found, or
/// an empty pointer if not.
ClientClassDefPtr
findClass
(
const
std
::
string
&
name
)
const
;
/// @brief Removes a given class definition from the dictionary
///
/// Removes the class defintion from the map if it exists, otherwise
/// no harm, no foul.
///
/// @param name the name of the class to remove
void
removeClass
(
const
std
::
string
&
name
);
/// @brief Fetches the dictionary's map of classes
///
/// @return ClientClassDefMapPtr to the map of classes
const
ClientClassDefMapPtr
&
getClasses
()
const
;
private:
/// @brief Map of the class definitions
ClientClassDefMapPtr
classes_
;
};
/// @brief Defines a pointer to a ClientClassDictionary
typedef
boost
::
shared_ptr
<
ClientClassDictionary
>
ClientClassDictionaryPtr
;
}
// namespace isc::dhcp
}
// namespace isc
#endif // CLIENT_CLASS_DEF_H
src/lib/dhcpsrv/tests/Makefile.am
View file @
1039a942
...
...
@@ -75,6 +75,7 @@ libdhcpsrv_unittests_SOURCES += cfg_rsoo_unittest.cc
libdhcpsrv_unittests_SOURCES
+=
cfg_subnets4_unittest.cc
libdhcpsrv_unittests_SOURCES
+=
cfg_subnets6_unittest.cc
libdhcpsrv_unittests_SOURCES
+=
cfgmgr_unittest.cc
libdhcpsrv_unittests_SOURCES
+=
client_class_def_unittest.cc
libdhcpsrv_unittests_SOURCES
+=
csv_lease_file4_unittest.cc
libdhcpsrv_unittests_SOURCES
+=
csv_lease_file6_unittest.cc
libdhcpsrv_unittests_SOURCES
+=
d2_client_unittest.cc
...
...
src/lib/dhcpsrv/tests/client_class_def_unittest.cc
0 → 100644
View file @
1039a942
// Copyright (C) 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
// 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
<dhcpsrv/client_class_def.h>
#include
<exceptions/exceptions.h>
#include
<boost/scoped_ptr.hpp>
#include
<gtest/gtest.h>
using
namespace
std
;
using
namespace
isc
::
dhcp
;
using
namespace
isc
::
util
;
using
namespace
isc
;
namespace
{
TEST
(
ClientClassDef
,
construction
)
{
boost
::
scoped_ptr
<
ClientClassDef
>
cclass
;
std
::
string
name
=
"class1"
;
ExpressionPtr
expr
;
OptionCollectionPtr
options
;
// Classes cannot have blank names
ASSERT_THROW
(
cclass
.
reset
(
new
ClientClassDef
(
""
,
expr
,
options
)),
BadValue
);
// Verify we can create a class with a name, expression, and no options
ASSERT_NO_THROW
(
cclass
.
reset
(
new
ClientClassDef
(
name
,
expr
)));
EXPECT_EQ
(
name
,
cclass
->
getName
());
ASSERT_FALSE
(
cclass
->
getMatchExpr
());
// Verify we get an empty collection of options
options
=
cclass
->
getOptions
();
ASSERT_TRUE
(
options
);
EXPECT_EQ
(
0
,
options
->
size
());
}
TEST
(
ClientClassDef
,
optionsBasics
)
{
boost
::
scoped_ptr
<
ClientClassDef
>
cclass
;
std
::
string
name
=
"class1"
;
ExpressionPtr
expr
;
OptionCollectionPtr
options
;
OptionPtr
opt
;
// First construct the class with empty option pointer
ASSERT_NO_THROW
(
cclass
.
reset
(
new
ClientClassDef
(
name
,
expr
,
options
)));
// We should get back a collection with no entries,
// not an empty collection pointer
options
=
cclass
->
getOptions
();
ASSERT_TRUE
(
options
);
EXPECT_EQ
(
0
,
options
->
size
());
// We should not be able find an option
opt
=
cclass
->
findOption
(
17
);
ASSERT_FALSE
(
opt
);
// Create an option container with two options
options
.
reset
(
new
OptionCollection
());
EXPECT_NO_THROW
(
opt
.
reset
(
new
Option
(
Option
::
V4
,
17
)));
options
->
insert
(
make_pair
(
17
,
opt
));
EXPECT_NO_THROW
(
opt
.
reset
(
new
Option
(
Option
::
V4
,
18
)));
options
->
insert
(
make_pair
(
18
,
opt
));
// Now remake the client class with options
ASSERT_NO_THROW
(
cclass
.
reset
(
new
ClientClassDef
(
name
,
expr
,
options
)));
options
=
cclass
->
getOptions
();
ASSERT_TRUE
(
options
);
EXPECT_EQ
(
2
,
options
->
size
());
// We should be able to find option 17
opt
=
cclass
->
findOption
(
17
);
ASSERT_TRUE
(
opt
);
EXPECT_EQ
(
17
,
opt
->
getType
());
// We should be able to find option 18
opt
=
cclass
->
findOption
(
18
);
ASSERT_TRUE
(
opt
);
EXPECT_EQ
(
18
,
opt
->
getType
());
// We should not be able to find option 90
opt
=
cclass
->
findOption
(
90
);
ASSERT_FALSE
(
opt
);
}
TEST
(
ClientClassDictionary
,
basics
)
{
ClientClassDictionaryPtr
dictionary
;
ClientClassDefPtr
cclass
;
ExpressionPtr
expr
;
OptionCollectionPtr
options
;
// Verify constructor doesn't throw
ASSERT_NO_THROW
(
dictionary
.
reset
(
new
ClientClassDictionary
()));
// Verify we can fetch a pointer the map of classes and
// that we start with no classes defined
const
ClientClassDefMapPtr
classes
=
dictionary
->
getClasses
();
ASSERT_TRUE
(
classes
);
EXPECT_EQ
(
0
,
classes
->
size
());
// Verify that we can add classes with both addClass variants
// First addClass(name, expression, options)
ASSERT_NO_THROW
(
dictionary
->
addClass
(
"cc1"
,
expr
,
options
));
ASSERT_NO_THROW
(
dictionary
->
addClass
(
"cc2"
,
expr
,
options
));
// Verify duplicate add attempt throws
ASSERT_THROW
(
dictionary
->
addClass
(
"cc2"
,
expr
,
options
),
DuplicateClientClassDef
);
// Verify that you cannot add a class with no name.
ASSERT_THROW
(
dictionary
->
addClass
(
""
,
expr
,
options
),
BadValue
);
// Now with addClass(class pointer)
ASSERT_NO_THROW
(
cclass
.
reset
(
new
ClientClassDef
(
"cc3"
,
expr
,
options
)));
ASSERT_NO_THROW
(
dictionary
->
addClass
(
cclass
));
// Verify duplicate add attempt throws
ASSERT_THROW
(
dictionary
->
addClass
(
cclass
),
DuplicateClientClassDef
);
// Verify that you cannot add emtpy class pointer
cclass
.
reset
();
ASSERT_THROW
(
dictionary
->
addClass
(
cclass
),
BadValue
);
// Map should show 3 entries.
EXPECT_EQ
(
3
,
classes
->
size
());
// Verify we can find them all.
ASSERT_NO_THROW
(
cclass
=
dictionary
->
findClass
(
"cc1"
));
ASSERT_TRUE
(
cclass
);
EXPECT_EQ
(
"cc1"
,
cclass
->
getName
());
ASSERT_NO_THROW
(
cclass
=
dictionary
->
findClass
(
"cc2"
));
ASSERT_TRUE
(
cclass
);
EXPECT_EQ
(
"cc2"
,
cclass
->
getName
());
ASSERT_NO_THROW
(
cclass
=
dictionary
->
findClass
(
"cc3"
));
ASSERT_TRUE
(
cclass
);
EXPECT_EQ
(
"cc3"
,
cclass
->
getName
());
// Verify the looking for non-existant returns empty pointer
ASSERT_NO_THROW
(
cclass
=
dictionary
->
findClass
(
"bogus"
));
EXPECT_FALSE
(
cclass
);
// Verify that we can remove a class
ASSERT_NO_THROW
(
dictionary
->
removeClass
(
"cc3"
));
EXPECT_EQ
(
2
,
classes
->
size
());
// Shouldn't be able to find anymore
ASSERT_NO_THROW
(
cclass
=
dictionary
->
findClass
(
"cc3"
));
EXPECT_FALSE
(
cclass
);
// Verify that we can attempt to remove a non-existant class
// without harm.
ASSERT_NO_THROW
(
dictionary
->
removeClass
(
"cc3"
));
EXPECT_EQ
(
2
,
classes
->
size
());
}
}
// end of anonymous namespace
src/lib/eval/token.h
View file @
1039a942
...
...
@@ -35,6 +35,8 @@ typedef boost::shared_ptr<Token> TokenPtr;
/// [2] = == operator (TokenEqual object)
typedef
std
::
vector
<
TokenPtr
>
Expression
;
typedef
boost
::
shared_ptr
<
Expression
>
ExpressionPtr
;
/// Evaluated values are stored as a stack of strings
typedef
std
::
stack
<
std
::
string
>
ValueStack
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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