static_datasrc.cc 8.79 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Copyright (C) 2010  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$
16

17
#include <config.h>
18

19 20
#include <cassert>

21 22 23 24
#include <dns/name.h>
#include <dns/rdataclass.h>
#include <dns/rrclass.h>
#include <dns/rrset.h>
25
#include <dns/rrsetlist.h>
26 27
#include <dns/rrtype.h>
#include <dns/rrttl.h>
28

29 30
#include <datasrc/data_source.h>
#include <datasrc/static_datasrc.h>
31

32 33
using namespace std;
using namespace isc::dns;
34 35
using namespace isc::dns::rdata;

36
namespace isc {
Evan Hunt's avatar
Evan Hunt committed
37
namespace datasrc {
38

39 40 41 42 43 44 45 46 47 48 49 50 51 52
// This class stores the "static" data for the built-in static data source.
// Since it's static, it could be literally static, i.e, defined as static
// objects.  But to avoid the static initialization order fiasco, which would
// be unlikely to happen for this class in practice but is still possible,
// we took a safer approach.  A downside of this approach is that redundant
// copies of exactly the same content of these objects can be created.
// In practice, however, there's normally at most one StaticDataSrc object,
// so this should be acceptable (if this turns out to be a real concern we
// might consider making this class a singleton).
// We use the "pimpl" idiom for this class.  Operations for this class is
// not expected to be performance sensitive, so the overhead due to the pimpl
// should be okay, and it's more beneficial to hide details and minimize
// inter module dependencies in header files.
struct StaticDataSrcImpl {
53
public:
54 55 56 57 58 59 60 61
    StaticDataSrcImpl();
    const Name authors_name;
    const Name version_name;
    // XXX: unfortunately these can't be ConstRRsetPtr because they'll be
    // passed to RRsetList::addRRset(), which expect non const RRsetPtr.
    // We should revisit this design later.
    RRsetPtr authors;
    RRsetPtr authors_ns;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
62
    RRsetPtr authors_soa;
63 64
    RRsetPtr version;
    RRsetPtr version_ns;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
65
    RRsetPtr version_soa;
66
};
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88

StaticDataSrcImpl::StaticDataSrcImpl() :
    authors_name("authors.bind"), version_name("version.bind")
{
    authors = RRsetPtr(new RRset(authors_name, RRClass::CH(),
                                 RRType::TXT(), RRTTL(0)));
    authors->addRdata(generic::TXT("Evan Hunt"));
    authors->addRdata(generic::TXT("Han Feng"));
    authors->addRdata(generic::TXT("Jelte Jansen"));
    authors->addRdata(generic::TXT("Jeremy C. Reed")); 
    authors->addRdata(generic::TXT("Jin Jian"));
    authors->addRdata(generic::TXT("JINMEI Tatuya"));
    authors->addRdata(generic::TXT("Kazunori Fujiwara"));
    authors->addRdata(generic::TXT("Michael Graff"));
    authors->addRdata(generic::TXT("Naoki Kambe"));
    authors->addRdata(generic::TXT("Shane Kerr"));
    authors->addRdata(generic::TXT("Zhang Likun"));

    authors_ns = RRsetPtr(new RRset(authors_name, RRClass::CH(),
                                    RRType::NS(), RRTTL(0)));
    authors_ns->addRdata(generic::NS(authors_name));

JINMEI Tatuya's avatar
JINMEI Tatuya committed
89
    authors_soa = RRsetPtr(new RRset(authors_name, RRClass::CH(),
90
                                     RRType::SOA(), RRTTL(0)));
JINMEI Tatuya's avatar
JINMEI Tatuya committed
91 92 93 94
    authors_soa->addRdata(generic::SOA(
                              "authors.bind. hostmaster.authors.bind. "
                              "0 28800 7200 604800 86400"));

95 96
    version = RRsetPtr(new RRset(version_name, RRClass::CH(),
                                 RRType::TXT(), RRTTL(0)));
97
    version->addRdata(generic::TXT(PACKAGE_STRING));
98 99 100 101

    version_ns = RRsetPtr(new RRset(version_name, RRClass::CH(),
                                    RRType::NS(), RRTTL(0)));
    version_ns->addRdata(generic::NS(version_name));
JINMEI Tatuya's avatar
JINMEI Tatuya committed
102 103

    version_soa = RRsetPtr(new RRset(version_name, RRClass::CH(),
104
                                     RRType::SOA(), RRTTL(0)));
JINMEI Tatuya's avatar
JINMEI Tatuya committed
105 106 107
    version_soa->addRdata(generic::SOA(
                              "version.bind. hostmaster.version.bind. "
                               "0 28800 7200 604800 86400"));
108 109 110
}

StaticDataSrc::StaticDataSrc()
111
{
112
    setClass(RRClass::CH());
113 114 115 116 117 118
    impl_ = new StaticDataSrcImpl;
}

StaticDataSrc::~StaticDataSrc()
{
    delete impl_;
119 120
}

121 122 123 124 125 126 127 128 129 130
namespace {
bool
isSubdomain(const Name& qname, const Name& zone) {
    const NameComparisonResult::NameRelation cmp =
        qname.compare(zone).getRelation();
    return (cmp == NameComparisonResult::EQUAL ||
            cmp == NameComparisonResult::SUBDOMAIN);
}
}

131
void
Evan Hunt's avatar
Evan Hunt committed
132 133
StaticDataSrc::findClosestEnclosure(DataSrcMatch& match) const {
    const Name& qname = match.getName();
134

Evan Hunt's avatar
Evan Hunt committed
135
    if (match.getClass() != getClass() && match.getClass() != RRClass::ANY()) {
136 137 138
        return;
    }

139
    if (isSubdomain(qname, impl_->version_name)) {
140
        match.update(*this, impl_->version_name);
141
        return;
142 143
    }

144
    if (isSubdomain(qname, impl_->authors_name)) {
145
        match.update(*this, impl_->authors_name);
146 147
        return;
    }
148 149
}

150
DataSrc::Result
151
StaticDataSrc::findRRset(const Name& qname,
152
                         const RRClass& qclass, const RRType& qtype,
153
                         RRsetList& target, uint32_t& flags,
154
                         const Name* const zonename) const
155
{
156
    flags = 0;
157
    if (qclass != getClass() && qclass != RRClass::ANY()) {
158
        return (ERROR);
159 160
    }

161 162 163 164 165 166 167 168 169
    // Identify the appropriate zone.
    bool is_versionname = false, is_authorsname = false;
    if (zonename != NULL) {
        if (*zonename == impl_->version_name &&
            isSubdomain(qname, impl_->version_name)) {
            is_versionname = true;
        } else if (*zonename == impl_->authors_name &&
                   isSubdomain(qname, impl_->authors_name)) {
            is_authorsname = true;
170
        } else {
171
            flags = NO_SUCH_ZONE;
172
            return (SUCCESS);
173 174 175 176 177 178 179 180
        }
    } else {
        if (isSubdomain(qname, impl_->version_name)) {
            is_versionname = true;
        } else if (isSubdomain(qname, impl_->authors_name)) {
            is_authorsname = true;
        } else {
            flags = NO_SUCH_ZONE;
181
            return (SUCCESS);
182 183 184 185 186 187 188 189 190
        }
    }

    const bool any = (qtype == RRType::ANY());

    if (is_versionname) {
        if (qname == impl_->version_name) {
            if (qtype == RRType::TXT() || any) {
                target.addRRset(impl_->version);
191 192
            }
            if (qtype == RRType::NS() || any) {
193
                target.addRRset(impl_->version_ns);
194 195
            }
            if (qtype == RRType::SOA() || any) {
JINMEI Tatuya's avatar
JINMEI Tatuya committed
196
                target.addRRset(impl_->version_soa);
197 198
            }
            if (target.size() == 0) {
199 200
                flags = TYPE_NOT_FOUND;
            }
201
        } else {
202
            flags = NAME_NOT_FOUND;
203 204
        }
    } else {
205 206 207 208
        assert(is_authorsname);
        if (qname == impl_->authors_name) {
            if (qtype == RRType::TXT() || any) {
                target.addRRset(impl_->authors);
209 210
            }
            if (qtype == RRType::NS() || any) {
211
                target.addRRset(impl_->authors_ns);
212 213
            }
            if (qtype == RRType::SOA() || any) {
JINMEI Tatuya's avatar
JINMEI Tatuya committed
214
                target.addRRset(impl_->authors_soa);
215 216
            }
            if (target.size() == 0 ) {
217 218 219 220 221
                flags = TYPE_NOT_FOUND;
            }
        } else {
            flags = NAME_NOT_FOUND;
        }
222 223 224
    }

    return (SUCCESS);
225 226
}

227
DataSrc::Result
228
StaticDataSrc::findExactRRset(const Name& qname,
229 230
                              const RRClass& qclass, const RRType& qtype,
                              RRsetList& target, uint32_t& flags,
231
                              const Name* zonename) const
232
{
233
    return (findRRset(qname, qclass, qtype, target, flags, zonename));
234 235 236
}

DataSrc::Result
237 238 239
StaticDataSrc::findPreviousName(const Name& qname UNUSED_PARAM,
                                Name& target UNUSED_PARAM,
                                const Name* zonename UNUSED_PARAM) const
240 241 242 243
{
    return (NOT_IMPLEMENTED);
}

Evan Hunt's avatar
Evan Hunt committed
244
DataSrc::Result
245 246 247
StaticDataSrc::findCoveringNSEC3(const Name& zonename UNUSED_PARAM,
                                 string& hash UNUSED_PARAM,
                                 RRsetList& target UNUSED_PARAM) const
Evan Hunt's avatar
Evan Hunt committed
248 249 250 251
{
   return (NOT_IMPLEMENTED);
}

252
DataSrc::Result
253
StaticDataSrc::init() {
254 255 256
    return (SUCCESS);
}

257 258
// Static data source is "configuration less", so the \c config parameter
// is intentionally ignored.
259
DataSrc::Result
260 261 262 263 264 265
StaticDataSrc::init(const isc::data::ElementPtr config UNUSED_PARAM) {
    return init();
}

DataSrc::Result
StaticDataSrc::close() {
266 267 268
    return (SUCCESS);
}

269 270
}
}