simple_parser.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. #include <dhcpsrv/parsers/simple_parser.h>
  2. #include <boost/foreach.hpp>
  3. #include <boost/lexical_cast.hpp>
  4. #include <cc/data.h>
  5. #include <string>
  6. using namespace std;
  7. using namespace isc::data;
  8. namespace isc {
  9. namespace dhcp {
  10. /// This table defines default values for option definitions in DHCPv4
  11. const SimpleDefaults OPTION4_DEF_DEFAULTS = {
  12. { "record-types", Element::string, ""},
  13. { "space", Element::string, "dhcp4"},
  14. { "array", Element::boolean, "false"},
  15. { "encapsulate", Element::string, "" }
  16. };
  17. /// This table defines default values for option definitions in DHCPv6
  18. const SimpleDefaults OPTION6_DEF_DEFAULTS = {
  19. { "record-types", Element::string, ""},
  20. { "space", Element::string, "dhcp6"},
  21. { "array", Element::boolean, "false"},
  22. { "encapsulate", Element::string, "" }
  23. };
  24. /// This table defines default values for options in DHCPv4
  25. const SimpleDefaults OPTION4_DEFAULTS = {
  26. { "space", Element::string, "dhcp4"},
  27. { "csv-format", Element::boolean, "true"},
  28. { "encapsulate", Element::string, "" }
  29. };
  30. /// This table defines default values for options in DHCPv6
  31. const SimpleDefaults OPTION6_DEFAULTS = {
  32. { "space", Element::string, "dhcp6"},
  33. { "csv-format", Element::boolean, "true"},
  34. { "encapsulate", Element::string, "" }
  35. };
  36. /// This table defines default values for DHCPv4
  37. const SimpleDefaults GLOBAL4_DEFAULTS = {
  38. { "renew-timer", Element::integer, "900" },
  39. { "rebind-timer", Element::integer, "1800" },
  40. { "valid-lifetime", Element::integer, "7200" }
  41. };
  42. /// This table defines default values for both DHCPv4 and DHCPv6
  43. const SimpleDefaults GLOBAL6_DEFAULTS = {
  44. { "renew-timer", Element::integer, "900" },
  45. { "rebind-timer", Element::integer, "1800" },
  46. { "preferred-lifetime", Element::integer, "3600" },
  47. { "valid-lifetime", Element::integer, "7200" }
  48. };
  49. /// This list defines parameters that can be inherited from the global
  50. /// scope to subnet scope.
  51. const ParamsList INHERIT_GLOBAL_TO_SUBNET = {
  52. "renew-timer",
  53. "rebind-timer",
  54. "preferred-lifetime",
  55. "valid-lifetime"
  56. };
  57. std::string
  58. SimpleParser::getString(isc::data::ConstElementPtr scope, const std::string& name) {
  59. ConstElementPtr x = scope->get(name);
  60. if (!x) {
  61. isc_throw(BadValue, "Element " << name << " not found");
  62. }
  63. if (x->getType() != Element::string) {
  64. isc_throw(BadValue, "Element " << name << " found, but is not a string");
  65. }
  66. return (x->stringValue());
  67. }
  68. int64_t
  69. SimpleParser::getInteger(isc::data::ConstElementPtr scope, const std::string& name) {
  70. ConstElementPtr x = scope->get(name);
  71. if (!x) {
  72. isc_throw(BadValue, "Element " << name << " not found");
  73. }
  74. if (x->getType() != Element::integer) {
  75. isc_throw(BadValue, "Element " << name << " found, but is not an integer");
  76. }
  77. return (x->intValue());
  78. }
  79. bool
  80. SimpleParser::getBoolean(isc::data::ConstElementPtr scope, const std::string& name) {
  81. ConstElementPtr x = scope->get(name);
  82. if (!x) {
  83. isc_throw(BadValue, "Element " << name << " not found");
  84. }
  85. if (x->getType() != Element::boolean) {
  86. isc_throw(BadValue, "Element " << name << " found, but is not a boolean");
  87. }
  88. return (x->boolValue());
  89. }
  90. const data::Element::Position&
  91. SimpleParser::getPosition(const std::string& name, const data::ConstElementPtr parent) const {
  92. if (!parent) {
  93. return (data::Element::ZERO_POSITION());
  94. }
  95. ConstElementPtr elem = parent->get(name);
  96. if (!elem) {
  97. return (data::Element::ZERO_POSITION());
  98. }
  99. return (elem->getPosition());
  100. }
  101. size_t SimpleParser::setDefaults(isc::data::ElementPtr scope,
  102. const SimpleDefaults& default_values) {
  103. size_t cnt = 0;
  104. // This is the position representing a default value. As the values
  105. // we're inserting here are not present in whatever the config file
  106. // came from, we need to make sure it's clearly labeled as default.
  107. const Element::Position pos("<default-value>", 0, 0);
  108. // Let's go over all parameters we have defaults for.
  109. BOOST_FOREACH(SimpleDefault def_value, default_values) {
  110. // Try if such a parameter is there. If it is, let's
  111. // skip it, because user knows best *cough*.
  112. ConstElementPtr x = scope->get(string(def_value.name_));
  113. if (x) {
  114. // There is such a value already, skip it.
  115. continue;
  116. }
  117. // There isn't such a value defined, let's create the default
  118. // value...
  119. switch (def_value.type_) {
  120. case Element::string: {
  121. x.reset(new StringElement(def_value.value_, pos));
  122. break;
  123. }
  124. case Element::integer: {
  125. int int_value = boost::lexical_cast<int>(def_value.value_);
  126. x.reset(new IntElement(int_value, pos));
  127. break;
  128. }
  129. case Element::boolean: {
  130. bool bool_value;
  131. if (def_value.value_ == string("true")) {
  132. bool_value = true;
  133. } else if (def_value.value_ == string("false")) {
  134. bool_value = false;
  135. } else {
  136. isc_throw(BadValue, "Internal error. Boolean value specified as "
  137. << def_value.value_ << ", expected true or false");
  138. }
  139. x.reset(new BoolElement(bool_value, pos));
  140. break;
  141. }
  142. case Element::real: {
  143. double dbl_value = boost::lexical_cast<double>(def_value.value_);
  144. x.reset(new DoubleElement(dbl_value, pos));
  145. break;
  146. }
  147. default:
  148. // No default values for null, list or map
  149. isc_throw(BadValue, "Internal error. Incorrect default value type.");
  150. }
  151. // ... and insert it into the provided Element tree.
  152. scope->set(def_value.name_, x);
  153. cnt++;
  154. }
  155. return (cnt);
  156. }
  157. size_t SimpleParser::setGlobalDefaults(isc::data::ElementPtr global, bool v6) {
  158. return (setDefaults(global, v6 ? GLOBAL6_DEFAULTS : GLOBAL4_DEFAULTS));
  159. }
  160. size_t SimpleParser::setOptionDefaults(isc::data::ElementPtr option, bool v6) {
  161. return (setDefaults(option, v6?OPTION6_DEFAULTS : OPTION4_DEFAULTS));
  162. }
  163. size_t SimpleParser::setOptionListDefaults(isc::data::ElementPtr option_list, bool v6) {
  164. size_t cnt = 0;
  165. BOOST_FOREACH(ElementPtr single_option, option_list->listValue()) {
  166. cnt += setOptionDefaults(single_option, v6);
  167. }
  168. return (cnt);
  169. }
  170. size_t SimpleParser::setOptionDefDefaults(isc::data::ElementPtr option_def, bool v6) {
  171. return (setDefaults(option_def, v6? OPTION6_DEF_DEFAULTS : OPTION4_DEF_DEFAULTS));
  172. }
  173. size_t SimpleParser::setOptionDefListDefaults(isc::data::ElementPtr option_def_list,
  174. bool v6) {
  175. size_t cnt = 0;
  176. BOOST_FOREACH(ElementPtr single_def, option_def_list->listValue()) {
  177. cnt += setOptionDefDefaults(single_def, v6);
  178. }
  179. return (cnt);
  180. }
  181. size_t SimpleParser::setAllDefaults(isc::data::ElementPtr global, bool v6) {
  182. size_t cnt = 0;
  183. // Set global defaults first.
  184. /// @todo: Uncomment as part of the ticket 5019 work.
  185. //cnt = setGlobalDefaults(global, v6);
  186. // Now set option defintion defaults for each specified option definition
  187. ConstElementPtr option_defs = global->get("option-def");
  188. if (option_defs) {
  189. BOOST_FOREACH(ElementPtr single_def, option_defs->listValue()) {
  190. cnt += setOptionDefDefaults(single_def, v6);
  191. }
  192. }
  193. ConstElementPtr options = global->get("option-data");
  194. if (options) {
  195. BOOST_FOREACH(ElementPtr single_option, options->listValue()) {
  196. cnt += setOptionDefaults(single_option, v6);
  197. }
  198. //setOptionListDefaults(options);
  199. }
  200. return (cnt);
  201. }
  202. size_t
  203. SimpleParser::deriveParams(isc::data::ConstElementPtr parent,
  204. isc::data::ElementPtr child,
  205. const ParamsList& params) {
  206. if ( (parent->getType() != Element::map) ||
  207. (child->getType() != Element::map)) {
  208. return (0);
  209. }
  210. size_t cnt = 0;
  211. BOOST_FOREACH(string param, params) {
  212. ConstElementPtr x = parent->get(param);
  213. if (!x) {
  214. // Parent doesn't define this parameter, so there's
  215. // nothing to derive from
  216. continue;
  217. }
  218. if (child->get(param)) {
  219. // Child defines this parameter already. There's
  220. // nothing to do here.
  221. continue;
  222. }
  223. // Copy the parameters to the child scope.
  224. child->set(param, x);
  225. cnt++;
  226. }
  227. return (cnt);
  228. }
  229. size_t
  230. SimpleParser::inheritGlobalToSubnet(isc::data::ConstElementPtr global,
  231. isc::data::ElementPtr subnet) {
  232. return deriveParams(global, subnet, INHERIT_GLOBAL_TO_SUBNET);
  233. }
  234. }; // end of isc::dhcp namespace
  235. }; // end of isc namespace