19#include <boost/format.hpp> 
   20#include <boost/algorithm/string/predicate.hpp>  
   21#include <boost/scoped_ptr.hpp> 
   22#include <boost/shared_ptr.hpp> 
   34using boost::algorithm::iequals;
 
   35using boost::shared_ptr;
 
   45class InternalException : 
public isc::Exception {
 
   47    InternalException(
const char* filename, 
size_t line, 
const char* what) :
 
   48        Exception(filename, line, what)
 
   83                     const Name& zone_origin,
 
   89        zone_origin_(zone_origin),
 
   90        active_origin_(zone_origin),
 
   91        zone_class_(zone_class),
 
   92        callbacks_(callbacks),
 
   93        add_callback_(add_callback),
 
   95        master_file_(master_file),
 
   99        previous_name_(false),
 
 
  118        if (!lexer_.pushSource(filename.c_str(), &error)) {
 
  120                isc_throw(InternalException, error.c_str());
 
  123                reportError(
"", 0, error);
 
  128        include_info_.push_back(IncludeInfo(current_origin, last_name_));
 
  130        previous_name_ = 
false;
 
 
  140        lexer_.pushSource(stream);
 
 
  152        return (lexer_.getTotalSourceSize());
 
 
  158        return (lexer_.getPosition());
 
 
  166    void reportError(
const std::string& filename, 
size_t line,
 
  167                     const std::string& reason) {
 
  169        callbacks_.
error(filename, line, reason);
 
  195        const IncludeInfo& info(include_info_.back());
 
  196        active_origin_ = info.first;
 
  197        last_name_ = info.second;
 
  198        include_info_.pop_back();
 
  199        previous_name_ = 
false;
 
  204    const string getString() {
 
  206        return (string_token_);
 
  223    MasterToken handleInitialToken();
 
  226    void doOrigin(
bool is_optional) {
 
  235            const MasterToken::StringRegion&
 
  236                name_string(name_tok.getStringRegion());
 
  237            active_origin_ = Name(name_string.beg, name_string.len,
 
  239            if (name_string.len > 0 &&
 
  240                name_string.beg[name_string.len - 1] != 
'.') {
 
  241                callbacks_.warning(lexer_.getSourceName(),
 
  242                                   lexer_.getSourceLine(),
 
  243                                   "The new origin is relative, did you really" 
  244                                   " mean " + active_origin_.toText() + 
"?");
 
  273        const Name current_origin = active_origin_;
 
  289    RRType parseRRParams(
bool& explicit_ttl, MasterToken rrparam_token) {
 
  299        if (setCurrentTTL(rrparam_token.getString())) {
 
  307        boost::scoped_ptr<RRClass> rrclass
 
  310            if (*rrclass != zone_class_) {
 
  311                isc_throw(InternalException, 
"Class mismatch: " << *rrclass <<
 
  312                          " vs. " << zone_class_);
 
  319        if (!explicit_ttl && setCurrentTTL(rrparam_token.getString())) {
 
  325        return (RRType(rrparam_token.getString()));
 
  347    void limitTTL(RRTTL& ttl, 
bool post_parsing) {
 
  349            const size_t src_line = lexer_.getSourceLine() -
 
  350                (post_parsing ? 1 : 0);
 
  351            callbacks_.warning(lexer_.getSourceName(), src_line,
 
  352                               "TTL " + ttl.toText() + 
" > MAXTTL, " 
  353                               "setting to 0 per RFC2181");
 
  363    void setDefaultTTL(
const RRTTL& ttl, 
bool post_parsing) {
 
  364        assignTTL(default_ttl_, ttl);
 
  365        limitTTL(*default_ttl_, post_parsing);
 
  377    bool setCurrentTTL(
const string& ttl_txt) {
 
  383            current_ttl_.reset(rrttl);
 
  384            limitTTL(*current_ttl_, 
false);
 
  399    const RRTTL& getCurrentTTL(
bool explicit_ttl, 
const RRType& rrtype,
 
  404        const size_t current_line = lexer_.getSourceLine() - 1;
 
  406        if (!current_ttl_ && !default_ttl_) {
 
  408                callbacks_.warning(lexer_.getSourceName(), current_line,
 
  410                                   "using SOA MINTTL instead");
 
  411                const uint32_t ttl_val =
 
  412                    dynamic_cast<const rdata::generic::SOA&
>(*rdata).
 
  414                setDefaultTTL(RRTTL(ttl_val), 
true);
 
  415                assignTTL(current_ttl_, *default_ttl_);
 
  420                throw InternalException(__FILE__, __LINE__,
 
  421                                        "no TTL specified; load rejected");
 
  423        } 
else if (!explicit_ttl && default_ttl_) {
 
  424            assignTTL(current_ttl_, *default_ttl_);
 
  428            callbacks_.warning(lexer_.getSourceName(), current_line,
 
  429                               "using RFC1035 TTL semantics; default to the " 
  430                               "last explicitly stated TTL");
 
  434        return (*current_ttl_);
 
  441    void handleDirective(
const char* directive, 
size_t length) {
 
  442        if (iequals(directive, 
"INCLUDE")) {
 
  444        } 
else if (iequals(directive, 
"ORIGIN")) {
 
  447        } 
else if (iequals(directive, 
"TTL")) {
 
  448            setDefaultTTL(RRTTL(getString()), 
false);
 
  451            isc_throw(InternalException, 
"Unknown directive '" <<
 
  452                      string(directive, directive + length) << 
"'");
 
  457    void eatUntilEOL(
bool reportExtra) {
 
  460            const MasterToken& token(lexer_.getNextToken());
 
  461            switch (token.getType()) {
 
  463                    callbacks_.warning(lexer_.getSourceName(),
 
  464                                       lexer_.getSourceLine(),
 
  465                                       "File does not end with newline");
 
  477                        reportError(lexer_.getSourceName(),
 
  478                                    lexer_.getSourceLine(),
 
  479                                    "Extra tokens at the end of line");
 
  489    static void assignTTL(boost::scoped_ptr<RRTTL>& left, 
const RRTTL& right) {
 
  491            left.reset(
new RRTTL(right));
 
  499    const Name zone_origin_;
 
  502    shared_ptr<Name> last_name_; 
 
  503    const RRClass zone_class_;
 
  504    MasterLoaderCallbacks callbacks_;
 
  506    boost::scoped_ptr<RRTTL> default_ttl_; 
 
  509    boost::scoped_ptr<RRTTL> current_ttl_; 
 
  514    const std::string master_file_;
 
  515    std::string string_token_;
 
  518    const bool many_errors_;    
 
  523    typedef pair<Name, shared_ptr<Name> > IncludeInfo;
 
  524    vector<IncludeInfo> include_info_;
 
 
  538MasterLoader::MasterLoaderImpl::handleInitialToken() {
 
  556            isc_throw(InternalException, 
"No previous name to use in " 
  557                      "place of initial whitespace");
 
  558        } 
else if (!previous_name_) {
 
  560                               "Owner name omitted around $INCLUDE, the result " 
  561                               "might not be as expected");
 
  570        if (name_string.len > 0 && name_string.beg[0] == 
'$') {
 
  576            handleDirective(name_string.beg + 1, name_string.len - 1);
 
  584        last_name_.reset(
new Name(name_string.beg, name_string.len,
 
  586        previous_name_ = 
true;
 
  590    switch (initial_token.
getType()) { 
 
  593            return (initial_token);
 
  602        return (initial_token); 
 
  608        isc_throw(InternalException, 
"Parser got confused (unexpected " 
  609                  "token " << initial_token.
getType() << 
")");
 
  615    if (count_limit == 0) {
 
  620                  "Trying to load when already loaded");
 
  626    while (ok_ && count < count_limit) {
 
  628            const MasterToken next_token = handleInitialToken();
 
  638            bool explicit_ttl = 
false;
 
  639            const RRType rrtype = parseRRParams(explicit_ttl, next_token);
 
  644                                   &active_origin_, options_, callbacks_);
 
  651                add_callback_(*last_name_, zone_class_, rrtype,
 
  652                              getCurrentTTL(explicit_ttl, rrtype, 
rdata),
 
  668            reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
 
  672            reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
 
  676            reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
 
  679        } 
catch (
const InternalException& e) {
 
  680            reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
 
 
  690                           const Name& zone_origin,
 
  699                                     zone_class, callbacks, add_callback, options));
 
 
  703                           const Name& zone_origin,
 
  712                                     callbacks, add_callback, options));
 
  713    impl_->pushStreamSource(stream);
 
 
  721    const bool result = impl_->loadIncremental(count_limit);
 
  722    impl_->complete_ = result;
 
 
  728    return (impl_->complete_ && !impl_->seen_error_);
 
 
  733    return (impl_->getSize());
 
 
  738    return (impl_->getPosition());
 
 
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
Base class for all sorts of text parse errors.
Exception thrown from a wrapper version of MasterLexer::getNextToken() for non fatal errors.
Exception thrown when we fail to read from the input stream or file.
@ QSTRING
recognize quoted string
@ INITIAL_WS
recognize begin-of-line spaces after an end-of-line
void ungetToken()
Return the last token back to the lexer.
size_t getSourceCount() const
Get number of sources inside the lexer.
std::string getSourceName() const
Return the name of the current input source name.
const MasterToken & getNextToken(Options options=NONE)
Parse and return another token from the input.
void popSource()
Stop using the most recently opened input source (file or stream).
size_t getSourceLine() const
Return the input source line number.
Set of issue callbacks for a loader.
void error(const std::string &source_name, size_t source_line, const std::string &reason) const
Call callback for serious errors.
void warning(const std::string &source_name, size_t source_line, const std::string &reason) const
Call callback for potential problems.
Error while loading by MasterLoader without specifying the MANY_ERRORS option.
Private implementation class for the MasterLoader.
bool loadIncremental(size_t count_limit)
Implementation of MasterLoader::loadIncremental()
MasterLoaderImpl(const char *master_file, const Name &zone_origin, const RRClass &zone_class, const MasterLoaderCallbacks &callbacks, const AddRRCallback &add_callback, MasterLoader::Options options)
Constructor.
size_t getPosition() const
Return the line number being parsed in the pushed input sources.
size_t getSize() const
Return the total size of the input sources pushed so far.
void pushSource(const std::string &filename, const Name ¤t_origin)
Wrapper around MasterLexer::pushSource() (file version)
void pushStreamSource(std::istream &stream)
Wrapper around MasterLexer::pushSource() (stream version)
size_t getPosition() const
Return the position of the loader in zone.
MasterLoader(const char *master_file, const Name &zone_origin, const RRClass &zone_class, const MasterLoaderCallbacks &callbacks, const AddRRCallback &add_callback, Options options=DEFAULT)
Constructor.
bool loadedSuccessfully() const
Was the loading successful?
Options
Options how the parsing should work.
@ MANY_ERRORS
Lenient mode (see documentation of MasterLoader constructor).
~MasterLoader()
Destructor.
size_t getSize() const
Return the total size of the zone files and streams.
bool loadIncremental(size_t count_limit)
Load some RRs.
@ INITIAL_WS
White spaces at the beginning of a line after an end of line or at the beginning of file (if asked.
@ ERROR
Error detected in getting a token.
@ END_OF_LINE
End of line detected.
@ QSTRING
A single string quoted by double-quotes (").
@ END_OF_FILE
End of file detected.
Type getType() const
Return the token type.
const StringRegion & getStringRegion() const
Return the value of a string-variant token.
std::string getErrorText() const
Return a textual description of the error of a error type token.
The Name class encapsulates DNS names.
The RRClass class encapsulates DNS resource record classes.
static RRClass * createFromText(const std::string &class_str)
A separate factory of RRClass from text.
static RRTTL * createFromText(const std::string &ttlstr)
A separate factory of RRTTL from text.
static const RRTTL & MAX_TTL()
The TTL of the max allowable value, per RFC2181 Section 8.
The RRType class encapsulates DNS resource record types.
static const RRType & SOA()
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
boost::shared_ptr< const Rdata > ConstRdataPtr
RdataPtr createRdata(const RRType &rrtype, const RRClass &rrclass, const std::string &rdata_string)
Create RDATA of a given pair of RR type and class from a string.
boost::shared_ptr< Rdata > RdataPtr
The RdataPtr type is a pointer-like type, pointing to an object of some concrete derived class of Rda...
std::function< void(const Name &name, const RRClass &rrclass, const RRType &rrtype, const RRTTL &rrttl, const rdata::RdataPtr &rdata)> AddRRCallback
Type of callback to add a RR.
Defines the logger used by the top-level component of kea-lfc.
A simple representation of a range of a string.