dhcp6_srv.cc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. // Copyright (C) 2011 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 "dhcp/dhcp6.h"
  15. #include "dhcp/pkt6.h"
  16. #include "dhcp6/iface_mgr.h"
  17. #include "dhcp6/dhcp6_srv.h"
  18. #include "dhcp/option6_ia.h"
  19. #include "dhcp/option6_iaaddr.h"
  20. #include "asiolink/io_address.h"
  21. using namespace std;
  22. using namespace isc;
  23. using namespace isc::dhcp;
  24. using namespace isc::asiolink;
  25. Dhcpv6Srv::Dhcpv6Srv() {
  26. cout << "Initialization" << endl;
  27. // first call to instance() will create IfaceMgr (it's a singleton)
  28. // it may throw something if things go wrong
  29. IfaceMgr::instance();
  30. /// @todo: instantiate LeaseMgr here once it is imlpemented.
  31. setServerID();
  32. shutdown = false;
  33. }
  34. Dhcpv6Srv::~Dhcpv6Srv() {
  35. cout << "DHCPv6 Srv shutdown." << endl;
  36. }
  37. bool
  38. Dhcpv6Srv::run() {
  39. while (!shutdown) {
  40. boost::shared_ptr<Pkt6> query; // client's message
  41. boost::shared_ptr<Pkt6> rsp; // server's response
  42. query = IfaceMgr::instance().receive();
  43. if (query) {
  44. if (!query->unpack()) {
  45. cout << "Failed to parse incoming packet" << endl;
  46. continue;
  47. }
  48. switch (query->getType()) {
  49. case DHCPV6_SOLICIT:
  50. rsp = processSolicit(query);
  51. break;
  52. case DHCPV6_REQUEST:
  53. rsp = processRequest(query);
  54. break;
  55. case DHCPV6_RENEW:
  56. rsp = processRenew(query);
  57. break;
  58. case DHCPV6_REBIND:
  59. rsp = processRebind(query);
  60. break;
  61. case DHCPV6_CONFIRM:
  62. rsp = processConfirm(query);
  63. break;
  64. case DHCPV6_RELEASE:
  65. rsp = processRelease(query);
  66. break;
  67. case DHCPV6_DECLINE:
  68. rsp = processDecline(query);
  69. break;
  70. case DHCPV6_INFORMATION_REQUEST:
  71. rsp = processInfRequest(query);
  72. break;
  73. default:
  74. cout << "Unknown pkt type received:"
  75. << query->getType() << endl;
  76. }
  77. cout << "Received " << query->data_len_ << " bytes packet type="
  78. << query->getType() << endl;
  79. cout << query->toText();
  80. if (rsp) {
  81. rsp->remote_addr_ = query->remote_addr_;
  82. rsp->local_addr_ = query->local_addr_;
  83. rsp->remote_port_ = DHCP6_CLIENT_PORT;
  84. rsp->local_port_ = DHCP6_SERVER_PORT;
  85. rsp->ifindex_ = query->ifindex_;
  86. rsp->iface_ = query->iface_;
  87. cout << "Replying with:" << rsp->getType() << endl;
  88. cout << rsp->toText();
  89. cout << "----" << endl;
  90. if (rsp->pack()) {
  91. cout << "#### pack successful." << endl;
  92. }
  93. IfaceMgr::instance().send(rsp);
  94. }
  95. }
  96. // TODO add support for config session (see src/bin/auth/main.cc)
  97. // so this daemon can be controlled from bob
  98. }
  99. return (true);
  100. }
  101. void
  102. Dhcpv6Srv::setServerID() {
  103. /// TODO implement this for real once interface detection is done.
  104. /// Use hardcoded server-id for now
  105. boost::shared_array<uint8_t> srvid(new uint8_t[14]);
  106. srvid[0] = 0;
  107. srvid[1] = 1; // DUID type 1 = DUID-LLT (see section 9.2 of RFC3315)
  108. srvid[2] = 0;
  109. srvid[3] = 6; // HW type = ethernet (I think. I'm typing this from my head
  110. // in hotel, without Internet connection)
  111. for (int i=4; i<14; i++) {
  112. srvid[i]=i-4;
  113. }
  114. serverid_ = boost::shared_ptr<Option>(new Option(Option::V6,
  115. D6O_SERVERID,
  116. srvid,
  117. 0, 14));
  118. }
  119. boost::shared_ptr<Pkt6>
  120. Dhcpv6Srv::processSolicit(boost::shared_ptr<Pkt6> solicit) {
  121. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_ADVERTISE,
  122. solicit->getTransid(),
  123. Pkt6::UDP));
  124. /// TODO Rewrite this once LeaseManager is implemented.
  125. // answer client's IA (this is mostly a dummy,
  126. // so let's answer only first IA and hope there is only one)
  127. boost::shared_ptr<Option> ia_opt = solicit->getOption(D6O_IA_NA);
  128. if (ia_opt) {
  129. // found IA
  130. Option* tmp = ia_opt.get();
  131. Option6IA* ia_req = dynamic_cast<Option6IA*>(tmp);
  132. if (ia_req) {
  133. boost::shared_ptr<Option6IA>
  134. ia_rsp(new Option6IA(D6O_IA_NA, ia_req->getIAID()));
  135. ia_rsp->setT1(1500);
  136. ia_rsp->setT2(2600);
  137. boost::shared_ptr<Option6IAAddr>
  138. addr(new Option6IAAddr(D6O_IAADDR,
  139. IOAddress("2001:db8:1234:5678::abcd"),
  140. 5000, 7000));
  141. ia_rsp->addOption(addr);
  142. reply->addOption(ia_rsp);
  143. }
  144. }
  145. // add client-id
  146. boost::shared_ptr<Option> clientid = solicit->getOption(D6O_CLIENTID);
  147. if (clientid) {
  148. reply->addOption(clientid);
  149. }
  150. // add server-id
  151. reply->addOption(getServerID());
  152. return reply;
  153. }
  154. boost::shared_ptr<Pkt6>
  155. Dhcpv6Srv::processRequest(boost::shared_ptr<Pkt6> request) {
  156. /// TODO: Implement processRequest() for real
  157. boost::shared_ptr<Pkt6> reply = processSolicit(request);
  158. reply->setType(DHCPV6_REPLY);
  159. return reply;
  160. }
  161. boost::shared_ptr<Pkt6>
  162. Dhcpv6Srv::processRenew(boost::shared_ptr<Pkt6> renew) {
  163. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
  164. renew->getTransid(),
  165. Pkt6::UDP));
  166. return reply;
  167. }
  168. boost::shared_ptr<Pkt6>
  169. Dhcpv6Srv::processRebind(boost::shared_ptr<Pkt6> rebind) {
  170. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
  171. rebind->getTransid(),
  172. Pkt6::UDP));
  173. return reply;
  174. }
  175. boost::shared_ptr<Pkt6>
  176. Dhcpv6Srv::processConfirm(boost::shared_ptr<Pkt6> confirm) {
  177. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
  178. confirm->getTransid(),
  179. Pkt6::UDP));
  180. return reply;
  181. }
  182. boost::shared_ptr<Pkt6>
  183. Dhcpv6Srv::processRelease(boost::shared_ptr<Pkt6> release) {
  184. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
  185. release->getTransid(),
  186. Pkt6::UDP));
  187. return reply;
  188. }
  189. boost::shared_ptr<Pkt6>
  190. Dhcpv6Srv::processDecline(boost::shared_ptr<Pkt6> decline) {
  191. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
  192. decline->getTransid(),
  193. Pkt6::UDP));
  194. return reply;
  195. }
  196. boost::shared_ptr<Pkt6>
  197. Dhcpv6Srv::processInfRequest(boost::shared_ptr<Pkt6> infRequest) {
  198. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
  199. infRequest->getTransid(),
  200. Pkt6::UDP));
  201. return reply;
  202. }