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
43fa9db5
Commit
43fa9db5
authored
Apr 03, 2013
by
Marcin Siodelski
Browse files
[991] Moved send/receive implementation to class derived from PktFilter.
parent
d919490c
Changes
7
Hide whitespace changes
Inline
Side-by-side
src/lib/dhcp/iface_mgr.cc
View file @
43fa9db5
...
...
@@ -581,7 +581,19 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
}
}
Iface
::
SocketInfo
info
(
sock
,
addr
,
port
);
SocketInfo
info
(
sock
,
addr
,
port
);
iface
.
addSocket
(
info
);
return
(
sock
);
}
int
IfaceMgr
::
openSocket4
(
Iface
&
iface
,
const
IOAddress
&
addr
,
uint16_t
port
,
bool
receive_bcast
,
bool
send_bcast
)
{
int
sock
=
packet_filter_
->
openSocket
(
iface
,
addr
,
port
,
receive_bcast
,
send_bcast
);
SocketInfo
info
(
sock
,
addr
,
port
);
iface
.
addSocket
(
info
);
return
(
sock
);
...
...
@@ -688,6 +700,18 @@ IfaceMgr::send(const Pkt6Ptr& pkt) {
return
(
result
);
}
bool
IfaceMgr
::
send
(
const
Pkt4Ptr
&
pkt
)
{
Iface
*
iface
=
getIface
(
pkt
->
getIface
());
if
(
!
iface
)
{
isc_throw
(
BadValue
,
"Unable to send Pkt4. Invalid interface ("
<<
pkt
->
getIface
()
<<
") specified."
);
}
return
(
packet_filter_
->
send
(
getSocket
(
*
pkt
),
pkt
));
}
boost
::
shared_ptr
<
Pkt4
>
IfaceMgr
::
receive4
(
uint32_t
timeout_sec
,
uint32_t
timeout_usec
/* = 0 */
)
{
...
...
@@ -696,7 +720,7 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
isc_throw
(
BadValue
,
"fractional timeout must be shorter than"
" one million microseconds"
);
}
const
Iface
::
SocketInfo
*
candidate
=
0
;
const
SocketInfo
*
candidate
=
0
;
IfaceCollection
::
const_iterator
iface
;
fd_set
sockets
;
int
maxfd
=
0
;
...
...
@@ -783,64 +807,7 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
}
// Now we have a socket, let's get some data from it!
struct
sockaddr_in
from_addr
;
uint8_t
buf
[
RCVBUFSIZE
];
memset
(
&
control_buf_
[
0
],
0
,
control_buf_len_
);
memset
(
&
from_addr
,
0
,
sizeof
(
from_addr
));
// Initialize our message header structure.
struct
msghdr
m
;
memset
(
&
m
,
0
,
sizeof
(
m
));
// Point so we can get the from address.
m
.
msg_name
=
&
from_addr
;
m
.
msg_namelen
=
sizeof
(
from_addr
);
struct
iovec
v
;
v
.
iov_base
=
static_cast
<
void
*>
(
buf
);
v
.
iov_len
=
RCVBUFSIZE
;
m
.
msg_iov
=
&
v
;
m
.
msg_iovlen
=
1
;
// Getting the interface is a bit more involved.
//
// We set up some space for a "control message". We have
// previously asked the kernel to give us packet
// information (when we initialized the interface), so we
// should get the destination address from that.
m
.
msg_control
=
&
control_buf_
[
0
];
m
.
msg_controllen
=
control_buf_len_
;
result
=
recvmsg
(
candidate
->
sockfd_
,
&
m
,
0
);
if
(
result
<
0
)
{
isc_throw
(
SocketReadError
,
"failed to receive UDP4 data"
);
}
// We have all data let's create Pkt4 object.
Pkt4Ptr
pkt
=
Pkt4Ptr
(
new
Pkt4
(
buf
,
result
));
pkt
->
updateTimestamp
();
unsigned
int
ifindex
=
iface
->
getIndex
();
IOAddress
from
(
htonl
(
from_addr
.
sin_addr
.
s_addr
));
uint16_t
from_port
=
htons
(
from_addr
.
sin_port
);
// Set receiving interface based on information, which socket was used to
// receive data. OS-specific info (see os_receive4()) may be more reliable,
// so this value may be overwritten.
pkt
->
setIndex
(
ifindex
);
pkt
->
setIface
(
iface
->
getName
());
pkt
->
setRemoteAddr
(
from
);
pkt
->
setRemotePort
(
from_port
);
pkt
->
setLocalPort
(
candidate
->
port_
);
if
(
!
os_receive4
(
m
,
pkt
))
{
isc_throw
(
SocketReadError
,
"unable to find pktinfo"
);
}
return
(
pkt
);
return
(
packet_filter_
->
receive
(
*
iface
,
*
candidate
));
}
Pkt6Ptr
IfaceMgr
::
receive6
(
uint32_t
timeout_sec
,
uint32_t
timeout_usec
/* = 0 */
)
{
...
...
@@ -850,7 +817,7 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
" one million microseconds"
);
}
const
Iface
::
SocketInfo
*
candidate
=
0
;
const
SocketInfo
*
candidate
=
0
;
fd_set
sockets
;
int
maxfd
=
0
;
stringstream
names
;
...
...
src/lib/dhcp/iface_mgr.h
View file @
43fa9db5
...
...
@@ -70,6 +70,24 @@ public:
isc
::
Exception
(
file
,
line
,
what
)
{
};
};
/// Holds information about socket.
struct
SocketInfo
{
uint16_t
sockfd_
;
/// socket descriptor
isc
::
asiolink
::
IOAddress
addr_
;
/// bound address
uint16_t
port_
;
/// socket port
uint16_t
family_
;
/// IPv4 or IPv6
/// @brief SocketInfo constructor.
///
/// @param sockfd socket descriptor
/// @param addr an address the socket is bound to
/// @param port a port the socket is bound to
SocketInfo
(
uint16_t
sockfd
,
const
isc
::
asiolink
::
IOAddress
&
addr
,
uint16_t
port
)
:
sockfd_
(
sockfd
),
addr_
(
addr
),
port_
(
port
),
family_
(
addr
.
getFamily
())
{
}
};
/// @brief represents a single network interface
///
/// Iface structure represents network interface with all useful
...
...
@@ -84,23 +102,6 @@ public:
/// type that defines list of addresses
typedef
std
::
vector
<
isc
::
asiolink
::
IOAddress
>
AddressCollection
;
/// Holds information about socket.
struct
SocketInfo
{
uint16_t
sockfd_
;
/// socket descriptor
isc
::
asiolink
::
IOAddress
addr_
;
/// bound address
uint16_t
port_
;
/// socket port
uint16_t
family_
;
/// IPv4 or IPv6
/// @brief SocketInfo constructor.
///
/// @param sockfd socket descriptor
/// @param addr an address the socket is bound to
/// @param port a port the socket is bound to
SocketInfo
(
uint16_t
sockfd
,
const
isc
::
asiolink
::
IOAddress
&
addr
,
uint16_t
port
)
:
sockfd_
(
sockfd
),
addr_
(
addr
),
port_
(
port
),
family_
(
addr
.
getFamily
())
{
}
};
/// type that holds a list of socket informations
/// @todo: Add SocketCollectionConstIter type
typedef
std
::
list
<
SocketInfo
>
SocketCollection
;
...
...
src/lib/dhcp/iface_mgr_linux.cc
View file @
43fa9db5
...
...
@@ -499,18 +499,6 @@ IfaceMgr::isDirectResponseSupported() {
return
(
false
);
}
int
IfaceMgr
::
openSocket4
(
Iface
&
iface
,
const
IOAddress
&
addr
,
uint16_t
port
,
bool
receive_bcast
,
bool
send_bcast
)
{
int
sock
=
packet_filter_
->
openSocket
(
iface
,
addr
,
port
,
receive_bcast
,
send_bcast
);
Iface
::
SocketInfo
info
(
sock
,
addr
,
port
);
iface
.
addSocket
(
info
);
return
(
sock
);
}
/// @brief sets flag_*_ fields.
///
/// This implementation is OS-specific as bits have different meaning
...
...
@@ -527,105 +515,15 @@ void Iface::setFlags(uint32_t flags) {
flag_broadcast_
=
flags
&
IFF_BROADCAST
;
}
bool
IfaceMgr
::
send
(
const
Pkt4Ptr
&
pkt
)
{
Iface
*
iface
=
getIface
(
pkt
->
getIface
());
if
(
!
iface
)
{
isc_throw
(
BadValue
,
"Unable to send Pkt4. Invalid interface ("
<<
pkt
->
getIface
()
<<
") specified."
);
}
memset
(
&
control_buf_
[
0
],
0
,
control_buf_len_
);
// Set the target address we're sending to.
sockaddr_in
to
;
memset
(
&
to
,
0
,
sizeof
(
to
));
to
.
sin_family
=
AF_INET
;
to
.
sin_port
=
htons
(
pkt
->
getRemotePort
());
to
.
sin_addr
.
s_addr
=
htonl
(
pkt
->
getRemoteAddr
());
struct
msghdr
m
;
// Initialize our message header structure.
memset
(
&
m
,
0
,
sizeof
(
m
));
m
.
msg_name
=
&
to
;
m
.
msg_namelen
=
sizeof
(
to
);
// Set the data buffer we're sending. (Using this wacky
// "scatter-gather" stuff... we only have a single chunk
// of data to send, so we declare a single vector entry.)
struct
iovec
v
;
memset
(
&
v
,
0
,
sizeof
(
v
));
// iov_base field is of void * type. We use it for packet
// transmission, so this buffer will not be modified.
v
.
iov_base
=
const_cast
<
void
*>
(
pkt
->
getBuffer
().
getData
());
v
.
iov_len
=
pkt
->
getBuffer
().
getLength
();
m
.
msg_iov
=
&
v
;
m
.
msg_iovlen
=
1
;
// call OS-specific routines (like setting interface index)
os_send4
(
m
,
control_buf_
,
control_buf_len_
,
pkt
);
pkt
->
updateTimestamp
();
int
result
=
sendmsg
(
getSocket
(
*
pkt
),
&
m
,
0
);
if
(
result
<
0
)
{
isc_throw
(
SocketWriteError
,
"pkt4 send failed"
);
}
return
(
result
);
}
void
IfaceMgr
::
os_send4
(
struct
msghdr
&
,
boost
::
scoped_array
<
char
>&
,
size_t
,
const
Pkt4Ptr
&
)
{
return
;
void
IfaceMgr
::
os_send4
(
struct
msghdr
&
m
,
boost
::
scoped_array
<
char
>&
control_buf
,
size_t
control_buf_len
,
const
Pkt4Ptr
&
pkt
)
{
// Setting the interface is a bit more involved.
//
// We have to create a "control message", and set that to
// define the IPv4 packet information. We could set the
// source address if we wanted, but we can safely let the
// kernel decide what that should be.
m
.
msg_control
=
&
control_buf
[
0
];
m
.
msg_controllen
=
control_buf_len
;
struct
cmsghdr
*
cmsg
=
CMSG_FIRSTHDR
(
&
m
);
cmsg
->
cmsg_level
=
IPPROTO_IP
;
cmsg
->
cmsg_type
=
IP_PKTINFO
;
cmsg
->
cmsg_len
=
CMSG_LEN
(
sizeof
(
struct
in_pktinfo
));
struct
in_pktinfo
*
pktinfo
=
(
struct
in_pktinfo
*
)
CMSG_DATA
(
cmsg
);
memset
(
pktinfo
,
0
,
sizeof
(
struct
in_pktinfo
));
pktinfo
->
ipi_ifindex
=
pkt
->
getIndex
();
m
.
msg_controllen
=
cmsg
->
cmsg_len
;
}
bool
IfaceMgr
::
os_receive4
(
struct
msghdr
&
m
,
Pkt4Ptr
&
pkt
)
{
struct
cmsghdr
*
cmsg
;
struct
in_pktinfo
*
pktinfo
;
struct
in_addr
to_addr
;
memset
(
&
to_addr
,
0
,
sizeof
(
to_addr
));
cmsg
=
CMSG_FIRSTHDR
(
&
m
);
while
(
cmsg
!=
NULL
)
{
if
((
cmsg
->
cmsg_level
==
IPPROTO_IP
)
&&
(
cmsg
->
cmsg_type
==
IP_PKTINFO
))
{
pktinfo
=
(
struct
in_pktinfo
*
)
CMSG_DATA
(
cmsg
);
pkt
->
setIndex
(
pktinfo
->
ipi_ifindex
);
pkt
->
setLocalAddr
(
IOAddress
(
htonl
(
pktinfo
->
ipi_addr
.
s_addr
)));
return
(
true
);
// This field is useful, when we are bound to unicast
// address e.g. 192.0.2.1 and the packet was sent to
// broadcast. This will return broadcast address, not
// the address we are bound to.
// XXX: Perhaps we should uncomment this:
// to_addr = pktinfo->ipi_spec_dst;
}
cmsg
=
CMSG_NXTHDR
(
&
m
,
cmsg
);
}
return
(
false
);
bool
IfaceMgr
::
os_receive4
(
struct
msghdr
&
,
Pkt4Ptr
&
)
{
return
(
true
);
}
}
// end of isc::dhcp namespace
...
...
src/lib/dhcp/pkt_filter.h
View file @
43fa9db5
...
...
@@ -20,6 +20,8 @@
namespace
isc
{
namespace
dhcp
{
struct
SocketInfo
;
/// Forward declaration to the class representing interface
class
Iface
;
...
...
@@ -57,15 +59,20 @@ public:
/// @brief Receive packet over specified socket.
///
/// @param sockfd descriptor of a socket to be used for packet reception
/// @param timeout_sec integral part of a timeout.
/// @param timeout_usec fractional part of a timeout (in microseconds).
/// @param iface interface
/// @param socket_info structure holding socket information
///
/// @return Received packet
Pkt4Ptr
receive
(
uint16_t
sockfd
,
uint32_t
timeout_sec
,
uint32_t
timeout_usec
=
0
)
;
virtual
Pkt4Ptr
receive
(
const
Iface
&
iface
,
const
SocketInfo
&
socket_info
)
=
0
;
// bool send(const Pkt4Ptr& pkt) = 0;
/// @brief Send packet over specified socket.
///
/// @param sockfd socket descriptor
/// @param pkt packet to be sent
///
/// @return result of sending the packet. It is 0 if successful.
virtual
int
send
(
uint16_t
sockfd
,
const
Pkt4Ptr
&
pkt
)
=
0
;
};
}
// namespace isc::dhcp
...
...
src/lib/dhcp/pkt_filter_inet.cc
View file @
43fa9db5
...
...
@@ -17,9 +17,17 @@
#include <dhcp/pkt4.h>
#include <dhcp/pkt_filter_inet.h>
using
namespace
isc
::
asiolink
;
namespace
isc
{
namespace
dhcp
{
PktFilterInet
::
PktFilterInet
()
:
control_buf_len_
(
CMSG_SPACE
(
sizeof
(
struct
in6_pktinfo
))),
control_buf_
(
new
char
[
control_buf_len_
])
{
}
int
PktFilterInet
::
openSocket
(
const
Iface
&
iface
,
const
isc
::
asiolink
::
IOAddress
&
addr
,
...
...
@@ -77,10 +85,152 @@ PktFilterInet::openSocket(const Iface& iface,
}
#endif
return
sock
;
return
(
sock
)
;
}
Pkt4Ptr
PktFilterInet
::
receive
(
const
Iface
&
iface
,
const
SocketInfo
&
socket_info
)
{
struct
sockaddr_in
from_addr
;
uint8_t
buf
[
IfaceMgr
::
RCVBUFSIZE
];
memset
(
&
control_buf_
[
0
],
0
,
control_buf_len_
);
memset
(
&
from_addr
,
0
,
sizeof
(
from_addr
));
// Initialize our message header structure.
struct
msghdr
m
;
memset
(
&
m
,
0
,
sizeof
(
m
));
// Point so we can get the from address.
m
.
msg_name
=
&
from_addr
;
m
.
msg_namelen
=
sizeof
(
from_addr
);
struct
iovec
v
;
v
.
iov_base
=
static_cast
<
void
*>
(
buf
);
v
.
iov_len
=
IfaceMgr
::
RCVBUFSIZE
;
m
.
msg_iov
=
&
v
;
m
.
msg_iovlen
=
1
;
// Getting the interface is a bit more involved.
//
// We set up some space for a "control message". We have
// previously asked the kernel to give us packet
// information (when we initialized the interface), so we
// should get the destination address from that.
m
.
msg_control
=
&
control_buf_
[
0
];
m
.
msg_controllen
=
control_buf_len_
;
int
result
=
recvmsg
(
socket_info
.
sockfd_
,
&
m
,
0
);
if
(
result
<
0
)
{
isc_throw
(
SocketReadError
,
"failed to receive UDP4 data"
);
}
// We have all data let's create Pkt4 object.
Pkt4Ptr
pkt
=
Pkt4Ptr
(
new
Pkt4
(
buf
,
result
));
pkt
->
updateTimestamp
();
unsigned
int
ifindex
=
iface
.
getIndex
();
IOAddress
from
(
htonl
(
from_addr
.
sin_addr
.
s_addr
));
uint16_t
from_port
=
htons
(
from_addr
.
sin_port
);
// Set receiving interface based on information, which socket was used to
// receive data. OS-specific info (see os_receive4()) may be more reliable,
// so this value may be overwritten.
pkt
->
setIndex
(
ifindex
);
pkt
->
setIface
(
iface
.
getName
());
pkt
->
setRemoteAddr
(
from
);
pkt
->
setRemotePort
(
from_port
);
pkt
->
setLocalPort
(
socket_info
.
port_
);
struct
cmsghdr
*
cmsg
;
struct
in_pktinfo
*
pktinfo
;
struct
in_addr
to_addr
;
memset
(
&
to_addr
,
0
,
sizeof
(
to_addr
));
cmsg
=
CMSG_FIRSTHDR
(
&
m
);
while
(
cmsg
!=
NULL
)
{
if
((
cmsg
->
cmsg_level
==
IPPROTO_IP
)
&&
(
cmsg
->
cmsg_type
==
IP_PKTINFO
))
{
pktinfo
=
(
struct
in_pktinfo
*
)
CMSG_DATA
(
cmsg
);
pkt
->
setIndex
(
pktinfo
->
ipi_ifindex
);
pkt
->
setLocalAddr
(
IOAddress
(
htonl
(
pktinfo
->
ipi_addr
.
s_addr
)));
break
;
// This field is useful, when we are bound to unicast
// address e.g. 192.0.2.1 and the packet was sent to
// broadcast. This will return broadcast address, not
// the address we are bound to.
// XXX: Perhaps we should uncomment this:
// to_addr = pktinfo->ipi_spec_dst;
}
cmsg
=
CMSG_NXTHDR
(
&
m
,
cmsg
);
}
return
(
pkt
);
}
int
PktFilterInet
::
send
(
uint16_t
sockfd
,
const
Pkt4Ptr
&
pkt
)
{
memset
(
&
control_buf_
[
0
],
0
,
control_buf_len_
);
// Set the target address we're sending to.
sockaddr_in
to
;
memset
(
&
to
,
0
,
sizeof
(
to
));
to
.
sin_family
=
AF_INET
;
to
.
sin_port
=
htons
(
pkt
->
getRemotePort
());
to
.
sin_addr
.
s_addr
=
htonl
(
pkt
->
getRemoteAddr
());
struct
msghdr
m
;
// Initialize our message header structure.
memset
(
&
m
,
0
,
sizeof
(
m
));
m
.
msg_name
=
&
to
;
m
.
msg_namelen
=
sizeof
(
to
);
// Set the data buffer we're sending. (Using this wacky
// "scatter-gather" stuff... we only have a single chunk
// of data to send, so we declare a single vector entry.)
struct
iovec
v
;
memset
(
&
v
,
0
,
sizeof
(
v
));
// iov_base field is of void * type. We use it for packet
// transmission, so this buffer will not be modified.
v
.
iov_base
=
const_cast
<
void
*>
(
pkt
->
getBuffer
().
getData
());
v
.
iov_len
=
pkt
->
getBuffer
().
getLength
();
m
.
msg_iov
=
&
v
;
m
.
msg_iovlen
=
1
;
// Setting the interface is a bit more involved.
//
// We have to create a "control message", and set that to
// define the IPv4 packet information. We could set the
// source address if we wanted, but we can safely let the
// kernel decide what that should be.
m
.
msg_control
=
&
control_buf_
[
0
];
m
.
msg_controllen
=
control_buf_len_
;
struct
cmsghdr
*
cmsg
=
CMSG_FIRSTHDR
(
&
m
);
cmsg
->
cmsg_level
=
IPPROTO_IP
;
cmsg
->
cmsg_type
=
IP_PKTINFO
;
cmsg
->
cmsg_len
=
CMSG_LEN
(
sizeof
(
struct
in_pktinfo
));
struct
in_pktinfo
*
pktinfo
=
(
struct
in_pktinfo
*
)
CMSG_DATA
(
cmsg
);
memset
(
pktinfo
,
0
,
sizeof
(
struct
in_pktinfo
));
pktinfo
->
ipi_ifindex
=
pkt
->
getIndex
();
m
.
msg_controllen
=
cmsg
->
cmsg_len
;
pkt
->
updateTimestamp
();
int
result
=
sendmsg
(
sockfd
,
&
m
,
0
);
if
(
result
<
0
)
{
isc_throw
(
SocketWriteError
,
"pkt4 send failed"
);
}
return
(
result
);
}
}
// end of isc::dhcp namespace
}
// end of isc namespace
src/lib/dhcp/pkt_filter_inet.h
View file @
43fa9db5
...
...
@@ -27,6 +27,11 @@ namespace dhcp {
class
PktFilterInet
:
public
PktFilter
{
public:
/// @brief Constructor
///
/// Allocates control buffer.
PktFilterInet
();
/// @brief Open socket.
///
/// @param iface interface descriptor
...
...
@@ -44,15 +49,25 @@ public:
/// @brief Receive packet over specified socket.
///
/// @param sockfd descriptor of a socket to be used for packet reception
/// @param timeout_sec integral part of a timeout.
/// @param timeout_usec fractional part of a timeout (in microseconds).
/// @param iface interface
/// @param socket_info structure holding socket information
///
/// @return Received packet
Pkt4Ptr
receive
(
uint16_t
sockfd
,
uint32_t
timeout_sec
,
uint32_t
timeout_usec
=
0
);
virtual
Pkt4Ptr
receive
(
const
Iface
&
iface
,
const
SocketInfo
&
socket_info
);
/// @brief Send packet over specified socket.
///
/// @param sockfd socket descriptor
/// @param pkt packet to be sent
///
/// @return result of sending a packet. It is 0 if successful.
virtual
int
send
(
uint16_t
sockfd
,
const
Pkt4Ptr
&
pkt
);
// bool send(const Pkt4Ptr& pkt) = 0;
private:
/// Length of the control_buf_ array.
size_t
control_buf_len_
;
/// Control buffer, used in transmission and reception.
boost
::
scoped_array
<
char
>
control_buf_
;
};
}
// namespace isc::dhcp
...
...
src/lib/dhcp/tests/iface_mgr_unittest.cc
View file @
43fa9db5
...
...
@@ -863,14 +863,14 @@ TEST_F(IfaceMgrTest, iface_methods) {
TEST_F
(
IfaceMgrTest
,
socketInfo
)
{
// check that socketinfo for IPv4 socket is functional
Iface
::
SocketInfo
sock1
(
7
,
IOAddress
(
"192.0.2.56"
),
DHCP4_SERVER_PORT
+
7
);
SocketInfo
sock1
(
7
,
IOAddress
(
"192.0.2.56"
),
DHCP4_SERVER_PORT
+
7
);
EXPECT_EQ
(
7
,
sock1
.
sockfd_
);
EXPECT_EQ
(
"192.0.2.56"
,
sock1
.
addr_
.
toText
());
EXPECT_EQ
(
AF_INET
,
sock1
.
family_
);
EXPECT_EQ
(
DHCP4_SERVER_PORT
+
7
,
sock1
.
port_
);
// check that socketinfo for IPv6 socket is functional
Iface
::
SocketInfo
sock2
(
9
,
IOAddress
(
"2001:db8:1::56"
),
DHCP4_SERVER_PORT
+
9
);
SocketInfo
sock2
(
9
,
IOAddress
(
"2001:db8:1::56"
),
DHCP4_SERVER_PORT
+
9
);
EXPECT_EQ
(
9
,
sock2
.
sockfd_
);
EXPECT_EQ
(
"2001:db8:1::56"
,
sock2
.
addr_
.
toText
());
EXPECT_EQ
(
AF_INET6
,
sock2
.
family_
);
...
...
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