dhcp6_srv.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. // Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <stdlib.h>
  15. #include <time.h>
  16. #include <asiolink/io_address.h>
  17. #include <dhcp6/dhcp6_log.h>
  18. #include <dhcp6/dhcp6_srv.h>
  19. #include <dhcp/dhcp6.h>
  20. #include <dhcp/iface_mgr.h>
  21. #include <dhcp/libdhcp++.h>
  22. #include <dhcp/option6_addrlst.h>
  23. #include <dhcp/option6_iaaddr.h>
  24. #include <dhcp/option6_ia.h>
  25. #include <dhcp/option6_int_array.h>
  26. #include <dhcp/pkt6.h>
  27. #include <dhcp/subnet.h>
  28. #include <dhcp/cfgmgr.h>
  29. #include <exceptions/exceptions.h>
  30. #include <util/io_utilities.h>
  31. #include <util/range_utilities.h>
  32. #include <dhcp/duid.h>
  33. #include <dhcp/lease_mgr.h>
  34. #include <dhcp/cfgmgr.h>
  35. #include <dhcp/option6_iaaddr.h>
  36. // @todo: Replace this with MySQL_LeaseMgr (or a LeaseMgr factory)
  37. // once it is merged
  38. #include <dhcp/memfile_lease_mgr.h>
  39. #include <boost/foreach.hpp>
  40. using namespace isc;
  41. using namespace isc::asiolink;
  42. using namespace isc::dhcp;
  43. using namespace isc::util;
  44. using namespace std;
  45. using namespace boost;
  46. Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
  47. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_OPEN_SOCKET).arg(port);
  48. // Initialize objects required for DHCP server operation.
  49. try {
  50. // Initialize standard DHCPv6 option definitions. This function
  51. // may throw bad_alloc if system goes out of memory during the
  52. // creation if option definitions. It may also throw isc::Unexpected
  53. // if definitions are wrong. This would mean error in implementation.
  54. initStdOptionDefs();
  55. // Port 0 is used for testing purposes. It means that the server should
  56. // not open any sockets at all. Some tests, e.g. configuration parser,
  57. // require Dhcpv6Srv object, but they don't really need it to do
  58. // anything. This speed up and simplifies the tests.
  59. if (port > 0) {
  60. if (IfaceMgr::instance().countIfaces() == 0) {
  61. LOG_ERROR(dhcp6_logger, DHCP6_NO_INTERFACES);
  62. shutdown_ = true;
  63. return;
  64. }
  65. IfaceMgr::instance().openSockets6(port);
  66. }
  67. setServerID();
  68. } catch (const std::exception &e) {
  69. LOG_ERROR(dhcp6_logger, DHCP6_SRV_CONSTRUCT_ERROR).arg(e.what());
  70. shutdown_ = true;
  71. return;
  72. }
  73. // Instantiate LeaseMgr
  74. // @todo: Replace this with MySQL_LeaseMgr (or a LeaseMgr factory)
  75. // once it is merged
  76. new isc::dhcp::test::Memfile_LeaseMgr("");
  77. LOG_INFO(dhcp6_logger, DHCP6_DB_BACKEND_STARTED)
  78. .arg(LeaseMgr::instance().getName());
  79. // Instantiate allocation engine
  80. alloc_engine_ = new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100);
  81. shutdown_ = false;
  82. }
  83. Dhcpv6Srv::~Dhcpv6Srv() {
  84. IfaceMgr::instance().closeSockets();
  85. LeaseMgr::destroy_instance();
  86. }
  87. void Dhcpv6Srv::shutdown() {
  88. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_SHUTDOWN_REQUEST);
  89. shutdown_ = true;
  90. }
  91. bool Dhcpv6Srv::run() {
  92. while (!shutdown_) {
  93. /// @todo: calculate actual timeout to the next event (e.g. lease
  94. /// expiration) once we have lease database. The idea here is that
  95. /// it is possible to do everything in a single process/thread.
  96. /// For now, we are just calling select for 1000 seconds. There
  97. /// were some issues reported on some systems when calling select()
  98. /// with too large values. Unfortunately, I don't recall the details.
  99. int timeout = 1000;
  100. // client's message and server's response
  101. Pkt6Ptr query;
  102. Pkt6Ptr rsp;
  103. try {
  104. query = IfaceMgr::instance().receive6(timeout);
  105. } catch (const std::exception& e) {
  106. LOG_ERROR(dhcp6_logger, DHCP6_PACKET_RECEIVE_FAIL).arg(e.what());
  107. }
  108. if (query) {
  109. if (!query->unpack()) {
  110. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL,
  111. DHCP6_PACKET_PARSE_FAIL);
  112. continue;
  113. }
  114. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PACKET_RECEIVED)
  115. .arg(serverReceivedPacketName(query->getType()));
  116. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_QUERY_DATA)
  117. .arg(static_cast<int>(query->getType()))
  118. .arg(query->getBuffer().getLength())
  119. .arg(query->toText());
  120. switch (query->getType()) {
  121. case DHCPV6_SOLICIT:
  122. rsp = processSolicit(query);
  123. break;
  124. case DHCPV6_REQUEST:
  125. rsp = processRequest(query);
  126. break;
  127. case DHCPV6_RENEW:
  128. rsp = processRenew(query);
  129. break;
  130. case DHCPV6_REBIND:
  131. rsp = processRebind(query);
  132. break;
  133. case DHCPV6_CONFIRM:
  134. rsp = processConfirm(query);
  135. break;
  136. case DHCPV6_RELEASE:
  137. rsp = processRelease(query);
  138. break;
  139. case DHCPV6_DECLINE:
  140. rsp = processDecline(query);
  141. break;
  142. case DHCPV6_INFORMATION_REQUEST:
  143. rsp = processInfRequest(query);
  144. break;
  145. default:
  146. // Only action is to output a message if debug is enabled,
  147. // and that will be covered by the debug statement before
  148. // the "switch" statement.
  149. ;
  150. }
  151. if (rsp) {
  152. rsp->setRemoteAddr(query->getRemoteAddr());
  153. rsp->setLocalAddr(query->getLocalAddr());
  154. rsp->setRemotePort(DHCP6_CLIENT_PORT);
  155. rsp->setLocalPort(DHCP6_SERVER_PORT);
  156. rsp->setIndex(query->getIndex());
  157. rsp->setIface(query->getIface());
  158. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA,
  159. DHCP6_RESPONSE_DATA)
  160. .arg(rsp->getType()).arg(rsp->toText());
  161. if (rsp->pack()) {
  162. try {
  163. IfaceMgr::instance().send(rsp);
  164. } catch (const std::exception& e) {
  165. LOG_ERROR(dhcp6_logger, DHCP6_PACKET_SEND_FAIL).arg(e.what());
  166. }
  167. } else {
  168. LOG_ERROR(dhcp6_logger, DHCP6_PACK_FAIL);
  169. }
  170. }
  171. }
  172. // TODO add support for config session (see src/bin/auth/main.cc)
  173. // so this daemon can be controlled from bob
  174. }
  175. return (true);
  176. }
  177. void Dhcpv6Srv::setServerID() {
  178. /// @todo: DUID should be generated once and then stored, rather
  179. /// than generated each time
  180. /// @todo: This code implements support for DUID-LLT (the recommended one).
  181. /// We should eventually add support for other DUID types: DUID-LL, DUID-EN
  182. /// and DUID-UUID
  183. const IfaceMgr::IfaceCollection& ifaces = IfaceMgr::instance().getIfaces();
  184. // Let's find suitable interface.
  185. for (IfaceMgr::IfaceCollection::const_iterator iface = ifaces.begin();
  186. iface != ifaces.end(); ++iface) {
  187. // All the following checks could be merged into one multi-condition
  188. // statement, but let's keep them separated as perhaps one day
  189. // we will grow knobs to selectively turn them on or off. Also,
  190. // this code is used only *once* during first start on a new machine
  191. // and then server-id is stored. (or at least it will be once
  192. // DUID storage is implemente
  193. // I wish there was a this_is_a_real_physical_interface flag...
  194. // MAC address should be at least 6 bytes. Although there is no such
  195. // requirement in any RFC, all decent physical interfaces (Ethernet,
  196. // WiFi, Infiniband, etc.) have 6 bytes long MAC address. We want to
  197. // base our DUID on real hardware address, rather than virtual
  198. // interface that pretends that underlying IP address is its MAC.
  199. if (iface->getMacLen() < MIN_MAC_LEN) {
  200. continue;
  201. }
  202. // Let's don't use loopback.
  203. if (iface->flag_loopback_) {
  204. continue;
  205. }
  206. // Let's skip downed interfaces. It is better to use working ones.
  207. if (!iface->flag_up_) {
  208. continue;
  209. }
  210. // Some interfaces (like lo on Linux) report 6-bytes long
  211. // MAC adress 00:00:00:00:00:00. Let's not use such weird interfaces
  212. // to generate DUID.
  213. if (isRangeZero(iface->getMac(), iface->getMac() + iface->getMacLen())) {
  214. continue;
  215. }
  216. // Ok, we have useful MAC. Let's generate DUID-LLT based on
  217. // it. See RFC3315, Section 9.2 for details.
  218. // DUID uses seconds since midnight of 01-01-2000, time() returns
  219. // seconds since 01-01-1970. DUID_TIME_EPOCH substution corrects that.
  220. time_t seconds = time(NULL);
  221. seconds -= DUID_TIME_EPOCH;
  222. OptionBuffer srvid(8 + iface->getMacLen());
  223. writeUint16(DUID::DUID_LLT, &srvid[0]);
  224. writeUint16(HWTYPE_ETHERNET, &srvid[2]);
  225. writeUint32(static_cast<uint32_t>(seconds), &srvid[4]);
  226. memcpy(&srvid[0] + 8, iface->getMac(), iface->getMacLen());
  227. serverid_ = OptionPtr(new Option(Option::V6, D6O_SERVERID,
  228. srvid.begin(), srvid.end()));
  229. return;
  230. }
  231. // If we reached here, there are no suitable interfaces found.
  232. // Either interface detection is not supported on this platform or
  233. // this is really weird box. Let's use DUID-EN instead.
  234. // See Section 9.3 of RFC3315 for details.
  235. OptionBuffer srvid(12);
  236. writeUint16(DUID::DUID_EN, &srvid[0]);
  237. writeUint32(ENTERPRISE_ID_ISC, &srvid[2]);
  238. // Length of the identifier is company specific. I hereby declare
  239. // ISC "standard" of 6 bytes long pseudo-random numbers.
  240. srandom(time(NULL));
  241. fillRandom(&srvid[6], &srvid[12]);
  242. serverid_ = OptionPtr(new Option(Option::V6, D6O_SERVERID,
  243. srvid.begin(), srvid.end()));
  244. }
  245. void Dhcpv6Srv::copyDefaultOptions(const Pkt6Ptr& question, Pkt6Ptr& answer) {
  246. // Add client-id.
  247. OptionPtr clientid = question->getOption(D6O_CLIENTID);
  248. if (clientid) {
  249. answer->addOption(clientid);
  250. }
  251. // TODO: Should throw if there is no client-id (except anonymous INF-REQUEST)
  252. }
  253. void Dhcpv6Srv::appendDefaultOptions(const Pkt6Ptr& question, Pkt6Ptr& answer) {
  254. // add server-id
  255. answer->addOption(getServerID());
  256. // Get the subnet object. It holds options to be sent to the client
  257. // that belongs to the particular subnet.
  258. Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(question->getRemoteAddr());
  259. // Warn if subnet is not supported and quit.
  260. if (!subnet) {
  261. LOG_WARN(dhcp6_logger, DHCP6_NO_SUBNET_DEF_OPT)
  262. .arg(question->getRemoteAddr().toText());
  263. return;
  264. }
  265. }
  266. void Dhcpv6Srv::appendRequestedOptions(const Pkt6Ptr& question, Pkt6Ptr& answer) {
  267. // Get the subnet for a particular address.
  268. Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(question->getRemoteAddr());
  269. if (!subnet) {
  270. LOG_WARN(dhcp6_logger, DHCP6_NO_SUBNET_REQ_OPT)
  271. .arg(question->getRemoteAddr().toText());
  272. return;
  273. }
  274. // Client requests some options using ORO option. Try to
  275. // get this option from client's message.
  276. boost::shared_ptr<Option6IntArray<uint16_t> > option_oro =
  277. boost::dynamic_pointer_cast<Option6IntArray<uint16_t> >(question->getOption(D6O_ORO));
  278. // Option ORO not found. Don't do anything then.
  279. if (!option_oro) {
  280. return;
  281. }
  282. // Get the list of options that client requested.
  283. const std::vector<uint16_t>& requested_opts = option_oro->getValues();
  284. // Get the list of options configured for a subnet.
  285. const Subnet::OptionContainer& options = subnet->getOptions();
  286. const Subnet::OptionContainerTypeIndex& idx = options.get<1>();
  287. // Try to match requested options with those configured for a subnet.
  288. // If match is found, append configured option to the answer message.
  289. BOOST_FOREACH(uint16_t opt, requested_opts) {
  290. const Subnet::OptionContainerTypeRange& range = idx.equal_range(opt);
  291. BOOST_FOREACH(Subnet::OptionDescriptor desc, range) {
  292. answer->addOption(desc.option);
  293. }
  294. }
  295. }
  296. OptionPtr Dhcpv6Srv::createStatusCode(uint16_t code, const std::string& text) {
  297. // @todo: Implement Option6_StatusCode and rewrite this code here
  298. vector<uint8_t> data(text.c_str(), text.c_str() + text.length());
  299. data.insert(data.begin(), static_cast<uint8_t>(code % 256));
  300. data.insert(data.begin(), static_cast<uint8_t>(code >> 8));
  301. OptionPtr status(new Option(Option::V6, D6O_STATUS_CODE, data));
  302. return (status);
  303. }
  304. Subnet6Ptr Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) {
  305. Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(question->getRemoteAddr());
  306. return (subnet);
  307. }
  308. void Dhcpv6Srv::assignLeases(const Pkt6Ptr& question, Pkt6Ptr& answer) {
  309. // We need to allocate addresses for all IA_NA options in the client's
  310. // question (i.e. SOLICIT or REQUEST) message.
  311. // We need to select a subnet the client is connected in.
  312. Subnet6Ptr subnet = selectSubnet(question);
  313. if (subnet) {
  314. // This particular client is out of luck today. We do not have
  315. // information about the subnet he is connected to. This likely means
  316. // misconfiguration of the server (or some relays). We will continue to
  317. // process this message, but our response will be almost useless: no
  318. // addresses or prefixes, no subnet specific configuration etc. The only
  319. // thing this client can get is some global information (like DNS
  320. // servers).
  321. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_SUBNET_SELECTED)
  322. .arg(subnet->toText());
  323. } else {
  324. // perhaps this should be logged on some higher level? This is most likely
  325. // configuration bug.
  326. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_SUBNET_SELECTION_FAILED);
  327. }
  328. // @todo: We should implement Option6Duid some day, but we can do without it
  329. // just fine for now
  330. // Let's find client's DUID. Client is supposed to include its client-id
  331. // option almost all the time (the only exception is an anonymous inf-request,
  332. // but that is mostly a theoretical case). Our allocation engine needs DUID
  333. // and will refuse to allocate anything to anonymous clients.
  334. DuidPtr duid;
  335. OptionPtr opt_duid = question->getOption(D6O_CLIENTID);
  336. if (opt_duid) {
  337. duid = DuidPtr(new DUID(opt_duid->getData()));
  338. }
  339. // Now that we have all information about the client, let's iterate over all
  340. // received options and handle IA_NA options one by one and store our
  341. // responses in answer message (ADVERTISE or REPLY).
  342. //
  343. // @todo: expand this to cover IA_PD and IA_TA once we implement support for
  344. // prefix delegation and temporary addresses.
  345. for (Option::OptionCollection::iterator opt = question->options_.begin();
  346. opt != question->options_.end(); ++opt) {
  347. switch (opt->second->getType()) {
  348. case D6O_IA_NA: {
  349. OptionPtr answer_opt = handleIA_NA(subnet, duid, question,
  350. boost::dynamic_pointer_cast<Option6IA>(opt->second));
  351. if (answer_opt) {
  352. answer->addOption(answer_opt);
  353. }
  354. break;
  355. }
  356. default:
  357. break;
  358. }
  359. }
  360. }
  361. OptionPtr Dhcpv6Srv::handleIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid, Pkt6Ptr question,
  362. boost::shared_ptr<Option6IA> ia) {
  363. // If there is no subnet selected for handling this IA_NA, the only thing to do left is
  364. // to say that we are sorry, but the user won't get an address. As a convenience, we
  365. // use a different status text to indicate that (compare to the same status code,
  366. // but different wording below)
  367. if (!subnet) {
  368. // Create empty IA_NA option with IAID matching the request.
  369. boost::shared_ptr<Option6IA> ia_rsp(new Option6IA(D6O_IA_NA, ia->getIAID()));
  370. // Insert status code NoAddrsAvail.
  371. ia_rsp->addOption(createStatusCode(STATUS_NoAddrsAvail, "Sorry, no subnet available."));
  372. return (ia_rsp);
  373. }
  374. // Check if the client sent us a hint in his IA_NA. Clients may send an
  375. // address in their IA_NA options as a suggestion (e.g. the last address
  376. // they used before).
  377. shared_ptr<Option6IAAddr> hintOpt = dynamic_pointer_cast<Option6IAAddr>
  378. (ia->getOption(D6O_IAADDR));
  379. IOAddress hint("::");
  380. if (hintOpt) {
  381. hint = hintOpt->getAddress();
  382. }
  383. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PROCESS_IA_NA_REQUEST)
  384. .arg(duid?duid->toText():"(no-duid)").arg(ia->getIAID())
  385. .arg(hintOpt?hint.toText():"(no hint)");
  386. // "Fake" allocation is processing of SOLICIT message. We pretend to do an
  387. // allocation, but we do not put the lease in the database. That is ok,
  388. // because we do not guarantee that the user will get that exact lease. If
  389. // the user selects this server to do actual allocation (i.e. sends REQUEST)
  390. // it should include this hint. That will help us during the actual lease
  391. // allocation.
  392. bool fake_allocation = false;
  393. if (question->getType() == DHCPV6_SOLICIT) {
  394. /// @todo: Check if we support rapid commit
  395. fake_allocation = true;
  396. }
  397. // Use allocation engine to pick a lease for this client. Allocation engine
  398. // will try to honour the hint, but it is just a hint - some other address
  399. // may be used instead. If fake_allocation is set to false, the lease will
  400. // be inserted into the LeaseMgr as well.
  401. Lease6Ptr lease = alloc_engine_->allocateAddress6(subnet, duid, ia->getIAID(),
  402. hint, fake_allocation);
  403. // Create IA_NA that we will put in the response.
  404. boost::shared_ptr<Option6IA> ia_rsp(new Option6IA(D6O_IA_NA, ia->getIAID()));
  405. if (lease) {
  406. // We have a lease! Let's wrap its content into IA_NA option
  407. // with IAADDR suboption.
  408. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, fake_allocation?
  409. DHCP6_LEASE_ADVERT:DHCP6_LEASE_ALLOC)
  410. .arg(lease->addr_.toText())
  411. .arg(duid?duid->toText():"(no-duid)")
  412. .arg(ia->getIAID());
  413. ia_rsp->setT1(subnet->getT1());
  414. ia_rsp->setT2(subnet->getT2());
  415. boost::shared_ptr<Option6IAAddr>
  416. addr(new Option6IAAddr(D6O_IAADDR,
  417. lease->addr_,
  418. lease->preferred_lft_,
  419. lease->valid_lft_));
  420. ia_rsp->addOption(addr);
  421. // It would be possible to insert status code=0(success) as well,
  422. // but this is considered waste of bandwidth as absence of status
  423. // code is considered a success.
  424. } else {
  425. // Allocation engine did not allocate a lease. The engine logged
  426. // cause of that failure. The only thing left is to insert
  427. // status code to pass the sad news to the client.
  428. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, fake_allocation?
  429. DHCP6_LEASE_ADVERT_FAIL:DHCP6_LEASE_ALLOC_FAIL)
  430. .arg(duid?duid->toText():"(no-duid)")
  431. .arg(ia->getIAID())
  432. .arg(subnet->toText());
  433. ia_rsp->addOption(createStatusCode(STATUS_NoAddrsAvail,
  434. "Sorry, no address could be allocated."));
  435. }
  436. return (ia_rsp);
  437. }
  438. Pkt6Ptr Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) {
  439. Pkt6Ptr advertise(new Pkt6(DHCPV6_ADVERTISE, solicit->getTransid()));
  440. copyDefaultOptions(solicit, advertise);
  441. appendDefaultOptions(solicit, advertise);
  442. appendRequestedOptions(solicit, advertise);
  443. assignLeases(solicit, advertise);
  444. return (advertise);
  445. }
  446. Pkt6Ptr Dhcpv6Srv::processRequest(const Pkt6Ptr& request) {
  447. Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, request->getTransid()));
  448. copyDefaultOptions(request, reply);
  449. appendDefaultOptions(request, reply);
  450. appendRequestedOptions(request, reply);
  451. assignLeases(request, reply);
  452. return (reply);
  453. }
  454. Pkt6Ptr Dhcpv6Srv::processRenew(const Pkt6Ptr& renew) {
  455. /// @todo: Implement this
  456. Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, renew->getTransid()));
  457. return reply;
  458. }
  459. Pkt6Ptr Dhcpv6Srv::processRebind(const Pkt6Ptr& rebind) {
  460. /// @todo: Implement this
  461. Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, rebind->getTransid()));
  462. return reply;
  463. }
  464. Pkt6Ptr Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm) {
  465. /// @todo: Implement this
  466. Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, confirm->getTransid()));
  467. return reply;
  468. }
  469. Pkt6Ptr Dhcpv6Srv::processRelease(const Pkt6Ptr& release) {
  470. /// @todo: Implement this
  471. Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, release->getTransid()));
  472. return reply;
  473. }
  474. Pkt6Ptr Dhcpv6Srv::processDecline(const Pkt6Ptr& decline) {
  475. /// @todo: Implement this
  476. Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, decline->getTransid()));
  477. return reply;
  478. }
  479. Pkt6Ptr Dhcpv6Srv::processInfRequest(const Pkt6Ptr& infRequest) {
  480. /// @todo: Implement this
  481. Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, infRequest->getTransid()));
  482. return reply;
  483. }
  484. const char*
  485. Dhcpv6Srv::serverReceivedPacketName(uint8_t type) {
  486. static const char* CONFIRM = "CONFIRM";
  487. static const char* DECLINE = "DECLINE";
  488. static const char* INFORMATION_REQUEST = "INFORMATION_REQUEST";
  489. static const char* REBIND = "REBIND";
  490. static const char* RELEASE = "RELEASE";
  491. static const char* RENEW = "RENEW";
  492. static const char* REQUEST = "REQUEST";
  493. static const char* SOLICIT = "SOLICIT";
  494. static const char* UNKNOWN = "UNKNOWN";
  495. switch (type) {
  496. case DHCPV6_CONFIRM:
  497. return (CONFIRM);
  498. case DHCPV6_DECLINE:
  499. return (DECLINE);
  500. case DHCPV6_INFORMATION_REQUEST:
  501. return (INFORMATION_REQUEST);
  502. case DHCPV6_REBIND:
  503. return (REBIND);
  504. case DHCPV6_RELEASE:
  505. return (RELEASE);
  506. case DHCPV6_RENEW:
  507. return (RENEW);
  508. case DHCPV6_REQUEST:
  509. return (REQUEST);
  510. case DHCPV6_SOLICIT:
  511. return (SOLICIT);
  512. default:
  513. ;
  514. }
  515. return (UNKNOWN);
  516. }
  517. void
  518. Dhcpv6Srv::initStdOptionDefs() {
  519. LibDHCP::initStdOptionDefs(Option::V6);
  520. }