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
ca4d87e7
Commit
ca4d87e7
authored
Jun 08, 2016
by
Francis Dupont
Browse files
[master] Merged trac4106 (DHCPv4-over-DHCPv6 IPC)
parents
d2da227c
3917a1b8
Changes
18
Expand all
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp4/Makefile.am
View file @
ca4d87e7
...
...
@@ -62,6 +62,7 @@ libdhcp4_la_SOURCES += ctrl_dhcp4_srv.cc ctrl_dhcp4_srv.h
libdhcp4_la_SOURCES
+=
json_config_parser.cc json_config_parser.h
libdhcp4_la_SOURCES
+=
dhcp4_log.cc dhcp4_log.h
libdhcp4_la_SOURCES
+=
dhcp4_srv.cc dhcp4_srv.h
libdhcp4_la_SOURCES
+=
dhcp4_dhcp4o6_ipc.cc dhcp4_dhcp4o6_ipc.h
libdhcp4_la_SOURCES
+=
kea_controller.cc
...
...
src/bin/dhcp4/ctrl_dhcp4_srv.cc
View file @
ca4d87e7
...
...
@@ -8,6 +8,7 @@
#include
<cc/data.h>
#include
<dhcp4/ctrl_dhcp4_srv.h>
#include
<dhcp4/dhcp4_log.h>
#include
<dhcp4/dhcp4_dhcp4o6_ipc.h>
#include
<hooks/hooks_manager.h>
#include
<dhcp4/json_config_parser.h>
#include
<dhcpsrv/cfgmgr.h>
...
...
@@ -189,6 +190,16 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
return
(
isc
::
config
::
createAnswer
(
1
,
err
.
str
()));
}
// Setup DHCPv4-over-DHCPv6 IPC
try
{
Dhcp4o6Ipc
::
instance
().
open
();
}
catch
(
const
std
::
exception
&
ex
)
{
std
::
ostringstream
err
;
err
<<
"error starting DHCPv4-over-DHCPv6 IPC "
" after server reconfiguration: "
<<
ex
.
what
();
return
(
isc
::
config
::
createAnswer
(
1
,
err
.
str
()));
}
// Configuration may change active interfaces. Therefore, we have to reopen
// sockets according to new configuration. It is possible that this
// operation will fail for some interfaces but the openSockets function
...
...
src/bin/dhcp4/dhcp4_dhcp4o6_ipc.cc
0 → 100644
View file @
ca4d87e7
// Copyright (C) 2015-2016 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
<util/buffer.h>
#include
<dhcp/iface_mgr.h>
#include
<dhcpsrv/cfgmgr.h>
#include
<dhcp4/dhcp4_dhcp4o6_ipc.h>
using
namespace
std
;
namespace
isc
{
namespace
dhcp
{
Dhcp4o6Ipc
::
Dhcp4o6Ipc
()
:
Dhcp4o6IpcBase
()
{}
Dhcp4o6Ipc
&
Dhcp4o6Ipc
::
instance
()
{
static
Dhcp4o6Ipc
dhcp4o6_ipc
;
return
(
dhcp4o6_ipc
);
}
void
Dhcp4o6Ipc
::
open
()
{
uint32_t
port
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getDhcp4o6Port
();
if
(
port
==
0
)
{
Dhcp4o6IpcBase
::
close
();
return
;
}
if
(
port
>
65534
)
{
isc_throw
(
OutOfRange
,
"DHCP4o6 port "
<<
port
);
}
int
old_fd
=
socket_fd_
;
socket_fd_
=
Dhcp4o6IpcBase
::
open
(
static_cast
<
uint16_t
>
(
port
),
4
);
if
((
old_fd
==
-
1
)
&&
(
socket_fd_
!=
old_fd
))
{
IfaceMgr
::
instance
().
addExternalSocket
(
socket_fd_
,
Dhcp4o6Ipc
::
handler
);
}
}
void
Dhcp4o6Ipc
::
handler
()
{
Dhcp4o6Ipc
&
ipc
=
Dhcp4o6Ipc
::
instance
();
Pkt6Ptr
pkt
=
ipc
.
receive
();
if
(
!
pkt
)
{
return
;
}
OptionCollection
msgs
=
pkt
->
getOptions
(
D6O_DHCPV4_MSG
);
if
(
msgs
.
size
()
!=
1
)
{
return
;
}
OptionPtr
msg
=
pkt
->
getOption
(
D6O_DHCPV4_MSG
);
if
(
!
msg
)
{
isc_throw
(
Unexpected
,
"Can't get DHCPv4 message option"
);
}
instance
().
received_
.
reset
(
new
Pkt4o6
(
msg
->
getData
(),
pkt
));
}
Pkt4o6Ptr
&
Dhcp4o6Ipc
::
getReceived
()
{
return
(
received_
);
}
};
// namespace dhcp
};
// namespace isc
src/bin/dhcp4/dhcp4_dhcp4o6_ipc.h
0 → 100644
View file @
ca4d87e7
// Copyright (C) 2015-2016 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 DHCP4_DHCP4O6_IPC_H
#define DHCP4_DHCP4O6_IPC_H
/// @file dhcp4_dhcp4o6_ipc.h Defines the Dhcp4o6Ipc class.
/// This file defines the class Kea uses to act as the DHCPv4 server
/// side of DHCPv4-over-DHCPv6 communication between servers.
///
#include
<dhcp/pkt4o6.h>
#include
<dhcpsrv/dhcp4o6_ipc.h>
#include
<boost/shared_ptr.hpp>
namespace
isc
{
namespace
dhcp
{
/// @brief Handles DHCPv4-over-DHCPv6 IPC on the DHCPv4 server side
class
Dhcp4o6Ipc
:
public
Dhcp4o6IpcBase
{
protected:
/// @brief Constructor
///
/// Default constructor
Dhcp4o6Ipc
();
/// @brief Destructor.
virtual
~
Dhcp4o6Ipc
()
{
}
public:
/// @brief Returns pointer to the sole instance of Dhcp4o6Ipc
///
/// Dhcp4o6Ipc is a singleton class
///
/// @return the only existing instance of DHCP4o6 IPC
static
Dhcp4o6Ipc
&
instance
();
/// @brief Open communication socket
///
/// Call base open method and sets the handler/callback when needed
virtual
void
open
();
/// @brief On receive handler
///
/// The handler processes the DHCPv4-query DHCPv6 packet and
/// sends the DHCPv4-response DHCPv6 packet back to the DHCPv6 server
static
void
handler
();
/// @brief Returns last received packet
///
/// @return a reference to a shared pointer to the last received packet
/// @note This reference should be cleared after use
Pkt4o6Ptr
&
getReceived
();
private:
/// @brief last received packet
Pkt4o6Ptr
received_
;
};
}
// namespace isc
}
// namespace dhcp
#endif
src/bin/dhcp4/json_config_parser.cc
View file @
ca4d87e7
...
...
@@ -415,9 +415,10 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
if
((
config_id
.
compare
(
"valid-lifetime"
)
==
0
)
||
(
config_id
.
compare
(
"renew-timer"
)
==
0
)
||
(
config_id
.
compare
(
"rebind-timer"
)
==
0
)
||
(
config_id
.
compare
(
"decline-probation-period"
)
==
0
)
)
{
(
config_id
.
compare
(
"decline-probation-period"
)
==
0
)
||
(
config_id
.
compare
(
"dhcp4o6-port"
)
==
0
)
)
{
parser
=
new
Uint32Parser
(
config_id
,
globalContext
()
->
uint32_values_
);
globalContext
()
->
uint32_values_
);
}
else
if
(
config_id
.
compare
(
"interfaces-config"
)
==
0
)
{
parser
=
new
IfacesConfigParser4
();
}
else
if
(
config_id
.
compare
(
"subnet4"
)
==
0
)
{
...
...
@@ -465,6 +466,7 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
///
/// - echo-client-id
/// - decline-probation-period
/// - dhcp4o6-port
void
setGlobalParameters4
()
{
// Although the function is modest for now, it is certain that the number
// of global switches will increase over time, hence the name.
...
...
@@ -487,6 +489,15 @@ void setGlobalParameters4() {
}
catch
(...)
{
// That's not really needed.
}
// Set the DHCPv4-over-DHCPv6 interserver port.
try
{
uint32_t
dhcp4o6_port
=
globalContext
()
->
uint32_values_
->
getOptionalParam
(
"dhcp4o6-port"
,
0
);
CfgMgr
::
instance
().
getStagingCfg
()
->
setDhcp4o6Port
(
dhcp4o6_port
);
}
catch
(...)
{
// Ignore errors. This flag is optional
}
}
isc
::
data
::
ConstElementPtr
...
...
src/bin/dhcp6/Makefile.am
View file @
ca4d87e7
...
...
@@ -63,6 +63,7 @@ libdhcp6_la_SOURCES += dhcp6_log.cc dhcp6_log.h
libdhcp6_la_SOURCES
+=
dhcp6_srv.cc dhcp6_srv.h
libdhcp6_la_SOURCES
+=
ctrl_dhcp6_srv.cc ctrl_dhcp6_srv.h
libdhcp6_la_SOURCES
+=
json_config_parser.cc json_config_parser.h
libdhcp6_la_SOURCES
+=
dhcp6_dhcp4o6_ipc.cc dhcp6_dhcp4o6_ipc.h
libdhcp6_la_SOURCES
+=
kea_controller.cc
...
...
src/bin/dhcp6/ctrl_dhcp6_srv.cc
View file @
ca4d87e7
...
...
@@ -11,6 +11,7 @@
#include
<dhcpsrv/cfgmgr.h>
#include
<dhcpsrv/cfg_db_access.h>
#include
<dhcp6/ctrl_dhcp6_srv.h>
#include
<dhcp6/dhcp6_dhcp4o6_ipc.h>
#include
<dhcp6/dhcp6_log.h>
#include
<dhcp6/json_config_parser.h>
#include
<hooks/hooks_manager.h>
...
...
@@ -213,6 +214,16 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
return
(
isc
::
config
::
createAnswer
(
1
,
err
.
str
()));
}
// Setup DHCPv4-over-DHCPv6 IPC
try
{
Dhcp4o6Ipc
::
instance
().
open
();
}
catch
(
const
std
::
exception
&
ex
)
{
std
::
ostringstream
err
;
err
<<
"error starting DHCPv4-over-DHCPv6 IPC "
" after server reconfiguration: "
<<
ex
.
what
();
return
(
isc
::
config
::
createAnswer
(
1
,
err
.
str
()));
}
// Configuration may change active interfaces. Therefore, we have to reopen
// sockets according to new configuration. It is possible that this
// operation will fail for some interfaces but the openSockets function
...
...
src/bin/dhcp6/dhcp6_dhcp4o6_ipc.cc
0 → 100644
View file @
ca4d87e7
// Copyright (C) 2015-2016 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
<util/buffer.h>
#include
<dhcp/iface_mgr.h>
#include
<dhcpsrv/cfgmgr.h>
#include
<dhcp6/dhcp6_dhcp4o6_ipc.h>
using
namespace
std
;
namespace
isc
{
namespace
dhcp
{
Dhcp4o6Ipc
::
Dhcp4o6Ipc
()
:
Dhcp4o6IpcBase
()
{}
Dhcp4o6Ipc
&
Dhcp4o6Ipc
::
instance
()
{
static
Dhcp4o6Ipc
dhcp4o6_ipc
;
return
(
dhcp4o6_ipc
);
}
void
Dhcp4o6Ipc
::
open
()
{
uint32_t
port
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getDhcp4o6Port
();
if
(
port
==
0
)
{
Dhcp4o6IpcBase
::
close
();
return
;
}
if
(
port
>
65534
)
{
isc_throw
(
OutOfRange
,
"DHCP4o6 port "
<<
port
);
}
int
old_fd
=
socket_fd_
;
socket_fd_
=
Dhcp4o6IpcBase
::
open
(
static_cast
<
uint16_t
>
(
port
),
6
);
if
((
old_fd
==
-
1
)
&&
(
socket_fd_
!=
old_fd
))
{
IfaceMgr
::
instance
().
addExternalSocket
(
socket_fd_
,
Dhcp4o6Ipc
::
handler
);
}
}
void
Dhcp4o6Ipc
::
handler
()
{
Dhcp4o6Ipc
&
ipc
=
Dhcp4o6Ipc
::
instance
();
Pkt6Ptr
pkt
=
ipc
.
receive
();
if
(
!
pkt
)
{
return
;
}
isc
::
util
::
OutputBuffer
&
buf
=
pkt
->
getBuffer
();
buf
.
clear
();
pkt
->
pack
();
uint8_t
msg_type
=
buf
[
0
];
if
((
msg_type
==
DHCPV6_RELAY_FORW
)
||
(
msg_type
==
DHCPV6_RELAY_REPL
))
{
pkt
->
setRemotePort
(
DHCP6_SERVER_PORT
);
}
else
{
pkt
->
setRemotePort
(
DHCP6_CLIENT_PORT
);
}
IfaceMgr
::
instance
().
send
(
pkt
);
// processStatsSent(pkt);
}
};
// namespace dhcp
};
// namespace isc
src/bin/dhcp6/dhcp6_dhcp4o6_ipc.h
0 → 100644
View file @
ca4d87e7
// Copyright (C) 2015-2016 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 DHCP6_DHCP4O6_IPC_H
#define DHCP6_DHCP4O6_IPC_H
/// @file dhcp6_dhcp4o6_ipc.h Defines the Dhcp4o6Ipc class.
/// This file defines the class Kea uses to act as the DHCPv6 server
/// side of DHCPv4-over-DHCPv6 communication between servers.
///
#include
<dhcpsrv/dhcp4o6_ipc.h>
#include
<boost/shared_ptr.hpp>
namespace
isc
{
namespace
dhcp
{
/// @brief Handles DHCPv4-over-DHCPv6 IPC on the DHCPv6 server side
class
Dhcp4o6Ipc
:
public
Dhcp4o6IpcBase
{
protected:
/// @brief Constructor
///
/// Default constructor
Dhcp4o6Ipc
();
/// @brief Destructor.
virtual
~
Dhcp4o6Ipc
()
{
}
public:
/// @brief Returns pointer to the sole instance of Dhcp4o6Ipc
///
/// Dhcp4o6Ipc is a singleton class
///
/// @return the only existing instance of DHCP4o6 IPC
static
Dhcp4o6Ipc
&
instance
();
/// @brief Open communication socket
///
/// Call base open method and sets the handler/callback when needed
virtual
void
open
();
/// @brief On receive handler
///
/// The handler sends the DHCPv6 packet back to the remote address
static
void
handler
();
};
}
// namespace isc
}
// namespace dhcp
#endif
src/bin/dhcp6/dhcp6_srv.cc
View file @
ca4d87e7
...
...
@@ -25,6 +25,7 @@
#include
<dhcp/option_vendor_class.h>
#include
<dhcp/option_int_array.h>
#include
<dhcp/pkt6.h>
#include
<dhcp6/dhcp6_dhcp4o6_ipc.h>
#include
<dhcp6/dhcp6_log.h>
#include
<dhcp6/dhcp6_srv.h>
#include
<dhcpsrv/callout_handle_store.h>
...
...
@@ -211,6 +212,13 @@ Dhcpv6Srv::~Dhcpv6Srv() {
LOG_ERROR
(
dhcp6_logger
,
DHCP6_SRV_D2STOP_ERROR
).
arg
(
ex
.
what
());
}
try
{
Dhcp4o6Ipc
::
instance
().
close
();
}
catch
(
const
std
::
exception
&
ex
)
{
// Highly unlikely, but lets Report it but go on
// LOG_ERROR(dhcp6_logger, DHCP6_SRV_DHCP4O6_ERROR).arg(ex.what());
}
IfaceMgr
::
instance
().
closeSockets
();
LeaseMgrFactory
::
destroy
();
...
...
src/bin/dhcp6/json_config_parser.cc
View file @
ca4d87e7
...
...
@@ -667,7 +667,8 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id,
(
config_id
.
compare
(
"valid-lifetime"
)
==
0
)
||
(
config_id
.
compare
(
"renew-timer"
)
==
0
)
||
(
config_id
.
compare
(
"rebind-timer"
)
==
0
)
||
(
config_id
.
compare
(
"decline-probation-period"
)
==
0
)
)
{
(
config_id
.
compare
(
"decline-probation-period"
)
==
0
)
||
(
config_id
.
compare
(
"dhcp4o6-port"
)
==
0
)
)
{
parser
=
new
Uint32Parser
(
config_id
,
globalContext
()
->
uint32_values_
);
}
else
if
(
config_id
.
compare
(
"interfaces-config"
)
==
0
)
{
...
...
@@ -718,6 +719,7 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id,
/// Currently this method sets the following global parameters:
///
/// - decline-probation-period
/// - dhcp4o6-port
void
setGlobalParameters6
()
{
// Set the probation period for decline handling.
...
...
@@ -729,6 +731,15 @@ void setGlobalParameters6() {
}
catch
(...)
{
// That's not really needed.
}
// Set the DHCPv4-over-DHCPv6 interserver port.
try
{
uint32_t
dhcp4o6_port
=
globalContext
()
->
uint32_values_
->
getOptionalParam
(
"dhcp4o6-port"
,
0
);
CfgMgr
::
instance
().
getStagingCfg
()
->
setDhcp4o6Port
(
dhcp4o6_port
);
}
catch
(...)
{
// Ignore errors. This flag is optional
}
}
isc
::
data
::
ConstElementPtr
...
...
src/lib/dhcpsrv/Makefile.am
View file @
ca4d87e7
...
...
@@ -107,6 +107,7 @@ libkea_dhcpsrv_la_SOURCES += d2_client_mgr.cc d2_client_mgr.h
libkea_dhcpsrv_la_SOURCES
+=
daemon.cc daemon.h
libkea_dhcpsrv_la_SOURCES
+=
database_connection.cc database_connection.h
libkea_dhcpsrv_la_SOURCES
+=
db_exceptions.h
libkea_dhcpsrv_la_SOURCES
+=
dhcp4o6_ipc.cc dhcp4o6_ipc.h
libkea_dhcpsrv_la_SOURCES
+=
dhcpsrv_log.cc dhcpsrv_log.h
libkea_dhcpsrv_la_SOURCES
+=
host.cc host.h
libkea_dhcpsrv_la_SOURCES
+=
host_container.h
...
...
src/lib/dhcpsrv/dhcp4o6_ipc.cc
0 → 100644
View file @
ca4d87e7
// Copyright (C) 2015-2016 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/dhcp6.h>
#include
<dhcp/iface_mgr.h>
#include
<dhcp/option6_addrlst.h>
#include
<dhcp/option_string.h>
#include
<dhcp/option_vendor.h>
#include
<dhcpsrv/dhcp4o6_ipc.h>
#include
<dhcpsrv/dhcpsrv_log.h>
#include
<netinet/in.h>
#include
<sys/fcntl.h>
#include
<string>
using
namespace
isc
::
asiolink
;
using
namespace
isc
::
util
;
using
namespace
std
;
namespace
isc
{
namespace
dhcp
{
Dhcp4o6IpcBase
::
Dhcp4o6IpcBase
()
:
port_
(
0
),
socket_fd_
(
-
1
)
{}
Dhcp4o6IpcBase
::~
Dhcp4o6IpcBase
()
{
close
();
}
int
Dhcp4o6IpcBase
::
open
(
uint16_t
port
,
int
side
)
{
if
(
port
==
port_
)
{
// No change: nothing to do
return
(
socket_fd_
);
}
// Port 0: closing
if
(
port
==
0
)
{
port_
=
0
;
if
(
socket_fd_
!=
-
1
)
{
IfaceMgr
::
instance
().
deleteExternalSocket
(
socket_fd_
);
::
close
(
socket_fd_
);
socket_fd_
=
-
1
;
}
return
(
socket_fd_
);
}
// Open socket
int
sock
=
socket
(
PF_INET6
,
SOCK_DGRAM
,
IPPROTO_UDP
);
if
(
sock
<
0
)
{
isc_throw
(
Unexpected
,
"Failed to create DHCP4o6 socket."
);
}
// Set reuse address
int
flag
=
1
;
if
(
setsockopt
(
sock
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
char
*
)
&
flag
,
sizeof
(
flag
))
<
0
)
{
::
close
(
sock
);
isc_throw
(
Unexpected
,
"Failed to set SO_REUSEADDR on DHCP4o6 socket."
);
}
// Set no blocking
if
(
fcntl
(
sock
,
F_SETFL
,
O_NONBLOCK
)
<
0
)
{
::
close
(
sock
);
isc_throw
(
Unexpected
,
"Failed to set O_NONBLOCK on DHCP4o6 socket."
);
}
// Bind to the local address
struct
sockaddr_in6
local6
;
memset
(
&
local6
,
0
,
sizeof
(
local6
));
local6
.
sin6_family
=
AF_INET6
;
#ifdef HAVE_SA_LEN
local6
.
sin6_len
=
sizeof
(
local6
);
#endif
if
(
side
==
6
)
{
local6
.
sin6_port
=
htons
(
port
);
}
else
{
local6
.
sin6_port
=
htons
(
port
+
1
);
}
// We'll connect to the loopback address so bind to it too.
local6
.
sin6_addr
.
s6_addr
[
15
]
=
1
;
if
(
bind
(
sock
,
(
struct
sockaddr
*
)
&
local6
,
sizeof
(
local6
))
<
0
)
{
::
close
(
sock
);
isc_throw
(
Unexpected
,
"Failed to bind DHCP4o6 socket."
);
}
// Connect to the remote address
struct
sockaddr_in6
remote6
;
memset
(
&
remote6
,
0
,
sizeof
(
remote6
));
remote6
.
sin6_family
=
AF_INET6
;
#ifdef HAVE_SA_LEN
remote6
.
sin6_len
=
sizeof
(
remote6
);
#endif
if
(
side
==
6
)
{
remote6
.
sin6_port
=
htons
(
port
+
1
);
}
else
{
remote6
.
sin6_port
=
htons
(
port
);
}
// At least OpenBSD requires the remote address to not be left
// unspecified, so we set it to the loopback address.
remote6
.
sin6_addr
.
s6_addr
[
15
]
=
1
;
if
(
connect
(
sock
,
reinterpret_cast
<
const
struct
sockaddr
*>
(
&
remote6
),
sizeof
(
remote6
))
<
0
)
{
::
close
(
sock
);
isc_throw
(
Unexpected
,
"Failed to connect DHCP4o6 socket."
);
}
if
(
socket_fd_
!=
-
1
)
{
if
(
dup2
(
sock
,
socket_fd_
)
==
-
1
)
{
::
close
(
sock
);
isc_throw
(
Unexpected
,
"Failed to duplicate DHCP4o6 socket."
);
}
if
(
sock
!=
socket_fd_
)
{
::
close
(
sock
);
sock
=
socket_fd_
;
}
}
// Success
port_
=
port
;
socket_fd_
=
sock
;
return
(
socket_fd_
);
}
void
Dhcp4o6IpcBase
::
close
()
{
static_cast
<
void
>
(
open
(
0
,
0
));
}
Pkt6Ptr
Dhcp4o6IpcBase
::
receive
()
{
uint8_t
buf
[
65536
];
ssize_t
cc
=
recv
(
socket_fd_
,
buf
,
sizeof
(
buf
),
0
);
if
(
cc
<
0
)
{
isc_throw
(
Unexpected
,
"Failed to receive on DHCP4o6 socket."
);
}
Pkt6Ptr
pkt
=
Pkt6Ptr
(
new
Pkt6
(
buf
,
cc
));
pkt
->
updateTimestamp
();
// Get interface name and remote address
pkt
->
unpack
();
OptionVendorPtr
vendor
=
boost
::
dynamic_pointer_cast
<
OptionVendor
>
(
pkt
->
getOption
(
D6O_VENDOR_OPTS
));
if
(
!
vendor
)
{
LOG_DEBUG
(
dhcpsrv_logger
,
DHCPSRV_DBG_TRACE_DETAIL
,
DHCPSRV_DHCP4O6_RECEIVED_BAD_PACKET
)
.
arg
(
"no vendor option"
);