lease.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. // Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <dhcpsrv/lease.h>
  7. #include <util/pointer_util.h>
  8. #include <sstream>
  9. #include <iostream>
  10. using namespace isc::util;
  11. using namespace isc::data;
  12. using namespace std;
  13. namespace isc {
  14. namespace dhcp {
  15. const uint32_t Lease::STATE_DEFAULT = 0x0;
  16. const uint32_t Lease::STATE_DECLINED = 0x1;
  17. const uint32_t Lease::STATE_EXPIRED_RECLAIMED = 0x2;
  18. Lease::Lease(const isc::asiolink::IOAddress& addr, uint32_t t1, uint32_t t2,
  19. uint32_t valid_lft, SubnetID subnet_id, time_t cltt,
  20. const bool fqdn_fwd, const bool fqdn_rev,
  21. const std::string& hostname, const HWAddrPtr& hwaddr)
  22. :addr_(addr), t1_(t1), t2_(t2), valid_lft_(valid_lft), cltt_(cltt),
  23. subnet_id_(subnet_id), hostname_(hostname), fqdn_fwd_(fqdn_fwd),
  24. fqdn_rev_(fqdn_rev), hwaddr_(hwaddr), state_(STATE_DEFAULT) {
  25. }
  26. std::string
  27. Lease::typeToText(Lease::Type type) {
  28. switch (type) {
  29. case Lease::TYPE_V4:
  30. return string("V4");
  31. case Lease::TYPE_NA:
  32. return string("IA_NA");
  33. case Lease::TYPE_TA:
  34. return string("IA_TA");
  35. case Lease::TYPE_PD:
  36. return string("IA_PD");
  37. break;
  38. default: {
  39. stringstream tmp;
  40. tmp << "unknown (" << type << ")";
  41. return (tmp.str());
  42. }
  43. }
  44. }
  45. std::string
  46. Lease::basicStatesToText(const uint32_t state) {
  47. switch (state) {
  48. case STATE_DEFAULT:
  49. return ("default");
  50. case STATE_DECLINED:
  51. return ("declined");
  52. case STATE_EXPIRED_RECLAIMED:
  53. return ("expired-reclaimed");
  54. default:
  55. // The default case will be handled further on
  56. ;
  57. }
  58. std::ostringstream s;
  59. s << "unknown (" << state << ")";
  60. return s.str();
  61. }
  62. bool
  63. Lease::expired() const {
  64. return (getExpirationTime() < time(NULL));
  65. }
  66. bool
  67. Lease::stateExpiredReclaimed() const {
  68. return (state_ == STATE_EXPIRED_RECLAIMED);
  69. }
  70. bool
  71. Lease::stateDeclined() const {
  72. return (state_ == STATE_DECLINED);
  73. }
  74. int64_t
  75. Lease::getExpirationTime() const {
  76. return (static_cast<int64_t>(cltt_) + valid_lft_);
  77. }
  78. bool
  79. Lease::hasIdenticalFqdn(const Lease& other) const {
  80. return (hostname_ == other.hostname_ &&
  81. fqdn_fwd_ == other.fqdn_fwd_ &&
  82. fqdn_rev_ == other.fqdn_rev_);
  83. }
  84. Lease4::Lease4(const Lease4& other)
  85. : Lease(other.addr_, other.t1_, other.t2_, other.valid_lft_,
  86. other.subnet_id_, other.cltt_, other.fqdn_fwd_,
  87. other.fqdn_rev_, other.hostname_, other.hwaddr_) {
  88. // Copy over fields derived from Lease.
  89. state_ = other.state_;
  90. // Copy the hardware address if it is defined.
  91. if (other.hwaddr_) {
  92. hwaddr_.reset(new HWAddr(*other.hwaddr_));
  93. } else {
  94. hwaddr_.reset();
  95. }
  96. if (other.client_id_) {
  97. client_id_.reset(new ClientId(other.client_id_->getClientId()));
  98. } else {
  99. client_id_.reset();
  100. }
  101. }
  102. Lease4::Lease4(const isc::asiolink::IOAddress& address,
  103. const HWAddrPtr& hw_address,
  104. const ClientIdPtr& client_id,
  105. const uint32_t valid_lifetime,
  106. const uint32_t t1,
  107. const uint32_t t2,
  108. const time_t cltt,
  109. const SubnetID subnet_id,
  110. const bool fqdn_fwd,
  111. const bool fqdn_rev,
  112. const std::string& hostname)
  113. : Lease(address, t1, t2, valid_lifetime, subnet_id, cltt, fqdn_fwd,
  114. fqdn_rev, hostname, hw_address),
  115. client_id_(client_id) {
  116. }
  117. std::string
  118. Lease4::statesToText(const uint32_t state) {
  119. return (Lease::basicStatesToText(state));
  120. }
  121. const std::vector<uint8_t>&
  122. Lease4::getClientIdVector() const {
  123. if(!client_id_) {
  124. static std::vector<uint8_t> empty_vec;
  125. return (empty_vec);
  126. }
  127. return (client_id_->getClientId());
  128. }
  129. const std::vector<uint8_t>&
  130. Lease::getHWAddrVector() const {
  131. if (!hwaddr_) {
  132. static std::vector<uint8_t> empty_vec;
  133. return (empty_vec);
  134. }
  135. return (hwaddr_->hwaddr_);
  136. }
  137. bool
  138. Lease4::belongsToClient(const HWAddrPtr& hw_address,
  139. const ClientIdPtr& client_id) const {
  140. // If client id matches, lease matches.
  141. if (equalValues(client_id, client_id_)) {
  142. return (true);
  143. } else if (!client_id || !client_id_) {
  144. // If client id is unspecified, use HW address.
  145. if (equalValues(hw_address, hwaddr_)) {
  146. return (true);
  147. }
  148. }
  149. return (false);
  150. }
  151. void
  152. Lease4::decline(uint32_t probation_period) {
  153. hwaddr_.reset(new HWAddr());
  154. client_id_.reset();
  155. t1_ = 0;
  156. t2_ = 0;
  157. cltt_ = time(NULL);
  158. hostname_ = string("");
  159. fqdn_fwd_ = false;
  160. fqdn_rev_ = false;
  161. state_ = STATE_DECLINED;
  162. valid_lft_ = probation_period;
  163. }
  164. Lease4&
  165. Lease4::operator=(const Lease4& other) {
  166. if (this != &other) {
  167. addr_ = other.addr_;
  168. t1_ = other.t1_;
  169. t2_ = other.t2_;
  170. valid_lft_ = other.valid_lft_;
  171. cltt_ = other.cltt_;
  172. subnet_id_ = other.subnet_id_;
  173. hostname_ = other.hostname_;
  174. fqdn_fwd_ = other.fqdn_fwd_;
  175. fqdn_rev_ = other.fqdn_rev_;
  176. state_ = other.state_;
  177. // Copy the hardware address if it is defined.
  178. if (other.hwaddr_) {
  179. hwaddr_.reset(new HWAddr(*other.hwaddr_));
  180. } else {
  181. hwaddr_.reset();
  182. }
  183. if (other.client_id_) {
  184. client_id_.reset(new ClientId(other.client_id_->getClientId()));
  185. } else {
  186. client_id_.reset();
  187. }
  188. }
  189. return (*this);
  190. }
  191. isc::data::ElementPtr
  192. Lease4::toElement() const {
  193. // Prepare the map
  194. ElementPtr map = Element::createMap();
  195. map->set("ip-address", Element::create(addr_.toText()));
  196. map->set("subnet-id", Element::create(static_cast<long int>(subnet_id_)));
  197. map->set("hw-address", Element::create(hwaddr_->toText(false)));
  198. if (client_id_) {
  199. map->set("client-id", Element::create(client_id_->toText()));
  200. }
  201. map->set("cltt", Element::create(cltt_));
  202. map->set("valid-lft", Element::create(static_cast<long int>(valid_lft_)));
  203. map->set("fqdn-fwd", Element::create(fqdn_fwd_));
  204. map->set("fqdn-rev", Element::create(fqdn_rev_));
  205. map->set("hostname", Element::create(hostname_));
  206. map->set("state", Element::create(static_cast<int>(state_)));
  207. return (map);
  208. }
  209. Lease6::Lease6(Lease::Type type, const isc::asiolink::IOAddress& addr,
  210. DuidPtr duid, uint32_t iaid, uint32_t preferred, uint32_t valid,
  211. uint32_t t1, uint32_t t2, SubnetID subnet_id,
  212. const HWAddrPtr& hwaddr, uint8_t prefixlen)
  213. : Lease(addr, t1, t2, valid, subnet_id, 0/*cltt*/, false, false, "", hwaddr),
  214. type_(type), prefixlen_(prefixlen), iaid_(iaid), duid_(duid),
  215. preferred_lft_(preferred) {
  216. if (!duid) {
  217. isc_throw(InvalidOperation, "DUID is mandatory for an IPv6 lease");
  218. }
  219. cltt_ = time(NULL);
  220. }
  221. Lease6::Lease6(Lease::Type type, const isc::asiolink::IOAddress& addr,
  222. DuidPtr duid, uint32_t iaid, uint32_t preferred, uint32_t valid,
  223. uint32_t t1, uint32_t t2, SubnetID subnet_id,
  224. const bool fqdn_fwd, const bool fqdn_rev,
  225. const std::string& hostname, const HWAddrPtr& hwaddr,
  226. uint8_t prefixlen)
  227. : Lease(addr, t1, t2, valid, subnet_id, 0/*cltt*/,
  228. fqdn_fwd, fqdn_rev, hostname, hwaddr),
  229. type_(type), prefixlen_(prefixlen), iaid_(iaid), duid_(duid),
  230. preferred_lft_(preferred) {
  231. if (!duid) {
  232. isc_throw(InvalidOperation, "DUID is mandatory for an IPv6 lease");
  233. }
  234. cltt_ = time(NULL);
  235. }
  236. Lease6::Lease6()
  237. : Lease(isc::asiolink::IOAddress("::"), 0, 0, 0, 0, 0, false, false, "",
  238. HWAddrPtr()), type_(TYPE_NA), prefixlen_(0), iaid_(0),
  239. duid_(DuidPtr()), preferred_lft_(0) {
  240. }
  241. std::string
  242. Lease6::statesToText(const uint32_t state) {
  243. return (Lease::basicStatesToText(state));
  244. }
  245. const std::vector<uint8_t>&
  246. Lease6::getDuidVector() const {
  247. if (!duid_) {
  248. static std::vector<uint8_t> empty_vec;
  249. return (empty_vec);
  250. }
  251. return (duid_->getDuid());
  252. }
  253. void
  254. Lease6::decline(uint32_t probation_period) {
  255. hwaddr_.reset();
  256. duid_.reset(new DUID(DUID::EMPTY()));
  257. t1_ = 0;
  258. t2_ = 0;
  259. preferred_lft_ = 0;
  260. valid_lft_ = probation_period;
  261. cltt_ = time(NULL);
  262. hostname_ = string("");
  263. fqdn_fwd_ = false;
  264. fqdn_rev_ = false;
  265. state_ = Lease::STATE_DECLINED;
  266. }
  267. std::string
  268. Lease6::toText() const {
  269. ostringstream stream;
  270. /// @todo: print out DUID
  271. stream << "Type: " << typeToText(type_) << "("
  272. << static_cast<int>(type_) << ")\n"
  273. << "Address: " << addr_ << "\n"
  274. << "Prefix length: " << static_cast<int>(prefixlen_) << "\n"
  275. << "IAID: " << iaid_ << "\n"
  276. << "Pref life: " << preferred_lft_ << "\n"
  277. << "Valid life: " << valid_lft_ << "\n"
  278. << "Cltt: " << cltt_ << "\n"
  279. << "DUID: " << (duid_?duid_->toText():"(none)") << "\n"
  280. << "Hardware addr: " << (hwaddr_?hwaddr_->toText(false):"(none)") << "\n"
  281. << "Subnet ID: " << subnet_id_ << "\n"
  282. << "State: " << statesToText(state_) << "\n";
  283. return (stream.str());
  284. }
  285. std::string
  286. Lease4::toText() const {
  287. ostringstream stream;
  288. stream << "Address: " << addr_ << "\n"
  289. << "Valid life: " << valid_lft_ << "\n"
  290. << "T1: " << t1_ << "\n"
  291. << "T2: " << t2_ << "\n"
  292. << "Cltt: " << cltt_ << "\n"
  293. << "Hardware addr: " << (hwaddr_ ? hwaddr_->toText(false) : "(none)") << "\n"
  294. << "Client id: " << (client_id_ ? client_id_->toText() : "(none)") << "\n"
  295. << "Subnet ID: " << subnet_id_ << "\n"
  296. << "State: " << statesToText(state_) << "\n";
  297. return (stream.str());
  298. }
  299. bool
  300. Lease4::operator==(const Lease4& other) const {
  301. return (nullOrEqualValues(hwaddr_, other.hwaddr_) &&
  302. nullOrEqualValues(client_id_, other.client_id_) &&
  303. addr_ == other.addr_ &&
  304. subnet_id_ == other.subnet_id_ &&
  305. t1_ == other.t1_ &&
  306. t2_ == other.t2_ &&
  307. valid_lft_ == other.valid_lft_ &&
  308. cltt_ == other.cltt_ &&
  309. hostname_ == other.hostname_ &&
  310. fqdn_fwd_ == other.fqdn_fwd_ &&
  311. fqdn_rev_ == other.fqdn_rev_ &&
  312. state_ == other.state_);
  313. }
  314. bool
  315. Lease6::operator==(const Lease6& other) const {
  316. return (nullOrEqualValues(duid_, other.duid_) &&
  317. nullOrEqualValues(hwaddr_, other.hwaddr_) &&
  318. addr_ == other.addr_ &&
  319. type_ == other.type_ &&
  320. prefixlen_ == other.prefixlen_ &&
  321. iaid_ == other.iaid_ &&
  322. preferred_lft_ == other.preferred_lft_ &&
  323. valid_lft_ == other.valid_lft_ &&
  324. t1_ == other.t1_ &&
  325. t2_ == other.t2_ &&
  326. cltt_ == other.cltt_ &&
  327. subnet_id_ == other.subnet_id_ &&
  328. hostname_ == other.hostname_ &&
  329. fqdn_fwd_ == other.fqdn_fwd_ &&
  330. fqdn_rev_ == other.fqdn_rev_ &&
  331. state_ == other.state_);
  332. }
  333. isc::data::ElementPtr
  334. Lease6::toElement() const {
  335. // Prepare the map
  336. ElementPtr map = Element::createMap();
  337. map->set("ip-address", Element::create(addr_.toText()));
  338. map->set("type", Element::create(typeToText(type_)));
  339. if (type_ == Lease::TYPE_PD) {
  340. map->set("prefix-len", Element::create(prefixlen_));
  341. }
  342. map->set("iaid", Element::create(static_cast<long int>(iaid_)));
  343. map->set("duid", Element::create(duid_->toText()));
  344. map->set("subnet-id", Element::create(static_cast<long int>(subnet_id_)));
  345. map->set("cltt", Element::create(cltt_));
  346. map->set("preferred-lft", Element::create(static_cast<long int>(preferred_lft_)));
  347. map->set("valid-lft", Element::create(static_cast<long int>(valid_lft_)));
  348. map->set("fqdn-fwd", Element::create(fqdn_fwd_));
  349. map->set("fqdn-rev", Element::create(fqdn_rev_));
  350. map->set("hostname", Element::create(hostname_));
  351. if (hwaddr_) {
  352. map->set("hw-address", Element::create(hwaddr_->toText(false)));
  353. }
  354. map->set("state", Element::create(static_cast<long int>(state_)));
  355. return (map);
  356. }
  357. std::ostream&
  358. operator<<(std::ostream& os, const Lease& lease) {
  359. os << lease.toText();
  360. return (os);
  361. }
  362. } // namespace isc::dhcp
  363. } // namespace isc