diff --git a/src/bin/parkinglot/Makefile.am b/src/bin/parkinglot/Makefile.am index 0d1a7392c6..5df7507afb 100644 --- a/src/bin/parkinglot/Makefile.am +++ b/src/bin/parkinglot/Makefile.am @@ -4,6 +4,7 @@ bin_PROGRAMS = parkinglot parkinglot_SOURCES = common.cc common.h zoneset.h zoneset.cc parkinglot.cc parkinglot_SOURCES += parkinglot.h main.cc parkinglot_SOURCES += data_source_plot.h data_source_plot.cc -parkinglot_LDADD = $(top_srcdir)/src/lib/dns/libdns.a +parkinglot_SOURCES += data_source.h data_source.cc +parkinglot_LDADD = $(top_srcdir)/src/lib/dns/cpp/.libs/libdns.a parkinglot_LDADD += $(top_srcdir)/src/lib/config/cpp/libclient.a parkinglot_LDADD += $(top_srcdir)/src/lib/cc/cpp/libcc.a diff --git a/src/bin/parkinglot/data_source.cc b/src/bin/parkinglot/data_source.cc new file mode 100644 index 0000000000..98e37d23b0 --- /dev/null +++ b/src/bin/parkinglot/data_source.cc @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +#include + +#include "data_source.h" + +namespace isc { +namespace dns { + +void +DataSource::getData(isc::dns::RRsetPtr query, isc::dns::Message& answer) +{ + return; +} + +} +} diff --git a/src/bin/parkinglot/data_source.h b/src/bin/parkinglot/data_source.h new file mode 100644 index 0000000000..016dfb0be9 --- /dev/null +++ b/src/bin/parkinglot/data_source.h @@ -0,0 +1,122 @@ +// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +// $Id$ + +#ifndef __DATA_SOURCE_H +#define __DATA_SOURCE_H + +#include +#include + +namespace isc { +namespace dns { + +// do we need to make a template for this? +// i.e. do we want this to be able to hold more types than RRset? +class SearchResult { +public: + enum status_type { success, error, not_implemented, + zone_not_found, name_not_found }; + + void addRRset(RRsetPtr rrset) { rrsets.push_back(rrset); } + + status_type getStatus() { return status; } + void setStatus(status_type s) { status = s; } + + /* forward iterator interface */ + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + std::vector::iterator begin() { return rrsets.begin(); } + std::vector::iterator end() { return rrsets.end(); } + std::vector::const_iterator begin() const { return rrsets.begin(); } + std::vector::const_iterator end() const { return rrsets.end(); } + +private: + status_type status; + std::vector rrsets; +}; + +// Base class for a DNS Data Source +class DataSource { +public: + //enum result { success, not_implemented, error, zone_not_found, + // name_not_found }; + + DataSource() {}; + virtual ~DataSource() {}; + + // + // 'high-level' methods, these may or may not be overwritten; + // depending on the data source the default implementation + // may not be most efficient, but should at least provide + // the needed functionality + // + + // fill in separate lists or simple fill in an answer Message object? + void getData(const RRsetPtr query, Message& answer); + + // how to provide highlevel update data? + //result handleUpdate() + + + // + // mandatory 'low-level' methods, an implementation must overwrite these + // + // + // for a 'catch-all' datasource, we need to be able to find + // out if it has a zone for a given name + // + // perhaps this should not set a zone Name, but rather a specific + // ZoneRef option (which could be datasource-specific, as it will + // only be used to pass along to other calls) + // Or even more abstract; + // SomeHandler initFind(name, whatever else); + virtual bool hasZoneFor(const Name& name, Name& zone_name) = 0; + + // for the zone_name, see getZoneFor, perhaps this needs to be a more + // general handle + // And perhaps we need a function that does not have that argument too + virtual SearchResult findRRsets(const Name& zone_name, + const Name& name, + const RRClass& clas, + const RRType& type) = 0; + + // + // optional 'low-level' methods, an implementation may overwrite these, + // by default they return not_implemented + // + virtual void init() {}; + virtual void close() {}; + //virtual result addRR(Name name, int clas, int type, + // int ttl, Rdata::RdataPtr data) + // { return not_implemented; }; + //virtual result delRR(isc::dns::Name name, int clas, int type) = 0; + // on name/class/type again? or use an already constructed object? + //virtual result getRRSigs(RRsetPtr target, const RRsetPtr rrset) + // { return not_implemented; }; + //virtual result getNSECs(RRsetPtr target, const RRsetPtr rrset) + // { return not_implemented; }; + + // check if the zone exists, and if so, return something that could + // be used as a pointer for the rest of these functions? + // do we need this? do we want this? + //virtual int getZone(void* zone, isc::dns::Name name); + +}; + +} +} + +#endif diff --git a/src/bin/parkinglot/data_source_plot.cc b/src/bin/parkinglot/data_source_plot.cc index a9f0255d01..aca9c812aa 100644 --- a/src/bin/parkinglot/data_source_plot.cc +++ b/src/bin/parkinglot/data_source_plot.cc @@ -1,6 +1,8 @@ #include +#include + #include "data_source_plot.h" namespace isc { @@ -10,8 +12,7 @@ namespace dns { // and does not allow update statements using namespace isc::dns; -using namespace isc::dns::Rdata::IN; -using namespace isc::dns::Rdata::Generic; +using namespace isc::dns::rdata; using namespace isc::data; void @@ -21,21 +22,21 @@ DataSourceParkingLot::serve(std::string zone_name) { void DataSourceParkingLot::addARecord(std::string data) { - a_records.push_back(Rdata::RdataPtr(new A(data))); + a_records.push_back(RdataPtr(new in::A(data))); } void DataSourceParkingLot::addAAAARecord(std::string data) { - aaaa_records.push_back(Rdata::RdataPtr(new AAAA(data))); + aaaa_records.push_back(RdataPtr(new in::AAAA(data))); } void DataSourceParkingLot::addNSRecord(std::string data) { - ns_records.push_back(Rdata::RdataPtr(new NS(data))); + ns_records.push_back(RdataPtr(new generic::NS(data))); } void -DataSourceParkingLot::setSOARecord(isc::dns::Rdata::RdataPtr soa_record) { +DataSourceParkingLot::setSOARecord(RdataPtr soa_record) { } void @@ -53,8 +54,9 @@ DataSourceParkingLot::setDefaultZoneData() { DataSourceParkingLot::DataSourceParkingLot() { setDefaultZoneData(); - soa = Rdata::RdataPtr(new SOA("parking.example", "noc.parking.example", - 1, 1800, 900, 604800, TTL(86400))); + soa = RdataPtr(new generic::SOA(Name("parking.example"), + Name("noc.parking.example"), + 1, 1800, 900, 604800, 86400)); } bool @@ -72,28 +74,32 @@ DataSourceParkingLot:: findRRsets(const isc::dns::Name& zone_name, Name authors_name("authors.bind"); Name version_name("version.bind"); - if (clas == RRClass::CH) { - if (type == RRType::TXT) { + if (clas == RRClass::CH()) { + if (type == RRType::TXT()) { if (name == authors_name) { - RRsetPtr rrset = RRsetPtr(new RRset(authors_name, RRClass::CH, RRType::TXT, TTL(3600))); - rrset->addRdata(Rdata::RdataPtr(TXT("JINMEI Tatuya").copy())); - rrset->addRdata(Rdata::RdataPtr(TXT("Han Feng").copy())); - rrset->addRdata(Rdata::RdataPtr(TXT("Kazunori Fujiwara").copy())); - rrset->addRdata(Rdata::RdataPtr(TXT("Michael Graff").copy())); - rrset->addRdata(Rdata::RdataPtr(TXT("Evan Hunt").copy())); - rrset->addRdata(Rdata::RdataPtr(TXT("Jelte Jansen").copy())); - rrset->addRdata(Rdata::RdataPtr(TXT("Jin Jian").copy())); - rrset->addRdata(Rdata::RdataPtr(TXT("JINMEI Tatuya").copy())); - rrset->addRdata(Rdata::RdataPtr(TXT("Naoki Kambe").copy())); - rrset->addRdata(Rdata::RdataPtr(TXT("Shane Kerr").copy())); - rrset->addRdata(Rdata::RdataPtr(TXT("Zhang Likun").copy())); - rrset->addRdata(Rdata::RdataPtr(TXT("Jeremy C. Reed").copy())); + RRsetPtr rrset = RRsetPtr(new RRset(authors_name, RRClass::CH(), + RRType::TXT(), + RRTTL(3600))); + rrset->addRdata(generic::TXT("JINMEI Tatuya")); + rrset->addRdata(generic::TXT("Han Feng")); + rrset->addRdata(generic::TXT("Kazunori Fujiwara")); + rrset->addRdata(generic::TXT("Michael Graff")); + rrset->addRdata(generic::TXT("Evan Hunt")); + rrset->addRdata(generic::TXT("Jelte Jansen")); + rrset->addRdata(generic::TXT("Jin Jian")); + rrset->addRdata(generic::TXT("JINMEI Tatuya")); + rrset->addRdata(generic::TXT("Naoki Kambe")); + rrset->addRdata(generic::TXT("Shane Kerr")); + rrset->addRdata(generic::TXT("Zhang Likun")); + rrset->addRdata(generic::TXT("Jeremy C. Reed")); result.addRRset(rrset); result.setStatus(SearchResult::success); } else if (name == version_name) { - RRsetPtr rrset = RRsetPtr(new RRset(version_name, RRClass::CH, RRType::TXT, TTL(3600))); - rrset->addRdata(Rdata::RdataPtr(TXT("BIND10 0.0.1").copy())); + RRsetPtr rrset = RRsetPtr(new RRset(version_name, RRClass::CH(), + RRType::TXT(), + RRTTL(3600))); + rrset->addRdata(generic::TXT("BIND10 0.0.1")); result.addRRset(rrset); result.setStatus(SearchResult::success); } else { @@ -102,23 +108,23 @@ DataSourceParkingLot:: findRRsets(const isc::dns::Name& zone_name, } else { result.setStatus(SearchResult::name_not_found); } - } else if (clas == RRClass::IN) { + } else if (clas == RRClass::IN()) { if (zones.contains(name)) { - RRsetPtr rrset = RRsetPtr(new RRset(name, clas, type, TTL(3600))); + RRsetPtr rrset = RRsetPtr(new RRset(name, clas, type, RRTTL(3600))); result.setStatus(SearchResult::success); - if (type == RRType::A) { - BOOST_FOREACH(isc::dns::Rdata::RdataPtr a, a_records) { + if (type == RRType::A()) { + BOOST_FOREACH(RdataPtr a, a_records) { rrset->addRdata(a); } - } else if (type == RRType::AAAA) { - BOOST_FOREACH(isc::dns::Rdata::RdataPtr aaaa, aaaa_records) { + } else if (type == RRType::AAAA()) { + BOOST_FOREACH(RdataPtr aaaa, aaaa_records) { rrset->addRdata(aaaa); } - } else if (type == RRType::NS) { - BOOST_FOREACH(isc::dns::Rdata::RdataPtr ns, ns_records) { + } else if (type == RRType::NS()) { + BOOST_FOREACH(RdataPtr ns, ns_records) { rrset->addRdata(ns); } - } else if (type == RRType::SOA) { + } else if (type == RRType::SOA()) { rrset->addRdata(soa); } result.addRRset(rrset); @@ -144,11 +150,11 @@ DataSourceParkingLot:: findRRsets(const isc::dns::Name& zone_name, /// we should probably make this private SearchResult::status_type DataSourceParkingLot::addToMessage(Message& msg, - section_t section, + const Section& section, const Name& zone_name, const Name& name, - const isc::dns::RRClass& clas, - const isc::dns::RRType& type) + const RRClass& clas, + const RRType& type) { SearchResult result = findRRsets(zone_name, name, clas, type); BOOST_FOREACH(RRsetPtr rrset, result) { diff --git a/src/bin/parkinglot/data_source_plot.h b/src/bin/parkinglot/data_source_plot.h index b1b5fcfa80..1be1d0fb92 100644 --- a/src/bin/parkinglot/data_source_plot.h +++ b/src/bin/parkinglot/data_source_plot.h @@ -18,17 +18,19 @@ #ifndef __DATA_SOURCE_SIMPLE_H #define __DATA_SOURCE_SIMPLE_H -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include "common.h" -#include "dns/data_source.h" -#include "dns/rrset.h" +#include "data_source.h" #include "zoneset.h" @@ -60,7 +62,7 @@ public: void addAAAARecord(std::string data); void addNSRecord(std::string data); - void setSOARecord(isc::dns::Rdata::RdataPtr soa_record); + void setSOARecord(isc::dns::rdata::RdataPtr soa_record); /// Do direct 'search' in database, no extra processing, /// and add the resulting rrsets to the specified section @@ -68,18 +70,18 @@ public: /// Once the dns logic is moved from parkinglot to this class, /// we should probably make this private SearchResult::status_type addToMessage(Message& msg, - section_t section, - const Name& zone_name, - const Name& name, - const isc::dns::RRClass& clas, - const isc::dns::RRType& type); + const isc::dns::Section& section, + const isc::dns::Name& zone_name, + const isc::dns::Name& name, + const isc::dns::RRClass& clas, + const isc::dns::RRType& type); private: // void setDefaultZoneData(); - std::vector a_records, aaaa_records, ns_records; - isc::dns::Rdata::RdataPtr soa; + std::vector a_records, aaaa_records, ns_records; + isc::dns::rdata::RdataPtr soa; ZoneSet zones; }; @@ -88,3 +90,7 @@ private: } #endif + +// Local Variables: +// mode: c++ +// End: diff --git a/src/bin/parkinglot/main.cc b/src/bin/parkinglot/main.cc index 81ca29db6a..ac0a2b93d9 100644 --- a/src/bin/parkinglot/main.cc +++ b/src/bin/parkinglot/main.cc @@ -25,10 +25,10 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include diff --git a/src/bin/parkinglot/parkinglot.cc b/src/bin/parkinglot/parkinglot.cc index 265803c3ba..142cc031a4 100644 --- a/src/bin/parkinglot/parkinglot.cc +++ b/src/bin/parkinglot/parkinglot.cc @@ -23,23 +23,27 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include "common.h" #include "parkinglot.h" +#include #include using namespace std; using namespace isc::dns; -using namespace isc::dns::Rdata::IN; -using namespace isc::dns::Rdata::Generic; +using namespace isc::dns::rdata::in; +using namespace isc::dns::rdata::generic; using namespace isc::data; ParkingLot::ParkingLot(int port) { @@ -77,10 +81,13 @@ ParkingLot::processMessage() { struct sockaddr* sa = static_cast((void*)&ss); int s = sock; Message msg; + char recvbuf[4096]; + int cc; - if (msg.getBuffer().recvFrom(s, sa, &sa_len) > 0) { + if ((cc = recvfrom(s, recvbuf, sizeof(recvbuf), 0, sa, &sa_len)) > 0) { + InputBuffer buffer(recvbuf, cc); try { - msg.fromWire(); + msg.fromWire(buffer); } catch (...) { cerr << "parse failed" << endl; return; @@ -88,69 +95,99 @@ ParkingLot::processMessage() { cout << "received a message:\n" << msg.toText() << endl; - if (msg.getSection(SECTION_QUESTION).size() != 1) + QuestionIterator qid = msg.beginQuestion(); + qid++; // XXX: should revise this code + if (qid != msg.endQuestion()) { return; + } + + QuestionPtr query = *msg.beginQuestion(); msg.makeResponse(); - msg.setAA(true); + msg.setHeaderFlag(MessageFlag::AA()); + RRTTL default_ttl = RRTTL(3600); - RRsetPtr query = msg.getSection(SECTION_QUESTION)[0]; - - msg.makeResponse(); - msg.setAA(true); - TTL default_ttl = TTL(3600); - - Name zname; + Name zname("."); // ugly, but should work for now Name name = query->getName(); RRClass qclass = query->getClass(); RRType qtype = query->getType(); SearchResult::status_type status; bool included_ns = false; if (data_source.hasZoneFor(query->getName(), zname)) { - status = data_source.addToMessage(msg, SECTION_ANSWER, zname, name, qclass, qtype); + status = data_source.addToMessage(msg, Section::ANSWER(), zname, + name, qclass, qtype); // rcode is based on this result? if (status == SearchResult::name_not_found) { - msg.setRcode(Message::RCODE_NXDOMAIN); - if (qtype != RRType::NS) { - status = data_source.addToMessage(msg, SECTION_AUTHORITY, zname, zname, qclass, RRType::SOA); + msg.setRcode(Rcode::NXDOMAIN()); + if (qtype != RRType::NS()) { + status = data_source.addToMessage(msg, Section::AUTHORITY(), + zname, zname, qclass, + RRType::SOA()); } } else { - if (qtype != RRType::NS) { - status = data_source.addToMessage(msg, SECTION_AUTHORITY, zname, zname, qclass, RRType::NS); + if (qtype != RRType::NS()) { + status = data_source.addToMessage(msg, Section::AUTHORITY(), + zname, zname, qclass, + RRType::NS()); } included_ns = true; } // If we included NS records, and their target falls below the zone, add glue if (included_ns) { - BOOST_FOREACH(RRsetPtr rrset, msg.getSection(SECTION_ANSWER)) { - if (rrset->getType() == RRType::NS) { - BOOST_FOREACH(Rdata::RdataPtr rdata, rrset->getRdatalist()) { + for (RRsetIterator it = msg.beginSection(Section::ANSWER()); + it != msg.endSection(Section::ANSWER()); + ++it) { + RRsetPtr rrset = (*it); + if (rrset->getType() == RRType::NS()) { + RdataIteratorPtr rrsetit = rrset->getRdataIterator(); + for (rrsetit->first(); + !rrsetit->isLast(); + rrsetit->next()) { + const rdata::Rdata& rdata = rrsetit->getCurrent(); /* no direct way to get the Name from the rdata fields? */ - Name ns_name = Name(rdata->toText()); - data_source.addToMessage(msg, SECTION_ADDITIONAL, zname, ns_name, qclass, RRType::A); - data_source.addToMessage(msg, SECTION_ADDITIONAL, zname, ns_name, qclass, RRType::AAAA); + Name ns_name = Name(rdata.toText()); + data_source.addToMessage(msg, Section::ADDITIONAL(), + zname, ns_name, qclass, + RRType::A()); + data_source.addToMessage(msg, Section::ADDITIONAL(), + zname, ns_name, qclass, + RRType::AAAA()); } } } - BOOST_FOREACH(RRsetPtr rrset, msg.getSection(SECTION_AUTHORITY)) { - if (rrset->getType() == RRType::NS) { - BOOST_FOREACH(Rdata::RdataPtr rdata, rrset->getRdatalist()) { + for (RRsetIterator it = msg.beginSection(Section::ANSWER()); + it != msg.endSection(Section::ANSWER()); + ++it) { + RRsetPtr rrset = (*it); + if (rrset->getType() == RRType::NS()) { + RdataIteratorPtr rrsetit = rrset->getRdataIterator(); + for (rrsetit->first(); + !rrsetit->isLast(); + rrsetit->next()) { + const rdata::Rdata& rdata = rrsetit->getCurrent(); /* no direct way to get the Name from the rdata fields? */ - Name ns_name = Name(rdata->toText()); - data_source.addToMessage(msg, SECTION_ADDITIONAL, zname, ns_name, qclass, RRType::A); - data_source.addToMessage(msg, SECTION_ADDITIONAL, zname, ns_name, qclass, RRType::AAAA); + Name ns_name = Name(rdata.toText()); + data_source.addToMessage(msg, Section::ADDITIONAL(), + zname, ns_name, qclass, + RRType::A()); + data_source.addToMessage(msg, Section::ADDITIONAL(), + zname, ns_name, qclass, + RRType::AAAA()); } } } } } else { - msg.setRcode(Message::RCODE_SERVFAIL); + msg.setRcode(Rcode::SERVFAIL()); } - msg.toWire(); + + OutputBuffer obuffer(4096); + MessageRenderer renderer(obuffer); + msg.toWire(renderer); cout << "sending a response (" << - boost::lexical_cast(msg.getBuffer().getSize()) + boost::lexical_cast(obuffer.getLength()) << " bytes):\n" << msg.toText() << endl; - msg.getBuffer().sendTo(s, *sa, sa_len); + sendto(s, obuffer.getData(), obuffer.getLength(), 0, sa, sa_len); } } diff --git a/src/bin/parkinglot/zoneset.h b/src/bin/parkinglot/zoneset.h index 72bc2316b8..15de450c89 100644 --- a/src/bin/parkinglot/zoneset.h +++ b/src/bin/parkinglot/zoneset.h @@ -18,8 +18,8 @@ #define __ZONESET_H 1 #include -#include -#include +#include +#include class ZoneSet { public: