Skip to content
GitLab
Menu
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
1f486ccd
Commit
1f486ccd
authored
Sep 25, 2012
by
Marcin Siodelski
Browse files
[2187] Throw exception in case of error when opening socket.
parent
d863d2f2
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/lib/dhcp/iface_mgr.cc
View file @
1f486ccd
...
...
@@ -132,13 +132,7 @@ IfaceMgr::IfaceMgr()
detectIfaces
();
}
catch
(
const
std
::
exception
&
ex
)
{
cout
<<
"IfaceMgr creation failed:"
<<
ex
.
what
()
<<
endl
;
// TODO Uncomment this (or call LOG_FATAL) once
// interface detection is implemented. Otherwise
// it is not possible to run tests in a portable
// way (see detectIfaces() method).
throw
;
isc_throw
(
IfaceDetectError
,
ex
.
what
());
}
}
...
...
@@ -164,45 +158,34 @@ void IfaceMgr::stubDetectIfaces() {
// is faked by detecting loopback interface (lo or lo0). It will eventually
// be removed once we have actual implementations for all supported systems.
try
{
if
(
if_nametoindex
(
"lo"
)
>
0
)
{
ifaceName
=
"lo"
;
// this is Linux-like OS
}
else
if
(
if_nametoindex
(
"lo0"
)
>
0
)
{
ifaceName
=
"lo0"
;
// this is BSD-like OS
}
else
{
// we give up. What OS is this, anyway? Solaris? Hurd?
isc_throw
(
NotImplemented
,
"Interface detection on this OS is not supported."
);
}
Iface
iface
(
ifaceName
,
if_nametoindex
(
ifaceName
.
c_str
()));
iface
.
flag_up_
=
true
;
iface
.
flag_running_
=
true
;
// Note that we claim that this is not a loopback. iface_mgr tries to open a
// socket on all interaces that are up, running and not loopback. As this is
// the only interface we were able to detect, let's pretend this is a normal
// interface.
iface
.
flag_loopback_
=
false
;
iface
.
flag_multicast_
=
true
;
iface
.
flag_broadcast_
=
true
;
iface
.
setHWType
(
HWTYPE_ETHERNET
);
iface
.
addAddress
(
IOAddress
(
v4addr
));
iface
.
addAddress
(
IOAddress
(
v6addr
));
addInterface
(
iface
);
}
catch
(
const
std
::
exception
&
ex
)
{
// TODO: deallocate whatever memory we used
// not that important, since this function is going to be
// thrown away as soon as we get proper interface detection
// implemented
// TODO Do LOG_FATAL here
std
::
cerr
<<
"Interface detection failed."
<<
std
::
endl
;
throw
;
if
(
if_nametoindex
(
"lo"
)
>
0
)
{
ifaceName
=
"lo"
;
// this is Linux-like OS
}
else
if
(
if_nametoindex
(
"lo0"
)
>
0
)
{
ifaceName
=
"lo0"
;
// this is BSD-like OS
}
else
{
// we give up. What OS is this, anyway? Solaris? Hurd?
isc_throw
(
NotImplemented
,
"Interface detection on this OS is not supported."
);
}
Iface
iface
(
ifaceName
,
if_nametoindex
(
ifaceName
.
c_str
()));
iface
.
flag_up_
=
true
;
iface
.
flag_running_
=
true
;
// Note that we claim that this is not a loopback. iface_mgr tries to open a
// socket on all interaces that are up, running and not loopback. As this is
// the only interface we were able to detect, let's pretend this is a normal
// interface.
iface
.
flag_loopback_
=
false
;
iface
.
flag_multicast_
=
true
;
iface
.
flag_broadcast_
=
true
;
iface
.
setHWType
(
HWTYPE_ETHERNET
);
iface
.
addAddress
(
IOAddress
(
v4addr
));
iface
.
addAddress
(
IOAddress
(
v6addr
));
addInterface
(
iface
);
}
bool
IfaceMgr
::
openSockets4
(
const
uint16_t
port
)
{
...
...
@@ -231,15 +214,13 @@ bool IfaceMgr::openSockets4(const uint16_t port) {
sock
=
openSocket
(
iface
->
getName
(),
*
addr
,
port
);
if
(
sock
<
0
)
{
cout
<<
"Failed to open unicast socket."
<<
endl
;
return
(
false
);
isc_throw
(
SocketConfigError
,
"failed to open unicast socket"
);
}
count
++
;
}
}
return
(
count
>
0
);
}
bool
IfaceMgr
::
openSockets6
(
const
uint16_t
port
)
{
...
...
@@ -268,8 +249,7 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
sock
=
openSocket
(
iface
->
getName
(),
*
addr
,
port
);
if
(
sock
<
0
)
{
cout
<<
"Failed to open unicast socket."
<<
endl
;
return
(
false
);
isc_throw
(
SocketConfigError
,
"failed to open unicast socket"
);
}
// Binding socket to unicast address and then joining multicast group
...
...
@@ -278,7 +258,8 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
if
(
!
joinMulticast
(
sock
,
iface
->
getName
(),
string
(
ALL_DHCP_RELAY_AGENTS_AND_SERVERS
)))
{
close
(
sock
);
isc_throw
(
Unexpected
,
"Failed to join "
<<
ALL_DHCP_RELAY_AGENTS_AND_SERVERS
isc_throw
(
SocketConfigError
,
"Failed to join "
<<
ALL_DHCP_RELAY_AGENTS_AND_SERVERS
<<
" multicast group."
);
}
...
...
@@ -293,7 +274,7 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
IOAddress
(
ALL_DHCP_RELAY_AGENTS_AND_SERVERS
),
port
);
if
(
sock2
<
0
)
{
isc_throw
(
Unexpected
,
"Failed to open multicast socket on "
isc_throw
(
SocketConfigError
,
"Failed to open multicast socket on "
<<
" interface "
<<
iface
->
getFullName
());
iface
->
delSocket
(
sock
);
// delete previously opened socket
}
...
...
@@ -406,7 +387,7 @@ int IfaceMgr::openSocketFromIface(const std::string& ifname,
family_name
=
"AF_INET6"
;
}
// We did not find address on the interface.
isc_throw
(
BadValue
,
"There is no address for interface: "
isc_throw
(
SocketConfigError
,
"There is no address for interface: "
<<
ifname
<<
", port: "
<<
port
<<
", address "
" family: "
<<
family_name
);
}
...
...
@@ -448,9 +429,13 @@ int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
int
IfaceMgr
::
openSocketFromRemoteAddress
(
const
IOAddress
&
remote_addr
,
const
uint16_t
port
)
{
// Get local address to be used to connect to remote location.
IOAddress
local_address
(
getLocalAddress
(
remote_addr
,
port
).
getAddress
());
return
openSocketFromAddress
(
local_address
,
port
);
try
{
// Get local address to be used to connect to remote location.
IOAddress
local_address
(
getLocalAddress
(
remote_addr
,
port
).
getAddress
());
return
openSocketFromAddress
(
local_address
,
port
);
}
catch
(
const
Exception
&
e
)
{
isc_throw
(
SocketConfigError
,
e
.
what
());
}
}
isc
::
asiolink
::
IOAddress
...
...
@@ -494,7 +479,7 @@ IfaceMgr::getLocalAddress(const IOAddress& remote_addr, const uint16_t port) {
sock
.
connect
(
remote_endpoint
->
getASIOEndpoint
(),
err_code
);
if
(
err_code
)
{
sock
.
close
();
isc_throw
(
Unexpected
,
"failed to connect to remote endpoint."
);
isc_throw
(
Unexpected
,
"failed to connect to remote endpoint."
);
}
// Once we are connected socket object holds local endpoint.
...
...
@@ -522,12 +507,12 @@ int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port) {
int
sock
=
socket
(
AF_INET
,
SOCK_DGRAM
,
0
);
if
(
sock
<
0
)
{
isc_throw
(
Unexpected
,
"Failed to create UDP6 socket."
);
isc_throw
(
SocketConfigError
,
"Failed to create UDP6 socket."
);
}
if
(
bind
(
sock
,
(
struct
sockaddr
*
)
&
addr4
,
sizeof
(
addr4
))
<
0
)
{
close
(
sock
);
isc_throw
(
Unexpected
,
"Failed to bind socket "
<<
sock
<<
" to "
<<
addr
.
toText
()
isc_throw
(
SocketConfigError
,
"Failed to bind socket "
<<
sock
<<
" to "
<<
addr
.
toText
()
<<
"/port="
<<
port
);
}
...
...
@@ -537,7 +522,7 @@ int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port) {
int
flag
=
1
;
if
(
setsockopt
(
sock
,
IPPROTO_IP
,
IP_PKTINFO
,
&
flag
,
sizeof
(
flag
))
!=
0
)
{
close
(
sock
);
isc_throw
(
Unexpected
,
"setsockopt: IP_PKTINFO: failed."
);
isc_throw
(
SocketConfigError
,
"setsockopt: IP_PKTINFO: failed."
);
}
#endif
...
...
@@ -569,7 +554,7 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
// make a socket
int
sock
=
socket
(
AF_INET6
,
SOCK_DGRAM
,
0
);
if
(
sock
<
0
)
{
isc_throw
(
Unexpected
,
"Failed to create UDP6 socket."
);
isc_throw
(
SocketConfigError
,
"Failed to create UDP6 socket."
);
}
// Set the REUSEADDR option so that we don't fail to start if
...
...
@@ -578,12 +563,12 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
if
(
setsockopt
(
sock
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
char
*
)
&
flag
,
sizeof
(
flag
))
<
0
)
{
close
(
sock
);
isc_throw
(
Unexpected
,
"Can't set SO_REUSEADDR option on dhcpv6 socket."
);
isc_throw
(
SocketConfigError
,
"Can't set SO_REUSEADDR option on dhcpv6 socket."
);
}
if
(
bind
(
sock
,
(
struct
sockaddr
*
)
&
addr6
,
sizeof
(
addr6
))
<
0
)
{
close
(
sock
);
isc_throw
(
Unexpected
,
"Failed to bind socket "
<<
sock
<<
" to "
<<
addr
.
toText
()
isc_throw
(
SocketConfigError
,
"Failed to bind socket "
<<
sock
<<
" to "
<<
addr
.
toText
()
<<
"/port="
<<
port
);
}
#ifdef IPV6_RECVPKTINFO
...
...
@@ -591,14 +576,14 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
if
(
setsockopt
(
sock
,
IPPROTO_IPV6
,
IPV6_RECVPKTINFO
,
&
flag
,
sizeof
(
flag
))
!=
0
)
{
close
(
sock
);
isc_throw
(
Unexpected
,
"setsockopt: IPV6_RECVPKTINFO failed."
);
isc_throw
(
SocketConfigError
,
"setsockopt: IPV6_RECVPKTINFO failed."
);
}
#else
// RFC2292 - an old way
if
(
setsockopt
(
sock
,
IPPROTO_IPV6
,
IPV6_PKTINFO
,
&
flag
,
sizeof
(
flag
))
!=
0
)
{
close
(
sock
);
isc_throw
(
Unexpected
,
"setsockopt: IPV6_PKTINFO: failed."
);
isc_throw
(
SocketConfigError
,
"setsockopt: IPV6_PKTINFO: failed."
);
}
#endif
...
...
@@ -611,7 +596,7 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
if
(
!
joinMulticast
(
sock
,
iface
.
getName
(),
string
(
ALL_DHCP_RELAY_AGENTS_AND_SERVERS
)
)
)
{
close
(
sock
);
isc_throw
(
Unexpected
,
"Failed to join "
<<
ALL_DHCP_RELAY_AGENTS_AND_SERVERS
isc_throw
(
SocketConfigError
,
"Failed to join "
<<
ALL_DHCP_RELAY_AGENTS_AND_SERVERS
<<
" multicast group."
);
}
}
...
...
src/lib/dhcp/iface_mgr.h
View file @
1f486ccd
...
...
@@ -28,6 +28,38 @@
namespace
isc
{
namespace
dhcp
{
/// @brief IfaceMgr exception thrown thrown when interface detection fails.
class
IfaceDetectError
:
public
Exception
{
public:
IfaceDetectError
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{
};
};
/// @brief IfaceMgr exception thrown thrown when socket opening
/// or configuration failed.
class
SocketConfigError
:
public
Exception
{
public:
SocketConfigError
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{
};
};
/// @brief IfaceMgr exception thrown thrown when error occured during
/// reading data from socket.
class
SocketReadError
:
public
Exception
{
public:
SocketReadError
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{
};
};
/// @brief IfaceMgr exception thrown thrown when error occured during
/// sedning data through socket.
class
SocketWriteError
:
public
Exception
{
public:
SocketWriteError
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{
};
};
/// @brief handles network interfaces, transmission and reception
///
/// IfaceMgr is an interface manager class that detects available network
...
...
@@ -460,6 +492,7 @@ public:
///
/// @param port specifies port number (usually DHCP6_SERVER_PORT)
///
/// @throw SocketOpenFailure if tried and failed to open socket.
/// @return true if any sockets were open
bool
openSockets6
(
const
uint16_t
port
=
DHCP6_SERVER_PORT
);
...
...
@@ -472,6 +505,7 @@ public:
///
/// @param port specifies port number (usually DHCP4_SERVER_PORT)
///
/// @throw SocketOpenFailure if tried and failed to open socket.
/// @return true if any sockets were open
bool
openSockets4
(
const
uint16_t
port
=
DHCP4_SERVER_PORT
);
...
...
src/lib/dhcp/tests/iface_mgr_unittest.cc
View file @
1f486ccd
...
...
@@ -419,7 +419,7 @@ TEST_F(IfaceMgrTest, sockets6) {
// testing socket operation in a portable way is tricky
// without interface detection implemented
NakedIfaceMgr
*
ifacemgr
=
new
NakedIfaceMgr
();
boost
::
scoped_ptr
<
NakedIfaceMgr
>
ifacemgr
(
new
NakedIfaceMgr
()
)
;
IOAddress
loAddr
(
"::1"
);
...
...
@@ -439,10 +439,20 @@ TEST_F(IfaceMgrTest, sockets6) {
// removed code for binding socket twice to the same address/port
// as it caused problems on some platforms (e.g. Mac OS X)
close
(
socket1
);
close
(
socket2
);
ifacemgr
->
closeSockets
();
delete
ifacemgr
;
// Use address that is not assigned to LOOPBACK iface.
IOAddress
invalidAddr
(
"::2"
);
EXPECT_THROW
(
ifacemgr
->
openSocket
(
LOOPBACK
,
invalidAddr
,
10547
),
SocketConfigError
);
// Use non-existing interface name.
EXPECT_THROW
(
ifacemgr
->
openSocket
(
"non_existing_interface"
,
loAddr
,
10548
),
BadValue
);
}
TEST_F
(
IfaceMgrTest
,
socketsFromIface
)
{
...
...
@@ -466,6 +476,13 @@ TEST_F(IfaceMgrTest, socketsFromIface) {
EXPECT_GT
(
socket2
,
0
);
close
(
socket2
);
ifacemgr
->
closeSockets
();
// Use invalid interface name.
EXPECT_THROW
(
ifacemgr
->
openSocketFromIface
(
"non_existing_interface"
,
PORT1
,
AF_INET
),
BadValue
);
}
...
...
@@ -480,7 +497,6 @@ TEST_F(IfaceMgrTest, socketsFromAddress) {
);
// socket descriptor must be positive integer
EXPECT_GT
(
socket1
,
0
);
close
(
socket1
);
// Open v4 socket on loopback interface and bind to different port
int
socket2
=
0
;
...
...
@@ -490,7 +506,14 @@ TEST_F(IfaceMgrTest, socketsFromAddress) {
);
// socket descriptor must be positive integer
EXPECT_GT
(
socket2
,
0
);
close
(
socket2
);
ifacemgr
->
closeSockets
();
// Use non-existing address.
IOAddress
invalidAddr
(
"1.2.3.4"
);
EXPECT_THROW
(
ifacemgr
->
openSocketFromAddress
(
invalidAddr
,
PORT1
),
BadValue
);
}
TEST_F
(
IfaceMgrTest
,
socketsFromRemoteAddress
)
{
...
...
@@ -505,7 +528,6 @@ TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
socket1
=
ifacemgr
->
openSocketFromRemoteAddress
(
loAddr6
,
PORT1
);
);
EXPECT_GT
(
socket1
,
0
);
close
(
socket1
);
// Open v4 socket to connect to remote address.
int
socket2
=
0
;
...
...
@@ -514,7 +536,8 @@ TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
socket2
=
ifacemgr
->
openSocketFromRemoteAddress
(
loAddr
,
PORT2
);
);
EXPECT_GT
(
socket2
,
0
);
close
(
socket2
);
ifacemgr
->
closeSockets
();
// The following test is currently disabled for OSes other than
// Linux because interface detection is not implemented on them.
...
...
@@ -528,7 +551,6 @@ TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
socket3
=
ifacemgr
->
openSocketFromRemoteAddress
(
bcastAddr
,
PORT2
);
);
EXPECT_GT
(
socket3
,
0
);
close
(
socket3
);
#endif
}
...
...
Write
Preview
Supports
Markdown
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