-3XX. [func] tomek
++362. [func] tomek
+ libdhcp++: Interface detection in Linux implemented. libdhcp++
+ if now able to detect available network interfaces, its link-layer
+ addresses, flags and configured IPv4 and IPv6 addresses.
- (Trac #1237, git TBD)
++ (Trac #1237, git 8a040737426aece7cc92a795f2b712d7c3407513)
++
+361. [func] tomek
+ libdhcp++: Transmission and reception of DHCPv4 packets is now
+ implemented. Low-level hacks are not implemented for transmission
+ to hosts that don't have IPv4 address yet, so currently the code
+ is usable for communication with relays only, not hosts on the
+ same link.
+ (Trac #1239, #1240, git f382050248b5b7ed1881b086d89be2d9dd8fe385)
+
+360. [func] fdupont
+ Alpha version of DHCP benchmarking tool added. "perfdhcp" is able to
+ test both IPv4 and IPv6 servers: it can time the four-packet exchange
+ (DORA and SARR) as well as time the initial two-packet exchange (DO and
+ SA). More information can be obtained by invoking the utility (in
+ tests/tools/perfdhcp) with the "-h" flag.
+ (Trac #1450, git 85083a76107ba2236732b45524ce7018eefbaf90)
+
+359. [func]* vorner
+ The target parameter of ZoneFinder::find is no longer present, as the
+ interface was awkward. To get all the RRsets of a single domain, use
+ the new findAll method (the same applies to python version, the method
+ is named find_all).
+ (Trac #1483,#1484, git 0020456f8d118c9f3fd6fc585757c822b79a96f6)
349. [bug] dvv
resolver: If an upstream server responds with FORMERR to an EDNS query,
using namespace isc::asiolink;
Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
-
- //void Dhcpv6Srv::Dhcpv6Srv_impl(uint16_t port) {
cout << "Initialization" << endl;
- // First call to instance() will create IfaceMgr (it's a singleton).
- // It may throw something if things go wrong.
- IfaceMgr::instance();
+ // first call to instance() will create IfaceMgr (it's a singleton)
+ // it may throw something if things go wrong
+ try {
+ IfaceMgr::instance();
+ } catch (const std::exception &e) {
+ cout << "Failed to instantiate InterfaceManager:" << e.what() << ". Aborting." << endl;
+ shutdown = true;
+ }
+
+ if (IfaceMgr::instance().countIfaces() == 0) {
+ cout << "Failed to detect any network interfaces. Aborting." << endl;
+ shutdown = true;
+ }
// Now try to open IPv6 sockets on detected interfaces.
- cout << "Opening sockets on port " << port << endl;
-#if 0
- // uncomment this once #1238, #992 and #1239 are merged
IfaceMgr::instance().openSockets6(port);
-#endif
/// @todo: instantiate LeaseMgr here once it is imlpemented.
}
}
-void IfaceMgr::openSockets6(uint16_t port) {
- int sock1, sock2;
+ #if !defined(OS_LINUX) && !defined(OS_BSD)
+ void IfaceMgr::detectIfaces() {
+ stubDetectIfaces();
+ }
+ #endif
+
+bool IfaceMgr::openSockets4(uint16_t port) {
+ int sock;
+ int count = 0;
- for (IfaceCollection::iterator iface = ifaces_.begin();
- iface != ifaces_.end(); ++iface) {
+ for (IfaceCollection::iterator iface=ifaces_.begin();
+ iface!=ifaces_.end();
+ ++iface) {
+
+ cout << "Trying interface " << iface->getFullName() << endl;
+
+#if 0
+ if (iface->flag_loopback_ ||
+ !iface->flag_up_ ||
+ !iface->flag_running_) {
+ continue;
+ }
+#endif
AddressCollection addrs = iface->getAddresses();
addr != addrs.end();
++addr) {
- sock1 = openSocket(iface->getName(), *addr, port);
- if (sock1 < 0) {
- isc_throw(Unexpected, "Failed to open unicast socket on "
- << " interface " << iface->getFullName());
+ // skip IPv4 addresses
+ if (addr->getFamily() != AF_INET) {
+ continue;
}
- if ( !joinMulticast(sock1, iface->getName(),
- string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
- close(sock1);
+ sock = openSocket(iface->getName(), *addr, port);
+ if (sock<0) {
+ cout << "Failed to open unicast socket." << endl;
+ return (false);
+ }
+
+ count++;
+ }
+ }
+ return (count > 0);
+
+}
+
+bool IfaceMgr::openSockets6(uint16_t port) {
+ int sock;
+ int count = 0;
+
+ for (IfaceCollection::iterator iface=ifaces_.begin();
+ iface!=ifaces_.end();
+ ++iface) {
+
+ AddressCollection addrs = iface->getAddresses();
+
+ for (AddressCollection::iterator addr= addrs.begin();
+ addr != addrs.end();
+ ++addr) {
+
+ // skip IPv4 addresses
+ if (addr->getFamily() != AF_INET6) {
+ continue;
+ }
+
+ sock = openSocket(iface->getName(), *addr, port);
+ if (sock<0) {
+ cout << "Failed to open unicast socket." << endl;
+ return (false);
+ }
+
- if ( !joinMcast(sock, iface->getName(),
- string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
++ if ( !joinMulticast(sock, iface->getName(),
++ string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
+ close(sock);
isc_throw(Unexpected, "Failed to join " << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
<< " multicast group.");
}
/// Is used in destructor, but also from Dhcpv4_srv and Dhcpv6_srv classes.
void closeSockets();
+ /// Opens IPv4 sockets on detected interfaces.
+ /// Will throw exception if socket creation fails.
+ ///
+ /// @param port specifies port number (usually DHCP6_SERVER_PORT)
+ ///
+ /// @return true if any sockets were open
+ bool openSockets4(uint16_t port = DHCP4_SERVER_PORT);
+
+ /// @brief returns number of detected interfaces
+ ///
+ /// @return number of detected interfaces
+ uint16_t countIfaces() { return ifaces_.size(); }
+
// don't use private, we need derived classes in tests
protected:
TEST_F(IfaceMgrTest, basic) {
// checks that IfaceManager can be instantiated
+ createLoInterfacesTxt();
+ createLoInterfacesTxt();
+
IfaceMgr & ifacemgr = IfaceMgr::instance();
ASSERT_TRUE(&ifacemgr != 0);
}
EXPECT_EQ(static_cast<void*>(NULL), ifacemgr->getIface("wifi0") );
delete ifacemgr;
+
}
- TEST_F(IfaceMgrTest, detectIfaces) {
+ #if !defined(OS_LINUX)
+ TEST_F(IfaceMgrTest, detectIfaces_stub) {
// test detects that interfaces can be detected
// there is no code for that now, but interfaces are
EXPECT_TRUE( (rcvPkt->remote_port_ == 10546) || (rcvPkt->remote_port_ == 10547) );
delete ifacemgr;
- unlink(INTERFACE_FILE);
}
+TEST_F(IfaceMgrTest, sendReceive4) {
+
+ // testing socket operation in a portable way is tricky
+ // without interface detection implemented
+ createLoInterfacesTxt();
+
+ NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
+
+ // let's assume that every supported OS have lo interface
+ IOAddress loAddr("127.0.0.1");
+ int socket1 = 0, socket2 = 0;
+ EXPECT_NO_THROW(
+ socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
+ socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000 + 1);
+ );
+
+ boost::shared_ptr<Pkt4> sendPkt(new Pkt4(DHCPDISCOVER, 1234) );
+
+ sendPkt->setLocalAddr(IOAddress("127.0.0.1"));
+
+ 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->setHops(6);
+ sendPkt->setSecs(42);
+ sendPkt->setCiaddr(IOAddress("192.0.2.1"));
+ sendPkt->setSiaddr(IOAddress("192.0.2.2"));
+ sendPkt->setYiaddr(IOAddress("192.0.2.3"));
+ sendPkt->setGiaddr(IOAddress("192.0.2.4"));
+
+ uint8_t sname[] = "That's just a string that will act as SNAME";
+ sendPkt->setSname(sname, strlen((const char*)sname));
+ uint8_t file[] = "/another/string/that/acts/as/a/file_name.txt";
+ sendPkt->setFile(file, strlen((const char*)file));
+
+ ASSERT_NO_THROW(
+ sendPkt->pack();
+ );
+
+ boost::shared_ptr<Pkt4> rcvPkt;
+
+ EXPECT_EQ(true, ifacemgr->send(sendPkt));
+
+ rcvPkt = ifacemgr->receive4();
+
+ ASSERT_TRUE( rcvPkt ); // received our own packet
+
+ ASSERT_NO_THROW(
+ rcvPkt->unpack();
+ );
+
+ // let's check that we received what was sent
+ EXPECT_EQ(sendPkt->len(), rcvPkt->len());
+
+ EXPECT_EQ("127.0.0.1", rcvPkt->getRemoteAddr().toText());
+ EXPECT_EQ(sendPkt->getRemotePort(), rcvPkt->getLocalPort());
+
+ // now let's check content
+ EXPECT_EQ(sendPkt->getHops(), rcvPkt->getHops());
+ EXPECT_EQ(sendPkt->getOp(), rcvPkt->getOp());
+ EXPECT_EQ(sendPkt->getSecs(), rcvPkt->getSecs());
+ EXPECT_EQ(sendPkt->getFlags(), rcvPkt->getFlags());
+ EXPECT_EQ(sendPkt->getCiaddr(), rcvPkt->getCiaddr());
+ EXPECT_EQ(sendPkt->getSiaddr(), rcvPkt->getSiaddr());
+ EXPECT_EQ(sendPkt->getYiaddr(), rcvPkt->getYiaddr());
+ EXPECT_EQ(sendPkt->getGiaddr(), rcvPkt->getGiaddr());
+ EXPECT_EQ(sendPkt->getTransid(), rcvPkt->getTransid());
+ EXPECT_EQ(sendPkt->getType(), rcvPkt->getType());
+ EXPECT_TRUE(sendPkt->getSname() == rcvPkt->getSname());
+ EXPECT_TRUE(sendPkt->getFile() == rcvPkt->getFile());
+ EXPECT_EQ(sendPkt->getHtype(), rcvPkt->getHtype());
+ EXPECT_EQ(sendPkt->getHlen(), rcvPkt->getHlen());
+
+ // since we opened 2 sockets on the same interface and none of them is multicast,
+ // none is preferred over the other for sending data, so we really should not
+ // assume the one or the other will always be choosen for sending data. We should
+ // skip checking source port of sent address.
+
+ delete ifacemgr;
+}
+
+
TEST_F(IfaceMgrTest, socket4) {
createLoInterfacesTxt();