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
ISC Open Source Projects
Kea
Commits
f89dbf48
Commit
f89dbf48
authored
Oct 14, 2011
by
Tomek Mrugalski
🛰
Browse files
[1186] Changes in reply to review comment 13.
parent
a91fbbe9
Changes
4
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
f89dbf48
299. [func]* tomek
libdhcp: DHCP packet library was implemented. Currently it handles
packet reception, option parsing, option generation and output
packet building. Generic and specialized classes for several
DHCPv6 options (IA_NA, IAADDR, address-list) are available. A
simple code was added that leverages libdhcp. It is a skeleton
DHCPv6 server. It receives incoming SOLICIT and REQUEST messages
and responds with proper ADVERTISE and REPLY. Note that since
LeaseManager is not implemented, server assigns a the same
hardcoded lease for every client.
bind10-devel-20111014 released on October 14, 2011
298. [doc] jreed
...
...
src/bin/dhcp6/dhcp6_srv.h
View file @
f89dbf48
...
...
@@ -23,143 +23,134 @@
namespace
isc
{
namespace
dhcp
{
/// @brief DHCPv6 server service.
///
/// This singleton class represents DHCPv6 server. It contains all
/// top-level methods and routines necessary for server operation.
/// In particular, it instantiates IfaceMgr, loads or generates DUID
/// that is going to be used as server-identifier, receives incoming
/// packets, processes them, manages leases assignment and generates
/// appropriate responses.
class
Dhcpv6Srv
:
public
boost
::
noncopyable
{
private:
/// @brief A private copy constructor.
///
/// Creates a single Dhcpv6Srv instance and all required objects,
/// including interface manager (IfaceMgr). It is defined private on
/// purpose. We don't want to have more than one copy of Dhcpv6Srv.
///
/// It may throw exceptions if server creation failed, e.g. due to
/// failures in IfaceMgr (e.g. socket creation) or unavailable
/// interfaces when attempting to create new DUID.
Dhcpv6Srv
(
const
Dhcpv6Srv
&
src
);
/// @brief A private assignment operator.
///
/// Note that there is no implementation of this assignment operator.
/// Its definition is here to prevent creation of any copies.
///
Dhcpv6Srv
&
operator
=
(
const
Dhcpv6Srv
&
src
);
/// @brief Sets server-identifier.
///
/// This method attempts to set server-identifier DUID. It loads it
/// from a file. If file load fails, it generates new DUID using
/// interface link-layer addresses (EUI-64) + timestamp (DUID type
/// duid-llt, see RFC3315, section 9.2). If there are no suitable
/// interfaces present, exception it thrown
///
/// @throws isc::Unexpected Failed to read DUID file and no suitable
/// interfaces for new DUID generation are detected.
void
setServerID
();
/// server DUID (to be sent in server-identifier option)
boost
::
shared_ptr
<
isc
::
dhcp
::
Option
>
serverid_
;
public:
/// @brief Default constructor.
///
/// Instantiates necessary services, required to run DHCPv6 server.
/// In particular, creates IfaceMgr that will be responsible for
/// network interaction. Will instantiate lease manager, and load
/// old or create new DUID.
Dhcpv6Srv
();
/// @brief Destructor. Shuts down DHCPv6 service.
~
Dhcpv6Srv
();
/// @brief Returns server-intentifier option
///
/// @return reference to server-id option
///
boost
::
shared_ptr
<
isc
::
dhcp
::
Option
>&
getServerID
()
{
return
serverid_
;
}
/// @brief Main server processing loop.
///
/// Main server processing loop. Receives incoming packets, verifies
/// their correctness, generates appropriate answer (if needed) and
/// transmits respones.
///
/// @return true, if being shut down gracefully, fail if experienced
/// critical error.
bool
run
();
protected:
/// @brief Processes incoming SOLICIT and returns response.
///
/// Processes received SOLICIT message and verifies that its sender
/// should be served. In particular IA, TA and PD options are populated
/// with to-be assinged addresses, temporary addresses and delegated
/// prefixes, respectively. In the usual 4 message exchange, server is
/// expected to respond with ADVERTISE message. However, if client
/// requests rapid-commit and server supports it, REPLY will be sent
/// instead of ADVERTISE and requested leases will be assigned
/// immediately.
///
/// @param solicit SOLICIT message received from client
///
/// @return ADVERTISE, REPLY message or NULL
///
boost
::
shared_ptr
<
Pkt6
>
processSolicit
(
boost
::
shared_ptr
<
Pkt6
>
solicit
);
/// @brief Processes incoming REQUEST and returns REPLY response.
///
/// Processes incoming REQUEST message and verifies that its sender
/// should be served. In particular IA, TA and PD options are populated
/// with assinged addresses, temporary addresses and delegated
/// prefixes, respectively. Uses LeaseMgr to allocate or update existing
/// leases.
///
/// @param request REQUEST message received from client
///
/// @return REPLY message or NULL
boost
::
shared_ptr
<
Pkt6
>
processRequest
(
boost
::
shared_ptr
<
Pkt6
>
request
);
/// @brief Stub function that will handle incoming RENEW messages.
boost
::
shared_ptr
<
Pkt6
>
processRenew
(
boost
::
shared_ptr
<
Pkt6
>
renew
);
/// @brief Stub function that will handle incoming REBIND messages.
boost
::
shared_ptr
<
Pkt6
>
processRebind
(
boost
::
shared_ptr
<
Pkt6
>
rebind
);
/// @brief Stub function that will handle incoming CONFIRM messages.
boost
::
shared_ptr
<
Pkt6
>
processConfirm
(
boost
::
shared_ptr
<
Pkt6
>
confirm
);
/// @brief Stub function that will handle incoming RELEASE messages.
boost
::
shared_ptr
<
Pkt6
>
processRelease
(
boost
::
shared_ptr
<
Pkt6
>
release
);
/// @brief Stub function that will handle incoming DECLINE messages.
boost
::
shared_ptr
<
Pkt6
>
processDecline
(
boost
::
shared_ptr
<
Pkt6
>
decline
);
/// @brief Stub function that will handle incoming INF-REQUEST messages.
boost
::
shared_ptr
<
Pkt6
>
processInfRequest
(
boost
::
shared_ptr
<
Pkt6
>
infRequest
);
/// indicates if shutdown is in progress. Setting it to true will
/// initiate server shutdown procedure.
volatile
bool
shutdown
;
};
};
// namespace isc::dhcp
namespace
dhcp
{
/// @brief DHCPv6 server service.
///
/// This singleton class represents DHCPv6 server. It contains all
/// top-level methods and routines necessary for server operation.
/// In particular, it instantiates IfaceMgr, loads or generates DUID
/// that is going to be used as server-identifier, receives incoming
/// packets, processes them, manages leases assignment and generates
/// appropriate responses.
class
Dhcpv6Srv
:
public
boost
::
noncopyable
{
public:
/// @brief Default constructor.
///
/// Instantiates necessary services, required to run DHCPv6 server.
/// In particular, creates IfaceMgr that will be responsible for
/// network interaction. Will instantiate lease manager, and load
/// old or create new DUID.
Dhcpv6Srv
();
/// @brief Destructor. Used during DHCPv6 service shutdown.
~
Dhcpv6Srv
();
/// @brief Returns server-intentifier option
///
/// @return server-id option
boost
::
shared_ptr
<
isc
::
dhcp
::
Option
>
getServerID
()
{
return
serverid_
;
}
/// @brief Main server processing loop.
///
/// Main server processing loop. Receives incoming packets, verifies
/// their correctness, generates appropriate answer (if needed) and
/// transmits respones.
///
/// @return true, if being shut down gracefully, fail if experienced
/// critical error.
bool
run
();
protected:
/// @brief Processes incoming SOLICIT and returns response.
///
/// Processes received SOLICIT message and verifies that its sender
/// should be served. In particular IA, TA and PD options are populated
/// with to-be assinged addresses, temporary addresses and delegated
/// prefixes, respectively. In the usual 4 message exchange, server is
/// expected to respond with ADVERTISE message. However, if client
/// requests rapid-commit and server supports it, REPLY will be sent
/// instead of ADVERTISE and requested leases will be assigned
/// immediately.
///
/// @param solicit SOLICIT message received from client
///
/// @return ADVERTISE, REPLY message or NULL
boost
::
shared_ptr
<
Pkt6
>
processSolicit
(
boost
::
shared_ptr
<
Pkt6
>
solicit
);
/// @brief Processes incoming REQUEST and returns REPLY response.
///
/// Processes incoming REQUEST message and verifies that its sender
/// should be served. In particular IA, TA and PD options are populated
/// with assinged addresses, temporary addresses and delegated
/// prefixes, respectively. Uses LeaseMgr to allocate or update existing
/// leases.
///
/// @param request a message received from client
///
/// @return REPLY message or NULL
boost
::
shared_ptr
<
Pkt6
>
processRequest
(
boost
::
shared_ptr
<
Pkt6
>
request
);
/// @brief Stub function that will handle incoming RENEW messages.
///
/// @param renew message received from client
boost
::
shared_ptr
<
Pkt6
>
processRenew
(
boost
::
shared_ptr
<
Pkt6
>
renew
);
/// @brief Stub function that will handle incoming REBIND messages.
///
/// @param rebind message received from client
boost
::
shared_ptr
<
Pkt6
>
processRebind
(
boost
::
shared_ptr
<
Pkt6
>
rebind
);
/// @brief Stub function that will handle incoming CONFIRM messages.
///
/// @param confirm message received from client
boost
::
shared_ptr
<
Pkt6
>
processConfirm
(
boost
::
shared_ptr
<
Pkt6
>
confirm
);
/// @brief Stub function that will handle incoming RELEASE messages.
///
/// @param release message received from client
boost
::
shared_ptr
<
Pkt6
>
processRelease
(
boost
::
shared_ptr
<
Pkt6
>
release
);
/// @brief Stub function that will handle incoming DECLINE messages.
///
/// @param decline message received from client
boost
::
shared_ptr
<
Pkt6
>
processDecline
(
boost
::
shared_ptr
<
Pkt6
>
decline
);
/// @brief Stub function that will handle incoming INF-REQUEST messages.
///
/// @param infRequest message received from client
boost
::
shared_ptr
<
Pkt6
>
processInfRequest
(
boost
::
shared_ptr
<
Pkt6
>
infRequest
);
/// @brief Sets server-identifier.
///
/// This method attempts to set server-identifier DUID. It loads it
/// from a file. If file load fails, it generates new DUID using
/// interface link-layer addresses (EUI-64) + timestamp (DUID type
/// duid-llt, see RFC3315, section 9.2). If there are no suitable
/// interfaces present, exception it thrown
///
/// @throws isc::Unexpected Failed to read DUID file and no suitable
/// interfaces for new DUID generation are detected.
void
setServerID
();
/// server DUID (to be sent in server-identifier option)
boost
::
shared_ptr
<
isc
::
dhcp
::
Option
>
serverid_
;
/// indicates if shutdown is in progress. Setting it to true will
/// initiate server shutdown procedure.
volatile
bool
shutdown
;
};
};
// namespace isc::dhcp
};
// namespace isc
#endif // DHCP6_SRV_H
src/bin/dhcp6/iface_mgr.cc
View file @
f89dbf48
...
...
@@ -69,10 +69,10 @@ IfaceMgr::Iface::getPlainMac() const {
ostringstream
tmp
;
tmp
.
fill
(
'0'
);
tmp
<<
hex
;
for
(
int
i
=
0
;
i
<
mac_len_
;
i
++
)
{
for
(
int
i
=
0
;
i
<
mac_len_
;
i
++
)
{
tmp
.
width
(
2
);
tmp
<<
mac_
[
i
];
if
(
i
<
mac_len_
-
1
)
{
if
(
i
<
mac_len_
-
1
)
{
tmp
<<
":"
;
}
}
...
...
src/bin/dhcp6/iface_mgr.h
View file @
f89dbf48
...
...
@@ -23,190 +23,201 @@
namespace
isc
{
namespace
dhcp
{
/// @brief handles network interfaces, transmission and reception
namespace
dhcp
{
/// @brief handles network interfaces, transmission and reception
///
/// IfaceMgr is an interface manager class that detects available network
/// interfaces, configured addresses, link-local addresses, and provides
/// API for using sockets.
///
class
IfaceMgr
:
public
boost
::
noncopyable
{
public:
/// type that defines list of addresses
typedef
std
::
list
<
isc
::
asiolink
::
IOAddress
>
Addr6Lst
;
/// maximum MAC address length (Infiniband uses 20 bytes)
static
const
unsigned
int
MAX_MAC_LEN
=
20
;
/// @brief represents a single network interface
///
/// IfaceMgr is an interface manager class that detects available network
/// interfaces, configured addresses, link-local addresses, and provides
/// API for using sockets.
///
class
IfaceMgr
:
public
boost
::
noncopyable
{
public:
/// type that defines list of addresses
typedef
std
::
list
<
isc
::
asiolink
::
IOAddress
>
Addr6Lst
;
/// Iface structure represents network interface with all useful
/// information, like name, interface index, MAC address and
/// list of assigned addresses
struct
Iface
{
/// constructor
Iface
(
const
std
::
string
&
name
,
int
ifindex
);
/// returns full interface name in format ifname/ifindex
std
::
string
getFullName
()
const
;
/// returns link-layer address a plain text
std
::
string
getPlainMac
()
const
;
/// maximum MAC address length (Infiniband uses 20 bytes)
static
const
unsigned
int
MAX_MAC_LEN
=
20
;
/// network interface name
std
::
string
name_
;
/// interface index (a value that uniquely indentifies an interface)
int
ifindex_
;
/// @brief represents a single network interface
///
/// Iface structure represents network interface with all useful
/// information, like name, interface index, MAC address and
/// list of assigned addresses
struct
Iface
{
/// constructor
Iface
(
const
std
::
string
&
name
,
int
ifindex
);
/// returns full interface name in format ifname/ifindex
std
::
string
getFullName
()
const
;
/// returns link-layer address a plain text
std
::
string
getPlainMac
()
const
;
std
::
string
name_
;
/// network interface name
int
ifindex_
;
/// interface index (a value that uniquely
/// indentifies an interface
Addr6Lst
addrs_
;
/// list of assigned addresses
uint8_t
mac_
[
MAX_MAC_LEN
];
/// link-layer address
int
mac_len_
;
/// length of link-layer address (usually 6)
int
sendsock_
;
/// socket used to sending data
int
recvsock_
;
/// socket used for receiving data
// next field is not needed, let's keep it in cointainers
};
// TODO performance improvement: we may change this into
// 2 maps (ifindex-indexed and name-indexed) and
// also hide it (make it public make tests easier for now)
typedef
std
::
list
<
Iface
>
IfaceLst
;
/// IfaceMgr is a singleton class. This method returns reference
/// to its sole instance.
///
/// @return the only existing instance of interface manager
static
IfaceMgr
&
instance
();
/// @brief Returns interface with specified interface index
///
/// @param ifindex index of searched interface
///
/// @return interface with requested index (or NULL if no such
/// interface is present)
///
Iface
*
getIface
(
int
ifindex
);
/// @brief Returns interface with specified interface name
///
/// @param ifname name of searched interface
///
/// @return interface with requested name (or NULL if no such
/// interface is present)
///
Iface
*
getIface
(
const
std
::
string
&
ifname
);
/// debugging method that prints out all available interfaces
///
/// @param out specifies stream to print list of interfaces to
void
printIfaces
(
std
::
ostream
&
out
=
std
::
cout
);
/// @brief Sends a packet.
///
/// Sends a packet. All parameters regarding interface, destination
/// address are set in pkt object.
///
/// @param pkt packet to be sent
///
/// @return true if sending was successful
///
bool
send
(
boost
::
shared_ptr
<
Pkt6
>
pkt
);
/// @brief Tries to receive packet over open sockets.
///
/// Attempts to receive a single packet of any of the open sockets.
/// If reception is successful and all information about its sender
/// are obtained, Pkt6 object is created and returned.
///
/// @return Pkt6 object representing received packet (or NULL)
///
boost
::
shared_ptr
<
Pkt6
>
receive
();
// don't use private, we need derived classes in tests
protected:
/// @brief Protected constructor.
///
/// Protected constructor. This is a singleton class. We don't want
/// anyone to create instances of IfaceMgr. Use instance() method
IfaceMgr
();
~
IfaceMgr
();
/// @brief Detects network interfaces.
///
/// This method will eventually detect available interfaces. For now
/// it offers stub implementation. First interface name and link-local
/// IPv6 address is read from intefaces.txt file.
void
detectIfaces
();
///
/// Opens UDP/IPv6 socket and binds it to address, interface nad port.
///
/// @param ifname name of the interface
/// @param addr address to be bound.
/// @param port UDP port.
///
/// @return socket descriptor, if socket creation, binding and multicast
/// group join were all successful. -1 otherwise.
int
openSocket
(
const
std
::
string
&
ifname
,
const
isc
::
asiolink
::
IOAddress
&
addr
,
int
port
);
// TODO: having 2 maps (ifindex->iface and ifname->iface would)
// probably be better for performance reasons
/// List of available interfaces
IfaceLst
ifaces_
;
/// a pointer to a sole instance of this class (a singleton)
static
IfaceMgr
*
instance_
;
// TODO: Also keep this interface on Iface once interface detection
// is implemented. We may need it e.g. to close all sockets on
// specific interface
int
recvsock_
;
// TODO: should be fd_set eventually, but we have only
int
sendsock_
;
// 2 sockets for now. Will do for until next release
// we can't use the same socket, as receiving socket
// is bound to multicast address. And we all know what happens
// to people who try to use multicast as source address.
/// control-buffer, used in transmission and reception
char
*
control_buf_
;
int
control_buf_len_
;
private:
/// Opens sockets on detected interfaces.
bool
openSockets
();
/// creates a single instance of this class (a singleton implementation)
static
void
instanceCreate
();
/// @brief Joins IPv6 multicast group on a socket.
///
/// Socket must be created and bound to an address. Note that this
/// address is different than the multicast address. For example DHCPv6
/// server should bind its socket to link-local address (fe80::1234...)
/// and later join ff02::1:2 multicast group.
///
/// @param sock socket fd (socket must be bound)
/// @param ifname interface name (for link-scoped multicast groups)
/// @param mcast multicast address to join (e.g. "ff02::1:2")
///
/// @return true if multicast join was successful
///
bool
joinMcast
(
int
sock
,
const
std
::
string
&
ifname
,
const
std
::
string
&
mcast
);
Addr6Lst
addrs_
;
/// link-layer address
uint8_t
mac_
[
MAX_MAC_LEN
];
/// length of link-layer address (usually 6)
int
mac_len_
;
/// socket used to sending data
int
sendsock_
;
/// socket used for receiving data
int
recvsock_
;
};
};
// namespace isc::dhcp
// TODO performance improvement: we may change this into
// 2 maps (ifindex-indexed and name-indexed) and
// also hide it (make it public make tests easier for now)
/// type that holds a list of interfaces
typedef
std
::
list
<
Iface
>
IfaceLst
;
/// IfaceMgr is a singleton class. This method returns reference
/// to its sole instance.
///
/// @return the only existing instance of interface manager
static
IfaceMgr
&
instance
();
/// @brief Returns interface with specified interface index
///
/// @param ifindex index of searched interface
///
/// @return interface with requested index (or NULL if no such
/// interface is present)
///
Iface
*
getIface
(
int
ifindex
);
/// @brief Returns interface with specified interface name
///
/// @param ifname name of searched interface
///
/// @return interface with requested name (or NULL if no such
/// interface is present)
///
Iface
*
getIface
(
const
std
::
string
&
ifname
);
/// debugging method that prints out all available interfaces
///
/// @param out specifies stream to print list of interfaces to
void
printIfaces
(
std
::
ostream
&
out
=
std
::
cout
);
/// @brief Sends a packet.
///
/// Sends a packet. All parameters regarding interface, destination
/// address are set in pkt object.
///
/// @param pkt packet to be sent
///
/// @return true if sending was successful
///
bool
send
(
boost
::
shared_ptr
<
Pkt6
>
pkt
);
/// @brief Tries to receive packet over open sockets.
///
/// Attempts to receive a single packet of any of the open sockets.
/// If reception is successful and all information about its sender
/// are obtained, Pkt6 object is created and returned.
///
/// @return Pkt6 object representing received packet (or NULL)
///
boost
::
shared_ptr
<
Pkt6
>
receive
();
// don't use private, we need derived classes in tests
protected:
/// @brief Protected constructor.
///
/// Protected constructor. This is a singleton class. We don't want
/// anyone to create instances of IfaceMgr. Use instance() method
IfaceMgr
();
~
IfaceMgr
();
/// @brief Detects network interfaces.
///
/// This method will eventually detect available interfaces. For now
/// it offers stub implementation. First interface name and link-local
/// IPv6 address is read from intefaces.txt file.
void
detectIfaces
();
///
/// Opens UDP/IPv6 socket and binds it to address, interface and port.
///
/// @param ifname name of the interface
/// @param addr address to be bound.
/// @param port UDP port.
///
/// @return socket descriptor, if socket creation, binding and multicast
/// group join were all successful. -1 otherwise.
int
openSocket
(
const
std
::
string
&
ifname
,
const
isc
::
asiolink
::
IOAddress
&
addr
,
int
port
);
// TODO: having 2 maps (ifindex->iface and ifname->iface would)
// probably be better for performance reasons
/// List of available interfaces
IfaceLst
ifaces_
;