option6_status_code.cc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Copyright (C) 2015-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 <config.h>
  7. #include <dhcp/dhcp4.h>
  8. #include <dhcp/dhcp6.h>
  9. #include <dhcp/option6_status_code.h>
  10. #include <dhcp/option_data_types.h>
  11. #include <util/io_utilities.h>
  12. #include <iterator>
  13. #include <sstream>
  14. using namespace isc;
  15. using namespace isc::dhcp;
  16. namespace {
  17. /// @brief Minimum length of the option (when status message is empty).
  18. const size_t OPTION6_STATUS_CODE_MIN_LEN = sizeof(uint16_t);
  19. const size_t OPTION4_SLP_SERVICE_SCOPEMIN_LEN = sizeof(uint8_t);
  20. }; // end of anonymous namespace
  21. namespace isc {
  22. namespace dhcp {
  23. Option6StatusCode::Option6StatusCode(const uint16_t status_code,
  24. const std::string& status_message)
  25. : Option(Option::V6, D6O_STATUS_CODE),
  26. status_code_(status_code), status_message_(status_message) {
  27. }
  28. Option6StatusCode::Option6StatusCode(OptionBufferConstIter begin,
  29. OptionBufferConstIter end)
  30. : Option(Option::V6, D6O_STATUS_CODE),
  31. status_code_(STATUS_Success), status_message_() {
  32. // Parse data
  33. unpack(begin, end);
  34. }
  35. OptionPtr
  36. Option6StatusCode::clone() const {
  37. return (cloneInternal<Option6StatusCode>());
  38. }
  39. void
  40. Option6StatusCode::pack(isc::util::OutputBuffer& buf) const {
  41. // Pack option header.
  42. packHeader(buf);
  43. // Write numeric status code.
  44. buf.writeUint16(getStatusCode());
  45. // If there is any status message, write it.
  46. if (!status_message_.empty()) {
  47. buf.writeData(&status_message_[0], status_message_.size());
  48. }
  49. // Status code has no options, so leave here.
  50. }
  51. void
  52. Option6StatusCode::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
  53. // Make sure that the option is not truncated.
  54. if (std::distance(begin, end) < OPTION6_STATUS_CODE_MIN_LEN) {
  55. isc_throw(OutOfRange, "Status Code option ("
  56. << D6O_STATUS_CODE << ") truncated");
  57. }
  58. status_code_ = util::readUint16(&(*begin), std::distance(begin, end));
  59. begin += sizeof(uint16_t);
  60. status_message_.assign(begin, end);
  61. }
  62. uint16_t
  63. Option6StatusCode::len() const {
  64. return (getHeaderLen() + sizeof(uint16_t) + status_message_.size());
  65. }
  66. std::string
  67. Option6StatusCode::toText(int indent) const {
  68. std::ostringstream output;
  69. output << headerToText(indent) << ": " << dataToText();
  70. return (output.str());
  71. }
  72. std::string
  73. Option6StatusCode::dataToText() const {
  74. std::ostringstream output;
  75. // Add status code name and numeric status code.
  76. output << getStatusCodeName() << "(" << getStatusCode() << ") ";
  77. // Include status message in quotes if status code is
  78. // non-empty.
  79. if (!status_message_.empty()) {
  80. output << "\"" << status_message_ << "\"";
  81. } else {
  82. output << "(no status message)";
  83. }
  84. return (output.str());
  85. }
  86. std::string
  87. Option6StatusCode::getStatusCodeName() const {
  88. switch (getStatusCode()) {
  89. case STATUS_Success:
  90. return ("Success");
  91. case STATUS_UnspecFail:
  92. return ("UnspecFail");
  93. case STATUS_NoAddrsAvail:
  94. return ("NoAddrsAvail");
  95. case STATUS_NoBinding:
  96. return ("NoBinding");
  97. case STATUS_NotOnLink:
  98. return ("NotOnLink");
  99. case STATUS_UseMulticast:
  100. return ("UseMulticast");
  101. case STATUS_NoPrefixAvail:
  102. return ("NoPrefixAvail");
  103. case STATUS_UnknownQueryType:
  104. return ("UnknownQueryType");
  105. case STATUS_MalformedQuery:
  106. return ("MalformedQuery");
  107. case STATUS_NotConfigured:
  108. return ("NotConfigured");
  109. case STATUS_NotAllowed:
  110. return ("NotAllowed");
  111. default:
  112. ;
  113. }
  114. return ("(unknown status code)");
  115. }
  116. Option4SlpServiceScope::Option4SlpServiceScope(const bool mandatory_flag,
  117. const std::string& scope_list)
  118. : Option(Option::V4, DHO_SERVICE_SCOPE),
  119. mandatory_flag_(mandatory_flag), scope_list_(scope_list) {
  120. }
  121. Option4SlpServiceScope::Option4SlpServiceScope(OptionBufferConstIter begin,
  122. OptionBufferConstIter end)
  123. : Option(Option::V4, DHO_SERVICE_SCOPE),
  124. mandatory_flag_(false), scope_list_() {
  125. // Parse data
  126. unpack(begin, end);
  127. }
  128. OptionPtr
  129. Option4SlpServiceScope::clone() const {
  130. return (cloneInternal<Option4SlpServiceScope>());
  131. }
  132. void
  133. Option4SlpServiceScope::pack(isc::util::OutputBuffer& buf) const {
  134. // Pack option header.
  135. packHeader(buf);
  136. // Write mandatory flag.
  137. buf.writeUint8(static_cast<uint8_t>(getMandatoryFlag() ? 1 : 0));
  138. // If there is any scope list, write it.
  139. if (!scope_list_.empty()) {
  140. buf.writeData(&scope_list_[0], scope_list_.size());
  141. }
  142. // SLP service scope has no options, so leave here.
  143. }
  144. void
  145. Option4SlpServiceScope::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
  146. // Make sure that the option is not truncated.
  147. if (std::distance(begin, end) < OPTION4_SLP_SERVICE_SCOPEMIN_LEN) {
  148. isc_throw(OutOfRange, "SLP Service Scope option ("
  149. << DHO_SERVICE_SCOPE << ") truncated");
  150. }
  151. if (*begin == 1) {
  152. mandatory_flag_ = true;
  153. } else if (*begin == 0) {
  154. mandatory_flag_ = false;
  155. } else {
  156. isc_throw(BadDataTypeCast, "unable to read the buffer as boolean"
  157. << " value. Invalid value " << static_cast<int>(*begin));
  158. }
  159. begin += sizeof(uint8_t);
  160. scope_list_.assign(begin, end);
  161. }
  162. uint16_t
  163. Option4SlpServiceScope::len() const {
  164. return (getHeaderLen() + sizeof(bool) + scope_list_.size());
  165. }
  166. std::string
  167. Option4SlpServiceScope::toText(int indent) const {
  168. std::ostringstream output;
  169. output << headerToText(indent) << ": " << dataToText();
  170. return (output.str());
  171. }
  172. std::string
  173. Option4SlpServiceScope::dataToText() const {
  174. std::ostringstream output;
  175. output << "mandatory:" << getMandatoryFlag();
  176. output << ", scope-list:\"" << scope_list_ << "\"";
  177. return (output.str());
  178. }
  179. } // end of namespace isc::dhcp
  180. } // end of namespace isc