dhcp6_srv.cc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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 "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. if (!setServerID()) {
  31. isc_throw(Unexpected, "Failed to set up server-id.");
  32. }
  33. }
  34. Dhcpv6Srv::~Dhcpv6Srv() {
  35. cout << "DHCPv6 Srv shutdown." << endl;
  36. }
  37. bool
  38. Dhcpv6Srv::run() {
  39. while (true) {
  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. default:
  71. cout << "Unknown pkt type received:"
  72. << query->getType() << endl;
  73. }
  74. cout << "Received " << query->data_len_ << " bytes packet type="
  75. << query->getType() << endl;
  76. cout << query->toText();
  77. if (rsp != boost::shared_ptr<Pkt6>()) {
  78. rsp->remote_addr_ = query->remote_addr_;
  79. rsp->local_addr_ = query->local_addr_;
  80. rsp->remote_port_ = DHCP6_CLIENT_PORT;
  81. rsp->local_port_ = DHCP6_SERVER_PORT;
  82. rsp->ifindex_ = query->ifindex_;
  83. rsp->iface_ = query->iface_;
  84. cout << "Replying with:" << rsp->getType() << endl;
  85. cout << rsp->toText();
  86. cout << "----" << endl;
  87. if (rsp->pack()) {
  88. cout << "#### pack successful." << endl;
  89. }
  90. IfaceMgr::instance().send(rsp);
  91. }
  92. }
  93. // TODO add support for config session (see src/bin/auth/main.cc)
  94. // so this daemon can be controlled from bob
  95. }
  96. return (true);
  97. }
  98. boost::shared_ptr<Option>
  99. Dhcpv6Srv::getServerID() {
  100. return serverid_;
  101. }
  102. bool
  103. Dhcpv6Srv::setServerID() {
  104. /// TODO implement this for real once interface detection is done.
  105. /// Use hardcoded server-id for now
  106. boost::shared_array<char> srvid(new char[14]);
  107. srvid[0] = 0;
  108. srvid[1] = 1; // DUID type 1 = DUID-LLT (see section 9.2 of RFC3315)
  109. srvid[2] = 0;
  110. srvid[3] = 6; // HW type = ethernet (I think. I'm typing this from my head
  111. // in hotel, without Internet connection)
  112. for (int i=4; i<14; i++) {
  113. srvid[i]=i-4;
  114. }
  115. serverid_ = boost::shared_ptr<Option>(new Option(Option::V6,
  116. D6O_SERVERID,
  117. srvid,
  118. 0, 14));
  119. return (true);
  120. }
  121. boost::shared_ptr<Pkt6>
  122. Dhcpv6Srv::processSolicit(boost::shared_ptr<Pkt6> solicit) {
  123. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_ADVERTISE,
  124. solicit->getTransid(),
  125. Pkt6::UDP));
  126. // answer client's IA (this is mostly a dummy,
  127. // so let's answer only first IA and hope there is only one)
  128. boost::shared_ptr<Option> ia_opt = solicit->getOption(D6O_IA_NA);
  129. if (ia_opt) {
  130. // found IA
  131. Option * tmp = ia_opt.get();
  132. Option6IA * ia_req = dynamic_cast<Option6IA*> (tmp);
  133. if (ia_req) {
  134. boost::shared_ptr<Option6IA> ia_rsp(new Option6IA(Option::V6, D6O_IA_NA, ia_req->getIAID()));
  135. ia_rsp->setT1(1500);
  136. ia_rsp->setT2(2600);
  137. boost::shared_ptr<Option6IAAddr> addr(new Option6IAAddr(D6O_IAADDR, IOAddress("2001:db8:1234:5678::abcd"), 5000, 7000));
  138. ia_rsp->addOption(addr);
  139. reply->addOption(ia_rsp);
  140. }
  141. }
  142. // add client-id
  143. boost::shared_ptr<Option> clientid = solicit->getOption(D6O_CLIENTID);
  144. if (clientid) {
  145. reply->addOption(clientid);
  146. }
  147. // add server-id
  148. reply->addOption(getServerID());
  149. return reply;
  150. }
  151. boost::shared_ptr<Pkt6>
  152. Dhcpv6Srv::processRequest(boost::shared_ptr<Pkt6> request) {
  153. /// TODO: Implement processRequest() for real
  154. boost::shared_ptr<Pkt6> reply = processSolicit(request);
  155. reply->setType(DHCPV6_REPLY);
  156. return reply;
  157. }
  158. boost::shared_ptr<Pkt6>
  159. Dhcpv6Srv::processRenew(boost::shared_ptr<Pkt6> renew) {
  160. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
  161. renew->getTransid(),
  162. Pkt6::UDP));
  163. return reply;
  164. }
  165. boost::shared_ptr<Pkt6>
  166. Dhcpv6Srv::processRebind(boost::shared_ptr<Pkt6> rebind) {
  167. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
  168. rebind->getTransid(),
  169. Pkt6::UDP));
  170. return reply;
  171. }
  172. boost::shared_ptr<Pkt6>
  173. Dhcpv6Srv::processConfirm(boost::shared_ptr<Pkt6> confirm) {
  174. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
  175. confirm->getTransid(),
  176. Pkt6::UDP));
  177. return reply;
  178. }
  179. boost::shared_ptr<Pkt6>
  180. Dhcpv6Srv::processRelease(boost::shared_ptr<Pkt6> release) {
  181. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
  182. release->getTransid(),
  183. Pkt6::UDP));
  184. return reply;
  185. }
  186. boost::shared_ptr<Pkt6>
  187. Dhcpv6Srv::processDecline(boost::shared_ptr<Pkt6> decline) {
  188. boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
  189. decline->getTransid(),
  190. Pkt6::UDP));
  191. return reply;
  192. }