summaryrefslogtreecommitdiffstats
path: root/src/bin/dhcp4/parser_context.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/bin/dhcp4/parser_context.h417
1 files changed, 417 insertions, 0 deletions
diff --git a/src/bin/dhcp4/parser_context.h b/src/bin/dhcp4/parser_context.h
new file mode 100644
index 0000000..a65ad3a
--- /dev/null
+++ b/src/bin/dhcp4/parser_context.h
@@ -0,0 +1,417 @@
+// Copyright (C) 2015-2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef PARSER_CONTEXT_H
+#define PARSER_CONTEXT_H
+#include <string>
+#include <map>
+#include <vector>
+#include <dhcp4/dhcp4_parser.h>
+#include <dhcp4/parser_context_decl.h>
+#include <exceptions/exceptions.h>
+
+// Tell Flex the lexer's prototype ...
+#define YY_DECL isc::dhcp::Dhcp4Parser::symbol_type parser4_lex (Parser4Context& driver)
+
+// ... and declare it for the parser's sake.
+YY_DECL;
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Evaluation error exception raised when trying to parse.
+///
+/// @todo: This probably should be common for Dhcp4 and Dhcp6.
+class Dhcp4ParseError : public isc::Exception {
+public:
+ Dhcp4ParseError(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
+/// @brief Evaluation context, an interface to the expression evaluation.
+class Parser4Context
+{
+public:
+
+ /// @brief Defines currently supported scopes
+ ///
+ /// Dhcp4Parser is able to parse several types of scope. Usually,
+ /// when it parses a config file, it expects the data to have a map
+ /// with Dhcp4 in it and all the parameters within that Dhcp4 map.
+ /// However, sometimes the parser is expected to parse only a subset
+ /// of that information. For example, it may be asked to parse
+ /// a structure that is host-reservation only, without the global
+ /// 'Dhcp4' or 'reservations' around it. In such case the parser
+ /// is being told to start parsing as PARSER_HOST_RESERVATION4.
+ typedef enum {
+ /// This parser will parse the content as generic JSON.
+ PARSER_JSON,
+
+ /// This parser will parse the content as Dhcp4 config wrapped in a map
+ /// (that's the regular config file)
+ PARSER_DHCP4,
+
+ /// This parser will parse the content of Dhcp4 (without outer { } and
+ /// without "Dhcp4"). It is mostly used in unit-tests as most of the
+ /// unit-tests do not define the outer map and Dhcp4 entity, just the
+ /// contents of it.
+ SUBPARSER_DHCP4,
+
+ /// This will parse the input as interfaces content.
+ PARSER_INTERFACES,
+
+ /// This will parse the input as Subnet4 content.
+ PARSER_SUBNET4,
+
+ /// This will parse the input as pool4 content.
+ PARSER_POOL4,
+
+ /// This will parse the input as host-reservation.
+ PARSER_HOST_RESERVATION,
+
+ /// This will parse the input option definitions (for tests).
+ PARSER_OPTION_DEFS,
+
+ /// This will parse the input as option definition.
+ PARSER_OPTION_DEF,
+
+ /// This will parse the input as option data.
+ PARSER_OPTION_DATA,
+
+ /// This will parse the input as hooks-library.
+ PARSER_HOOKS_LIBRARY,
+
+ /// This will parse the input as dhcp-ddns.
+ PARSER_DHCP_DDNS,
+
+ /// This will parse the input as config-control.
+ PARSER_CONFIG_CONTROL,
+ } ParserType;
+
+ /// @brief Default constructor.
+ Parser4Context();
+
+ /// @brief destructor
+ virtual ~Parser4Context();
+
+ /// @brief JSON elements being parsed.
+ std::vector<isc::data::ElementPtr> stack_;
+
+ /// @brief Method called before scanning starts on a string.
+ ///
+ /// @param str string to be parsed
+ /// @param type specifies expected content
+ void scanStringBegin(const std::string& str, ParserType type);
+
+ /// @brief Method called before scanning starts on a file.
+ ///
+ /// @param f stdio FILE pointer
+ /// @param filename file to be parsed
+ /// @param type specifies expected content
+ void scanFileBegin(FILE* f, const std::string& filename, ParserType type);
+
+ /// @brief Method called after the last tokens are scanned.
+ void scanEnd();
+
+ /// @brief Divert input to an include file.
+ ///
+ /// @param filename file to be included
+ void includeFile(const std::string& filename);
+
+ /// @brief Run the parser on the string specified.
+ ///
+ /// This method parses specified string. Depending on the value of
+ /// parser_type, parser may either check only that the input is valid
+ /// JSON, or may do more specific syntax checking. See @ref ParserType
+ /// for supported syntax checkers.
+ ///
+ /// @param str string to be parsed
+ /// @param parser_type specifies expected content (usually DHCP4 or generic JSON)
+ /// @return Element structure representing parsed text.
+ isc::data::ElementPtr parseString(const std::string& str,
+ ParserType parser_type);
+
+ /// @brief Run the parser on the file specified.
+ ///
+ /// This method parses specified file. Depending on the value of
+ /// parser_type, parser may either check only that the input is valid
+ /// JSON, or may do more specific syntax checking. See @ref ParserType
+ /// for supported syntax checkers.
+ ///
+ /// @param filename file to be parsed
+ /// @param parser_type specifies expected content (usually DHCP4 or generic JSON)
+ /// @return Element structure representing parsed text.
+ isc::data::ElementPtr parseFile(const std::string& filename,
+ ParserType parser_type);
+
+ /// @brief Error handler
+ ///
+ /// @note The optional position for an error in a string begins by 1
+ /// so the caller should add 1 to the position of the C++ string.
+ ///
+ /// @param loc location within the parsed file where the problem was experienced.
+ /// @param what string explaining the nature of the error.
+ /// @param pos optional position for in string errors.
+ /// @throw Dhcp4ParseError
+ void error(const isc::dhcp::location& loc,
+ const std::string& what,
+ size_t pos = 0);
+
+ /// @brief Error handler
+ ///
+ /// This is a simplified error reporting tool for possible future
+ /// cases when the Dhcp4Parser is not able to handle the packet.
+ ///
+ /// @param what string explaining the nature of the error.
+ /// @throw Dhcp4ParseError
+ void error(const std::string& what);
+
+ /// @brief Fatal error handler
+ ///
+ /// This is for should not happen but fatal errors.
+ /// Used by YY_FATAL_ERROR macro so required to be static.
+ ///
+ /// @param what string explaining the nature of the error.
+ /// @throw Dhcp4ParseError
+ static void fatal(const std::string& what);
+
+ /// @brief Converts bison's position to one understandable by isc::data::Element
+ ///
+ /// Convert a bison location into an element position
+ /// (take the begin, the end is lost)
+ ///
+ /// @param loc location in bison format
+ /// @return Position in format accepted by Element
+ isc::data::Element::Position loc2pos(isc::dhcp::location& loc);
+
+ /// @brief Check if a required parameter is present
+ ///
+ /// Check if a required parameter is present in the map at the top
+ /// of the stack and raise an error when it is not.
+ ///
+ /// @param name name of the parameter to check
+ /// @param open_loc location of the opening curly bracket
+ /// @param close_loc location of the closing curly bracket
+ /// @throw Dhcp4ParseError
+ void require(const std::string& name,
+ isc::data::Element::Position open_loc,
+ isc::data::Element::Position close_loc);
+
+ /// @brief Check if a parameter is already present
+ ///
+ /// Check if a parameter is already present in the map at the top
+ /// of the stack and raise an error when it is.
+ ///
+ /// @param name name of the parameter to check
+ /// @param loc location of the current parameter
+ /// @throw Dhcp4ParseError
+ void unique(const std::string& name,
+ isc::data::Element::Position loc);
+
+ /// @brief Warning handler
+ ///
+ /// @param loc location within the parsed file where the problem was experienced
+ /// @param what string explaining the nature of the error
+ ///
+ /// @throw ParseError
+ void warning(const isc::dhcp::location& loc, const std::string& what);
+
+ /// @brief Warning for extra commas
+ ///
+ /// @param loc location within the parsed file of the extra comma
+ ///
+ /// @throw ParseError
+ void warnAboutExtraCommas(const isc::dhcp::location& loc);
+
+ /// @brief Defines syntactic contexts for lexical tie-ins
+ typedef enum {
+ ///< This one is used in pure JSON mode.
+ NO_KEYWORD,
+
+ ///< Used while parsing top level (that contains Dhcp4)
+ CONFIG,
+
+ ///< Used while parsing content of Dhcp4.
+ DHCP4,
+
+ /// Used while parsing Dhcp4/interfaces structures.
+ INTERFACES_CONFIG,
+
+ /// Sanity checks.
+ SANITY_CHECKS,
+
+ /// Used while parsing Dhcp4/interfaces/dhcp-socket-type structures.
+ DHCP_SOCKET_TYPE,
+
+ /// Used while parsing Dhcp4/interfaces/outbound-interface structures.
+ OUTBOUND_INTERFACE,
+
+ /// Used while parsing Dhcp4/lease-database structures.
+ LEASE_DATABASE,
+
+ /// Used while parsing Dhcp4/hosts-database[s] structures.
+ HOSTS_DATABASE,
+
+ /// Used while parsing Dhcp4/*-database/type.
+ DATABASE_TYPE,
+
+ /// Used while parsing Dhcp4/*-database/on-fail.
+ DATABASE_ON_FAIL,
+
+ /// Used while parsing Dhcp4/host-reservation-identifiers.
+ HOST_RESERVATION_IDENTIFIERS,
+
+ /// Used while parsing Dhcp4/hooks-libraries.
+ HOOKS_LIBRARIES,
+
+ /// Used while parsing Dhcp4/Subnet4 structures.
+ SUBNET4,
+
+ /// Used while parsing shared-networks structures.
+ SHARED_NETWORK,
+
+ /// Used while parsing Dhcp4/reservation-mode.
+ RESERVATION_MODE,
+
+ /// Used while parsing Dhcp4/option-def structures.
+ OPTION_DEF,
+
+ /// Used while parsing Dhcp4/option-data, Dhcp4/subnet4/option-data
+ /// or anywhere option-data is present (client classes, host
+ /// reservations and possibly others).
+ OPTION_DATA,
+
+ /// Used while parsing Dhcp4/client-classes structures.
+ CLIENT_CLASSES,
+
+ /// Used while parsing Dhcp4/expired-leases-processing.
+ EXPIRED_LEASES_PROCESSING,
+
+ /// Used while parsing Dhcp4/server-id structures.
+ SERVER_ID,
+
+ /// Used while parsing Dhcp4/control-socket structures.
+ CONTROL_SOCKET,
+
+ /// Used while parsing Dhcp4/dhcp-queue-control structures.
+ DHCP_QUEUE_CONTROL,
+
+ /// Used while parsing Dhcp4/multi-threading structures.
+ DHCP_MULTI_THREADING,
+
+ /// Used while parsing Dhcp4/subnet4/pools structures.
+ POOLS,
+
+ /// Used while parsing Dhcp4/reservations structures.
+ RESERVATIONS,
+
+ /// Used while parsing Dhcp4/subnet4relay structures.
+ RELAY,
+
+ /// Used while parsing Dhcp4/loggers structures.
+ LOGGERS,
+
+ /// Used while parsing Dhcp4/loggers/output_options structures.
+ OUTPUT_OPTIONS,
+
+ /// Used while parsing Dhcp4/dhcp-ddns.
+ DHCP_DDNS,
+
+ /// Used while parsing Dhcp4/dhcp-ddns/ncr-protocol
+ NCR_PROTOCOL,
+
+ /// Used while parsing Dhcp4/dhcp-ddns/ncr-format
+ NCR_FORMAT,
+
+ /// Used while parsing Dhcp4/dhcp-ddns/replace-client-name.
+ REPLACE_CLIENT_NAME,
+
+ /// Used while parsing Dhcp4/config-control
+ CONFIG_CONTROL,
+
+ /// Used while parsing config-control/config-databases
+ CONFIG_DATABASE,
+
+ /// Used while parsing compatibility parameters
+ COMPATIBILITY,
+
+ } ParserContext;
+
+ /// @brief File name
+ std::string file_;
+
+ /// @brief File name stack
+ std::vector<std::string> files_;
+
+ /// @brief Location of the current token
+ ///
+ /// The lexer will keep updating it. This variable will be useful
+ /// for logging errors.
+ isc::dhcp::location loc_;
+
+ /// @brief Location stack
+ std::vector<isc::dhcp::location> locs_;
+
+ /// @brief Lexer state stack
+ std::vector<struct yy_buffer_state*> states_;
+
+ /// @brief sFile (aka FILE)
+ FILE* sfile_;
+
+ /// @brief sFile (aka FILE) stack
+ ///
+ /// This is a stack of files. Typically there's only one file (the
+ /// one being currently parsed), but there may be more if one
+ /// file includes another.
+ std::vector<FILE*> sfiles_;
+
+ /// @brief Current syntactic context
+ ParserContext ctx_;
+
+ /// @brief Enter a new syntactic context
+ ///
+ /// Entering a new syntactic context is useful in several ways.
+ /// First, it allows the parser to avoid conflicts. Second, it
+ /// allows the lexer to return different tokens depending on
+ /// context (e.g. if "renew-timer" string is detected, the lexer
+ /// will return STRING token if in JSON mode or RENEW_TIMER if
+ /// in DHCP4 mode. Finally, the syntactic context allows the
+ /// error message to be more descriptive if the input string
+ /// does not parse properly.
+ ///
+ /// @param ctx the syntactic context to enter into
+ void enter(const ParserContext& ctx);
+
+ /// @brief Leave a syntactic context
+ ///
+ /// @throw isc::Unexpected if unbalanced
+ void leave();
+
+ /// @brief Get the syntactic context name
+ ///
+ /// @return printable name of the context.
+ const std::string contextName();
+
+ private:
+ /// @brief Flag determining scanner debugging.
+ bool trace_scanning_;
+
+ /// @brief Flag determining parser debugging.
+ bool trace_parsing_;
+
+ /// @brief Syntactic context stack
+ std::vector<ParserContext> cstack_;
+
+ /// @brief Common part of parseXXX
+ ///
+ /// @return Element structure representing parsed text.
+ isc::data::ElementPtr parseCommon();
+};
+
+}; // end of isc::eval namespace
+}; // end of isc namespace
+
+#endif