Pkt4Ptr query = ex.getQuery();
if (local_addr.isV4Bcast() || query->isDhcp4o6()) {
- SocketInfo sock_info = IfaceMgr::instance().getSocket(*query);
- local_addr = sock_info.addr_;
+ local_addr = IfaceMgr::instance().getSocket(query).addr_;
}
OptionPtr opt_srvid(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER,
// use this address as a source address for the response.
// Do the same for DHCPv4-over-DHCPv6 exchanges.
if (local_addr.isV4Bcast() || query->isDhcp4o6()) {
- SocketInfo sock_info = IfaceMgr::instance().getSocket(*query);
- local_addr = sock_info.addr_;
+ local_addr = IfaceMgr::instance().getSocket(query).addr_;
}
// We assume that there is an appropriate socket bound to this address
-// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
#include <dhcp/option.h>
#include <dhcp/option_int_array.h>
#include <dhcp/option_vendor.h>
+#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcpsrv/lease.h>
#include <dhcp4/tests/dhcp4_client.h>
#include <util/range_utilities.h>
Dhcp4Client::Configuration::Configuration()
: routers_(), dns_servers_(), log_servers_(), quotes_servers_(),
- serverid_("0.0.0.0"), siaddr_(asiolink::IOAddress::IPV4_ZERO_ADDRESS()) {
+ serverid_("0.0.0.0"), siaddr_(IOAddress::IPV4_ZERO_ADDRESS()) {
reset();
}
dns_servers_.clear();
log_servers_.clear();
quotes_servers_.clear();
- serverid_ = asiolink::IOAddress("0.0.0.0");
- siaddr_ = asiolink::IOAddress::IPV4_ZERO_ADDRESS();
+ serverid_ = IOAddress("0.0.0.0");
+ siaddr_ = IOAddress::IPV4_ZERO_ADDRESS();
sname_.clear();
boot_file_name_.clear();
lease_ = Lease4();
hwaddr_(generateHWAddr()),
clientid_(),
iface_name_("eth0"),
+ iface_index_(ETH0_INDEX),
relay_addr_("192.0.2.2"),
requested_options_(),
server_facing_relay_addr_("10.0.0.2"),
hwaddr_(generateHWAddr()),
clientid_(),
iface_name_("eth0"),
+ iface_index_(ETH0_INDEX),
relay_addr_("192.0.2.2"),
requested_options_(),
server_facing_relay_addr_("10.0.0.2"),
}
void
-Dhcp4Client::addRequestedAddress(const asiolink::IOAddress& addr) {
+Dhcp4Client::addRequestedAddress(const IOAddress& addr) {
if (context_.query_) {
Option4AddrLstPtr opt(new Option4AddrLst(DHO_DHCP_REQUESTED_ADDRESS,
addr));
}
void
-Dhcp4Client::createLease(const asiolink::IOAddress& addr,
- const uint32_t valid_lft) {
+Dhcp4Client::createLease(const IOAddress& addr, const uint32_t valid_lft) {
Lease4 lease(addr, hwaddr_, 0, 0, valid_lft,
time(NULL), 0, false, false, "");
config_.lease_ = lease;
msg_copy->setRemoteAddr(msg->getLocalAddr());
msg_copy->setLocalAddr(dest_addr_);
msg_copy->setIface(iface_name_);
+ msg_copy->setIndex(iface_index_);
// Copy classes
const ClientClasses& classes = msg->getClasses();
for (ClientClasses::const_iterator cclass = classes.cbegin();
-// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
iface_name_ = iface_name;
}
+ /// @brief Sets the interface over which the messages should be sent.
+ ///
+ /// @param iface_index Index of the interface over which the
+ /// messages should be sent.
+ void setIfaceIndex(uint32_t iface_index) {
+ iface_index_ = iface_index;
+ }
+
/// @brief Sets client state.
///
/// Depending on the current state the client's behavior is different
/// @brief Current client identifier.
ClientIdPtr clientid_;
- /// @brief Interface to be used to send the messages.
+ /// @brief Interface to be used to send the messages (name).
std::string iface_name_;
+ /// @brief Interface to be used to send the messages (index).
+ uint32_t iface_index_;
+
/// @brief Relay address to use.
asiolink::IOAddress relay_addr_;
req->setLocalAddr(IOAddress("192.0.2.5"));
req->setLocalPort(1001);
req->setIface("eth1");
- req->setIndex(1);
+ req->setIndex(ETH1_INDEX);
// Set remote port (it will be used in the next test).
req->setRemotePort(1234);
// We will send response over the same interface which was used to receive
// query.
EXPECT_EQ("eth1", resp->getIface());
- EXPECT_EQ(1, resp->getIndex());
+ EXPECT_EQ(ETH1_INDEX, resp->getIndex());
// Let's do another test and set other fields: ciaddr and
// flags. By doing it, we want to make sure that the relay
req->setLocalAddr(IOAddress("192.0.2.5"));
req->setLocalPort(1001);
req->setIface("eth1");
- req->setIndex(1);
+ req->setIndex(ETH1_INDEX);
// Set remote port.
req->setRemotePort(1234);
// We will send response over the same interface which was used to receive
// query.
EXPECT_EQ("eth1", resp->getIface());
- EXPECT_EQ(1, resp->getIndex());
+ EXPECT_EQ(ETH1_INDEX, resp->getIndex());
}
// This test verifies that it is possible to configure the server to use
req->setLocalAddr(IOAddress("192.0.2.5"));
req->setLocalPort(1001);
req->setIface("eth1");
- req->setIndex(1);
+ req->setIndex(ETH1_INDEX);
// Create the exchange using the req.
Dhcpv4Exchange ex = createExchange(req);
EXPECT_EQ("192.0.2.5", resp->getLocalAddr().toText());
EXPECT_EQ("eth1", resp->getIface());
- EXPECT_EQ(1, resp->getIndex());
+ EXPECT_EQ(ETH1_INDEX, resp->getIndex());
}
// This test verifies that the destination address of the response
req->setLocalAddr(IOAddress("192.0.2.5"));
req->setLocalPort(1001);
req->setIface("eth1");
- req->setIndex(1);
+ req->setIndex(ETH1_INDEX);
// Set remote address and port.
req->setRemoteAddr(IOAddress("192.0.2.1"));
req->setLocalPort(DHCP4_SERVER_PORT);
// Set the interface. The response should be sent over the same interface.
req->setIface("eth1");
- req->setIndex(1);
+ req->setIndex(ETH1_INDEX);
// Create the exchange using the req.
Dhcpv4Exchange ex = createExchange(req);
EXPECT_EQ(DHCP4_SERVER_PORT, resp->getLocalPort());
// The interface data should match the data in the query.
EXPECT_EQ("eth1", resp->getIface());
- EXPECT_EQ(1, resp->getIndex());
-
+ EXPECT_EQ(ETH1_INDEX, resp->getIndex());
}
// This test verifies that the destination address of the response message
req->setLocalPort(DHCP4_SERVER_PORT);
// Set the interface. The response should be sent over the same interface.
req->setIface("eth1");
- req->setIndex(1);
+ req->setIndex(ETH1_INDEX);
// Set remote address.
req->setRemoteAddr(IOAddress("192.0.2.1"));
req->setLocalPort(DHCP4_SERVER_PORT);
// Set the interface. The response should be sent via the same interface.
req->setIface("eth1");
- req->setIndex(1);
+ req->setIndex(ETH1_INDEX);
// Create the exchange using the req.
Dhcpv4Exchange ex = createExchange(req);
resp->setHops(req->getHops());
// We want to test the case, when the server (packet filter) doesn't support
- // ddirect responses to the client which doesn't have an address yet. In
+ // direct responses to the client which doesn't have an address yet. In
// case, the server should send its response to the broadcast address.
// We can control whether the current packet filter returns that its support
// direct responses or not.
// The response should be sent via the same interface through which
// query has been received.
EXPECT_EQ("eth1", resp->getIface());
- EXPECT_EQ(1, resp->getIndex());
+ EXPECT_EQ(ETH1_INDEX, resp->getIndex());
// We also want to test the case when the server has capability to
// respond directly to the client which is not configured. Server
req->setLocalPort(DHCP4_SERVER_PORT);
// Set the interface. The response should be sent via the same interface.
req->setIface("eth1");
- req->setIndex(1);
+ req->setIndex(ETH1_INDEX);
// Set remote address.
req->setRemoteAddr(IOAddress("192.0.2.1"));
req->setLocalPort(DHCP4_SERVER_PORT);
// Set the interface. The response should be sent via the same interface.
req->setIface("eth1");
- req->setIndex(1);
+ req->setIndex(ETH1_INDEX);
// Let's set the broadcast flag.
req->setFlags(Pkt4::FLAG_BROADCAST_MASK);
// The response should be sent via the same interface through which
// query has been received.
EXPECT_EQ("eth1", resp->getIface());
- EXPECT_EQ(1, resp->getIndex());
+ EXPECT_EQ(ETH1_INDEX, resp->getIndex());
}
req->setLocalPort(DHCP4_SERVER_PORT);
// Set the interface. The response should be sent via the same interface.
req->setIface("eth1");
- req->setIndex(1);
+ req->setIndex(ETH1_INDEX);
// Set remote address.
req->setRemoteAddr(IOAddress("192.0.2.1"));
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
// Pass it to the server and get an offer
Pkt4Ptr offer = srv->processDiscover(dis);
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
// Add dhcp-lease-time option.
if (test.hint) {
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
// Iterate over the test scenarios.
for (auto test = tests.begin(); test != tests.end(); ++test) {
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
// Iterate over the test scenarios.
for (auto test = tests.begin(); test != tests.end(); ++test) {
dis->addOption(clientid);
dis->setYiaddr(hint);
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
// Pass it to the server and get an offer
Pkt4Ptr offer = srv->processDiscover(dis);
// Assign interfaces
dis1->setIface("eth1");
+ dis1->setIndex(ETH1_INDEX);
dis2->setIface("eth1");
+ dis2->setIndex(ETH1_INDEX);
dis3->setIface("eth1");
+ dis3->setIndex(ETH1_INDEX);
// Different client-id sizes
OptionPtr clientid1 = generateClientId(4); // length 4
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
// Pass it to the server and get an offer
Pkt4Ptr offer = srv.processDiscover(dis);
OptionPtr clientid = generateClientId();
req->addOption(clientid);
req->setIface("eth1");
+ req->setIndex(ETH1_INDEX);
// Recreate a subnet but set T1 and T2 to "unspecified".
subnet_.reset(new Subnet4(IOAddress("192.0.2.0"), 24,
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
// Pass it to the server and get ACK
Pkt4Ptr ack = srv.processRequest(dis);
req->setYiaddr(addr);
req->setCiaddr(addr); // client's address
req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
req->setHWAddr(hwaddr2);
req->addOption(clientid);
c.req->setYiaddr(c.addr);
c.req->setCiaddr(c.addr); // client's address
c.req->setIface("eth0");
+ c.req->setIndex(ETH0_INDEX);
c.req->setHWAddr(c.hwaddr);
c.req->addOption(c.clientid);
dis->addOption(clientid);
dis->setYiaddr(hint);
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
// Pass it to the server and get an offer
Pkt4Ptr offer = srv->processDiscover(dis);
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
dis->setRemoteAddr(IOAddress("192.0.2.1"));
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
dis->setRemoteAddr(IOAddress("192.0.2.1"));
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
dis->setRemoteAddr(IOAddress("192.0.2.1"));
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
EXPECT_EQ(0, std::memcmp(filename_buf, &offer->getFile()[0], Pkt4::MAX_FILE_LEN));
}
-
-
// Checks if client packets are classified properly using match expressions.
TEST_F(Dhcpv4SrvTest, matchClassification) {
IfaceMgrTestConfig test_config(true);
query1->setRemoteAddr(IOAddress("192.0.2.1"));
query1->addOption(clientid);
query1->setIface("eth1");
+ query1->setIndex(ETH1_INDEX);
Pkt4Ptr query2(new Pkt4(DHCPDISCOVER, 1234));
query2->setRemoteAddr(IOAddress("192.0.2.1"));
query2->addOption(clientid);
query2->setIface("eth1");
+ query2->setIndex(ETH1_INDEX);
Pkt4Ptr query3(new Pkt4(DHCPDISCOVER, 1234));
query3->setRemoteAddr(IOAddress("192.0.2.1"));
query3->addOption(clientid);
query3->setIface("eth1");
+ query3->setIndex(ETH1_INDEX);
// Create and add a PRL option to the first 2 queries
OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a PRL option to the query
OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a PRL option to the query
OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a PRL option to the query
OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Do not add a PRL
OptionPtr prl = query->getOption(DHO_DHCP_PARAMETER_REQUEST_LIST);
dis->setRemoteAddr(IOAddress("192.0.2.1"));
dis->setCiaddr(IOAddress("192.0.2.1"));
dis->setIface("eth0");
+ dis->setIndex(ETH0_INDEX);
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
dis->setRemoteAddr(IOAddress("192.0.2.1"));
dis->setCiaddr(IOAddress("192.0.2.1"));
dis->setIface("eth0");
+ dis->setIndex(ETH0_INDEX);
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
dis->setRemoteAddr(IOAddress("192.0.2.1"));
dis->setCiaddr(IOAddress("192.0.2.1"));
dis->setIface("eth0");
+ dis->setIndex(ETH0_INDEX);
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
dis->setRemoteAddr(IOAddress("192.0.2.1"));
dis->setCiaddr(IOAddress("192.0.2.1"));
dis->setIface("eth0");
+ dis->setIndex(ETH0_INDEX);
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a private option with code 234
OptionBuffer buf;
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a PRL option for another option
OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
dis->setRemoteAddr(IOAddress("192.0.2.1"));
dis->setIface("eth0");
+ dis->setIndex(ETH0_INDEX);
dis->setHops(1);
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
dis->setRemoteAddr(IOAddress("192.0.2.1"));
dis->setIface("eth0");
+ dis->setIndex(ETH0_INDEX);
dis->setHops(1);
dis->setGiaddr(IOAddress("192.0.5.1"));
OptionPtr clientid = generateClientId();
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
dis->setRemoteAddr(IOAddress("192.0.2.1"));
dis->setIface("eth0");
+ dis->setIndex(ETH0_INDEX);
dis->setHops(1);
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
dis->setRemoteAddr(IOAddress("192.0.2.1"));
dis->setIface("eth0");
+ dis->setIndex(ETH0_INDEX);
dis->setHops(1);
OptionPtr clientid = generateClientId();
dis->addOption(clientid);
pkt->setRemoteAddr(IOAddress("0.0.0.0"));
pkt->setLocalAddr(IOAddress("192.0.2.3"));
pkt->setIface("eth1");
+ pkt->setIndex(ETH1_INDEX);
EXPECT_TRUE(srv.accept(pkt));
// Let's set hops and check that the message is still accepted as
// For eth0, there is no subnet configured. Such message is expected
// to be silently dropped.
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
EXPECT_FALSE(srv.accept(pkt));
// But, if the message is unicast it should be accepted, even though
-// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
boost::shared_ptr<Pkt4> rsp;
// Set the name of the interface on which packet is received.
req->setIface("eth0");
- // Set the interface index. It is just a dummy value and will
- // not be interpreted.
- req->setIndex(17);
+ // Set the interface index.
+ req->setIndex(ETH0_INDEX);
// Set the target HW address. This value is normally used to
// construct the data link layer header.
req->setRemoteHWAddr(1, 6, dst_mac);
ASSERT_TRUE(createPacketFromBuffer(req, received));
// Set interface. It is required for the server to generate server id.
received->setIface("eth0");
+ received->setIndex(ETH0_INDEX);
if (msg_type == DHCPDISCOVER) {
ASSERT_NO_THROW(
rsp = srv->processDiscover(received);
// Set interface. It is required for the server to generate server id.
received->setIface("eth0");
+ received->setIndex(ETH0_INDEX);
if (msg_type == DHCPDISCOVER) {
ASSERT_NO_THROW(rsp = srv->processDiscover(received));
// Set interface. It is required for the server to generate server id.
received->setIface("eth0");
+ received->setIndex(ETH0_INDEX);
if (msg_type == DHCPDISCOVER) {
ASSERT_NO_THROW(rsp = srv->processDiscover(received));
Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234));
pkt->addOption(createDHCPv4MsgOption());
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
ASSERT_NO_THROW(pkt->pack());
Pkt6Ptr pkt6_received = pkt_received->getPkt6();
ASSERT_TRUE(pkt6_received);
EXPECT_EQ("eth0", pkt6_received->getIface());
+ EXPECT_EQ(ETH0_INDEX, pkt6_received->getIndex());
EXPECT_EQ("2001:db8:1::123", pkt6_received->getRemoteAddr().toText());
// Both DHCP4o6 and encapsulated DHCPv6 packet should have the
pkt->addOption(createDHCPv4MsgOption());
pkt->addOption(createDHCPv4MsgOption());
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
ASSERT_NO_THROW(pkt->pack());
// Create message to be sent over IPC without DHCPv4 query option.
Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234));
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
ASSERT_NO_THROW(pkt->pack());
Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234));
pkt->addOption(opt_msg);
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
ASSERT_NO_THROW(pkt->pack());
Pkt6Ptr pkt6_received = pkt_received->getPkt6();
ASSERT_TRUE(pkt6_received);
EXPECT_EQ("eth0", pkt6_received->getIface());
+ EXPECT_EQ(ETH0_INDEX, pkt6_received->getIndex());
EXPECT_EQ("2001:db8:1::123", pkt6_received->getRemoteAddr().toText());
// Make sure that the message has been processed.
ASSERT_TRUE(pkt6_sent);
EXPECT_EQ(DHCPV6_DHCPV4_RESPONSE, pkt6_sent->getType());
EXPECT_EQ("eth0", pkt6_sent->getIface());
+ EXPECT_EQ(ETH0_INDEX, pkt6_sent->getIndex());
EXPECT_EQ("2001:db8:1::123", pkt6_sent->getRemoteAddr().toText());
// Both DHCP4o6 and encapsulated DHCPv6 packet should have the
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
/// @param msg_type Type of the message to be created.
/// @param iface Name of the interface on which the message has been
/// "received" by the server.
+ /// @param ifindex Index of the interface on which the message has been
+ /// "received" by the server.
///
/// @return Generated message.
Pkt4Ptr createClientMessage(const uint16_t msg_type,
- const std::string& iface);
+ const std::string& iface,
+ const uint32_t ifindex);
/// @brief Creates simple message from a client.
///
/// not be NULL.
/// @param iface Name of the interface on which the message has been
/// "received" by the server.
+ /// @param ifindex Index of the interface on which the message has been
+ /// "received" by the server.
///
/// @return Configured and parsed message.
- Pkt4Ptr createClientMessage(const Pkt4Ptr &msg, const std::string& iface);
+ Pkt4Ptr createClientMessage(const Pkt4Ptr &msg,
+ const std::string& iface,
+ const uint32_t ifindex);
/// @brief classes the client belongs to
///
}
Pkt4Ptr
-DirectClientTest:: createClientMessage(const uint16_t msg_type,
- const std::string& iface) {
+DirectClientTest::createClientMessage(const uint16_t msg_type,
+ const std::string& iface,
+ const uint32_t ifindex) {
// Create a source packet.
Pkt4Ptr msg = Pkt4Ptr(new Pkt4(msg_type, 1234));
- return (createClientMessage(msg, iface));
+ return (createClientMessage(msg, iface, ifindex));
}
Pkt4Ptr
DirectClientTest::createClientMessage(const Pkt4Ptr& msg,
- const std::string& iface) {
+ const std::string& iface,
+ const uint32_t ifindex) {
msg->setRemoteAddr(IOAddress("255.255.255.255"));
msg->addOption(generateClientId());
msg->setIface(iface);
+ msg->setIndex(ifindex);
// Create copy of this packet by parsing its wire data. Make sure that the
// local and remote address are set like it was a message sent from the
Pkt4Ptr received;
createPacketFromBuffer(msg, received);
received->setIface(iface);
+ received->setIndex(ifindex);
received->setLocalAddr(IOAddress("255.255.255.255"));
received->setRemoteAddr(IOAddress("0.0.0.0"));
// address on eth1 belongs to the first subnet.
ASSERT_NO_FATAL_FAILURE(configureTwoSubnets("192.0.2.0", "10.0.0.0"));
// Create Discover and simulate reception of this message through eth0.
- Pkt4Ptr dis = createClientMessage(DHCPDISCOVER, "eth0");
+ Pkt4Ptr dis = createClientMessage(DHCPDISCOVER, "eth0", ETH0_INDEX);
srv_.fakeReceive(dis);
// Create Request and simulate reception of this message through eth1.
- Pkt4Ptr req = createClientMessage(DHCPREQUEST, "eth1");
+ Pkt4Ptr req = createClientMessage(DHCPREQUEST, "eth1", ETH1_INDEX);
srv_.fakeReceive(req);
// Process clients' messages.
// connected client is received through interface eth0.
ASSERT_NO_FATAL_FAILURE(configureSubnet("10.0.0.0"));
// Create Discover and simulate reception of this message through eth0.
- Pkt4Ptr dis = createClientMessage(DHCPDISCOVER, "eth0");
+ Pkt4Ptr dis = createClientMessage(DHCPDISCOVER, "eth0", ETH0_INDEX);
srv_.fakeReceive(dis);
// Create Request and simulate reception of this message through eth1.
- Pkt4Ptr req = createClientMessage(DHCPDISCOVER, "eth1");
+ Pkt4Ptr req = createClientMessage(DHCPDISCOVER, "eth1", ETH1_INDEX);
srv_.fakeReceive(req);
// Process clients' messages.
// Broadcast Request through an interface for which there is no subnet
// configured. This message should be discarded by the server.
client.setIfaceName("eth1");
+ client.setIfaceIndex(ETH1_INDEX);
ASSERT_NO_THROW(client.doRequest());
EXPECT_FALSE(client.getContext().response_);
// Send Rebind over the correct interface, and make sure we have obtained
// the same address.
client.setIfaceName("eth0");
+ client.setIfaceIndex(ETH0_INDEX);
ASSERT_NO_THROW(client.doRequest());
ASSERT_TRUE(client.getContext().response_);
EXPECT_EQ(DHCPACK, static_cast<int>(client.getContext().response_->getType()));
// Repeat the test for different subnet.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setIfaceName("eth1");
+ client2.setIfaceIndex(ETH1_INDEX);
ASSERT_NO_THROW(client2.doDORA());
ASSERT_TRUE(client2.getContext().response_);
Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(msg_type, 1234));
pkt->setRemoteAddr(IOAddress("192.0.2.3"));
pkt->setIface("eth1");
+ pkt->setIndex(ETH1_INDEX);
// For DISCOVER we don't include server id, because client broadcasts
// the message to all servers.
if (msg_type != DHCPDISCOVER) {
// Set interface for the incoming packet. The server requires it to
// generate client id.
req->setIface("eth1");
+ req->setIndex(ETH1_INDEX);
Pkt4Ptr reply;
ASSERT_NO_THROW(reply = srv_->processRequest(req));
// Set interface for the incoming packet. The server requires it to
// generate client id.
req1->setIface("eth1");
-
+ req1->setIndex(ETH1_INDEX);
Pkt4Ptr reply;
ASSERT_NO_THROW(reply = srv_->processRequest(req1));
// Set interface for the incoming packet. The server requires it to
// generate client id.
req2->setIface("eth1");
+ req2->setIndex(ETH1_INDEX);
ASSERT_NO_THROW(reply = srv_->processRequest(req2));
// Set interface for the incoming packet. The server requires it to
// generate client id.
req1->setIface("eth1");
+ req1->setIndex(ETH1_INDEX);
Pkt4Ptr reply;
ASSERT_NO_THROW(reply = srv_->processRequest(req1));
// Set interface for the incoming packet. The server requires it to
// generate client id.
req2->setIface("eth1");
+ req2->setIndex(ETH1_INDEX);
ASSERT_NO_THROW(reply = srv_->processRequest(req2));
TEST_F(NameDhcpv4SrvTest, ddnsScopeTest) {
Dhcp4Client client1(Dhcp4Client::SELECTING);
client1.setIfaceName("eth0");
+ client1.setIfaceIndex(ETH0_INDEX);
// Load a configuration with D2 enabled
ASSERT_NO_FATAL_FAILURE(configure(CONFIGS[8], *client1.getServer()));
// Now let's try with a client on subnet 2.
Dhcp4Client client2(Dhcp4Client::SELECTING);
client2.setIfaceName("eth1");
+ client2.setIfaceIndex(ETH1_INDEX);
// Include the Client FQDN option.
ASSERT_NO_THROW(client2.includeFQDN((Option4ClientFqdn::FLAG_S
// and the fake eth0 interface has IPv4 address matching the subnet
// currently configured for this test.
dis->setIface("eth1");
+ dis->setIndex(ETH1_INDEX);
return (dis);
}
Pkt4Ptr sol = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
sol->setRemoteAddr(IOAddress("192.0.2.1"));
sol->setIface("eth1");
+ sol->setIndex(ETH1_INDEX);
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
Pkt4Ptr sol = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
sol->setRemoteAddr(IOAddress("192.0.2.1"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setIfaceName("eth1");
+ client.setIfaceIndex(ETH1_INDEX);
ASSERT_NO_THROW(client.doDiscover());
// Make sure that we received a response
req->setYiaddr(addr);
req->setCiaddr(addr); // client's address
req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
req->setHWAddr(hwaddr2);
req->addOption(clientid);
req->setYiaddr(addr);
req->setCiaddr(addr); // client's address
req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
req->setHWAddr(hwaddr2);
req->addOption(clientid);
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setIfaceName("eth1");
+ client.setIfaceIndex(ETH1_INDEX);
ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.100"))));
// Make sure that we received a response
// Create first client and perform DORA.
Dhcp4Client client1(Dhcp4Client::SELECTING);
client1.setIfaceName("eth1");
+ client1.setIfaceIndex(ETH1_INDEX);
ASSERT_NO_THROW(client1.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.100"))));
// We should be offered an address but the DHCPACK should not arrive
// server while the previous packet is parked.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setIfaceName("eth1");
+ client2.setIfaceIndex(ETH1_INDEX);
ASSERT_NO_THROW(client2.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.101"))));
// The DHCPOFFER should have been returned but not DHCPACK, as this
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setIfaceName("eth1");
+ client.setIfaceIndex(ETH1_INDEX);
ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.100"))));
// Make sure that we received a response
// Perform 4-way exchange with the server but to not request any
// specific address in the DHCPDISCOVER message.
- boost::shared_ptr<IOAddress> hint;
+ boost::shared_ptr<IOAddress> hint;
if (!requested_addr.empty()) {
hint = boost::make_shared<IOAddress>(requested_addr);
}
// client class.
client_resrv.setHWAddress("aa:bb:cc:dd:ee:fe");
client_resrv.setIfaceName("eth0");
+ client_resrv.setIfaceIndex(ETH0_INDEX);
ASSERT_NO_FATAL_FAILURE(configure(CONFIGS[config_idx], *client_resrv.getServer()));
Dhcp4Client client_no_resrv(client_resrv.getServer(), Dhcp4Client::SELECTING);
client_no_resrv.setHWAddress("aa:bb:cc:dd:ee:ff");
client_no_resrv.setIfaceName("eth0");
+ client_no_resrv.setIfaceIndex(ETH0_INDEX);
// Let's use the address of 10.0.0.10 as a hint to make sure that the
// server refuses it in favor of the 192.0.3.10.
// Change to subnet 20
client.setIfaceName("eth1");
+ client.setIfaceIndex(ETH1_INDEX);
// Subnet 20 usses global HR mode, so the global
// reservation should be used, rather than the subnet one.
// Create client and set MAC address to the one that has a reservation.
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setIfaceName("eth1");
+ client.setIfaceIndex(ETH1_INDEX);
client.setHWAddress("aa:bb:cc:dd:ee:ff");
// Request domain-name-servers.
client.requestOptions(DHO_DOMAIN_NAME_SERVERS);
// Create client #1
Dhcp4Client client1(Dhcp4Client::SELECTING);
client1.setIfaceName("eth1");
+ client1.setIfaceIndex(ETH1_INDEX);
// Configure the server with one shared network including two subnets and
// one subnet outside of the shared network.
// an address from the second subnet.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setIfaceName("eth1");
+ client2.setIfaceIndex(ETH1_INDEX);
testAssigned([this, &client2]() {
doDORA(client2, "10.0.0.16");
});
// the server has no more addresses to assign.
Dhcp4Client client3(client1.getServer(), Dhcp4Client::SELECTING);
client3.setIfaceName("eth1");
+ client3.setIfaceIndex(ETH1_INDEX);
testAssigned([&client3]() {
ASSERT_NO_THROW(client3.doDiscover());
Pkt4Ptr resp3 = client3.getContext().response_;
// Client #3 should be assigned an address if subnet 3 is selected for this client.
client3.setIfaceName("eth0");
+ client3.setIfaceIndex(ETH0_INDEX);
testAssigned([this, &client3]() {
doDORA(client3, "192.0.2.65");
});
// Create client.
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setIfaceName("eth1");
+ client.setIfaceIndex(ETH1_INDEX);
client.includeClientId("01:02:03:04");
// Configure the server with one shared network including two subnets and
// Create client.
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setIfaceName("eth1");
+ client.setIfaceIndex(ETH1_INDEX);
// Configure the server with one shared network including two subnets and
// one subnet outside of the shared network.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.useRelay(true, IOAddress("192.3.5.6"));
client2.setIfaceName("eth1");
+ client2.setIfaceIndex(ETH1_INDEX);
testAssigned([this, &client2] {
doDORA(client2, "10.0.0.16");
});
// Client #1.
Dhcp4Client client1(Dhcp4Client::SELECTING);
client1.setIfaceName("eth1");
+ client1.setIfaceIndex(ETH1_INDEX);
client1.requestOptions(DHO_LOG_SERVERS, DHO_COOKIE_SERVERS, DHO_DOMAIN_NAME_SERVERS);
configure(NETWORKS_CONFIG[7], *client1.getServer());
// Client #2.
Dhcp4Client client2(Dhcp4Client::SELECTING);
client2.setIfaceName("eth1");
+ client2.setIfaceIndex(ETH1_INDEX);
client2.requestOptions(DHO_LOG_SERVERS, DHO_COOKIE_SERVERS, DHO_DOMAIN_NAME_SERVERS);
// Request an address from the second subnet within the shared network.
// Client #3.
Dhcp4Client client3(Dhcp4Client::SELECTING);
client3.setIfaceName("eth0");
+ client3.setIfaceIndex(ETH0_INDEX);
client3.requestOptions(DHO_LOG_SERVERS, DHO_COOKIE_SERVERS, DHO_DOMAIN_NAME_SERVERS);
// Client 3 should get an address from the subnet defined outside of the shared network.
// Create client #1.
Dhcp4Client client1(Dhcp4Client::SELECTING);
client1.setIfaceName("eth1");
+ client1.setIfaceIndex(ETH1_INDEX);
configure(NETWORKS_CONFIG[0], *client1.getServer());
// Create client #2.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setIfaceName("eth1");
+ client2.setIfaceIndex(ETH1_INDEX);
// Let's make sure that the behavior is the same for the other subnet within the
// same shared network.
// Create client.
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setIfaceName("eth1");
+ client.setIfaceIndex(ETH1_INDEX);
client.setHWAddress("11:22:33:44:55:66");
// Include hostname to force the server to return hostname to
// this client.
Dhcp4Client client1(Dhcp4Client::SELECTING);
client1.setIfaceName("eth1");
+ client1.setIfaceIndex(ETH1_INDEX);
// Create server configuration with two shared networks selected
// by the local interface: eth1 and eth0.
// Create client #2 which requests are received on eth0.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setIfaceName("eth0");
+ client2.setIfaceIndex(ETH0_INDEX);
// Perform 4-way exchange.
testAssigned([&client2] {
Dhcp4Client client(Dhcp4Client::SELECTING);
client.includeClientId("01:02:03:04");
client.setIfaceName("eth1");
+ client.setIfaceIndex(ETH1_INDEX);
// Create server configuration with match-client-id value initially
// set to true. The client should be allocated a lease and the
// Create client #1.
Dhcp4Client client1(Dhcp4Client::SELECTING);
client1.setIfaceName("eth1");
+ client1.setIfaceIndex(ETH1_INDEX);
// Add option93 which would cause the client1 to be classified as "b-devices".
OptionPtr option93(new OptionUint16(Option::V4, 93, 0x0002));
// Create another client which will belong to a different class.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setIfaceName("eth1");
+ client2.setIfaceIndex(ETH1_INDEX);
// Add option93 which would cause the client1 to be classified as "a-devices".
option93.reset(new OptionUint16(Option::V4, 93, 0x0001));
TEST_F(Dhcpv4SharedNetworkTest, customServerIdentifier) {
Dhcp4Client client1(Dhcp4Client::SELECTING);
client1.setIfaceName("eth1");
+ client1.setIfaceIndex(ETH1_INDEX);
// Configure DHCP server.
ASSERT_NO_THROW(configure(NETWORKS_CONFIG[15], *client1.getServer()));
// Create another client using different interface.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setIfaceName("eth0");
+ client2.setIfaceIndex(ETH0_INDEX);
testAssigned([&client2] {
ASSERT_NO_THROW(client2.doDORA());
// Create client #1
Dhcp4Client client1(Dhcp4Client::SELECTING);
client1.setIfaceName("eth1");
+ client1.setIfaceIndex(ETH1_INDEX);
// Configure the server with one shared network including one subnet and
// in 2 pools in it. The access to one of the pools is restricted
// Client 2 should be assigned an address from the unrestricted pool.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setIfaceName("eth1");
+ client2.setIfaceIndex(ETH1_INDEX);
testAssigned([this, &client2] {
doDORA(client2, "192.0.2.100");
});
// Create client #1
Dhcp4Client client1(Dhcp4Client::SELECTING);
client1.setIfaceName("eth1");
+ client1.setIfaceIndex(ETH1_INDEX);
// Configure the server with one plain subnet including two pools.
// The access to one of the pools is restricted by client classification.
// Client 2 should be assigned an address from the unrestricted pool.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setIfaceName("eth1");
+ client2.setIfaceIndex(ETH1_INDEX);
testAssigned([this, &client2] {
doDORA(client2, "192.0.2.100");
});
dis->addOption(clientid);
// Set interface. It is required by the server to generate server id.
dis->setIface("eth0");
+ dis->setIndex(ETH0_INDEX);
// Pass it to the server and get an advertise
Pkt4Ptr offer = srv.processDiscover(dis);
dis->addOption(clientid);
// Set interface. It is required by the server to generate server id.
dis->setIface("eth0");
+ dis->setIndex(ETH0_INDEX);
// Let's add a vendor-option (vendor-id=4491).
OptionPtr vendor(new OptionVendor(Option::V4, 4491));
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a PRL option to the query
OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a vendor-encapsulated-options (code 43)
// with not compatible (not parsable as suboptions) content
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a vendor-encapsulated-options (code 43)
// with not compatible (not parsable as suboptions) content
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a vendor-encapsulated-options (code 43)
// with not compatible (not parsable as suboptions) content
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a vendor-encapsulated-options (code 43)
// with not compatible (not parsable as suboptions) content
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a vendor-encapsulated-options (code 43)
OptionBuffer buf;
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a vendor-encapsulated-options (code 43)
OptionBuffer buf;
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a vendor-encapsulated-options (code 43)
OptionBuffer buf;
OptionPtr clientid = generateClientId();
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
// Create and add a PRL option to the query
OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
-// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
query->setRemoteAddr(IOAddress(remote_addr));
query->addOption(clientid);
query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
query->addOption(generateIA(D6O_IA_NA, 123, 1500, 3000));
return (query);
}
query1->setRemoteAddr(IOAddress("fe80::abcd"));
query1->addOption(clientid);
query1->setIface("eth1");
+ query1->setIndex(ETH1_INDEX);
query1->addOption(generateIA(D6O_IA_NA, 123, 1500, 3000));
Pkt6Ptr query2(new Pkt6(DHCPV6_SOLICIT, 1234));
query2->setRemoteAddr(IOAddress("fe80::abcd"));
query2->addOption(clientid);
query2->setIface("eth1");
+ query2->setIndex(ETH1_INDEX);
query2->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
Pkt6Ptr query3(new Pkt6(DHCPV6_SOLICIT, 1234));
query3->setRemoteAddr(IOAddress("fe80::abcd"));
query3->addOption(clientid);
query3->setIface("eth1");
+ query3->setIndex(ETH1_INDEX);
query3->addOption(generateIA(D6O_IA_NA, 345, 1500, 3000));
// Create and add an ORO option to the first 2 queries
query1->setRemoteAddr(IOAddress("fe80::abcd"));
query1->addOption(clientid);
query1->setIface("eth1");
+ query1->setIndex(ETH1_INDEX);
query1->addOption(generateIA(D6O_IA_NA, 123, 1500, 3000));
Pkt6Ptr query2(new Pkt6(DHCPV6_SOLICIT, 1234));
query2->setRemoteAddr(IOAddress("fe80::abcd"));
query2->addOption(clientid);
query2->setIface("eth1");
+ query2->setIndex(ETH1_INDEX);
query2->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
Pkt6Ptr query3(new Pkt6(DHCPV6_SOLICIT, 1234));
query3->setRemoteAddr(IOAddress("fe80::abcd"));
query3->addOption(clientid);
query3->setIface("eth1");
+ query3->setIndex(ETH1_INDEX);
query3->addOption(generateIA(D6O_IA_NA, 345, 1500, 3000));
// Create and add an ORO option to the first 2 queries
query1->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
query1->addOption(clientid1);
query1->setIface("eth1");
+ query1->setIndex(ETH1_INDEX);
// First pool requires reservation so the second will be used
srv.classifyPacket(query1);
query2->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
query2->addOption(clientid2);
query2->setIface("eth1");
+ query2->setIndex(ETH1_INDEX);
// Now the first pool will be used
srv.classifyPacket(query2);
query1->setRemoteAddr(IOAddress("fe80::abcd"));
query1->addOption(clientid);
query1->setIface("eth1");
+ query1->setIndex(ETH1_INDEX);
query1->addOption(generateIA(D6O_IA_NA, 123, 1500, 3000));
Pkt6Ptr query2(new Pkt6(DHCPV6_SOLICIT, 1234));
query2->setRemoteAddr(IOAddress("fe80::abcd"));
query2->addOption(clientid);
query2->setIface("eth1");
+ query2->setIndex(ETH1_INDEX);
query2->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
Pkt6Ptr query3(new Pkt6(DHCPV6_SOLICIT, 1234));
query3->setRemoteAddr(IOAddress("fe80::abcd"));
query3->addOption(clientid);
query3->setIface("eth1");
+ query3->setIndex(ETH1_INDEX);
query3->addOption(generateIA(D6O_IA_NA, 345, 1500, 3000));
// Create and add an ORO option to queries
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
sol->addOption(generateIA(D6O_IA_PD, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
OptionPtr iapd = generateIA(D6O_IA_PD, 234, 1500, 3000);
sol->addOption(iapd);
OptionPtr clientid = generateClientId();
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
OptionPtr iana = generateIA(D6O_IA_NA, 234, 1500, 3000);
sol->addOption(iana);
OptionPtr clientid = generateClientId();
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
OptionPtr iapd = generateIA(D6O_IA_PD, 234, 1500, 3000);
sol->addOption(iapd);
OptionPtr clientid = generateClientId();
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
OptionPtr iana = generateIA(D6O_IA_NA, 234, 1500, 3000);
sol->addOption(iana);
OptionPtr clientid = generateClientId();
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
// with a valid hint
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
IOAddress hint("2001:db8:1::cafe:babe");
ASSERT_FALSE(subnet_->inPool(Lease::TYPE_NA, hint));
sol3->setRemoteAddr(IOAddress("fe80::3467"));
sol1->setIface("eth0");
+ sol1->setIndex(ETH0_INDEX);
sol2->setIface("eth0");
+ sol2->setIndex(ETH0_INDEX);
sol3->setIface("eth0");
+ sol3->setIndex(ETH0_INDEX);
sol1->addOption(generateIA(D6O_IA_NA, 1, 1500, 3000));
sol2->addOption(generateIA(D6O_IA_NA, 2, 1500, 3000));
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
req->setRemoteAddr(IOAddress("fe80::abcd"));
req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
// with a valid hint
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
req->setRemoteAddr(IOAddress("fe80::abcd"));
req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_PD, 234, 1500, 3000);
// with a valid hint
req3->setRemoteAddr(IOAddress("fe80::3467"));
req1->setIface("eth0");
+ req1->setIndex(ETH0_INDEX);
req2->setIface("eth0");
+ req2->setIndex(ETH0_INDEX);
req3->setIface("eth0");
+ req3->setIndex(ETH0_INDEX);
req1->addOption(generateIA(D6O_IA_NA, 1, 1500, 3000));
req2->addOption(generateIA(D6O_IA_NA, 2, 1500, 3000));
Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
bool drop = false;
Subnet6Ptr selected = srv.selectSubnet(pkt, drop);
CfgMgr::instance().commit();
pkt->setIface("eth1");
+ pkt->setIndex(ETH1_INDEX);
selected = srv.selectSubnet(pkt, drop);
EXPECT_FALSE(selected);
CfgMgr::instance().commit();
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
EXPECT_EQ(subnet1, srv.selectSubnet(pkt, drop));
EXPECT_FALSE(drop);
pkt->setIface("eth3"); // no such interface
+ pkt->setIndex(3);
EXPECT_EQ(Subnet6Ptr(), srv.selectSubnet(pkt, drop)); // nothing selected
EXPECT_FALSE(drop);
pkt->setIface("wifi1");
+ pkt->setIndex(101); // arbitrary value
EXPECT_EQ(subnet3, srv.selectSubnet(pkt, drop));
EXPECT_FALSE(drop);
}
Pkt6Ptr sol(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
query->setLocalAddr(sol->getLocalAddr());
query->setLocalPort(sol->getLocalPort());
query->setIface(sol->getIface());
+ query->setIndex(sol->getIndex());
srv.fakeReceive(query);
Pkt6Ptr sol(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
// Iterate over the test scenarios.
for (auto test = tests.begin(); test != tests.end(); ++test) {
}
valid_iface_ = (*ifaces.begin())->getName();
+ valid_ifindex_ = (*ifaces.begin())->getIndex();
// Let's wipe all existing statistics.
isc::stats::StatsMgr::instance().removeAll();
-// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// Name of a valid network interface
std::string valid_iface_;
+
+ // Index of a valid network interface
+ uint32_t valid_ifindex_;
};
// We need to pass one reference to the Dhcp6Client, which is defined in
Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_RESPONSE, 1234));
pkt->addOption(createDHCPv4MsgOption());
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
ASSERT_NO_THROW(pkt->pack());
EXPECT_EQ(forwarded->getType(), pkt->getType());
EXPECT_TRUE(forwarded->getOption(D6O_DHCPV4_MSG));
EXPECT_EQ("eth0", forwarded->getIface());
+ EXPECT_EQ(ETH0_INDEX, forwarded->getIndex());
EXPECT_EQ("2001:db8:1::123", forwarded->getRemoteAddr().toText());
// Verify statistics
relay.hop_count_ = 1;
pkt->relay_info_.push_back(relay);
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
ASSERT_NO_THROW(pkt->pack());
EXPECT_EQ(forwarded->getType(), pkt->getType());
EXPECT_TRUE(forwarded->getOption(D6O_DHCPV4_MSG));
EXPECT_EQ("eth0", forwarded->getIface());
+ EXPECT_EQ(ETH0_INDEX, forwarded->getIndex());
EXPECT_EQ("2001:db8:1::123", forwarded->getRemoteAddr().toText());
EXPECT_EQ(DHCP6_CLIENT_PORT, forwarded->getRemotePort());
Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_RESPONSE, 1234));
pkt->addOption(createDHCPv4MsgOption());
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
ASSERT_NO_THROW(pkt->pack());
OptionPtr srvid = OptionPtr()) {
Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(msg_type, 1234));
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
Option6IAPtr ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
if (msg_type != DHCPV6_REPLY) {
IOAddress hint("2001:db8:1:1::dead:beef");
Pkt6Ptr generateMessageWithIds(const uint8_t msg_type) {
Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(msg_type, 1234));
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
// Generate client-id.
OptionPtr opt_clientid = generateClientId();
pkt->addOption(opt_clientid);
}
-} // end of anonymous namespace
+} // end of anonymous namespace
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface(valid_iface_);
+ sol->setIndex(valid_ifindex_);
sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface(valid_iface_);
+ sol->setIndex(valid_ifindex_);
sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
req->setRemoteAddr(IOAddress("fe80::abcd"));
req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
req->setRemoteAddr(IOAddress("fe80::abcd"));
req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
req->setRemoteAddr(IOAddress("fe80::abcd"));
req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REBIND, 1234));
req->setRemoteAddr(IOAddress("fe80::abcd"));
req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
OptionPtr rebound_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REBIND, 1234));
req->setRemoteAddr(IOAddress("fe80::abcd"));
req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
OptionPtr rebound_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REBIND, 1234));
req->setRemoteAddr(IOAddress("fe80::abcd"));
req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
OptionPtr rebound_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface(valid_iface_);
+ sol->setIndex(valid_ifindex_);
sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface(valid_iface_);
+ sol->setIndex(valid_ifindex_);
sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
-// Copyright (C) 2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2019-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
sol->setRemoteAddr(IOAddress("fe80::abcd"));
sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
OptionPtr clientid = generateClientId();
sol->addOption(clientid);
void
IfaceMgr::setPacketFilter(const PktFilterPtr& packet_filter) {
- // Do not allow NULL pointer.
+ // Do not allow null pointer.
if (!packet_filter) {
isc_throw(InvalidPacketFilter, "NULL packet filter object specified for"
" DHCPv4");
}
}
+void
+IfaceMgr::addInterface(const IfacePtr& iface) {
+ for (const IfacePtr& existing : ifaces_) {
+ if ((existing->getName() == iface->getName()) ||
+ (existing->getIndex() == iface->getIndex())) {
+ isc_throw(Unexpected, "Can't add " << iface->getFullName() <<
+ " when " << existing->getFullName() <<
+ " already exists.");
+ }
+ }
+ ifaces_.push_back(iface);
+}
+
void
IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
BOOST_FOREACH(IfacePtr iface, ifaces_) {
IfacePtr
IfaceMgr::getIface(const std::string& ifname) {
+ std::cerr << "getIface(name) unefficient\n";
BOOST_FOREACH(IfacePtr iface, ifaces_) {
if (iface->getName() == ifname)
return (iface);
return (IfacePtr()); // not found
}
+IfacePtr
+IfaceMgr::getIface(const PktPtr& pkt) {
+ IfacePtr iface = getIface(pkt->getIndex());
+ if (!iface) {
+ iface = getIface(pkt->getIface());
+ }
+ return (iface);
+}
+
void
IfaceMgr::clearIfaces() {
ifaces_.clear();
const uint16_t port, const bool receive_bcast,
const bool send_bcast) {
- // Assuming that packet filter is not NULL, because its modifier checks it.
+ // Assuming that packet filter is not null, because its modifier checks it.
SocketInfo info = packet_filter_->openSocket(iface, addr, port,
receive_bcast, send_bcast);
iface.addSocket(info);
bool
IfaceMgr::send(const Pkt6Ptr& pkt) {
- IfacePtr iface = getIface(pkt->getIface());
+ IfacePtr iface = getIface(pkt);
if (!iface) {
isc_throw(BadValue, "Unable to send DHCPv6 message. Invalid interface ("
<< pkt->getIface() << ") specified.");
}
- // Assuming that packet filter is not NULL, because its modifier checks it.
+ // Assuming that packet filter is not null, because its modifier checks it.
// The packet filter returns an int but in fact it either returns 0 or throws.
- return (packet_filter6_->send(*iface, getSocket(*pkt), pkt) == 0);
+ return (packet_filter6_->send(*iface, getSocket(pkt), pkt) == 0);
}
bool
IfaceMgr::send(const Pkt4Ptr& pkt) {
-
- IfacePtr iface = getIface(pkt->getIface());
+ IfacePtr iface = getIface(pkt);
if (!iface) {
isc_throw(BadValue, "Unable to send DHCPv4 message. Invalid interface ("
<< pkt->getIface() << ") specified.");
}
- // Assuming that packet filter is not NULL, because its modifier checks it.
+ // Assuming that packet filter is not null, because its modifier checks it.
// The packet filter returns an int but in fact it either returns 0 or throws.
- return (packet_filter_->send(*iface, getSocket(*pkt).sockfd_, pkt) == 0);
+ return (packet_filter_->send(*iface, getSocket(pkt).sockfd_, pkt) == 0);
}
Pkt4Ptr IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
// zero out the errno to be safe
errno = 0;
- int result = select(maxfd + 1, &sockets, NULL, NULL, &select_timeout);
+ int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
if ((result == 0) && getPacketQueue4()->empty()) {
// nothing received and timeout has been reached
// zero out the errno to be safe
errno = 0;
- int result = select(maxfd + 1, &sockets, NULL, NULL, &select_timeout);
+ int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
if (result == 0) {
// nothing received and timeout has been reached
- return (Pkt4Ptr()); // NULL
+ return (Pkt4Ptr()); // null
} else if (result < 0) {
// In most cases we would like to know whether select() returned
}
// Now we have a socket, let's get some data from it!
- // Assuming that packet filter is not NULL, because its modifier checks it.
+ // Assuming that packet filter is not null, because its modifier checks it.
return (packet_filter_->receive(*iface, *candidate));
}
// zero out the errno to be safe
errno = 0;
- int result = select(maxfd + 1, &sockets, NULL, NULL, &select_timeout);
+ int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
if (result == 0) {
// nothing received and timeout has been reached
- return (Pkt6Ptr()); // NULL
+ return (Pkt6Ptr()); // null
} else if (result < 0) {
// In most cases we would like to know whether select() returned
if (!candidate) {
isc_throw(SocketReadError, "received data over unknown socket");
}
- // Assuming that packet filter is not NULL, because its modifier checks it.
+ // Assuming that packet filter is not null, because its modifier checks it.
return (packet_filter6_->receive(*candidate));
}
// zero out the errno to be safe
errno = 0;
- int result = select(maxfd + 1, &sockets, NULL, NULL, &select_timeout);
+ int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
if ((result == 0) && getPacketQueue6()->empty()) {
// nothing received and timeout has been reached
}
uint16_t
-IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
- IfacePtr iface = getIface(pkt.getIface());
+IfaceMgr::getSocket(const isc::dhcp::Pkt6Ptr& pkt) {
+ IfacePtr iface = getIface(pkt);
if (!iface) {
isc_throw(IfaceNotFound, "Tried to find socket for non-existent interface");
}
continue;
}
- if (s->addr_ == pkt.getLocalAddr()) {
+ if (s->addr_ == pkt->getLocalAddr()) {
// This socket is bound to the source address. This is perfect
// match, no need to look any further.
return (s->sockfd_);
// If we want to send something to link-local and the socket is
// bound to link-local or we want to send to global and the socket
// is bound to global, then use it as candidate
- if ( (pkt.getRemoteAddr().isV6LinkLocal() &&
+ if ( (pkt->getRemoteAddr().isV6LinkLocal() &&
s->addr_.isV6LinkLocal()) ||
- (!pkt.getRemoteAddr().isV6LinkLocal() &&
+ (!pkt->getRemoteAddr().isV6LinkLocal() &&
!s->addr_.isV6LinkLocal()) ) {
candidate = s;
}
}
SocketInfo
-IfaceMgr::getSocket(isc::dhcp::Pkt4 const& pkt) {
- IfacePtr iface = getIface(pkt.getIface());
- if (iface == NULL) {
+IfaceMgr::getSocket(const isc::dhcp::Pkt4Ptr& pkt) {
+ IfacePtr iface = getIface(pkt);
+ if (!iface) {
isc_throw(IfaceNotFound, "Tried to find socket for non-existent interface");
}
Iface::SocketCollection::const_iterator s;
for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
if (s->family_ == AF_INET) {
- if (s->addr_ == pkt.getLocalAddr()) {
+ if (s->addr_ == pkt->getLocalAddr()) {
return (*s);
}
/// NULL if the buffer is empty.
uint8_t* getReadBuffer() {
if (read_buffer_.empty()) {
- return NULL;
+ return (0);
}
return (&read_buffer_[0]);
}
///
/// @param ifindex index of searched interface
///
- /// @return interface with requested index (or NULL if no such
+ /// @return interface with requested index (or null if no such
/// interface is present)
///
IfacePtr getIface(int ifindex);
///
/// @param ifname name of searched interface
///
- /// @return interface with requested name (or NULL if no such
+ /// @return interface with requested name (or null if no such
/// interface is present)
IfacePtr getIface(const std::string& ifname);
+ /// @brief Returns interface with specified packet
+ ///
+ /// @param pkt packet with interface index and name
+ ///
+ /// @return interface with packet interface index or name
+ /// (or null if no such interface is present)
+ IfacePtr getIface(const PktPtr& pkt);
+
/// @brief Returns container with all interfaces.
///
/// This reference is only valid as long as IfaceMgr is valid. However,
/// @brief Return most suitable socket for transmitting specified IPv6 packet.
///
- /// This method takes Pkt6 (see overloaded implementation that takes
- /// Pkt4) and chooses appropriate socket to send it. This method
+ /// This method takes Pkt6Ptr (see overloaded implementation that takes
+ /// Pkt4Ptr) and chooses appropriate socket to send it. This method
/// may throw if specified packet does not have outbound interface specified,
/// no such interface exists, or specified interface does not have any
/// appropriate sockets open.
/// @return a socket descriptor
/// @throw SocketNotFound If no suitable socket found.
/// @throw IfaceNotFound If interface is not set for the packet.
- uint16_t getSocket(const isc::dhcp::Pkt6& pkt);
+ uint16_t getSocket(const isc::dhcp::Pkt6Ptr& pkt);
/// @brief Return most suitable socket for transmitting specified IPv4 packet.
///
///
/// @return A structure describing a socket.
/// @throw SocketNotFound if no suitable socket found.
- SocketInfo getSocket(const isc::dhcp::Pkt4& pkt);
+ SocketInfo getSocket(const isc::dhcp::Pkt4Ptr& pkt);
/// Debugging method that prints out all available interfaces.
///
/// @param timeout_usec specifies fractional part of the timeout
/// (in microseconds)
///
- /// @return Pkt4 object representing received packet (or NULL)
+ /// @return Pkt4 object representing received packet (or null)
Pkt6Ptr receive6(uint32_t timeout_sec, uint32_t timeout_usec = 0);
/// @brief Receive IPv4 packets or data from external sockets
/// @param timeout_usec specifies fractional part of the timeout
/// (in microseconds)
///
- /// @return Pkt4 object representing received packet (or NULL)
+ /// @return Pkt4 object representing received packet (or null)
Pkt4Ptr receive4(uint32_t timeout_sec, uint32_t timeout_usec = 0);
/// Opens UDP/IP socket and binds it to address, interface and port.
/// to the error handler, e.g. Iface if it was really supposed to do
/// some more sophisticated error handling.
///
- /// If the error handler is not installed (is NULL), the exception is thrown
+ /// If the error handler is not installed (is null), the exception is thrown
/// for each failure (default behavior).
///
/// @warning This function does not check if there has been any sockets
/// @param port specifies port number (usually DHCP6_SERVER_PORT)
/// @param error_handler A pointer to an error handler function which is
/// called by the openSockets6 when it fails to open a socket. This
- /// parameter can be NULL to indicate that the callback should not be used.
+ /// parameter can be null to indicate that the callback should not be used.
///
/// @throw SocketOpenFailure if tried and failed to open socket.
/// @return true if any sockets were open
/// to the error handler, e.g. Iface if it was really supposed to do
/// some more sophisticated error handling.
///
- /// If the error handler is not installed (is NULL), the exception is thrown
+ /// If the error handler is not installed (is null), the exception is thrown
/// for each failure (default behavior).
///
/// @warning This function does not check if there has been any sockets
/// @param use_bcast configure sockets to support broadcast messages.
/// @param error_handler A pointer to an error handler function which is
/// called by the openSockets4 when it fails to open a socket. This
- /// parameter can be NULL to indicate that the callback should not be used.
+ /// parameter can be null to indicate that the callback should not be used.
///
/// @throw SocketOpenFailure if tried and failed to open socket and callback
/// function hasn't been specified.
/// @param packet_filter A pointer to the new packet filter object to be
/// used by @c IfaceMgr.
///
- /// @throw InvalidPacketFilter if provided packet filter object is NULL.
+ /// @throw InvalidPacketFilter if provided packet filter object is null.
/// @throw PacketFilterChangeDenied if there are open IPv4 sockets.
void setPacketFilter(const PktFilterPtr& packet_filter);
/// @param packet_filter A pointer to the new packet filter object to be
/// used by @c IfaceMgr.
///
- /// @throw isc::dhcp::InvalidPacketFilter if specified object is NULL.
+ /// @throw isc::dhcp::InvalidPacketFilter if specified object is null.
/// @throw isc::dhcp::PacketFilterChangeDenied if there are open IPv6
/// sockets.
void setPacketFilter(const PktFilter6Ptr& packet_filter);
/// @param iface reference to Iface object.
/// @note This function must be public because it has to be callable
/// from unit tests.
- void addInterface(const IfacePtr& iface) {
- ifaces_.push_back(iface);
- }
+ /// @throw Unexpected when name or index already exists.
+ void addInterface(const IfacePtr& iface);
/// @brief Checks if there is at least one socket of the specified family
/// open.
/// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is
/// interrupted by a signal.
///
- /// @return Pkt4 object representing received packet (or NULL)
+ /// @return Pkt4 object representing received packet (or null)
Pkt4Ptr receive4Direct(uint32_t timeout_sec, uint32_t timeout_usec = 0);
/// @brief Receive IPv4 packets indirectly or data from external sockets.
/// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is
/// interrupted by a signal.
///
- /// @return Pkt4 object representing received packet (or NULL)
+ /// @return Pkt4 object representing received packet (or null)
Pkt4Ptr receive4Indirect(uint32_t timeout_sec, uint32_t timeout_usec = 0);
/// @brief Opens IPv6 socket.
/// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is
/// interrupted by a signal.
///
- /// @return Pkt6 object representing received packet (or NULL)
+ /// @return Pkt6 object representing received packet (or null)
Pkt6Ptr receive6Direct(uint32_t timeout_sec, uint32_t timeout_usec = 0);
/// @brief Receive IPv6 packets indirectly or data from external sockets.
/// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is
/// interrupted by a signal.
///
- /// @return Pkt6 object representing received packet (or NULL)
+ /// @return Pkt6 object representing received packet (or null)
Pkt6Ptr receive6Indirect(uint32_t timeout_sec, uint32_t timeout_usec = 0);
/// @param addr Link-local address to bind the socket to.
/// @param port Port number to bind socket to.
/// @param error_handler Error handler function to be called when an
- /// error occurs during opening a socket, or NULL if exception should
+ /// error occurs during opening a socket, or null if exception should
/// be thrown upon error.
bool openMulticastSocket(Iface& iface,
const isc::asiolink::IOAddress& addr,
-// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
}
nl.ipaddrs_get(*iface, addr_info);
- addInterface(iface);
+
+ // addInterface can now throw so protect against memory leaks.
+ try {
+ addInterface(iface);
+ } catch (...) {
+ nl.release_list(link_info);
+ nl.release_list(addr_info);
+ throw;
+ }
}
nl.release_list(link_info);
}
#endif
+#ifdef IPV6_V6ONLY
+ // Set IPV6_V6ONLY to get only IPv6 packets.
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&flag, sizeof(flag)) < 0) {
+ close(sock);
+ isc_throw(SocketConfigError, "Can't set IPPROTO_IPV6 option on "
+ "IPv6 socket.");
+ }
+#endif
+
if (bind(sock, (struct sockaddr *)&addr6, sizeof(addr6)) < 0) {
// Get the error message immediately after the bind because the
// invocation to close() below would override the errno.
<< addr.toText() << "/port=" << port
<< ": " << errmsg);
}
+
#ifdef IPV6_RECVPKTINFO
// RFC3542 - a new way
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
-// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
namespace dhcp {
namespace test {
+//@{
+/// @brief Index of the lo fake interface.
+const uint32_t LO_INDEX = 0;
+
+/// @brief Index of the eth0 fake interface.
+const uint32_t ETH0_INDEX = 1;
+
+/// @brief Index of the eth1 fake interface.
+const uint32_t ETH1_INDEX = 2;
+//@}
+
///
/// @name Set of structures describing interface flags.
///
/// The class allows the caller to create custom fake interfaces (with custom
/// IPv4 and IPv6 addresses, flags etc.), but it also provides a default
/// test configuration for interfaces as follows:
-/// - lo
+/// - lo #0
/// - 127.0.0.1
/// - ::1
-/// - eth0
+/// - eth0 #1
/// - 10.0.0.1
/// - fe80::3a60:77ff:fed5:cdef
/// - 2001:db8:1::1
-/// - eth1
+/// - eth1 #2
/// - 192.0.2.3
/// - fe80::3a60:77ff:fed5:abcd
///
-// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// Name of loopback interface detection
const size_t BUF_SIZE = 32;
-char LOOPBACK[BUF_SIZE] = "lo";
+char LOOPBACK_NAME[BUF_SIZE] = "lo";
+uint32_t LOOPBACK_INDEX = 0;
// Ports used during testing
const uint16_t PORT1 = 10547; // V6 socket
// Poor man's interface detection. It will go away as soon as proper
// interface detection is implemented
if (if_nametoindex("lo") > 0) {
- snprintf(LOOPBACK, BUF_SIZE - 1, "lo");
+ snprintf(LOOPBACK_NAME, BUF_SIZE - 1, "lo");
} else if (if_nametoindex("lo0") > 0) {
- snprintf(LOOPBACK, BUF_SIZE - 1, "lo0");
+ snprintf(LOOPBACK_NAME, BUF_SIZE - 1, "lo0");
} else {
cout << "Failed to detect loopback interface. Neither "
<< "lo nor lo0 worked. I give up." << endl;
FAIL();
}
+ LOOPBACK_INDEX = if_nametoindex(LOOPBACK_NAME);
}
/// @brief Returns the collection of existing interfaces.
}
}
}
-
};
/// @brief A test fixture class for IfaceMgr.
IOAddress lo_addr("::1");
int socket1 = 0, socket2 = 0;
EXPECT_NO_THROW(
- socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10547);
- socket2 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10546);
+ socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547);
+ socket2 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10546);
);
EXPECT_GE(socket1, 0);
sendPkt->repack();
sendPkt->setRemotePort(10547);
sendPkt->setRemoteAddr(IOAddress("::1"));
- sendPkt->setIndex(1);
- sendPkt->setIface(LOOPBACK);
+ sendPkt->setIndex(LOOPBACK_INDEX);
+ sendPkt->setIface(LOOPBACK_NAME);
// Send the packet.
EXPECT_EQ(true, ifacemgr->send(sendPkt));
ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
}
-
/// @brief Tests the ability to send and receive DHCPv4 packets
///
/// This test calls @r IfaceMgr::configureDHCPPacketQueue, passing in the
IOAddress lo_addr("127.0.0.1");
int socket1 = 0;
EXPECT_NO_THROW(
- socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, DHCP4_SERVER_PORT + 10000);
+ socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr,
+ DHCP4_SERVER_PORT + 10000);
);
EXPECT_GE(socket1, 0);
sendPkt->setLocalPort(DHCP4_SERVER_PORT + 10000 + 1);
sendPkt->setRemotePort(DHCP4_SERVER_PORT + 10000);
sendPkt->setRemoteAddr(IOAddress("127.0.0.1"));
- sendPkt->setIndex(1);
- sendPkt->setIface(string(LOOPBACK));
+ sendPkt->setIndex(LOOPBACK_INDEX);
+ sendPkt->setIface(string(LOOPBACK_NAME));
sendPkt->setHops(6);
sendPkt->setSecs(42);
sendPkt->setCiaddr(IOAddress("192.0.2.1"));
/// Holds the invocation counter for ifaceMgrErrorHandler.
int errors_count_;
-
};
// We need some known interface to work reliably. Loopback interface is named
// This new address should now be returned.
EXPECT_TRUE(iface.getAddress4(addr));
EXPECT_EQ("192.0.2.3", addr.toText());
-
}
// This test checks if it is possible to check that the specific address is
cout << " " << (*iface)->getFullName() << endl;
}
-
// Check that interface can be retrieved by ifindex
IfacePtr tmp = ifacemgr->getIface(102);
ASSERT_TRUE(tmp);
IOAddress lo_addr("::1");
int socket1 = 0;
ASSERT_NO_THROW(
- socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10547)
+ socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547)
);
// Socket is open if result is non-negative.
ASSERT_GE(socket1, 0);
IOAddress lo_addr("127.0.0.1");
int socket1 = 0;
ASSERT_NO_THROW(
- socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10067)
+ socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10067)
);
// Socket is open if returned value is non-negative.
ASSERT_GE(socket1, 0);
// Create socket #1
int socket1 = 0;
ASSERT_NO_THROW(
- socket1 = ifacemgr->openSocketFromIface(LOOPBACK, PORT1, AF_INET);
+ socket1 = ifacemgr->openSocketFromIface(LOOPBACK_NAME, PORT1, AF_INET);
);
ASSERT_GE(socket1, 0);
init_sockets.push_back(socket1);
// Get loopback interface. If we don't find one we are unable to run
// this test but we don't want to fail.
- IfacePtr iface_ptr = ifacemgr->getIface(LOOPBACK);
+ IfacePtr iface_ptr = ifacemgr->getIface(LOOPBACK_NAME);
if (iface_ptr == NULL) {
cout << "Local loopback interface not found. Skipping test. " << endl;
return;
}
+ ASSERT_EQ(LOOPBACK_INDEX, iface_ptr->getIndex());
// Once sockets have been successfully opened, they are supposed to
// be on the list. Here we start to test if all expected sockets
// are on the list and no other (unexpected) socket is there.
IOAddress lo_addr("::1");
- Pkt6 pkt6(DHCPV6_SOLICIT, 123);
- pkt6.setIface(LOOPBACK);
+ Pkt6Ptr pkt6(new Pkt6(DHCPV6_SOLICIT, 123));
+ pkt6->setIface(LOOPBACK_NAME);
// Bind multicast socket to port 10547
- int socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10547);
+ int socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547);
EXPECT_GE(socket1, 0); // socket >= 0
EXPECT_EQ(socket1, ifacemgr->getSocket(pkt6));
// Bind unicast socket to port 10548
- int socket2 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10548);
+ int socket2 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10548);
EXPECT_GE(socket2, 0);
// Removed code for binding socket twice to the same address/port
// Use address that is not assigned to LOOPBACK iface.
IOAddress invalidAddr("::2");
EXPECT_THROW(
- ifacemgr->openSocket(LOOPBACK, invalidAddr, 10547),
+ ifacemgr->openSocket(LOOPBACK_NAME, invalidAddr, 10547),
SocketConfigError
);
// Open v6 socket on loopback interface and bind to port
int socket1 = 0;
EXPECT_NO_THROW(
- socket1 = ifacemgr->openSocketFromIface(LOOPBACK, PORT1, AF_INET6);
+ socket1 = ifacemgr->openSocketFromIface(LOOPBACK_NAME, PORT1, AF_INET6);
);
// Socket descriptor must be non-negative integer
EXPECT_GE(socket1, 0);
// Open v4 socket on loopback interface and bind to different port
int socket2 = 0;
EXPECT_NO_THROW(
- socket2 = ifacemgr->openSocketFromIface(LOOPBACK, PORT2, AF_INET);
+ socket2 = ifacemgr->openSocketFromIface(LOOPBACK_NAME, PORT2, AF_INET);
);
// socket descriptor must be non-negative integer
EXPECT_GE(socket2, 0);
IOAddress mcastAddr("ff02::1:2");
// bind multicast socket to port 10547
- int socket1 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
+ int socket1 = ifacemgr->openSocket(LOOPBACK_NAME, mcastAddr, 10547);
EXPECT_GE(socket1, 0); // socket > 0
// expect success. This address/port is already bound, but
// we are using SO_REUSEADDR, so we can bind it twice
- int socket2 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
+ int socket2 = ifacemgr->openSocket(LOOPBACK_NAME, mcastAddr, 10547);
EXPECT_GE(socket2, 0);
// there's no good way to test negative case here.
IOAddress lo_addr("127.0.0.1");
int socket1 = 0;
EXPECT_NO_THROW(
- socket1 = iface_mgr->openSocket(LOOPBACK, lo_addr, DHCP4_SERVER_PORT + 10000);
+ socket1 = iface_mgr->openSocket(LOOPBACK_NAME, lo_addr,
+ DHCP4_SERVER_PORT + 10000);
);
// Check that openSocket function was called.
IOAddress lo_addr("::1");
int socket1 = 0;
EXPECT_NO_THROW(
- socket1 = iface_mgr->openSocket(LOOPBACK, lo_addr,
+ socket1 = iface_mgr->openSocket(LOOPBACK_NAME, lo_addr,
DHCP6_SERVER_PORT + 10000);
);
// Check that openSocket function has been actually called on the packet
// So, let's close the sockets and retry. Now it should succeed.
iface_mgr->closeSockets();
EXPECT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));
-
}
-
#if defined OS_LINUX || OS_BSD
// This test is only supported on Linux and BSD systems. It checks
// PktFilterInet.
EXPECT_NO_THROW(iface_mgr1->setMatchingPacketFilter(false));
// Let's open a loopback socket with handy unpriviliged port number
- socket1 = iface_mgr1->openSocket(LOOPBACK, lo_addr,
+ socket1 = iface_mgr1->openSocket(LOOPBACK_NAME, lo_addr,
DHCP4_SERVER_PORT + 10000);
EXPECT_GE(socket1, 0);
// The socket is open and bound. Another attempt to open socket and
// bind to the same address and port should result in an exception.
EXPECT_THROW(
- socket2 = iface_mgr2->openSocket(LOOPBACK, lo_addr,
+ socket2 = iface_mgr2->openSocket(LOOPBACK_NAME, lo_addr,
DHCP4_SERVER_PORT + 10000),
isc::dhcp::SocketConfigError
);
int socket1 = 0;
EXPECT_NO_THROW(
- socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, DHCP4_SERVER_PORT + 10000);
+ socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr,
+ DHCP4_SERVER_PORT + 10000);
);
EXPECT_GE(socket1, 0);
- Pkt4 pkt(DHCPDISCOVER, 1234);
- pkt.setIface(LOOPBACK);
+ Pkt4Ptr pkt(new Pkt4(DHCPDISCOVER, 1234));
+ pkt->setIface(LOOPBACK_NAME);
+ pkt->setIndex(LOOPBACK_INDEX);
// Expect that we get the socket that we just opened.
EXPECT_EQ(socket1, ifacemgr->getSocket(pkt).sockfd_);
// Expect that the sockets are open on both eth0 and eth1.
EXPECT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
+ EXPECT_EQ(1, ifacemgr.getIface(1)->getSockets().size());
EXPECT_EQ(1, ifacemgr.getIface("eth1")->getSockets().size());
+ EXPECT_EQ(1, ifacemgr.getIface(2)->getSockets().size());
// Socket shouldn't have been opened on loopback.
EXPECT_TRUE(ifacemgr.getIface("lo")->getSockets().empty());
+ EXPECT_TRUE(ifacemgr.getIface(0)->getSockets().empty());
}
// This test verifies that IPv4 sockets are open on the loopback interface
// Expect that the sockets are open on all interfaces.
EXPECT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
+ EXPECT_EQ(1, ifacemgr.getIface(1)->getSockets().size());
EXPECT_EQ(1, ifacemgr.getIface("eth1")->getSockets().size());
+ EXPECT_EQ(1, ifacemgr.getIface(2)->getSockets().size());
EXPECT_EQ(1, ifacemgr.getIface("lo")->getSockets().size());
+ EXPECT_EQ(1, ifacemgr.getIface(0)->getSockets().size());
}
// This test verifies that the socket is not open on the interface which is
FlagRunning(false), FlagInactive4(false),
FlagInactive6(false));
ASSERT_FALSE(IfaceMgr::instance().getIface("eth0")->flag_up_);
+ ASSERT_FALSE(IfaceMgr::instance().getIface(1)->flag_up_);
// Install an error handler before trying to open sockets. This handler
// should be called when the IfaceMgr fails to open socket on an interface
// There should be no socket on eth0 open, because interface was down.
EXPECT_TRUE(IfaceMgr::instance().getIface("eth0")->getSockets().empty());
+ EXPECT_TRUE(IfaceMgr::instance().getIface(1)->getSockets().empty());
// Expecting that the socket is open on eth1 because it was up, running
// and active.
EXPECT_EQ(2, IfaceMgr::instance().getIface("eth1")->getSockets().size());
+ EXPECT_EQ(2, IfaceMgr::instance().getIface(2)->getSockets().size());
// Never open socket on loopback interface.
EXPECT_TRUE(IfaceMgr::instance().getIface("lo")->getSockets().empty());
-
+ EXPECT_TRUE(IfaceMgr::instance().getIface(0)->getSockets().empty());
}
// This test verifies that the socket is not open on the interface which is
// - is inactive
ifacemgr.setIfaceFlags("eth1", false, true, true, true, false);
ASSERT_TRUE(ifacemgr.getIface("eth1")->inactive4_);
+ ASSERT_TRUE(ifacemgr.getIface(2)->inactive4_);
ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0));
// The socket on eth0 should be open because interface is up, running and
// active (not disabled through DHCP configuration, for example).
EXPECT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
+ EXPECT_EQ(1, ifacemgr.getIface(1)->getSockets().size());
// There should be no socket open on eth1 because it was marked inactive.
EXPECT_TRUE(ifacemgr.getIface("eth1")->getSockets().empty());
+ EXPECT_TRUE(ifacemgr.getIface(2)->getSockets().empty());
// Sockets are not open on loopback interfaces too.
EXPECT_TRUE(ifacemgr.getIface("lo")->getSockets().empty());
+ EXPECT_TRUE(ifacemgr.getIface(0)->getSockets().empty());
}
// Test that exception is thrown when trying to bind a new socket to the port
// and bind it to the address in use.
EXPECT_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0),
isc::dhcp::SocketConfigError);
-
}
// Test that the external error handler is called when trying to bind a new
// when opening a socket on eth1.
ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, error_handler));
EXPECT_EQ(2, errors_count_);
-
}
// This test verifies that the function correctly checks that the v4 socket is
// Expect that the sockets are open on both eth0 and eth1.
ASSERT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
+ ASSERT_EQ(1, ifacemgr.getIface(1)->getSockets().size());
ASSERT_EQ(1, ifacemgr.getIface("eth1")->getSockets().size());
+ ASSERT_EQ(1, ifacemgr.getIface(2)->getSockets().size());
// Socket shouldn't have been opened on loopback.
ASSERT_TRUE(ifacemgr.getIface("lo")->getSockets().empty());
+ ASSERT_TRUE(ifacemgr.getIface(0)->getSockets().empty());
// Check that there are sockets bound to addresses that we have
// set for interfaces.
// Check that v4 sockets are open, but no v6 socket is open.
EXPECT_TRUE(ifacemgr.hasOpenSocket(AF_INET));
EXPECT_FALSE(ifacemgr.hasOpenSocket(AF_INET6));
-
}
// This test checks that the sockets are open and bound to link local addresses
// Check that the number of sockets is correct on each interface.
checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(0), 0);
checkSocketsCount6(*ifacemgr.getIface("eth0"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(1), 0);
checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(2), 0);
// Sockets on eth0 should be bound to link-local and should not be bound
// to global unicast address, even though this address is configured on
// Check that the loopback interface has at least an open socket.
EXPECT_EQ(1, ifacemgr.getIface("lo")->getSockets().size());
+ EXPECT_EQ(1, ifacemgr.getIface(0)->getSockets().size());
// This socket should be bound to ::1
EXPECT_TRUE(ifacemgr.isBound("lo", "::1"));
// Check that the number of sockets is correct on each interface.
checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(0), 0);
// The third parameter specifies that the number of link-local
// addresses for eth0 is equal to 0.
checkSocketsCount6(*ifacemgr.getIface("eth0"), 0, 0);
+ checkSocketsCount6(*ifacemgr.getIface(1), 0, 0);
checkSocketsCount6(*ifacemgr.getIface("eth1"), 0, 1);
+ checkSocketsCount6(*ifacemgr.getIface(2), 0, 1);
// There should be no sockets open on eth0 because it neither has
// link-local nor global unicast addresses.
#if defined OS_LINUX
EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
-
}
// This test checks that socket is open on the non-multicast-capable
// Check that the number of sockets is correct on each interface.
checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(0), 0);
checkSocketsCount6(*ifacemgr.getIface("eth0"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(1), 0);
checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(2), 0);
// Sockets on eth0 should be bound to link-local and should not be bound
// to global unicast address, even though this address is configured on
// Check that we have correct number of sockets on each interface.
checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(0), 0);
checkSocketsCount6(*ifacemgr.getIface("eth0"), 1); // one unicast address.
+ checkSocketsCount6(*ifacemgr.getIface(1), 1);
checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(2), 0);
// eth0 should have two sockets, one bound to link-local, another one
// bound to unicast address.
EXPECT_TRUE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
-
}
// This test checks that the socket is open and bound to a global unicast
// Check that we have correct number of sockets on each interface.
checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(0), 0);
checkSocketsCount6(*ifacemgr.getIface("eth0"), 1, 0);
+ checkSocketsCount6(*ifacemgr.getIface(1), 1, 0);
checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(2), 0);
// The link-local address is not present on eth0. Therefore, no socket
// must be bound to this address, nor to multicast address.
#if defined OS_LINUX
EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
-
}
// This test checks that no sockets are open for the interface which is down.
// Check that we have correct number of sockets on each interface.
checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(0), 0);
// There should be no sockets on eth0 because interface is down.
ASSERT_TRUE(ifacemgr.getIface("eth0")->getSockets().empty());
+ ASSERT_TRUE(ifacemgr.getIface(1)->getSockets().empty());
checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(2), 0);
// eth0 should have no sockets because the interface is down.
EXPECT_FALSE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
#if defined OS_LINUX
EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
-
}
// This test checks that no sockets are open for the interface which is
// Check that we have correct number of sockets on each interface.
checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
+ checkSocketsCount6(*ifacemgr.getIface(0), 0);
checkSocketsCount6(*ifacemgr.getIface("eth0"), 1); // one unicast address
+ checkSocketsCount6(*ifacemgr.getIface(1), 1);
// There should be no sockets on eth1 because interface is inactive
ASSERT_TRUE(ifacemgr.getIface("eth1")->getSockets().empty());
+ ASSERT_TRUE(ifacemgr.getIface(2)->getSockets().empty());
// eth0 should have one socket bound to a link-local address, another one
// bound to unicast address.
#if defined OS_LINUX
EXPECT_TRUE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
-
}
// Test that the openSockets6 function does not throw if there are no interfaces
// when opening a socket on eth1.
ASSERT_NO_THROW(ifacemgr.openSockets6(DHCP6_SERVER_PORT, error_handler));
EXPECT_EQ(2, errors_count_);
-
}
// This test verifies that the function correctly checks that the v6 socket is
// Check that there is no socket bound to the address which hasn't been
// configured on any interface.
EXPECT_FALSE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:feed:1")));
-
}
// Test the Iface structure itself
// Now let's test if IfaceMgr handles socket info properly
scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
- IfacePtr loopback = ifacemgr->getIface(LOOPBACK);
+ IfacePtr loopback = ifacemgr->getIface(LOOPBACK_NAME);
ASSERT_TRUE(loopback);
loopback->addSocket(sock1);
loopback->addSocket(sock2);
loopback->addSocket(sock3);
- Pkt6 pkt6(DHCPV6_REPLY, 123456);
+ Pkt6Ptr pkt6(new Pkt6(DHCPV6_REPLY, 123456));
// pkt6 does not have interface set yet
EXPECT_THROW(
);
// Try to send over non-existing interface
- pkt6.setIface("nosuchinterface45");
+ pkt6->setIface("nosuchinterface45");
+ pkt6->setIndex(12345);
EXPECT_THROW(
ifacemgr->getSocket(pkt6),
IfaceNotFound
);
// This will work
- pkt6.setIface(LOOPBACK);
+ pkt6->setIface(LOOPBACK_NAME);
+ EXPECT_EQ(9, ifacemgr->getSocket(pkt6));
+ pkt6->setIndex(LOOPBACK_INDEX);
EXPECT_EQ(9, ifacemgr->getSocket(pkt6));
bool deleted = false;
EXPECT_NO_THROW(
- deleted = ifacemgr->getIface(LOOPBACK)->delSocket(9);
+ deleted = ifacemgr->getIface(LOOPBACK_NAME)->delSocket(9);
);
EXPECT_EQ(true, deleted);
);
// Repeat for pkt4
- Pkt4 pkt4(DHCPDISCOVER, 1);
+ Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 1));
// pkt4 does not have interface set yet.
EXPECT_THROW(
);
// Try to send over non-existing interface.
- pkt4.setIface("nosuchinterface45");
+ pkt4->setIface("nosuchinterface45");
+ pkt4->setIndex(12345);
EXPECT_THROW(
ifacemgr->getSocket(pkt4),
IfaceNotFound
);
// Socket info is set, packet has well defined interface. It should work.
- pkt4.setIface(LOOPBACK);
+ pkt4->setIface(LOOPBACK_NAME);
+ EXPECT_EQ(7, ifacemgr->getSocket(pkt4).sockfd_);
+ pkt4->setIndex(LOOPBACK_INDEX);
EXPECT_EQ(7, ifacemgr->getSocket(pkt4).sockfd_);
// Set the local address to check if the socket for this address will
// be returned.
- pkt4.setLocalAddr(IOAddress("192.0.2.56"));
+ pkt4->setLocalAddr(IOAddress("192.0.2.56"));
EXPECT_EQ(7, ifacemgr->getSocket(pkt4).sockfd_);
// Modify the local address and expect that the other socket will be
// returned.
- pkt4.setLocalAddr(IOAddress("192.0.2.53"));
+ pkt4->setLocalAddr(IOAddress("192.0.2.53"));
EXPECT_EQ(8, ifacemgr->getSocket(pkt4).sockfd_);
EXPECT_NO_THROW(
- ifacemgr->getIface(LOOPBACK)->delSocket(7);
- ifacemgr->getIface(LOOPBACK)->delSocket(8);
+ ifacemgr->getIface(LOOPBACK_NAME)->delSocket(7);
+ ifacemgr->getIface(LOOPBACK_NAME)->delSocket(8);
);
// It should throw again, there's no usable socket anymore.
TEST_F(IfaceMgrTest, unicastDuplicates) {
NakedIfaceMgr ifacemgr;
- IfacePtr iface = ifacemgr.getIface(LOOPBACK);
+ IfacePtr iface = ifacemgr.getIface(LOOPBACK_NAME);
if (!iface) {
cout << "Local loopback interface not found. Skipping test. " << endl;
return;
IOAddress dst_global("2001:db8:15c::dead:beef");
// Bind loopback address
- int socket1 = ifacemgr->openSocket(LOOPBACK, lo_addr, 10547);
+ int socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547);
EXPECT_GE(socket1, 0); // socket >= 0
// Bind link-local address
- int socket2 = ifacemgr->openSocket(LOOPBACK, link_local, 10547);
+ int socket2 = ifacemgr->openSocket(LOOPBACK_NAME, link_local, 10547);
EXPECT_GE(socket2, 0);
- int socket3 = ifacemgr->openSocket(LOOPBACK, global, 10547);
+ int socket3 = ifacemgr->openSocket(LOOPBACK_NAME, global, 10547);
EXPECT_GE(socket3, 0);
// Let's make sure those sockets are unique
EXPECT_NE(socket3, socket1);
// Create a packet
- Pkt6 pkt6(DHCPV6_SOLICIT, 123);
- pkt6.setIface(LOOPBACK);
+ Pkt6Ptr pkt6(new Pkt6(DHCPV6_SOLICIT, 123));
+ pkt6->setIface(LOOPBACK_NAME);
+ pkt6->setIndex(LOOPBACK_INDEX);
// Check that packets sent to link-local will get socket bound to link local
- pkt6.setLocalAddr(global);
- pkt6.setRemoteAddr(dst_global);
+ pkt6->setLocalAddr(global);
+ pkt6->setRemoteAddr(dst_global);
EXPECT_EQ(socket3, ifacemgr->getSocket(pkt6));
// Check that packets sent to link-local will get socket bound to link local
- pkt6.setLocalAddr(link_local);
- pkt6.setRemoteAddr(dst_link_local);
+ pkt6->setLocalAddr(link_local);
+ pkt6->setRemoteAddr(dst_link_local);
EXPECT_EQ(socket2, ifacemgr->getSocket(pkt6));
// Close sockets here because the following tests will want to
-// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// this test includes two interfaces: "eth0" and "eth1". Therefore,
// we pick one or another, depending on the index of the iteration.
pkt->setIface(concatenate("eth", postfix % 2));
+ pkt->setIndex(ETH0_INDEX + postfix % 2);
// The remote address of the sender of the DHCPv6 packet is carried
// between the servers in the dedicated option. We use different
// Check that the interface is correct.
EXPECT_EQ(concatenate("eth", i % 2), pkt_received->getIface());
+ EXPECT_EQ(ETH0_INDEX + i % 2, pkt_received->getIndex());
// Check that the address conveyed is correct.
EXPECT_EQ(concatenate("2001:db8:1::", i),
ASSERT_NO_THROW(ipc_dest.open());
pkt->setIface("eth0");
+ pkt->setIndex(ETH0_INDEX);
pkt->setRemoteAddr(IOAddress("2001:db8:1::1"));
pkt->setRemotePort(TEST_PORT);
pkt->addOption(createDHCPv4MsgOption(TestIpc::ENDPOINT_TYPE_V6));