eval_context.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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 <dhcp/dhcp6.h>
  7. #include <dhcp/option.h>
  8. #include <dhcp/option_definition.h>
  9. #include <dhcp/libdhcp++.h>
  10. #include <dhcp/option_space.h>
  11. #include <eval/eval_context.h>
  12. #include <eval/parser.h>
  13. #include <exceptions/exceptions.h>
  14. #include <boost/lexical_cast.hpp>
  15. #include <fstream>
  16. #include <limits>
  17. EvalContext::EvalContext(const Option::Universe& option_universe)
  18. : trace_scanning_(false), trace_parsing_(false),
  19. option_universe_(option_universe)
  20. {
  21. }
  22. EvalContext::~EvalContext()
  23. {
  24. }
  25. bool
  26. EvalContext::parseString(const std::string& str, ParserType type)
  27. {
  28. file_ = "<string>";
  29. string_ = str;
  30. scanStringBegin(type);
  31. isc::eval::EvalParser parser(*this);
  32. parser.set_debug_level(trace_parsing_);
  33. int res = parser.parse();
  34. scanStringEnd();
  35. return (res == 0);
  36. }
  37. void
  38. EvalContext::error(const isc::eval::location& loc, const std::string& what)
  39. {
  40. isc_throw(EvalParseError, loc << ": " << what);
  41. }
  42. void
  43. EvalContext::error (const std::string& what)
  44. {
  45. isc_throw(EvalParseError, what);
  46. }
  47. uint16_t
  48. EvalContext::convertOptionCode(const std::string& option_code,
  49. const isc::eval::location& loc)
  50. {
  51. int n = 0;
  52. try {
  53. n = boost::lexical_cast<int>(option_code);
  54. } catch (const boost::bad_lexical_cast &) {
  55. // This can't happen...
  56. error(loc, "Option code has invalid value in " + option_code);
  57. }
  58. if (option_universe_ == Option::V6) {
  59. if (n < 0 || n > 65535) {
  60. error(loc, "Option code has invalid value in "
  61. + option_code + ". Allowed range: 0..65535");
  62. }
  63. } else {
  64. if (n < 0 || n > 255) {
  65. error(loc, "Option code has invalid value in "
  66. + option_code + ". Allowed range: 0..255");
  67. }
  68. }
  69. return (static_cast<uint16_t>(n));
  70. }
  71. uint16_t
  72. EvalContext::convertOptionName(const std::string& option_name,
  73. const isc::eval::location& loc)
  74. {
  75. const std::string global_space = (option_universe_ == Option::V4) ?
  76. DHCP4_OPTION_SPACE : DHCP6_OPTION_SPACE;
  77. OptionDefinitionPtr option_def = LibDHCP::getOptionDef(global_space,
  78. option_name);
  79. if (!option_def) {
  80. option_def = LibDHCP::getRuntimeOptionDef(global_space, option_name);
  81. }
  82. if (!option_def) {
  83. option_def = LibDHCP::getLastResortOptionDef(global_space, option_name);
  84. }
  85. if (!option_def) {
  86. error(loc, "option '" + option_name + "' is not defined");
  87. }
  88. return (option_def->getCode());
  89. }
  90. int8_t
  91. EvalContext::convertNestLevelNumber(const std::string& nest_level,
  92. const isc::eval::location& loc)
  93. {
  94. int8_t n = convertInt8(nest_level, loc);
  95. if (option_universe_ == Option::V6) {
  96. if ((n < - HOP_COUNT_LIMIT) || (n >= HOP_COUNT_LIMIT)) {
  97. error(loc, "Nest level has invalid value in "
  98. + nest_level + ". Allowed range: -32..31");
  99. }
  100. } else {
  101. error(loc, "Nest level invalid for DHCPv4 packets");
  102. }
  103. return (n);
  104. }
  105. uint8_t
  106. EvalContext::convertUint8(const std::string& number,
  107. const isc::eval::location& loc)
  108. {
  109. int n = 0;
  110. try {
  111. n = boost::lexical_cast<int>(number);
  112. } catch (const boost::bad_lexical_cast &) {
  113. error(loc, "Invalid integer value in " + number);
  114. }
  115. if (n < 0 || n > std::numeric_limits<uint8_t>::max()) {
  116. error(loc, "Invalid value in "
  117. + number + ". Allowed range: 0..255");
  118. }
  119. return (static_cast<uint8_t>(n));
  120. }
  121. int8_t
  122. EvalContext::convertInt8(const std::string& number,
  123. const isc::eval::location& loc)
  124. {
  125. int n = 0;
  126. try {
  127. n = boost::lexical_cast<int>(number);
  128. } catch (const boost::bad_lexical_cast &) {
  129. error(loc, "Invalid integer value in " + number);
  130. }
  131. if (n < std::numeric_limits<int8_t>::min() ||
  132. n > std::numeric_limits<int8_t>::max()) {
  133. error(loc, "Invalid value in "
  134. + number + ". Allowed range: 0..255");
  135. }
  136. return (static_cast<uint8_t>(n));
  137. }
  138. uint32_t
  139. EvalContext::convertUint32(const std::string& number,
  140. const isc::eval::location& loc)
  141. {
  142. uint64_t n = 0;
  143. try {
  144. n = boost::lexical_cast<uint64_t>(number);
  145. } catch (const boost::bad_lexical_cast &) {
  146. error(loc, "Invalid value in " + number);
  147. }
  148. if (n > std::numeric_limits<uint32_t>::max()) {
  149. error(loc, "Invalid value in "
  150. + number + ". Allowed range: 0..4294967295");
  151. }
  152. return (static_cast<uint32_t>(n));
  153. }
  154. std::string
  155. EvalContext::fromUint32(const uint32_t integer) {
  156. std::string tmp(4, 0);
  157. tmp[0] = (integer >> 24) & 0xff;
  158. tmp[1] = (integer >> 16) & 0xff;
  159. tmp[2] = (integer >> 8) & 0xff;
  160. tmp[3] = integer & 0xff;
  161. return (tmp);
  162. }
  163. void
  164. EvalContext::fatal (const std::string& what)
  165. {
  166. isc_throw(Unexpected, what);
  167. }