Commit f389d000 authored by Jelte Jansen's avatar Jelte Jansen

merged back branches/jelte_datasource1 branch


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/parkinglot@515 e5f2f494-b856-4b98-b285-d166d9295462
parents 86b6d221 845df07f
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/ext
bin_PROGRAMS = parkinglot
parkinglot_SOURCES = common.cc common.h zoneset.h parkinglot.cc parkinglot.h ccsession.cc ccsession.h main.cc
parkinglot_SOURCES = common.cc common.h zoneset.h zoneset.cc parkinglot.cc
parkinglot_SOURCES += parkinglot.h ccsession.cc ccsession.h main.cc
parkinglot_SOURCES += data_source_plot.h data_source_plot.cc
parkinglot_LDADD = $(top_srcdir)/src/lib/dns/libdns.a $(top_srcdir)/src/lib/cc/cpp/libcc.a
#include <boost/foreach.hpp>
#include "data_source_plot.h"
namespace isc {
namespace dns {
// this implementation returns fixed records,
// 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::data;
void
DataSourceParkingLot::serve(std::string zone_name) {
zones.serve(zone_name);
}
void
DataSourceParkingLot::addARecord(std::string data) {
a_records.push_back(Rdata::RdataPtr(new A(data)));
}
void
DataSourceParkingLot::addAAAARecord(std::string data) {
aaaa_records.push_back(Rdata::RdataPtr(new AAAA(data)));
}
void
DataSourceParkingLot::addNSRecord(std::string data) {
ns_records.push_back(Rdata::RdataPtr(new NS(data)));
}
void
DataSourceParkingLot::setSOARecord(isc::dns::Rdata::RdataPtr soa_record) {
}
void
DataSourceParkingLot::setDefaultZoneData() {
clearARecords();
clearAAAARecords();
clearNSRecords();
addARecord("127.0.0.1");
addAAAARecord("::1");
addNSRecord("ns1.parking.example");
addNSRecord("ns2.parking.example");
addNSRecord("ns3.parking.example");
}
DataSourceParkingLot::DataSourceParkingLot() {
setDefaultZoneData();
soa = Rdata::RdataPtr(new SOA("parking.example", "noc.parking.example",
1, 1800, 900, 604800, TTL(86400)));
}
bool
DataSourceParkingLot::hasZoneFor(const Name& name, Name &zone_name)
{
return zones.findClosest(name, zone_name);
}
SearchResult
DataSourceParkingLot:: findRRsets(const isc::dns::Name& zone_name,
const isc::dns::Name& name,
const isc::dns::RRClass& clas,
const isc::dns::RRType& type) {
SearchResult result;
Name authors_name("authors.bind");
Name version_name("version.bind");
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()));
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()));
result.addRRset(rrset);
result.setStatus(SearchResult::success);
} else {
result.setStatus(SearchResult::name_not_found);
}
} else {
result.setStatus(SearchResult::name_not_found);
}
} else if (clas == RRClass::IN) {
if (zones.contains(name)) {
RRsetPtr rrset = RRsetPtr(new RRset(name, clas, type, TTL(3600)));
result.setStatus(SearchResult::success);
if (type == RRType::A) {
BOOST_FOREACH(isc::dns::Rdata::RdataPtr a, a_records) {
rrset->addRdata(a);
}
} else if (type == RRType::AAAA) {
BOOST_FOREACH(isc::dns::Rdata::RdataPtr aaaa, aaaa_records) {
rrset->addRdata(aaaa);
}
} else if (type == RRType::NS) {
BOOST_FOREACH(isc::dns::Rdata::RdataPtr ns, ns_records) {
rrset->addRdata(ns);
}
} else if (type == RRType::SOA) {
rrset->addRdata(soa);
}
result.addRRset(rrset);
} else {
// we don't have the name itself. Do we have the zone?
if (zones.contains(zone_name)) {
result.setStatus(SearchResult::name_not_found);
} else {
result.setStatus(SearchResult::zone_not_found);
}
}
} else {
result.setStatus(SearchResult::zone_not_found);
}
return result;
}
/// Do direct 'search' in database, no extra processing,
/// and add the resulting rrsets to the specified section
/// in the given message
/// returns the status code of the searchresult
/// Once the dns logic is moved from parkinglot to this class,
/// we should probably make this private
SearchResult::status_type
DataSourceParkingLot::addToMessage(Message& msg,
section_t section,
const Name& zone_name,
const Name& name,
const isc::dns::RRClass& clas,
const isc::dns::RRType& type)
{
SearchResult result = findRRsets(zone_name, name, clas, type);
BOOST_FOREACH(RRsetPtr rrset, result) {
msg.addRRset(section, rrset);
}
return result.getStatus();
}
}
}
// 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_SIMPLE_H
#define __DATA_SOURCE_SIMPLE_H
#include <dns/buffer.h>
#include <dns/name.h>
#include <dns/rrset.h>
#include <dns/message.h>
#include <cc/cpp/data.h>
#include "common.h"
#include "dns/data_source.h"
#include "dns/rrset.h"
#include "zoneset.h"
namespace isc {
namespace dns {
class DataSourceParkingLot : public DataSource {
public:
DataSourceParkingLot();
void init() {};
void close() {};
bool hasZoneFor(const Name& name, Name &zone_name);
SearchResult findRRsets(const isc::dns::Name& zone_name,
const isc::dns::Name& name,
const isc::dns::RRClass& clas,
const isc::dns::RRType& type);
/* move these to private (or to zoneset) and the calling functions
* from parkinglot to here? */
void serve(std::string zone_name);
void clear_zones() { zones.clear_zones(); };
void clearARecords() { a_records.clear(); };
void clearAAAARecords() { aaaa_records.clear(); };
void clearNSRecords() { ns_records.clear(); };
void addARecord(std::string data);
void addAAAARecord(std::string data);
void addNSRecord(std::string data);
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
/// in the given message
/// 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);
private:
//
void setDefaultZoneData();
std::vector<isc::dns::Rdata::RdataPtr> a_records, aaaa_records, ns_records;
isc::dns::Rdata::RdataPtr soa;
ZoneSet zones;
};
}
}
#endif
......@@ -61,36 +61,7 @@ usage() {
isc::data::ElementPtr
my_config_handler(isc::data::ElementPtr config)
{
cout << "[XX] Handle config: " << endl << config->str() << endl;
if (config->contains("zones")) {
plot.clear_zones();
BOOST_FOREACH(isc::data::ElementPtr zone_el, config->get("zones")->listValue()) {
plot.serve(zone_el->stringValue());
}
}
if (config->contains("port")) {
// todo: what to do with port change. restart automatically?
// ignore atm
}
if (config->contains("a_records")) {
plot.clearARecords();
BOOST_FOREACH(isc::data::ElementPtr rel, config->get("a_records")->listValue()) {
plot.addARecord(rel->stringValue());
}
}
if (config->contains("aaaa_records")) {
plot.clearAAAARecords();
BOOST_FOREACH(isc::data::ElementPtr rel, config->get("aaaa_records")->listValue()) {
plot.addAAAARecord(rel->stringValue());
}
}
if (config->contains("ns_records")) {
plot.clearNSRecords();
BOOST_FOREACH(isc::data::ElementPtr rel, config->get("ns_records")->listValue()) {
plot.addNSRecord(rel->stringValue());
}
}
return isc::data::Element::createFromString("{ \"result\": [0] }");
return plot.updateConfig(config);
}
isc::data::ElementPtr
......
......@@ -42,48 +42,13 @@ using namespace isc::dns::Rdata::IN;
using namespace isc::dns::Rdata::Generic;
using namespace isc::data;
void
ParkingLot::addARecord(std::string data) {
a_records.push_back(Rdata::RdataPtr(new A(data)));
}
void
ParkingLot::addAAAARecord(std::string data) {
aaaa_records.push_back(Rdata::RdataPtr(new AAAA(data)));
}
void
ParkingLot::addNSRecord(std::string data) {
ns_records.push_back(Rdata::RdataPtr(new NS(data)));
}
void
ParkingLot::setSOARecord(isc::dns::Rdata::RdataPtr soa_record) {
}
void
ParkingLot::setDefaultZoneData() {
clearARecords();
clearAAAARecords();
clearNSRecords();
addARecord("127.0.0.1");
addAAAARecord("::1");
addNSRecord("ns1.parking.example");
addNSRecord("ns2.parking.example");
addNSRecord("ns3.parking.example");
}
ParkingLot::ParkingLot(int port) {
setDefaultZoneData();
/*ns1 = Rdata::RdataPtr(new NS("ns1.parking.example"));
ns2 = Rdata::RdataPtr(new NS("ns2.parking.example"));
ns3 = Rdata::RdataPtr(new NS("ns3.parking.example"));
a = Rdata::RdataPtr(new A("127.0.0.1"));
aaaa = Rdata::RdataPtr(new AAAA("::1"));
*/
soa = Rdata::RdataPtr(new SOA("parking.example", "noc.parking.example",
1, 1800, 900, 604800, TTL(86400)));
int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s < 0)
......@@ -107,8 +72,6 @@ ParkingLot::ParkingLot(int port) {
void
ParkingLot::processMessage() {
Name authors_name("authors.bind");
Name version_name("version.bind");
struct sockaddr_storage ss;
socklen_t sa_len = sizeof(ss);
struct sockaddr* sa = static_cast<struct sockaddr*>((void*)&ss);
......@@ -133,90 +96,56 @@ ParkingLot::processMessage() {
RRsetPtr query = msg.getSection(SECTION_QUESTION)[0];
string name = query->getName().toText(true);
if (query->getClass() == RRClass::CH &&
query->getType() == RRType::TXT &&
query->getName() == authors_name) {
msg.setRcode(Message::RCODE_NOERROR);
msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("Han Feng")));
msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("Kazunori Fujiwara")));
msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("Michael Graff")));
msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("Evan Hunt")));
msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("Jelte Jansen")));
msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("Jin Jian")));
msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("JINMEI Tatuya")));
msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("Naoki Kambe")));
msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("Shane Kerr")));
msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("Zhang Likun")));
msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("Jeremy C. Reed")));
msg.addRR(SECTION_AUTHORITY, RR(authors_name, RRClass::CH,
RRType::NS, TTL(0),
NS("authors.bind")));
} else if (query->getClass() == RRClass::CH &&
query->getType() == RRType::TXT &&
query->getName() == version_name) {
msg.setRcode(Message::RCODE_NOERROR);
msg.addRR(SECTION_ANSWER, RR(version_name, RRClass::CH,
RRType::TXT, TTL(0),
TXT("10.0.0s20091030")));
msg.addRR(SECTION_AUTHORITY, RR(version_name, RRClass::CH,
RRType::NS, TTL(0),
NS("version.bind")));
} else if (zones.contains(name)) {
msg.setRcode(Message::RCODE_NOERROR);
RRset* nsset = new RRset(query->getName(), RRClass::IN,
RRType::NS, TTL(3600));
BOOST_FOREACH(isc::dns::Rdata::RdataPtr ns, ns_records) {
nsset->addRdata(ns);
msg.makeResponse();
msg.setAA(true);
TTL default_ttl = TTL(3600);
Name zname;
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);
// 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);
}
} else {
if (qtype != RRType::NS) {
status = data_source.addToMessage(msg, SECTION_AUTHORITY, zname, zname, qclass, RRType::NS);
}
included_ns = true;
}
if (query->getType() == RRType::NS)
msg.addRRset(SECTION_ANSWER, RRsetPtr(nsset));
else if (query->getType() == RRType::A) {
msg.addRRset(SECTION_AUTHORITY, RRsetPtr(nsset));
BOOST_FOREACH(isc::dns::Rdata::RdataPtr a, a_records) {
RR arr(query->getName(), RRClass::IN, RRType::A, TTL(3600), a);
msg.addRR(SECTION_ANSWER, arr);
// 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()) {
/* 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);
}
}
}
} else if (query->getType() == RRType::AAAA) {
msg.addRRset(SECTION_AUTHORITY, RRsetPtr(nsset));
BOOST_FOREACH(isc::dns::Rdata::RdataPtr aaaa, aaaa_records) {
RR aaaarr(query->getName(), RRClass::IN, RRType::AAAA,
TTL(3600), aaaa);
msg.addRR(SECTION_ANSWER, aaaarr);
BOOST_FOREACH(RRsetPtr rrset, msg.getSection(SECTION_AUTHORITY)) {
if (rrset->getType() == RRType::NS) {
BOOST_FOREACH(Rdata::RdataPtr rdata, rrset->getRdatalist()) {
/* 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);
}
}
}
} else {
RR soarr(query->getName(), RRClass::IN, RRType::SOA,
TTL(3600), soa);
msg.addRR(SECTION_AUTHORITY, soarr);
}
} else {
msg.setRcode(Message::RCODE_NXDOMAIN);
msg.setRcode(Message::RCODE_SERVFAIL);
}
msg.toWire();
cout << "sending a response (" <<
boost::lexical_cast<string>(msg.getBuffer().getSize())
......@@ -225,23 +154,37 @@ ParkingLot::processMessage() {
}
}
void
ParkingLot::command(pair<string,ElementPtr> cmd) {
if (cmd.first == "shutdown")
exit(0);
else if (cmd.first == "config_update") {
// what to do with port settings?
ElementPtr zonelist_el = (cmd.second)->get("zones");
// We could walk through both lists and remove and serve
// accordingly, or simply clear all and add everything
zones.clear_zones();
BOOST_FOREACH(ElementPtr zone, zonelist_el->listValue()) {
zones.serve(zone->stringValue());
ElementPtr
ParkingLot::updateConfig(isc::data::ElementPtr config) {
if (config->contains("zones")) {
data_source.clear_zones();
BOOST_FOREACH(isc::data::ElementPtr zone_el, config->get("zones")->listValue()) {
data_source.serve(zone_el->stringValue());
}
}
if (config->contains("port")) {
// todo: what to do with port change. restart automatically?
// ignore atm
}
if (config->contains("a_records")) {
data_source.clearARecords();
BOOST_FOREACH(isc::data::ElementPtr rel, config->get("a_records")->listValue()) {
data_source.addARecord(rel->stringValue());
}
}
if (config->contains("aaaa_records")) {
data_source.clearAAAARecords();
BOOST_FOREACH(isc::data::ElementPtr rel, config->get("aaaa_records")->listValue()) {
data_source.addAAAARecord(rel->stringValue());
}
}
if (config->contains("ns_records")) {
data_source.clearNSRecords();
BOOST_FOREACH(isc::data::ElementPtr rel, config->get("ns_records")->listValue()) {
data_source.addNSRecord(rel->stringValue());
}
}
return isc::data::Element::createFromString("{ \"result\": [0] }");
}
void
ParkingLot::serve(std::string zone_name) {
zones.serve(zone_name);
}
......@@ -19,6 +19,7 @@
#include "zoneset.h"
#include <cc/cpp/data.h>
#include "data_source_plot.h"
class ParkingLot {
public:
......@@ -28,24 +29,11 @@ public:
void processMessage();
void command(std::pair<std::string,isc::data::ElementPtr>);
void serve(std::string zone_name);
void clear_zones() { zones.clear_zones(); };
void clearARecords() { a_records.clear(); };
void clearAAAARecords() { aaaa_records.clear(); };
void clearNSRecords() { ns_records.clear(); };
void addARecord(std::string data);
void addAAAARecord(std::string data);
void addNSRecord(std::string data);
void setSOARecord(isc::dns::Rdata::RdataPtr soa_record);
isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
private:
void setDefaultZoneData();
std::vector<isc::dns::Rdata::RdataPtr> a_records, aaaa_records, ns_records;
isc::dns::Rdata::RdataPtr soa;
ZoneSet zones;
isc::dns::DataSourceParkingLot data_source;
int sock;
};
......
#include "zoneset.h"
// see findClosest()
static bool
stripLabel(isc::dns::Name& n) {
std::string str = n.toText(false);
size_t pos = str.find('.');
if (pos + 1 < str.size()) {
n = isc::dns::Name(str.substr(pos+1));
return true;
} else {
return false;