dhcp6_srv.cc 8.0 KB

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