|
@@ -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));
|