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;
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;
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] !=
'.') {
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) {
350 (post_parsing ? 1 : 0);
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,
406 if (!current_ttl_ && !default_ttl_) {
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_);
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) {
461 switch (token.getType()) {
465 "File does not end with newline");
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");
568 name_string(initial_token.getStringRegion());
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);
605 isc_throw(InternalException, initial_token.getErrorText());
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");
623 pushSource(master_file_, active_origin_);
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());
This is a base class for exceptions thrown from the DNS library module.
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.
bool pushSource(const char *filename, std::string *error=0)
Open a file and make it the current input source of MasterLexer.
size_t getTotalSourceSize() const
Return the total size of pushed sources.
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.
size_t getPosition() const
Return the position of lexer in the pushed sources so far.
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.
The Name class encapsulates DNS names.
std::string toText(bool omit_final_dot=false) const
Convert the Name to a string.
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.