]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1680] added EvalContext convert functions
authorRazvan Becheriu <razvan@isc.org>
Tue, 16 Mar 2021 13:11:34 +0000 (15:11 +0200)
committerRazvan Becheriu <razvan@isc.org>
Wed, 5 May 2021 17:12:18 +0000 (20:12 +0300)
src/lib/eval/eval_context.cc
src/lib/eval/eval_context.h
src/lib/eval/token.cc

index 548ad1542359363462bc62a032ada623dc10f490..5830007e2af96738a1bffb5fe4a5effd124dc1c5 100644 (file)
@@ -25,8 +25,7 @@ EvalContext::EvalContext(const Option::Universe& option_universe,
 {
 }
 
-EvalContext::~EvalContext()
-{
+EvalContext::~EvalContext() {
 }
 
 bool
@@ -35,8 +34,7 @@ EvalContext::acceptAll(const ClientClass&) {
 }
 
 bool
-EvalContext::parseString(const std::string& str, ParserType type)
-{
+EvalContext::parseString(const std::string& str, ParserType type) {
     file_ = "<string>";
     string_ = str;
     scanStringBegin(type);
@@ -54,21 +52,18 @@ EvalContext::parseString(const std::string& str, ParserType type)
 }
 
 void
-EvalContext::error(const isc::eval::location& loc, const std::string& what)
-{
+EvalContext::error(const isc::eval::location& loc, const std::string& what) {
     isc_throw(EvalParseError, loc << ": " << what);
 }
 
 void
-EvalContext::error (const std::string& what)
-{
+EvalContext::error (const std::string& what) {
     isc_throw(EvalParseError, what);
 }
 
 uint16_t
 EvalContext::convertOptionCode(const std::string& option_code,
-                               const isc::eval::location& loc)
-{
+                               const isc::eval::location& loc) {
     int n = 0;
     try {
         n  = boost::lexical_cast<int>(option_code);
@@ -92,8 +87,7 @@ EvalContext::convertOptionCode(const std::string& option_code,
 
 uint16_t
 EvalContext::convertOptionName(const std::string& option_name,
-                               const isc::eval::location& loc)
-{
+                               const isc::eval::location& loc) {
     const std::string global_space = (option_universe_ == Option::V4) ?
         DHCP4_OPTION_SPACE : DHCP6_OPTION_SPACE;
 
@@ -116,8 +110,7 @@ EvalContext::convertOptionName(const std::string& option_name,
 
 int8_t
 EvalContext::convertNestLevelNumber(const std::string& nest_level,
-                                    const isc::eval::location& loc)
-{
+                                    const isc::eval::location& loc) {
     int8_t n = convertInt8(nest_level, loc);
     if (option_universe_ == Option::V6) {
         if ((n < - HOP_COUNT_LIMIT) || (n >= HOP_COUNT_LIMIT)) {
@@ -133,11 +126,10 @@ EvalContext::convertNestLevelNumber(const std::string& nest_level,
 
 uint8_t
 EvalContext::convertUint8(const std::string& number,
-                          const isc::eval::location& loc)
-{
-    int n = 0;
+                          const isc::eval::location& loc) {
+    int32_t n = 0;
     try {
-        n  = boost::lexical_cast<int>(number);
+        n = boost::lexical_cast<int32_t>(number);
     } catch (const boost::bad_lexical_cast &) {
         error(loc, "Invalid integer value in " + number);
     }
@@ -151,34 +143,67 @@ EvalContext::convertUint8(const std::string& number,
 
 int8_t
 EvalContext::convertInt8(const std::string& number,
-                         const isc::eval::location& loc)
-{
-    int n = 0;
+                         const isc::eval::location& loc) {
+    int32_t n = 0;
     try {
-        n  = boost::lexical_cast<int>(number);
+        n = boost::lexical_cast<int32_t>(number);
     } catch (const boost::bad_lexical_cast &) {
         error(loc, "Invalid integer value in " + number);
     }
     if (n < std::numeric_limits<int8_t>::min() ||
         n > std::numeric_limits<int8_t>::max()) {
         error(loc, "Invalid value in "
-              + number + ". Allowed range: 0..255");
+              + number + ". Allowed range: -128..127");
     }
 
-    return (static_cast<uint8_t>(n));
+    return (static_cast<int8_t>(n));
+}
+
+uint16_t
+EvalContext::convertUint16(const std::string& number,
+                           const isc::eval::location& loc) {
+    int64_t n = 0;
+    try {
+        n = boost::lexical_cast<int64_t>(number);
+    } catch (const boost::bad_lexical_cast &) {
+        error(loc, "Invalid value in " + number);
+    }
+    if (n < 0 || n > std::numeric_limits<uint16_t>::max()) {
+        error(loc, "Invalid value in "
+              + number + ". Allowed range: 0..65535");
+    }
+
+    return (static_cast<uint16_t>(n));
+}
+
+int16_t
+EvalContext::convertInt16(const std::string& number,
+                          const isc::eval::location& loc) {
+    uint64_t n = 0;
+    try {
+        n = boost::lexical_cast<int64_t>(number);
+    } catch (const boost::bad_lexical_cast &) {
+        error(loc, "Invalid value in " + number);
+    }
+    if (n > std::numeric_limits<int16_t>::max() ||
+        n < std::numeric_limits<int16_t>::max()) {
+        error(loc, "Invalid value in "
+              + number + ". Allowed range: -32768..32767");
+    }
+
+    return (static_cast<int16_t>(n));
 }
 
 uint32_t
 EvalContext::convertUint32(const std::string& number,
-                          const isc::eval::location& loc)
-{
-    uint64_t n = 0;
+                           const isc::eval::location& loc) {
+    int64_t n = 0;
     try {
-        n  = boost::lexical_cast<uint64_t>(number);
+        n = boost::lexical_cast<int64_t>(number);
     } catch (const boost::bad_lexical_cast &) {
         error(loc, "Invalid value in " + number);
     }
-    if (n > std::numeric_limits<uint32_t>::max()) {
+    if (n < 0 || n > std::numeric_limits<uint32_t>::max()) {
         error(loc, "Invalid value in "
               + number + ". Allowed range: 0..4294967295");
     }
@@ -186,6 +211,24 @@ EvalContext::convertUint32(const std::string& number,
     return (static_cast<uint32_t>(n));
 }
 
+int32_t
+EvalContext::convertInt32(const std::string& number,
+                          const isc::eval::location& loc) {
+    int64_t n = 0;
+    try {
+        n = boost::lexical_cast<int64_t>(number);
+    } catch (const boost::bad_lexical_cast &) {
+        error(loc, "Invalid value in " + number);
+    }
+    if (n > std::numeric_limits<int32_t>::max() ||
+        n < std::numeric_limits<int32_t>::max()) {
+        error(loc, "Invalid value in "
+              + number + ". Allowed range: -2147483648..2147483647");
+    }
+
+    return (static_cast<int32_t>(n));
+}
+
 std::string
 EvalContext::fromUint32(const uint32_t integer) {
     std::string tmp(4, 0);
@@ -197,13 +240,21 @@ EvalContext::fromUint32(const uint32_t integer) {
     return (tmp);
 }
 
+std::string
+EvalContext::fromUint16(const uint16_t integer) {
+    std::string tmp(2, 0);
+    tmp[0] = (integer >> 8) & 0xff;
+    tmp[1] = integer & 0xff;
+
+    return (tmp);
+}
+
 bool
 EvalContext::isClientClassDefined(const ClientClass& client_class) {
     return (check_defined_(client_class));
 }
 
 void
-EvalContext::fatal (const std::string& what)
-{
+EvalContext::fatal(const std::string& what) {
     isc_throw(Unexpected, what);
 }
index bd47ae791e4b05c631e3eb7f13b58c4f424bc2ad..2895e90dff8d95d926b5778956a5f3c7290a6ea3 100644 (file)
@@ -31,8 +31,7 @@ public:
 
 
 /// @brief Evaluation context, an interface to the expression evaluation.
-class EvalContext
-{
+class EvalContext {
 public:
 
     /// @brief Specifies what type of expression the parser is expected to see
@@ -136,6 +135,35 @@ public:
     static uint32_t convertUint32(const std::string& number,
                                   const isc::eval::location& loc);
 
+    /// @brief Attempts to convert string to signed 32bit integer
+    ///
+    /// @param number string to be converted
+    /// @param loc the location of the token
+    /// @return the integer value
+    /// @throw EvalParseError if conversion fails or the value is out of range.
+    static int32_t convertInt32(const std::string& number,
+                                const isc::eval::location& loc);
+
+    /// @brief Attempts to convert string to unsigned 16bit integer
+    ///
+    /// For reverse conversion, see @ref fromUint16
+    ///
+    /// @param number string to be converted
+    /// @param loc the location of the token
+    /// @return the integer value
+    /// @throw EvalParseError if conversion fails or the value is out of range.
+    static uint16_t convertUint16(const std::string& number,
+                                  const isc::eval::location& loc);
+
+    /// @brief Attempts to convert string to signed 16bit integer
+    ///
+    /// @param number string to be converted
+    /// @param loc the location of the token
+    /// @return the integer value
+    /// @throw EvalParseError if conversion fails or the value is out of range.
+    static int16_t convertInt16(const std::string& number,
+                                const isc::eval::location& loc);
+
     /// @brief Attempts to convert string to unsigned 8bit integer
     ///
     /// @param number string to be converted
@@ -164,7 +192,7 @@ public:
     int8_t convertNestLevelNumber(const std::string& nest_level,
                                   const isc::eval::location& loc);
 
-    /// @brief Converts integer to string representation
+    /// @brief Converts unsigned 32bit integer to string representation
     ///
     /// The integer is coded as a 4 byte long string in network order, e.g.
     /// 6 is represented as 00000006. For reverse conversion, see
@@ -174,6 +202,16 @@ public:
     /// @return 4 byte long string that encodes the value.
     static std::string fromUint32(const uint32_t integer);
 
+    /// @brief Converts unsigned 16bit integer to string representation
+    ///
+    /// The integer is coded as a 2 byte long string in network order, e.g.
+    /// 6 is represented as 0006. For reverse conversion, see
+    /// @ref convertUint16.
+    ///
+    /// @param integer value to be converted
+    /// @return 2 byte long string that encodes the value.
+    static std::string fromUint16(const uint16_t integer);
+
     /// @brief Returns the universe (v4 or v6)
     ///
     /// @return universe
@@ -205,7 +243,7 @@ public:
 
 };
 
-}; // end of isc::eval namespace
-}; // end of isc namespace
+} // end of isc::eval namespace
+} // end of isc namespace
 
 #endif
index fded03d7cb69aa8b1568a242cc31ceaab392448c..760d460038810027500efc6fd95fd60d823479b5 100644 (file)
@@ -171,7 +171,8 @@ TokenInt16ToText::evaluate(Pkt& /*pkt*/, ValueStack& values) {
 
     stringstream tmp;
     uint16_t value = *(reinterpret_cast<uint16_t*>(const_cast<char*>(op.data())));
-    tmp << static_cast<int16_t>(ntohs(value));
+    std::string data = EvalContext::fromUint16(value);
+    tmp << *(reinterpret_cast<int16_t *>(const_cast<char *>(data.data())));
     op = tmp.str();
     values.push(op);
 
@@ -195,7 +196,8 @@ TokenInt32ToText::evaluate(Pkt& /*pkt*/, ValueStack& values) {
 
     stringstream tmp;
     uint32_t value = *(reinterpret_cast<uint32_t*>(const_cast<char*>(op.data())));
-    tmp << static_cast<int32_t>(ntohl(value));
+    std::string data = EvalContext::fromUint32(value);
+    tmp << *(reinterpret_cast<int32_t *>(const_cast<char *>(data.data())));
     op = tmp.str();
     values.push(op);
 
@@ -242,7 +244,8 @@ TokenUInt16ToText::evaluate(Pkt& /*pkt*/, ValueStack& values) {
 
     stringstream tmp;
     uint16_t value = *(reinterpret_cast<uint16_t*>(const_cast<char*>(op.data())));
-    tmp << ntohs(value);
+    std::string data = EvalContext::fromUint16(value);
+    tmp << *(reinterpret_cast<uint16_t *>(const_cast<char *>(data.data())));
     op = tmp.str();
     values.push(op);
 
@@ -266,7 +269,8 @@ TokenUInt32ToText::evaluate(Pkt& /*pkt*/, ValueStack& values) {
 
     stringstream tmp;
     uint32_t value = *(reinterpret_cast<uint32_t*>(const_cast<char*>(op.data())));
-    tmp << ntohl(value);
+    std::string data = EvalContext::fromUint32(value);
+    tmp << *(reinterpret_cast<uint32_t *>(const_cast<char *>(data.data())));
     op = tmp.str();
     values.push(op);