BIND 10 trac1230, updated. de6f226ae7bc45d144b6e012884bfd28ca74e350 [1230] Generic DHCPv6 server clean-up:
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Dec 27 13:49:08 UTC 2011
The branch, trac1230 has been updated
via de6f226ae7bc45d144b6e012884bfd28ca74e350 (commit)
from 3344e8b8d949fa9b4bcd9cf007f6a234f0fa5b1c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit de6f226ae7bc45d144b6e012884bfd28ca74e350
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Tue Dec 27 14:48:29 2011 +0100
[1230] Generic DHCPv6 server clean-up:
- DHCPv6 server now sends DNS-SERVERS option
- refactored processSolicit(), processRequest()
- added appendDefaultOptions(), appendRequestedOptions(), assignLeases()
- many parameters are now const &
- const HARDCODDED_* parameters added for similar customizations
- IfaceMgr::openSockets6() now skips loopback, down, or unicast interfaces.
-----------------------------------------------------------------------
Summary of changes:
src/bin/dhcp6/dhcp6_srv.cc | 123 ++++++++++++++++++++++++++++++-------------
src/bin/dhcp6/dhcp6_srv.h | 60 ++++++++++++++++++---
src/lib/dhcp/iface_mgr.cc | 49 +++++++++++------
3 files changed, 169 insertions(+), 63 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 7d1b549..4e69f05 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -18,6 +18,7 @@
#include <dhcp6/dhcp6_srv.h>
#include <dhcp/option6_ia.h>
#include <dhcp/option6_iaaddr.h>
+#include <dhcp/option6_addrlst.h>
#include <asiolink/io_address.h>
#include <exceptions/exceptions.h>
@@ -26,21 +27,28 @@ using namespace isc;
using namespace isc::dhcp;
using namespace isc::asiolink;
+const std::string HARDCODED_LEASE = "2001:db8:1::1234:abcd";
+const uint32_t HARDCODED_T1 = 1500; // in seconds
+const uint32_t HARDCODED_T2 = 2600; // in seconds
+const uint32_t HARDCODED_PREFERRED_LIFETIME = 3600; // in seconds
+const uint32_t HARDCODED_VALID_LIFETIME = 7200; // in seconds
+const std::string HARDCODED_DNS_SERVER = "2001:db8:1::1";
+
Dhcpv6Srv::Dhcpv6Srv(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
try {
- IfaceMgr::instance();
+ IfaceMgr::instance();
} catch (const std::exception &e) {
- cout << "Failed to instantiate InterfaceManager:" << e.what() << ". Aborting." << endl;
- shutdown = true;
+ 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;
+ cout << "Failed to detect any network interfaces. Aborting." << endl;
+ shutdown = true;
}
// Now try to open IPv6 sockets on detected interfaces.
@@ -115,8 +123,9 @@ Dhcpv6Srv::run() {
cout << "Replying with:" << rsp->getType() << endl;
cout << rsp->toText();
cout << "----" << endl;
- if (rsp->pack()) {
- cout << "#### pack successful." << endl;
+ if (!rsp->pack()) {
+ cout << "Failed to assemble response packet." << endl;
+ continue;
}
IfaceMgr::instance().send(rsp);
}
@@ -149,18 +158,45 @@ Dhcpv6Srv::setServerID() {
0, 14));
}
-boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processSolicit(boost::shared_ptr<Pkt6> solicit) {
+void Dhcpv6Srv::copyDefaultOptions(const boost::shared_ptr<Pkt6>& question,
+ boost::shared_ptr<Pkt6>& answer) {
+ // add client-id
+ boost::shared_ptr<Option> clientid = question->getOption(D6O_CLIENTID);
+ if (clientid) {
+ answer->addOption(clientid);
+ }
- boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_ADVERTISE,
- solicit->getTransid(),
- Pkt6::UDP));
+ // TODO: Should throw if there is no client-id (except anonymous INF-REQUEST)
+}
+
+void Dhcpv6Srv::appendDefaultOptions(const boost::shared_ptr<Pkt6>& /*question*/,
+ boost::shared_ptr<Pkt6>& answer) {
+ // TODO: question is currently unused, but we need it at least to know
+ // message type we are answering
+ // add server-id
+ answer->addOption(getServerID());
+}
+
+
+void Dhcpv6Srv::appendRequestedOptions(const boost::shared_ptr<Pkt6>& /*question*/,
+ boost::shared_ptr<Pkt6>& answer) {
+ // TODO: question is currently unused, but we need to extract ORO from it
+ // and act on its content. Now we just send DNS-SERVERS option.
+
+ // add dns-servers option
+ boost::shared_ptr<Option> dnsservers(new Option6AddrLst(D6O_NAME_SERVERS,
+ IOAddress(HARDCODED_DNS_SERVER)));
+ answer->addOption(dnsservers);
+}
+
+void Dhcpv6Srv::assignLeases(const boost::shared_ptr<Pkt6>& question,
+ boost::shared_ptr<Pkt6>& answer) {
/// TODO Rewrite this once LeaseManager is implemented.
// answer client's IA (this is mostly a dummy,
// so let's answer only first IA and hope there is only one)
- boost::shared_ptr<Option> ia_opt = solicit->getOption(D6O_IA_NA);
+ boost::shared_ptr<Option> ia_opt = question->getOption(D6O_IA_NA);
if (ia_opt) {
// found IA
Option* tmp = ia_opt.get();
@@ -168,38 +204,51 @@ Dhcpv6Srv::processSolicit(boost::shared_ptr<Pkt6> solicit) {
if (ia_req) {
boost::shared_ptr<Option6IA>
ia_rsp(new Option6IA(D6O_IA_NA, ia_req->getIAID()));
- ia_rsp->setT1(1500);
- ia_rsp->setT2(2600);
+ ia_rsp->setT1(HARDCODED_T1);
+ ia_rsp->setT2(HARDCODED_T2);
boost::shared_ptr<Option6IAAddr>
addr(new Option6IAAddr(D6O_IAADDR,
- IOAddress("2001:db8:1234:5678::abcd"),
- 5000, 7000));
+ IOAddress(HARDCODED_LEASE),
+ HARDCODED_PREFERRED_LIFETIME,
+ HARDCODED_VALID_LIFETIME));
ia_rsp->addOption(addr);
- reply->addOption(ia_rsp);
+ answer->addOption(ia_rsp);
}
}
+}
- // add client-id
- boost::shared_ptr<Option> clientid = solicit->getOption(D6O_CLIENTID);
- if (clientid) {
- reply->addOption(clientid);
- }
+boost::shared_ptr<Pkt6>
+Dhcpv6Srv::processSolicit(const boost::shared_ptr<Pkt6>& solicit) {
- // add server-id
- reply->addOption(getServerID());
- return reply;
+ boost::shared_ptr<Pkt6> advertise(new Pkt6(DHCPV6_ADVERTISE,
+ solicit->getTransid()));
+
+ copyDefaultOptions(solicit, advertise);
+ appendDefaultOptions(solicit, advertise);
+ appendRequestedOptions(solicit, advertise);
+
+ assignLeases(solicit, advertise);
+
+ return (advertise);
}
boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processRequest(boost::shared_ptr<Pkt6> request) {
- /// TODO: Implement processRequest() for real
- boost::shared_ptr<Pkt6> reply = processSolicit(request);
- reply->setType(DHCPV6_REPLY);
- return reply;
+Dhcpv6Srv::processRequest(const boost::shared_ptr<Pkt6>& request) {
+
+ boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
+ request->getTransid()));
+
+ copyDefaultOptions(request, reply);
+ appendDefaultOptions(request, reply);
+ appendRequestedOptions(request, reply);
+
+ assignLeases(request, reply);
+
+ return (reply);
}
boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processRenew(boost::shared_ptr<Pkt6> renew) {
+Dhcpv6Srv::processRenew(const boost::shared_ptr<Pkt6>& renew) {
boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
renew->getTransid(),
Pkt6::UDP));
@@ -207,7 +256,7 @@ Dhcpv6Srv::processRenew(boost::shared_ptr<Pkt6> renew) {
}
boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processRebind(boost::shared_ptr<Pkt6> rebind) {
+Dhcpv6Srv::processRebind(const boost::shared_ptr<Pkt6>& rebind) {
boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
rebind->getTransid(),
Pkt6::UDP));
@@ -215,7 +264,7 @@ Dhcpv6Srv::processRebind(boost::shared_ptr<Pkt6> rebind) {
}
boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processConfirm(boost::shared_ptr<Pkt6> confirm) {
+Dhcpv6Srv::processConfirm(const boost::shared_ptr<Pkt6>& confirm) {
boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
confirm->getTransid(),
Pkt6::UDP));
@@ -223,7 +272,7 @@ Dhcpv6Srv::processConfirm(boost::shared_ptr<Pkt6> confirm) {
}
boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processRelease(boost::shared_ptr<Pkt6> release) {
+Dhcpv6Srv::processRelease(const boost::shared_ptr<Pkt6>& release) {
boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
release->getTransid(),
Pkt6::UDP));
@@ -231,7 +280,7 @@ Dhcpv6Srv::processRelease(boost::shared_ptr<Pkt6> release) {
}
boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processDecline(boost::shared_ptr<Pkt6> decline) {
+Dhcpv6Srv::processDecline(const boost::shared_ptr<Pkt6>& decline) {
boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
decline->getTransid(),
Pkt6::UDP));
@@ -239,7 +288,7 @@ Dhcpv6Srv::processDecline(boost::shared_ptr<Pkt6> decline) {
}
boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processInfRequest(boost::shared_ptr<Pkt6> infRequest) {
+Dhcpv6Srv::processInfRequest(const boost::shared_ptr<Pkt6>& infRequest) {
boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
infRequest->getTransid(),
Pkt6::UDP));
diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h
index bcc7818..44a9f8a 100644
--- a/src/bin/dhcp6/dhcp6_srv.h
+++ b/src/bin/dhcp6/dhcp6_srv.h
@@ -81,7 +81,7 @@ protected:
///
/// @return ADVERTISE, REPLY message or NULL
boost::shared_ptr<Pkt6>
- processSolicit(boost::shared_ptr<Pkt6> solicit);
+ processSolicit(const boost::shared_ptr<Pkt6>& solicit);
/// @brief Processes incoming REQUEST and returns REPLY response.
///
@@ -95,43 +95,87 @@ protected:
///
/// @return REPLY message or NULL
boost::shared_ptr<Pkt6>
- processRequest(boost::shared_ptr<Pkt6> request);
+ processRequest(const boost::shared_ptr<Pkt6>& request);
/// @brief Stub function that will handle incoming RENEW messages.
///
/// @param renew message received from client
boost::shared_ptr<Pkt6>
- processRenew(boost::shared_ptr<Pkt6> renew);
+ processRenew(const boost::shared_ptr<Pkt6>& renew);
/// @brief Stub function that will handle incoming REBIND messages.
///
/// @param rebind message received from client
boost::shared_ptr<Pkt6>
- processRebind(boost::shared_ptr<Pkt6> rebind);
+ processRebind(const boost::shared_ptr<Pkt6>& rebind);
/// @brief Stub function that will handle incoming CONFIRM messages.
///
/// @param confirm message received from client
boost::shared_ptr<Pkt6>
- processConfirm(boost::shared_ptr<Pkt6> confirm);
+ processConfirm(const boost::shared_ptr<Pkt6>& confirm);
/// @brief Stub function that will handle incoming RELEASE messages.
///
/// @param release message received from client
boost::shared_ptr<Pkt6>
- processRelease(boost::shared_ptr<Pkt6> release);
+ processRelease(const boost::shared_ptr<Pkt6>& release);
/// @brief Stub function that will handle incoming DECLINE messages.
///
/// @param decline message received from client
boost::shared_ptr<Pkt6>
- processDecline(boost::shared_ptr<Pkt6> decline);
+ processDecline(const boost::shared_ptr<Pkt6>& decline);
/// @brief Stub function that will handle incoming INF-REQUEST messages.
///
/// @param infRequest message received from client
boost::shared_ptr<Pkt6>
- processInfRequest(boost::shared_ptr<Pkt6> infRequest);
+ processInfRequest(const boost::shared_ptr<Pkt6>& infRequest);
+
+ /// @brief Copies required options from client message to server answer
+ ///
+ /// Copies options that must appear in any server response (ADVERTISE, REPLY)
+ /// to client's messages (SOLICIT, REQUEST, RENEW, REBIND, DECLINE, RELEASE).
+ /// One notable example is client-id. Other options may be copied as required.
+ ///
+ /// @param question client's message (options will be copied from here)
+ /// @param answer server's message (options will be copied here)
+ void copyDefaultOptions(const boost::shared_ptr<Pkt6>& question,
+ boost::shared_ptr<Pkt6>& answer);
+
+ /// @brief Appends default options to server's answer.
+ ///
+ /// Adds required options to server's answer. In particular, server-id
+ /// is added. Possibly other mandatory options will be added, depending
+ /// on type (or content) of client message.
+ ///
+ /// @param question client's message
+ /// @param answer server's message (options will be added here)
+ void appendDefaultOptions(const boost::shared_ptr<Pkt6>& question,
+ boost::shared_ptr<Pkt6>& answer);
+
+ /// @brief Appends requested options to server's answer.
+ ///
+ /// Appends options requested by client to the server's answer.
+ /// TODO: This method is currently a stub. It just appends DNS-SERVERS
+ /// option.
+ ///
+ /// @param question client's message
+ /// @param answer server's message (options will be added here)
+ void appendRequestedOptions(const boost::shared_ptr<Pkt6>& question,
+ boost::shared_ptr<Pkt6>& answer);
+
+ /// @brief Assigns leases.
+ ///
+ /// TODO: This method is currently a stub. It just appends one
+ /// hardcoded lease. It supports addresses (IA_NA) only. It does NOT
+ /// support temporary addresses (IA_TA) nor prefixes (IA_PD).
+ ///
+ /// @param question client's message (with requested IA_NA)
+ /// @param answer server's message (IA_NA options will be added here)
+ void assignLeases(const boost::shared_ptr<Pkt6>& question,
+ boost::shared_ptr<Pkt6>& answer);
/// @brief Sets server-identifier.
///
diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc
index e3e2a4a..c1aa36b 100644
--- a/src/lib/dhcp/iface_mgr.cc
+++ b/src/lib/dhcp/iface_mgr.cc
@@ -249,6 +249,12 @@ bool IfaceMgr::openSockets6(uint16_t port) {
iface!=ifaces_.end();
++iface) {
+ if (iface->flag_loopback_ ||
+ !iface->flag_up_ ||
+ !iface->flag_running_) {
+ continue;
+ }
+
AddressCollection addrs = iface->getAddresses();
for (AddressCollection::iterator addr= addrs.begin();
@@ -274,15 +280,15 @@ bool IfaceMgr::openSockets6(uint16_t port) {
}
count++;
-#if 0
+#if defined(OS_LINUX)
// this doesn't work too well on NetBSD
- sock2 = openSocket(iface->getName(),
- IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
- DHCP6_SERVER_PORT);
+ int sock2 = openSocket(iface->getName(),
+ IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
+ port);
if (sock2<0) {
isc_throw(Unexpected, "Failed to open multicast socket on "
<< " interface " << iface->getFullName());
- iface->delSocket(sock1); // delete previously opened socket
+ iface->delSocket(sock); // delete previously opened socket
}
#endif
}
@@ -875,25 +881,32 @@ IfaceMgr::receive6() {
/// all available sockets. For now, we just take the
/// first interface and use first socket from it.
IfaceCollection::const_iterator iface = ifaces_.begin();
- if (iface == ifaces_.end()) {
- isc_throw(Unexpected, "No interfaces detected. Can't receive anything.");
- }
- SocketCollection::const_iterator s = iface->sockets_.begin();
const SocketInfo* candidate = 0;
- while (s != iface->sockets_.end()) {
- if (s->addr_.getFamily() != AF_INET6) {
+ while (iface != ifaces_.end()) {
+ SocketCollection::const_iterator s = iface->sockets_.begin();
+ while (s != iface->sockets_.end()) {
+ if (s->addr_.getFamily() != AF_INET6) {
+ ++s;
+ continue;
+ }
+ if (s->addr_.getAddress().to_v6().is_multicast()) {
+ candidate = &(*s);
+ break;
+ }
+ if (!candidate) {
+ candidate = &(*s); // it's not multicast, but it's better than nothing
+ }
++s;
- continue;
}
- if (s->addr_.getAddress().to_v6().is_multicast()) {
- candidate = &(*s);
+ if (candidate) {
break;
}
- if (!candidate) {
- candidate = &(*s); // it's not multicast, but it's better than nothing
- }
- ++s;
+ ++iface;
}
+ if (iface == ifaces_.end()) {
+ isc_throw(Unexpected, "No interfaces detected. Can't receive anything.");
+ }
+
if (!candidate) {
isc_throw(Unexpected, "Interface " << iface->getFullName()
<< " does not have any sockets open.");
More information about the bind10-changes
mailing list