Commit 31162437 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[master] Merge branch 'trac3695'

parents 4ace9f75 15d0f2ed
......@@ -377,11 +377,9 @@ It is anticipated that this form of usage will only be used when it is desired t
temporarily override a list of interface names and listen on all interfaces.
</para>
<para>Some deployments of the DHCP servers require that the servers listen
on the interfaces with multiple IPv4 addresses configured. In some cases,
multiple instances of the DHCP servers are running concurrently and each
instance should be bound to a different address on the particular interface.
In these situations, the address to use can be selected by
appending an IPv4 address to the interface name in the following manner:
on the interfaces with multiple IPv4 addresses configured. In these situations,
the address to use can be selected by appending an IPv4 address to the interface
name in the following manner:
<screen>
"Dhcp4": {
"interfaces-config": {
......@@ -390,9 +388,24 @@ temporarily override a list of interface names and listen on all interfaces.
...
}
</screen>
Note that only one address can be specified on each interface.
</para>
<para>If it is desired that the server listens on multiple IPv4 addresses assigned
to the same interface, multiple addresses can be specified for this interface
as in the example below:
<screen>
"Dhcp4": {
"interfaces-config": {
"interfaces": [ <userinput>"eth1/10.0.0.1", "eth1/10.0.0.2"</userinput> ]
},
...
}
</screen>
</para>
<para>Alternatively, if the server should listen on all addresses for the particular
interface, an interface name without any address should be specified.</para>
<para>Kea supports responding to directly connected clients which don't have
an address configured on the interface yet. This requires that the server
injects the hardware address of the destination into the data link layer
......@@ -428,6 +441,20 @@ temporarily override a list of interface names and listen on all interfaces.
default value <userinput>raw</userinput> is used.
</para>
<para>Using UDP sockets automatically disables the reception of brodcast
packets from directly connected clients. This effectively means that the
UDP sockets can be used for relayed traffic only. When using the raw sockets,
both the traffic from the directly connected clients and the relayed traffic
will be handled. Caution should be taken when configuring the server to open
multiple raw sockets on the interface with several IPv4 addresses assigned.
If the directly connected client sends the message to the brodcast address
all sockets on this link will receive this message and multiple responses
will be sent to the client. Hence, the configuration with multiple IPv4
addresses assigned to the interface should not be used when the directly
connected clients are operating on that link. To use a single address on
such interface, the "interface-name/address" notation should be used.
</para>
<note>
<para>Specifying the value <userinput>raw</userinput> as the socket type,
doesn't guarantee that the raw sockets will be used! The use of raw sockets
......
......@@ -522,10 +522,10 @@ Dhcpv4Srv::copyDefaultFields(const Pkt4Ptr& question, Pkt4Ptr& answer) {
answer->setIface(question->getIface());
answer->setIndex(question->getIndex());
answer->setSiaddr(IOAddress("0.0.0.0")); // explicitly set this to 0
answer->setSiaddr(IOAddress::IPV4_ZERO_ADDRESS()); // explicitly set this to 0
// ciaddr is always 0, except for the Renew/Rebind state when it may
// be set to the ciaddr sent by the client.
answer->setCiaddr(IOAddress("0.0.0.0"));
answer->setCiaddr(IOAddress::IPV4_ZERO_ADDRESS());
answer->setHops(question->getHops());
// copy MAC address
......@@ -949,7 +949,7 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
.arg(question->getRemoteAddr().toText())
.arg(serverReceivedPacketName(question->getType()));
answer->setType(DHCPNAK);
answer->setYiaddr(IOAddress("0.0.0.0"));
answer->setYiaddr(IOAddress::IPV4_ZERO_ADDRESS());
return;
}
......@@ -981,11 +981,11 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
// ciaddr.
OptionCustomPtr opt_requested_address = boost::dynamic_pointer_cast<
OptionCustom>(question->getOption(DHO_DHCP_REQUESTED_ADDRESS));
IOAddress hint("0.0.0.0");
IOAddress hint(0);
if (opt_requested_address) {
hint = opt_requested_address->readAddress();
} else if (question->getCiaddr() != IOAddress("0.0.0.0")) {
} else if (question->getCiaddr() != IOAddress::IPV4_ZERO_ADDRESS()) {
hint = question->getCiaddr();
}
......@@ -1023,7 +1023,7 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
.arg(hwaddr ? hwaddr->toText():"(no hwaddr info)");
answer->setType(DHCPNAK);
answer->setYiaddr(IOAddress("0.0.0.0"));
answer->setYiaddr(IOAddress::IPV4_ZERO_ADDRESS());
return;
}
// Now check the second error case: unknown client.
......@@ -1191,7 +1191,7 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
.arg(hint.toText());
answer->setType(DHCPNAK);
answer->setYiaddr(IOAddress("0.0.0.0"));
answer->setYiaddr(IOAddress::IPV4_ZERO_ADDRESS());
answer->delOption(DHO_FQDN);
answer->delOption(DHO_HOST_NAME);
......@@ -1211,6 +1211,27 @@ Dhcpv4Srv::adjustIfaceData(const Pkt4Ptr& query, const Pkt4Ptr& response) {
response->setRemotePort(query->isRelayed() ? DHCP4_SERVER_PORT :
DHCP4_CLIENT_PORT);
IOAddress local_addr = query->getLocalAddr();
// In many cases the query is sent to a broadcast address. This address
// apears as a local address in the query message. We can't simply copy
// this address to a response message and use it as a source address.
// Instead we will need to use the address assigned to the interface
// on which the query has been received. In other cases, we will just
// use this address as a source address for the response.
if (local_addr == IOAddress::IPV4_BCAST_ADDRESS()) {
SocketInfo sock_info = IfaceMgr::instance().getSocket(*query);
local_addr = sock_info.addr_;
}
// We assume that there is an appropriate socket bound to this address
// and that the address is correct. This is safe assumption because
// the local address of the query is set when the query is received.
// The query sent to an incorrect address wouldn't have been received.
// However, if socket is closed for this address between the reception
// of the query and sending a response, the IfaceMgr should detect it
// and return an error.
response->setLocalAddr(local_addr);
// In many cases the query is sent to a broadcast address. This address
// appears as a local address in the query message. Therefore we can't
// simply copy local address from the query and use it as a source
......@@ -1219,9 +1240,6 @@ Dhcpv4Srv::adjustIfaceData(const Pkt4Ptr& query, const Pkt4Ptr& response) {
// may throw if for some reason the socket is closed.
/// @todo Consider an optimization that we use local address from
/// the query if this address is not broadcast.
SocketInfo sock_info = IfaceMgr::instance().getSocket(*query);
// Set local address, port and interface.
response->setLocalAddr(sock_info.addr_);
response->setLocalPort(DHCP4_SERVER_PORT);
response->setIface(query->getIface());
response->setIndex(query->getIndex());
......@@ -1229,13 +1247,6 @@ Dhcpv4Srv::adjustIfaceData(const Pkt4Ptr& query, const Pkt4Ptr& response) {
void
Dhcpv4Srv::adjustRemoteAddr(const Pkt4Ptr& question, const Pkt4Ptr& response) {
// Let's create static objects representing zeroed and broadcast
// addresses. We will use them further in this function to test
// other addresses against them. Since they are static, they will
// be created only once.
static const IOAddress zero_addr("0.0.0.0");
static const IOAddress bcast_addr("255.255.255.255");
// The DHCPINFORM is slightly different than other messages in a sense
// that the server should always unicast the response to the ciaddr.
// It appears however that some clients don't set the ciaddr. We still
......@@ -1244,7 +1255,7 @@ Dhcpv4Srv::adjustRemoteAddr(const Pkt4Ptr& question, const Pkt4Ptr& response) {
if (question->getType() == DHCPINFORM) {
// If client adheres to RFC2131 it will set the ciaddr and in this
// case we always unicast our response to this address.
if (question->getCiaddr() != zero_addr) {
if (question->getCiaddr() != IOAddress::IPV4_ZERO_ADDRESS()) {
response->setRemoteAddr(question->getCiaddr());
// If we received DHCPINFORM via relay and the ciaddr is not set we
......@@ -1275,24 +1286,24 @@ Dhcpv4Srv::adjustRemoteAddr(const Pkt4Ptr& question, const Pkt4Ptr& response) {
// the message is relayed. Therefore, we set the BROADCAST flag so
// as the relay can broadcast the packet.
if ((question->getType() == DHCPINFORM) &&
(question->getCiaddr() == zero_addr)) {
(question->getCiaddr() == IOAddress::IPV4_ZERO_ADDRESS())) {
response->setFlags(BOOTP_BROADCAST);
}
response->setRemoteAddr(question->getGiaddr());
// If giaddr is 0 but client set ciaddr, server should unicast the
// response to ciaddr.
} else if (question->getCiaddr() != zero_addr) {
} else if (question->getCiaddr() != IOAddress::IPV4_ZERO_ADDRESS()) {
response->setRemoteAddr(question->getCiaddr());
// We can't unicast the response to the client when sending NAK,
// because we haven't allocated address for him. Therefore,
// NAK is broadcast.
} else if (response->getType() == DHCPNAK) {
response->setRemoteAddr(bcast_addr);
response->setRemoteAddr(IOAddress::IPV4_BCAST_ADDRESS());
// If yiaddr is set it means that we have created a lease for a client.
} else if (response->getYiaddr() != zero_addr) {
} else if (response->getYiaddr() != IOAddress::IPV4_ZERO_ADDRESS()) {
// If the broadcast bit is set in the flags field, we have to
// send the response to broadcast address. Client may have requested it
// because it doesn't support reception of messages on the interface
......@@ -1301,7 +1312,7 @@ Dhcpv4Srv::adjustRemoteAddr(const Pkt4Ptr& question, const Pkt4Ptr& response) {
// directly to a client without address assigned.
const bool bcast_flag = ((question->getFlags() & Pkt4::FLAG_BROADCAST_MASK) != 0);
if (!IfaceMgr::instance().isDirectResponseSupported() || bcast_flag) {
response->setRemoteAddr(bcast_addr);
response->setRemoteAddr(IOAddress::IPV4_BCAST_ADDRESS());
// Client cleared the broadcast bit and we support direct responses
// so we should unicast the response to a newly allocated address -
......@@ -1356,7 +1367,7 @@ Dhcpv4Srv::processDiscover(Pkt4Ptr& discover) {
}
// Adding any other options makes sense only when we got the lease.
if (offer->getYiaddr() != IOAddress("0.0.0.0")) {
if (offer->getYiaddr() != IOAddress::IPV4_ZERO_ADDRESS()) {
appendRequestedOptions(discover, offer);
appendRequestedVendorOptions(discover, offer);
// There are a few basic options that we always want to
......@@ -1408,7 +1419,7 @@ Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
}
// Adding any other options makes sense only when we got the lease.
if (ack->getYiaddr() != IOAddress("0.0.0.0")) {
if (ack->getYiaddr() != IOAddress::IPV4_ZERO_ADDRESS()) {
appendRequestedOptions(request, ack);
appendRequestedVendorOptions(request, ack);
// There are a few basic options that we always want to
......@@ -1562,7 +1573,7 @@ Dhcpv4Srv::processInform(Pkt4Ptr& inform) {
// Also Relay Agent Options should be removed if present.
if (ack->getRemoteAddr() != inform->getGiaddr()) {
ack->setHops(0);
ack->setGiaddr(IOAddress("0.0.0.0"));
ack->setGiaddr(IOAddress::IPV4_ZERO_ADDRESS());
ack->delOption(DHO_DHCP_AGENT_OPTIONS);
}
......@@ -1703,11 +1714,10 @@ Dhcpv4Srv::acceptDirectRequest(const Pkt4Ptr& pkt) const {
// The source address must not be zero for the DHCPINFORM message from
// the directly connected client because the server will not know where
// to respond if the ciaddr was not present.
static const IOAddress zero_addr("0.0.0.0");
try {
if (pkt->getType() == DHCPINFORM) {
if ((pkt->getRemoteAddr() == zero_addr) &&
(pkt->getCiaddr() == zero_addr)) {
if ((pkt->getRemoteAddr() == IOAddress::IPV4_ZERO_ADDRESS()) &&
(pkt->getCiaddr() == IOAddress::IPV4_ZERO_ADDRESS())) {
return (false);
}
}
......@@ -1717,8 +1727,7 @@ Dhcpv4Srv::acceptDirectRequest(const Pkt4Ptr& pkt) const {
// we validate the message type prior to calling this function.
return (false);
}
static const IOAddress bcast("255.255.255.255");
return ((pkt->getLocalAddr() != bcast || selectSubnet(pkt)));
return ((pkt->getLocalAddr() != IOAddress::IPV4_BCAST_ADDRESS() || selectSubnet(pkt)));
}
bool
......@@ -2034,7 +2043,7 @@ bool Dhcpv4Srv::classSpecificProcessing(const Pkt4Ptr& query, const Pkt4Ptr& rsp
if (query->inClass(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_EROUTER)) {
// Do not set TFTP server address for eRouter devices.
rsp->setSiaddr(IOAddress("0.0.0.0"));
rsp->setSiaddr(IOAddress::IPV4_ZERO_ADDRESS());
}
return (true);
......
......@@ -81,7 +81,7 @@ TEST_F(Dhcpv4SrvTest, adjustIfaceDataRelay) {
req->setFlags(0x0000);
// Set local address, port and interface.
req->setLocalAddr(IOAddress("192.0.2.1"));
req->setLocalAddr(IOAddress("192.0.2.5"));
req->setLocalPort(1001);
req->setIface("eth1");
req->setIndex(1);
......@@ -104,7 +104,7 @@ TEST_F(Dhcpv4SrvTest, adjustIfaceDataRelay) {
// The query has been relayed, so the response must be sent to the port 67.
EXPECT_EQ(DHCP4_SERVER_PORT, resp->getRemotePort());
// Local address should be the address assigned to interface eth1.
EXPECT_EQ("192.0.2.3", resp->getLocalAddr().toText());
EXPECT_EQ("192.0.2.5", resp->getLocalAddr().toText());
// The local port is always DHCPv4 server port 67.
EXPECT_EQ(DHCP4_SERVER_PORT, resp->getLocalPort());
// We will send response over the same interface which was used to receive
......@@ -184,7 +184,7 @@ TEST_F(Dhcpv4SrvTest, adjustIfaceDataRenew) {
EXPECT_EQ(DHCP4_CLIENT_PORT, resp->getRemotePort());
// The response should be sent from the unicast address on which the
// query has been received.
EXPECT_EQ("192.0.2.3", resp->getLocalAddr().toText());
EXPECT_EQ("192.0.2.1", resp->getLocalAddr().toText());
// The response should be sent from the DHCPv4 server port.
EXPECT_EQ(DHCP4_SERVER_PORT, resp->getLocalPort());
// The interface data should match the data in the query.
......
......@@ -656,6 +656,8 @@ TEST_F(DORATest, reservationsWithConflicts) {
// Client A performs 4-way exchange.
client.setState(Dhcp4Client::SELECTING);
// Revert to the broadcast address for the selcting client.
client.setDestAddress(IOAddress::IPV4_BCAST_ADDRESS());
// Obtain a lease from the server using the 4-way exchange.
ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<
IOAddress>(new IOAddress("0.0.0.0"))));
......
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2010,2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -230,6 +230,29 @@ public:
/// network byte order
operator uint32_t () const;
/// @name Methods returning @c IOAddress objects encapsulating typical addresses.
///
//@{
/// @brief Returns an address set to all zeros.
static const IOAddress& IPV4_ZERO_ADDRESS() {
static IOAddress address(0);
return (address);
}
/// @brief Returns a "255.255.255.255" broadcast address.
static const IOAddress& IPV4_BCAST_ADDRESS() {
static IOAddress address(0xFFFFFFFF);
return (address);
}
/// @brief Returns an IPv6 zero address.
static const IOAddress& IPV6_ZERO_ADDRESS() {
static IOAddress address("::");
return (address);
}
//@}
private:
asio::ip::address asio_address_;
};
......
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011, 2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -217,3 +217,9 @@ TEST(IOAddressTest, accessClassificationMethods) {
EXPECT_FALSE(addr5.isV6LinkLocal());
EXPECT_TRUE (addr5.isV6Multicast());
}
TEST(IOAddressTest, staticAddresses) {
EXPECT_EQ(IOAddress("0.0.0.0"), IOAddress::IPV4_ZERO_ADDRESS());
EXPECT_EQ(IOAddress("255.255.255.255"), IOAddress::IPV4_BCAST_ADDRESS());
EXPECT_EQ(IOAddress("::"), IOAddress::IPV6_ZERO_ADDRESS());
}
......@@ -257,6 +257,18 @@ Iface::setActive(const bool active) {
}
}
unsigned int
Iface::countActive4() const {
uint16_t count = 0;
for (AddressCollection::const_iterator addr_it = addrs_.begin();
addr_it != addrs_.end(); ++addr_it) {
if (addr_it->get().isV4() && addr_it->isSpecified()) {
++count;
}
}
return (count);
}
void IfaceMgr::closeSockets() {
for (IfaceCollection::iterator iface = ifaces_.begin();
iface != ifaces_.end(); ++iface) {
......@@ -1140,7 +1152,7 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
uint16_t IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
Iface* iface = getIface(pkt.getIface());
if (iface == NULL) {
isc_throw(BadValue, "Tried to find socket for non-existent interface");
isc_throw(IfaceNotFound, "Tried to find socket for non-existent interface");
}
......@@ -1189,7 +1201,7 @@ uint16_t IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
return (candidate->sockfd_);
}
isc_throw(Unexpected, "Interface " << iface->getFullName()
isc_throw(SocketNotFound, "Interface " << iface->getFullName()
<< " does not have any suitable IPv6 sockets open.");
}
......@@ -1197,22 +1209,33 @@ SocketInfo
IfaceMgr::getSocket(isc::dhcp::Pkt4 const& pkt) {
Iface* iface = getIface(pkt.getIface());
if (iface == NULL) {
isc_throw(BadValue, "Tried to find socket for non-existent interface");
isc_throw(IfaceNotFound, "Tried to find socket for non-existent interface");
}
const Iface::SocketCollection& socket_collection = iface->getSockets();
// A candidate being an end of the iterator marks that it is a begining of
// the socket search and that the candidate needs to be set to the first
// socket found.
Iface::SocketCollection::const_iterator candidate = socket_collection.end();
Iface::SocketCollection::const_iterator s;
for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
if (s->family_ == AF_INET) {
return (*s);
if (s->addr_ == pkt.getLocalAddr()) {
return (*s);
}
if (candidate == socket_collection.end()) {
candidate = s;
}
}
/// TODO: Add more checks here later. If remote address is
/// not link-local, we can't use link local bound socket
/// to send data.
}
isc_throw(Unexpected, "Interface " << iface->getFullName()
<< " does not have any suitable IPv4 sockets open.");
if (candidate == socket_collection.end()) {
isc_throw(SocketNotFound, "Interface " << iface->getFullName()
<< " does not have any suitable IPv4 sockets open.");
}
return (*candidate);
}
} // end of namespace isc::dhcp
......
......@@ -82,6 +82,20 @@ public:
isc::Exception(file, line, what) { };
};
/// @brief IfaceMgr exception thrown when there is no suitable interface.
class IfaceNotFound : public Exception {
public:
IfaceNotFound(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) { };
};
/// @brief IfaceMgr exception thrown when there is no suitable socket found.
class SocketNotFound : public Exception {
public:
SocketNotFound(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) { };
};
/// Holds information about socket.
struct SocketInfo {
......@@ -325,6 +339,9 @@ public:
/// should be active (if true) or inactive (if false).
void setActive(const bool active);
/// @brief Returns a number of activated IPv4 addresses on the interface.
unsigned int countActive4() const;
/// @brief Deletes an address from an interface.
///
/// This only deletes address from collection, it does not physically
......@@ -614,26 +631,30 @@ public:
///
/// This method takes Pkt6 (see overloaded implementation that takes
/// Pkt4) and chooses appropriate socket to send it. This method
/// may throw BadValue if specified packet does not have outbound
/// interface specified, no such interface exists, or specified
/// interface does not have any appropriate sockets open.
/// 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.
///
/// @param pkt a packet to be transmitted
///
/// @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);
/// @brief Return most suitable socket for transmitting specified IPv4 packet.
///
/// This method takes Pkt4 (see overloaded implementation that takes
/// Pkt6) and chooses appropriate socket to send it. This method
/// may throw BadValue if specified packet does not have outbound
/// interface specified, no such interface exists, or specified
/// interface does not have any appropriate sockets open.
/// This method uses the local address assigned to the packet and tries
/// to match it with addresses to which sockets are bound for the particular
/// interface. If the match is not found, the method returns the first IPv4
/// socket found for the particular interface. In case, there are no IPv4
/// sockets assigned to the interface the exception is thrown.
///
/// @param pkt a packet to be transmitted
/// @param pkt A packet to be transmitted. It must hold a local address and
/// a valid pointer to the interface.
///
/// @return A structure describing a socket.
/// @throw SocketNotFound if no suitable socket found.
SocketInfo getSocket(const isc::dhcp::Pkt4& pkt);
/// Debugging method that prints out all available interfaces.
......
......@@ -90,6 +90,28 @@ TEST(IfaceTest, readBuffer) {
}
}
// Check that counting the number of active addresses on the interface
// works as expected.
TEST(IfaceTest, countActive4) {
Iface iface("eth0", 0);
ASSERT_EQ(0, iface.countActive4());
iface.addAddress(IOAddress("192.168.0.2"));
ASSERT_EQ(1, iface.countActive4());
iface.addAddress(IOAddress("2001:db8:1::1"));
ASSERT_EQ(1, iface.countActive4());
iface.addAddress(IOAddress("192.168.0.3"));
ASSERT_EQ(2, iface.countActive4());
ASSERT_NO_THROW(iface.setActive(IOAddress("192.168.0.2"), false));
ASSERT_EQ(1, iface.countActive4());
ASSERT_NO_THROW(iface.setActive(IOAddress("192.168.0.3"), false));
ASSERT_EQ(0, iface.countActive4());
}
/// Mock object implementing PktFilter class. It is used by
/// IfaceMgrTest::setPacketFilter to verify that IfaceMgr::setPacketFilter
/// sets this object as a handler for opening sockets. This dummy
......@@ -2158,17 +2180,17 @@ TEST_F(IfaceMgrTest, socketInfo) {
Pkt6 pkt6(DHCPV6_REPLY, 123456);
// pkt6 dos not have interface set yet
// pkt6 does not have interface set yet
EXPECT_THROW(
ifacemgr->getSocket(pkt6),
BadValue
IfaceNotFound
);
// Try to send over non-existing interface
pkt6.setIface("nosuchinterface45");
EXPECT_THROW(
ifacemgr->getSocket(pkt6),
BadValue
IfaceNotFound
);
// This will work
......@@ -2184,7 +2206,7 @@ TEST_F(IfaceMgrTest, socketInfo) {
// It should throw again, there's no usable socket anymore
EXPECT_THROW(
ifacemgr->getSocket(pkt6),
Unexpected
SocketNotFound
);
// Repeat for pkt4
......@@ -2193,20 +2215,30 @@ TEST_F(IfaceMgrTest, socketInfo) {
// pkt4 does not have interface set yet.
EXPECT_THROW(
ifacemgr->getSocket(pkt4),
BadValue
IfaceNotFound
);
// Try to send over non-existing interface.
pkt4.setIface("nosuchinterface45");
EXPECT_THROW(
ifacemgr->getSocket(pkt4),
BadValue
IfaceNotFound
);
// Socket info is set, packet has well defined interface. It should work.
pkt4.setIface(LOOPBACK);
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"));
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"));
EXPECT_EQ(8, ifacemgr->getSocket(pkt4).sockfd_);
EXPECT_NO_THROW(
ifacemgr->getIface(LOOPBACK)->delSocket(7);
ifacemgr->getIface(LOOPBACK)->delSocket(8);
......@@ -2215,7 +2247,7 @@ TEST_F(IfaceMgrTest, socketInfo) {
// It should throw again, there's no usable socket anymore.
EXPECT_THROW(
ifacemgr->getSocket(pkt4),
Unexpected
SocketNotFound
);
}
......
......@@ -62,9 +62,9 @@ Pkt4Ptr PktCaptures::packetFromCapture(const std::string& hex_string) {
void PktCaptures::captureSetDefaultFields(const Pkt4Ptr& pkt) {
pkt->setRemotePort(546);
pkt->setRemoteAddr(IOAddress("fe80::1"));
pkt->setRemoteAddr(IOAddress("10.0.0.2"));
pkt->setLocalPort(0);
pkt->setLocalAddr(IOAddress("ff02::1:2"));
pkt->setLocalAddr(IOAddress("10.0.0.1"));
pkt->setIndex(2);
pkt->setIface("eth0");
}
......