summaryrefslogtreecommitdiffstats
path: root/net/dns
diff options
context:
space:
mode:
authornoamsml@chromium.org <noamsml@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-26 04:12:30 +0000
committernoamsml@chromium.org <noamsml@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-26 04:12:30 +0000
commit7e09a30e33119b4d44626b555ecb28e56f303bf2 (patch)
tree8c99002cffb4f66a255e6cea3a0163dc86104adf /net/dns
parent5d82f982460d43ec460e06762bf87ae0fb5ffff3 (diff)
downloadchromium_src-7e09a30e33119b4d44626b555ecb28e56f303bf2.zip
chromium_src-7e09a30e33119b4d44626b555ecb28e56f303bf2.tar.gz
chromium_src-7e09a30e33119b4d44626b555ecb28e56f303bf2.tar.bz2
Limited NSEC support to RecordParsed
Add support for parsing the subset of nsec records specified for multicast DNS to RecordParsed, in order to allow support for domain negation in multicast DNS (see section 6.1 "Negative Responses" of http://www.rfc-editor.org/rfc/rfc6762.txt). BUG=233821 TEST=RecordRdataTest.ParseNsecRecord Review URL: https://chromiumcodereview.appspot.com/17143006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208616 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/dns')
-rw-r--r--net/dns/dns_protocol.h2
-rw-r--r--net/dns/record_parsed.cc3
-rw-r--r--net/dns/record_rdata.cc69
-rw-r--r--net/dns/record_rdata.h31
-rw-r--r--net/dns/record_rdata_unittest.cc33
5 files changed, 138 insertions, 0 deletions
diff --git a/net/dns/dns_protocol.h b/net/dns/dns_protocol.h
index 4516b29..a8aad65 100644
--- a/net/dns/dns_protocol.h
+++ b/net/dns/dns_protocol.h
@@ -117,6 +117,8 @@ static const uint16 kTypePTR = 12;
static const uint16 kTypeTXT = 16;
static const uint16 kTypeAAAA = 28;
static const uint16 kTypeSRV = 33;
+static const uint16 kTypeNSEC = 47;
+
// DNS rcode values.
static const uint8 kRcodeMask = 0xf;
diff --git a/net/dns/record_parsed.cc b/net/dns/record_parsed.cc
index 0ef9646..bee6c7a 100644
--- a/net/dns/record_parsed.cc
+++ b/net/dns/record_parsed.cc
@@ -49,6 +49,9 @@ scoped_ptr<const RecordParsed> RecordParsed::CreateFrom(
case TxtRecordRdata::kType:
rdata = TxtRecordRdata::Create(record.rdata, *parser);
break;
+ case NsecRecordRdata::kType:
+ rdata = NsecRecordRdata::Create(record.rdata, *parser);
+ break;
default:
LOG(WARNING) << "Unknown RData type for recieved record: " << record.type;
return scoped_ptr<const RecordParsed>();
diff --git a/net/dns/record_rdata.cc b/net/dns/record_rdata.cc
index 55967f9..4ebc643 100644
--- a/net/dns/record_rdata.cc
+++ b/net/dns/record_rdata.cc
@@ -215,4 +215,73 @@ bool TxtRecordRdata::IsEqual(const RecordRdata* other) const {
return texts_ == txt_other->texts_;
}
+NsecRecordRdata::NsecRecordRdata() {
+}
+
+NsecRecordRdata::~NsecRecordRdata() {
+}
+
+// static
+scoped_ptr<NsecRecordRdata> NsecRecordRdata::Create(
+ const base::StringPiece& data,
+ const DnsRecordParser& parser) {
+ scoped_ptr<NsecRecordRdata> rdata(new NsecRecordRdata);
+
+ // Read the "next domain". This part for the NSEC record format is
+ // ignored for mDNS, since it has no semantic meaning.
+ unsigned next_domain_length = parser.ReadName(data.data(), NULL);
+
+ // If we did not succeed in getting the next domain or the data length
+ // is too short for reading the bitmap header, return.
+ if (next_domain_length == 0 || data.length() < next_domain_length + 2)
+ return scoped_ptr<NsecRecordRdata>();
+
+ struct BitmapHeader {
+ uint8 block_number; // The block number should be zero.
+ uint8 length; // Bitmap length in bytes. Between 1 and 32.
+ };
+
+ const BitmapHeader* header = reinterpret_cast<const BitmapHeader*>(
+ data.data() + next_domain_length);
+
+ // The block number must be zero in mDns-specific NSEC records. The bitmap
+ // length must be between 1 and 32.
+ if (header->block_number != 0 || header->length == 0 || header->length > 32)
+ return scoped_ptr<NsecRecordRdata>();
+
+ base::StringPiece bitmap_data = data.substr(next_domain_length + 2);
+
+ // Since we may only have one block, the data length must be exactly equal to
+ // the domain length plus bitmap size.
+ if (bitmap_data.length() != header->length)
+ return scoped_ptr<NsecRecordRdata>();
+
+ rdata->bitmap_.insert(rdata->bitmap_.begin(),
+ bitmap_data.begin(),
+ bitmap_data.end());
+
+ return rdata.Pass();
+}
+
+uint16 NsecRecordRdata::Type() const {
+ return NsecRecordRdata::kType;
+}
+
+bool NsecRecordRdata::IsEqual(const RecordRdata* other) const {
+ if (other->Type() != Type())
+ return false;
+ const NsecRecordRdata* nsec_other =
+ static_cast<const NsecRecordRdata*>(other);
+ return bitmap_ == nsec_other->bitmap_;
+}
+
+bool NsecRecordRdata::GetBit(unsigned i) const {
+ unsigned byte_num = i/8;
+ if (bitmap_.size() < byte_num + 1)
+ return false;
+
+ unsigned bit_num = 7 - i % 8;
+ return (bitmap_[byte_num] & (1 << bit_num)) != 0;
+}
+
} // namespace net
diff --git a/net/dns/record_rdata.h b/net/dns/record_rdata.h
index 13a2b1e..f83a4865 100644
--- a/net/dns/record_rdata.h
+++ b/net/dns/record_rdata.h
@@ -181,6 +181,37 @@ class NET_EXPORT_PRIVATE TxtRecordRdata : public RecordRdata {
DISALLOW_COPY_AND_ASSIGN(TxtRecordRdata);
};
+// Only the subset of the NSEC record format required by mDNS is supported.
+// Nsec record format is described in http://www.ietf.org/rfc/rfc3845.txt and
+// the limited version required for mDNS described in
+// http://www.rfc-editor.org/rfc/rfc6762.txt Section 6.1.
+class NET_EXPORT_PRIVATE NsecRecordRdata : public RecordRdata {
+ public:
+ static const uint16 kType = dns_protocol::kTypeNSEC;
+
+ virtual ~NsecRecordRdata();
+ static scoped_ptr<NsecRecordRdata> Create(const base::StringPiece& data,
+ const DnsRecordParser& parser);
+ virtual bool IsEqual(const RecordRdata* other) const OVERRIDE;
+ virtual uint16 Type() const OVERRIDE;
+
+ // Length of the bitmap in bits.
+ unsigned bitmap_length() const { return bitmap_.size() * 8; }
+
+ // Returns bit i-th bit in the bitmap, where bits withing a byte are organized
+ // most to least significant. If it is set, a record with rrtype i exists for
+ // the domain name of this nsec record.
+ bool GetBit(unsigned i) const;
+
+ private:
+ NsecRecordRdata();
+
+ std::vector<uint8> bitmap_;
+
+ DISALLOW_COPY_AND_ASSIGN(NsecRecordRdata);
+};
+
+
} // namespace net
#endif // NET_DNS_RECORD_RDATA_H_
diff --git a/net/dns/record_rdata_unittest.cc b/net/dns/record_rdata_unittest.cc
index 1c731d5..7dc73bb 100644
--- a/net/dns/record_rdata_unittest.cc
+++ b/net/dns/record_rdata_unittest.cc
@@ -180,4 +180,37 @@ TEST(RecordRdataTest, ParseTxtRecord) {
ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
}
+TEST(RecordRdataTest, ParseNsecRecord) {
+ scoped_ptr<NsecRecordRdata> record_obj;
+
+ // These are just the rdata portions of the DNS records, rather than complete
+ // records, but it works well enough for this test.
+
+ const char record[] = {
+ 0x03, 'w', 'w', 'w',
+ 0x06, 'g', 'o', 'o', 'g', 'l', 'e',
+ 0x03, 'c', 'o', 'm',
+ 0x00,
+ 0x00, 0x02, 0x40, 0x01
+ };
+
+ DnsRecordParser parser(record, sizeof(record), 0);
+ base::StringPiece record_strpiece(record, sizeof(record));
+
+ record_obj = NsecRecordRdata::Create(record_strpiece, parser);
+ ASSERT_TRUE(record_obj != NULL);
+
+ ASSERT_EQ(16u, record_obj->bitmap_length());
+
+ EXPECT_FALSE(record_obj->GetBit(0));
+ EXPECT_TRUE(record_obj->GetBit(1));
+ for (int i = 2; i < 15; i++) {
+ EXPECT_FALSE(record_obj->GetBit(i));
+ }
+ EXPECT_TRUE(record_obj->GetBit(15));
+
+ ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
+}
+
+
} // namespace net