Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Kea
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Adam Osuchowski
Kea
Commits
84076d91
Commit
84076d91
authored
Mar 28, 2013
by
Marcin Siodelski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[991] Server responds with broadcast if direct response not supported.
parent
b59d780f
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
331 additions
and
244 deletions
+331
-244
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/dhcp4_srv.cc
+17
-1
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
+137
-188
src/lib/dhcp/iface_mgr.cc
src/lib/dhcp/iface_mgr.cc
+1
-51
src/lib/dhcp/iface_mgr.h
src/lib/dhcp/iface_mgr.h
+10
-0
src/lib/dhcp/iface_mgr_bsd.cc
src/lib/dhcp/iface_mgr_bsd.cc
+55
-1
src/lib/dhcp/iface_mgr_linux.cc
src/lib/dhcp/iface_mgr_linux.cc
+55
-1
src/lib/dhcp/iface_mgr_sun.cc
src/lib/dhcp/iface_mgr_sun.cc
+55
-1
src/lib/dhcp/tests/iface_mgr_unittest.cc
src/lib/dhcp/tests/iface_mgr_unittest.cc
+1
-1
No files found.
src/bin/dhcp4/dhcp4_srv.cc
View file @
84076d91
...
...
@@ -317,7 +317,7 @@ Dhcpv4Srv::writeServerID(const std::string& file_name) {
return
(
true
);
}
string
string
Dhcpv4Srv
::
srvidToString
(
const
OptionPtr
&
srvid
)
{
if
(
!
srvid
)
{
isc_throw
(
BadValue
,
"NULL pointer passed to srvidToString()"
);
...
...
@@ -517,6 +517,22 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
answer
->
setYiaddr
(
lease
->
addr_
);
// If remote address is not set, we are dealing with a directly
// connected client requesting new lease. We scan end response to
// the address assigned in the lease, but first we have to make sure
// that IfaceMgr supports responding directly to the client when
// client doesn't have address assigned to its interface yet.
if
(
answer
->
getRemoteAddr
().
toText
()
==
"0.0.0.0"
)
{
if
(
IfaceMgr
::
instance
().
isDirectResponseSupported
())
{
answer
->
setRemoteAddr
(
lease
->
addr_
);
}
else
{
// Since IfaceMgr does not support direct responses to
// clients not having IP address, we have to send response
// to broadcast.
answer
->
setRemoteAddr
(
IOAddress
(
"255.255.255.255"
));
}
}
// IP Address Lease time (type 51)
opt
=
OptionPtr
(
new
Option
(
Option
::
V4
,
DHO_DHCP_LEASE_TIME
));
opt
->
setUint32
(
lease
->
valid_lft_
);
...
...
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
View file @
84076d91
...
...
@@ -17,6 +17,7 @@
#include <asiolink/io_address.h>
#include <dhcp/dhcp4.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/option.h>
#include <dhcp/option4_addrlst.h>
#include <dhcp/option_custom.h>
...
...
@@ -345,6 +346,113 @@ public:
EXPECT_TRUE
(
expected_clientid
->
getData
()
==
opt
->
getData
());
}
/// @brief Tests if Discover or Request message is processed correctly
///
/// @param msg_type DHCPDISCOVER or DHCPREQUEST
/// @param client_addr client address
/// @param relay_addr relay address
void
testDiscoverRequest
(
const
uint8_t
msg_type
,
const
IOAddress
&
client_addr
,
const
IOAddress
&
relay_addr
)
{
NakedDhcpv4Srv
*
srv
=
new
NakedDhcpv4Srv
(
0
);
vector
<
uint8_t
>
mac
(
6
);
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
mac
[
i
]
=
i
*
10
;
}
boost
::
shared_ptr
<
Pkt4
>
req
(
new
Pkt4
(
msg_type
,
1234
));
boost
::
shared_ptr
<
Pkt4
>
rsp
;
req
->
setIface
(
"eth0"
);
req
->
setIndex
(
17
);
req
->
setHWAddr
(
1
,
6
,
mac
);
req
->
setRemoteAddr
(
IOAddress
(
client_addr
));
req
->
setGiaddr
(
relay_addr
);
// We are going to test that certain options are returned
// in the response message when requested using 'Parameter
// Request List' option. Let's configure those options that
// are returned when requested.
configureRequestedOptions
();
if
(
msg_type
==
DHCPDISCOVER
)
{
ASSERT_NO_THROW
(
rsp
=
srv
->
processDiscover
(
req
);
);
// Should return OFFER
ASSERT_TRUE
(
rsp
);
EXPECT_EQ
(
DHCPOFFER
,
rsp
->
getType
());
}
else
{
ASSERT_NO_THROW
(
rsp
=
srv
->
processRequest
(
req
);
);
// Should return ACK
ASSERT_TRUE
(
rsp
);
EXPECT_EQ
(
DHCPACK
,
rsp
->
getType
());
}
if
(
relay_addr
.
toText
()
!=
"0.0.0.0"
)
{
// This is relayed message. It should be sent brsp to relay address.
EXPECT_EQ
(
req
->
getGiaddr
().
toText
(),
rsp
->
getRemoteAddr
().
toText
());
}
else
if
(
client_addr
.
toText
()
!=
"0.0.0.0"
)
{
// This is a message from a client having an IP address.
EXPECT_EQ
(
req
->
getRemoteAddr
().
toText
(),
rsp
->
getRemoteAddr
().
toText
());
}
else
{
// This is a message from a client having no IP address yet.
// If IfaceMgr supports direct traffic the response should
// be sent to the new address assigned to the client.
if
(
IfaceMgr
::
instance
().
isDirectResponseSupported
())
{
EXPECT_EQ
(
rsp
->
getYiaddr
(),
rsp
->
getRemoteAddr
().
toText
());
// If direct response to the client having no IP address is
// not supported, response should go to broadcast.
}
else
{
EXPECT_EQ
(
"255.255.255.255"
,
rsp
->
getRemoteAddr
().
toText
());
}
}
messageCheck
(
req
,
rsp
);
// There are some options that are always present in the
// message, even if not requested.
EXPECT_TRUE
(
rsp
->
getOption
(
DHO_DOMAIN_NAME
));
EXPECT_TRUE
(
rsp
->
getOption
(
DHO_DOMAIN_NAME_SERVERS
));
// We did not request any options so these should not be present
// in the RSP.
EXPECT_FALSE
(
rsp
->
getOption
(
DHO_LOG_SERVERS
));
EXPECT_FALSE
(
rsp
->
getOption
(
DHO_COOKIE_SERVERS
));
EXPECT_FALSE
(
rsp
->
getOption
(
DHO_LPR_SERVERS
));
// Add 'Parameter Request List' option.
addPrlOption
(
req
);
// Repeat the test but request some options.
ASSERT_NO_THROW
(
rsp
=
srv
->
processRequest
(
req
);
);
// Should return something
ASSERT_TRUE
(
rsp
);
EXPECT_EQ
(
DHCPACK
,
rsp
->
getType
());
// Check that the requested options are returned.
optionsCheck
(
rsp
);
}
~
Dhcpv4SrvTest
()
{
CfgMgr
::
instance
().
deleteSubnets4
();
...
...
@@ -389,7 +497,7 @@ TEST_F(Dhcpv4SrvTest, basic) {
delete
naked_srv
;
}
// Verifies that
received DISCOVER
can be processed correctly,
// Verifies that
DISCOVER received via relay
can be processed correctly,
// that the OFFER message generated in response is valid and
// contains necessary options.
//
...
...
@@ -397,203 +505,44 @@ TEST_F(Dhcpv4SrvTest, basic) {
// are other tests that verify correctness of the allocation
// engine. See DiscoverBasic, DiscoverHint, DiscoverNoClientId
// and DiscoverInvalidHint.
TEST_F
(
Dhcpv4SrvTest
,
processDiscover
)
{
NakedDhcpv4Srv
*
srv
=
new
NakedDhcpv4Srv
(
0
);
vector
<
uint8_t
>
mac
(
6
);
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
mac
[
i
]
=
255
-
i
;
}
boost
::
shared_ptr
<
Pkt4
>
pkt
(
new
Pkt4
(
DHCPDISCOVER
,
1234
));
boost
::
shared_ptr
<
Pkt4
>
offer
;
pkt
->
setIface
(
"eth0"
);
pkt
->
setIndex
(
17
);
pkt
->
setHWAddr
(
1
,
6
,
mac
);
pkt
->
setRemoteAddr
(
IOAddress
(
"192.0.2.56"
));
pkt
->
setGiaddr
(
IOAddress
(
"192.0.2.67"
));
// Let's make it a relayed message
pkt
->
setHops
(
3
);
pkt
->
setRemotePort
(
DHCP4_SERVER_PORT
);
// We are going to test that certain options are returned
// (or not returned) in the OFFER message when requested
// using 'Parameter Request List' option. Let's configure
// those options that are returned when requested.
configureRequestedOptions
();
// Should not throw
EXPECT_NO_THROW
(
offer
=
srv
->
processDiscover
(
pkt
);
);
// Should return something
ASSERT_TRUE
(
offer
);
EXPECT_EQ
(
DHCPOFFER
,
offer
->
getType
());
// This is relayed message. It should be sent back to relay address.
EXPECT_EQ
(
pkt
->
getGiaddr
(),
offer
->
getRemoteAddr
());
messageCheck
(
pkt
,
offer
);
// There are some options that are always present in the
// message, even if not requested.
EXPECT_TRUE
(
offer
->
getOption
(
DHO_DOMAIN_NAME
));
EXPECT_TRUE
(
offer
->
getOption
(
DHO_DOMAIN_NAME_SERVERS
));
// We did not request any options so they should not be present
// in the OFFER.
EXPECT_FALSE
(
offer
->
getOption
(
DHO_LOG_SERVERS
));
EXPECT_FALSE
(
offer
->
getOption
(
DHO_COOKIE_SERVERS
));
EXPECT_FALSE
(
offer
->
getOption
(
DHO_LPR_SERVERS
));
// Add 'Parameter Request List' option.
addPrlOption
(
pkt
);
// Now repeat the test but request some options.
EXPECT_NO_THROW
(
offer
=
srv
->
processDiscover
(
pkt
);
);
// Should return something
ASSERT_TRUE
(
offer
);
EXPECT_EQ
(
DHCPOFFER
,
offer
->
getType
());
// This is relayed message. It should be sent back to relay address.
EXPECT_EQ
(
pkt
->
getGiaddr
(),
offer
->
getRemoteAddr
());
messageCheck
(
pkt
,
offer
);
// Check that the requested options are returned.
optionsCheck
(
offer
);
// Now repeat the test for directly sent message
pkt
->
setHops
(
0
);
pkt
->
setGiaddr
(
IOAddress
(
"0.0.0.0"
));
pkt
->
setRemotePort
(
DHCP4_CLIENT_PORT
);
EXPECT_NO_THROW
(
offer
=
srv
->
processDiscover
(
pkt
);
);
// Should return something
ASSERT_TRUE
(
offer
);
EXPECT_EQ
(
DHCPOFFER
,
offer
->
getType
());
// This is direct message. It should be sent back to origin, not
// to relay.
EXPECT_EQ
(
pkt
->
getRemoteAddr
(),
offer
->
getRemoteAddr
());
messageCheck
(
pkt
,
offer
);
TEST_F
(
Dhcpv4SrvTest
,
processDiscoverRelay
)
{
testDiscoverRequest
(
DHCPDISCOVER
,
IOAddress
(
"192.0.2.56"
),
IOAddress
(
"192.0.2.67"
));
}
// Check that the requested options are returned.
optionsCheck
(
offer
);
// Verifies that the non-relayed DISCOVER is processed correctly when
// client source address is specified.
TEST_F
(
Dhcpv4SrvTest
,
processDiscoverNoRelay
)
{
testDiscoverRequest
(
DHCPDISCOVER
,
IOAddress
(
"0.0.0.0"
),
IOAddress
(
"192.0.2.67"
));
}
delete
srv
;
// Verified that the non-relayed DISCOVER is processed correctly when
// client source address is not specified.
TEST_F
(
Dhcpv4SrvTest
,
processDiscoverNoClientAddr
)
{
testDiscoverRequest
(
DHCPDISCOVER
,
IOAddress
(
"0.0.0.0"
),
IOAddress
(
"0.0.0.0"
));
}
// Verifies that
received REQUEST
can be processed correctly,
// that the
ACK
message generated in response is valid and
// Verifies that
REQUEST received via relay
can be processed correctly,
// that the
OFFER
message generated in response is valid and
// contains necessary options.
//
// Note: this test focuses on the packet correctness. There
// are other tests that verify correctness of the allocation
// engine. See RequestBasic.
TEST_F
(
Dhcpv4SrvTest
,
processRequest
)
{
NakedDhcpv4Srv
*
srv
=
new
NakedDhcpv4Srv
(
0
);
vector
<
uint8_t
>
mac
(
6
);
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
mac
[
i
]
=
i
*
10
;
}
boost
::
shared_ptr
<
Pkt4
>
req
(
new
Pkt4
(
DHCPREQUEST
,
1234
));
boost
::
shared_ptr
<
Pkt4
>
ack
;
req
->
setIface
(
"eth0"
);
req
->
setIndex
(
17
);
req
->
setHWAddr
(
1
,
6
,
mac
);
req
->
setRemoteAddr
(
IOAddress
(
"192.0.2.56"
));
req
->
setGiaddr
(
IOAddress
(
"192.0.2.67"
));
// We are going to test that certain options are returned
// in the ACK message when requested using 'Parameter
// Request List' option. Let's configure those options that
// are returned when requested.
configureRequestedOptions
();
// Should not throw
ASSERT_NO_THROW
(
ack
=
srv
->
processRequest
(
req
);
);
// Should return something
ASSERT_TRUE
(
ack
);
EXPECT_EQ
(
DHCPACK
,
ack
->
getType
());
// This is relayed message. It should be sent back to relay address.
EXPECT_EQ
(
req
->
getGiaddr
(),
ack
->
getRemoteAddr
());
messageCheck
(
req
,
ack
);
// There are some options that are always present in the
// message, even if not requested.
EXPECT_TRUE
(
ack
->
getOption
(
DHO_DOMAIN_NAME
));
EXPECT_TRUE
(
ack
->
getOption
(
DHO_DOMAIN_NAME_SERVERS
));
// We did not request any options so these should not be present
// in the ACK.
EXPECT_FALSE
(
ack
->
getOption
(
DHO_LOG_SERVERS
));
EXPECT_FALSE
(
ack
->
getOption
(
DHO_COOKIE_SERVERS
));
EXPECT_FALSE
(
ack
->
getOption
(
DHO_LPR_SERVERS
));
// Add 'Parameter Request List' option.
addPrlOption
(
req
);
// Repeat the test but request some options.
ASSERT_NO_THROW
(
ack
=
srv
->
processRequest
(
req
);
);
// Should return something
ASSERT_TRUE
(
ack
);
EXPECT_EQ
(
DHCPACK
,
ack
->
getType
());
// This is relayed message. It should be sent back to relay address.
EXPECT_EQ
(
req
->
getGiaddr
(),
ack
->
getRemoteAddr
());
// Check that the requested options are returned.
optionsCheck
(
ack
);
// Now repeat the test for directly sent message
req
->
setHops
(
0
);
req
->
setGiaddr
(
IOAddress
(
"0.0.0.0"
));
req
->
setRemotePort
(
DHCP4_CLIENT_PORT
);
EXPECT_NO_THROW
(
ack
=
srv
->
processDiscover
(
req
);
);
// Should return something
ASSERT_TRUE
(
ack
);
EXPECT_EQ
(
DHCPOFFER
,
ack
->
getType
());
// This is direct message. It should be sent back to origin, not
// to relay.
EXPECT_EQ
(
ack
->
getRemoteAddr
(),
req
->
getRemoteAddr
());
messageCheck
(
req
,
ack
);
// engine. See DiscoverBasic, DiscoverHint, DiscoverNoClientId
// and DiscoverInvalidHint.
TEST_F
(
Dhcpv4SrvTest
,
processRequestRelay
)
{
testDiscoverRequest
(
DHCPREQUEST
,
IOAddress
(
"192.0.2.56"
),
IOAddress
(
"192.0.2.67"
));
}
// Check that the requested options are returned.
optionsCheck
(
ack
);
// Verifies that the non-relayed REQUEST is processed correctly when
// client source address is specified.
TEST_F
(
Dhcpv4SrvTest
,
processRequestNoRelay
)
{
testDiscoverRequest
(
DHCPREQUEST
,
IOAddress
(
"0.0.0.0"
),
IOAddress
(
"192.0.2.67"
));
}
delete
srv
;
// Verified that the non-relayed REQUEST is processed correctly when
// client source address is not specified.
TEST_F
(
Dhcpv4SrvTest
,
processRequestNoClientAddr
)
{
testDiscoverRequest
(
DHCPREQUEST
,
IOAddress
(
"0.0.0.0"
),
IOAddress
(
"0.0.0.0"
));
}
TEST_F
(
Dhcpv4SrvTest
,
processRelease
)
{
...
...
src/lib/dhcp/iface_mgr.cc
View file @
84076d91
// Copyright (C) 2011-201
2
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-201
3
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
...
...
@@ -721,56 +721,6 @@ 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."
);
}
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
);
}
boost
::
shared_ptr
<
Pkt4
>
IfaceMgr
::
receive4
(
uint32_t
timeout_sec
,
uint32_t
timeout_usec
/* = 0 */
)
{
...
...
src/lib/dhcp/iface_mgr.h
View file @
84076d91
...
...
@@ -306,6 +306,16 @@ public:
/// @return the only existing instance of interface manager
static
IfaceMgr
&
instance
();
/// @brief Can be packet can be send directly to the client without address.
///
/// Checks if IfaceMgr can send DHCPv4 packet to the client
/// who hasn't got address assigned. If this is not supported
/// broadcast address should be used to send response to
/// the client.
///
/// @return true if direct response is supported.
bool
isDirectResponseSupported
();
/// @brief Returns interface with specified interface index
///
/// @param ifindex index of searched interface
...
...
src/lib/dhcp/iface_mgr_bsd.cc
View file @
84076d91
// Copyright (C) 2011
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011
, 2013
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
...
...
@@ -34,6 +34,60 @@ IfaceMgr::detectIfaces() {
stubDetectIfaces
();
}
bool
IfaceMgr
::
isDirectResponseSupported
()
{
return
(
false
);
}
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
&
/*m*/
,
boost
::
scoped_array
<
char
>&
/*control_buf*/
,
size_t
/*control_buf_len*/
,
...
...
src/lib/dhcp/iface_mgr_linux.cc
View file @
84076d91
// Copyright (C) 2011-201
2
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-201
3
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
...
...
@@ -494,6 +494,11 @@ void IfaceMgr::detectIfaces() {
nl
.
release_list
(
addr_info
);
}
bool
IfaceMgr
::
isDirectResponseSupported
()
{
return
(
false
);
}
/// @brief sets flag_*_ fields.
///
/// This implementation is OS-specific as bits have different meaning
...
...
@@ -510,6 +515,55 @@ void IfaceMgr::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
&
m
,
boost
::
scoped_array
<
char
>&
control_buf
,
size_t
control_buf_len
,
const
Pkt4Ptr
&
pkt
)
{
...
...
src/lib/dhcp/iface_mgr_sun.cc
View file @