Branch data Line data Source code
1 : : // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
2 : : //
3 : : // Permission to use, copy, modify, and/or distribute this software for any
4 : : // purpose with or without fee is hereby granted, provided that the above
5 : : // copyright notice and this permission notice appear in all copies.
6 : : //
7 : : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
8 : : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9 : : // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
10 : : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 : : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
12 : : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 : : // PERFORMANCE OF THIS SOFTWARE.
14 : :
15 : : #include <exceptions/exceptions.h>
16 : :
17 : : #include <dns/exceptions.h>
18 : : #include <dns/rdata.h>
19 : : #include <dns/rrtype.h>
20 : :
21 : : #include <cassert>
22 : : #include <sstream>
23 : : #include <vector>
24 : : #include <cstring>
25 : : #include <stdint.h>
26 : :
27 : : using namespace std;
28 : :
29 : : namespace isc {
30 : : namespace dns {
31 : : namespace rdata {
32 : : namespace generic {
33 : : namespace detail {
34 : : namespace nsec {
35 : : void
36 : 23 : checkRRTypeBitmaps(const char* const rrtype_name,
37 : : const vector<uint8_t>& typebits)
38 : : {
39 : 23 : bool first = true;
40 : 23 : unsigned int lastblock = 0;
41 : 23 : const size_t total_len = typebits.size();
42 : 23 : size_t i = 0;
43 : :
44 [ + + ]: 34 : while (i < total_len) {
45 [ + + ]: 25 : if (i + 2 > total_len) {
46 [ + - ][ + - ]: 4 : isc_throw(DNSMessageFORMERR, rrtype_name <<
[ + - ]
47 : : " RDATA from wire: incomplete bit map field");
48 : : }
49 : 23 : const unsigned int block = typebits[i];
50 : 46 : const size_t len = typebits[i + 1];
51 : : // Check that bitmap window blocks are in the correct order.
52 [ + + ][ + - ]: 23 : if (!first && block <= lastblock) {
53 [ + - ][ + - ]: 8 : isc_throw(DNSMessageFORMERR, rrtype_name <<
[ + - ][ + - ]
54 : : " RDATA from wire: Disordered window blocks found: "
55 : : << lastblock << " then " << block);
56 : : }
57 : : // Check for legal length
58 [ + + ]: 21 : if (len < 1 || len > 32) {
59 [ + - ][ + - ]: 18 : isc_throw(DNSMessageFORMERR, rrtype_name <<
[ + - ]
60 : : " RDATA from wire: Invalid bitmap length: " << len);
61 : : }
62 : : // Check for overflow.
63 : 15 : i += 2;
64 [ + + ]: 15 : if (i + len > total_len) {
65 [ + - ][ + - ]: 6 : isc_throw(DNSMessageFORMERR, rrtype_name <<
[ + - ]
66 : : " RDATA from wire: bitmap length too large: " << len);
67 : : }
68 : : // The last octet of the bitmap must be non zero.
69 [ + + ]: 13 : if (typebits[i + len - 1] == 0) {
70 [ + - ][ + - ]: 4 : isc_throw(DNSMessageFORMERR, rrtype_name <<
[ + - ]
71 : : " RDATA from wire: bitmap ending an all-zero byte");
72 : : }
73 : :
74 : 11 : i += len;
75 : 11 : lastblock = block;
76 : 11 : first = false;
77 : : }
78 : 9 : }
79 : :
80 : : void
81 : 2762 : buildBitmapsFromText(const char* const rrtype_name,
82 : : istringstream& iss, vector<uint8_t>& typebits)
83 : : {
84 : : uint8_t bitmap[8 * 1024]; // 64k bits
85 : : memset(bitmap, 0, sizeof(bitmap));
86 : :
87 [ + + ]: 8043 : do {
88 : 8048 : string type;
89 [ + - ]: 8048 : iss >> type;
90 [ + - ][ + + ]: 8048 : if (iss.bad() || iss.fail()) {
[ + + ]
91 [ + - ][ + - ]: 4 : isc_throw(InvalidRdataText, "Unexpected input for "
[ + - ][ + - ]
92 : : << rrtype_name << " bitmap");
93 : : }
94 : : try {
95 [ + + ]: 8046 : const int code = RRType(type).getCode();
96 : 8043 : bitmap[code / 8] |= (0x80 >> (code % 8));
97 [ - + ]: 6 : } catch (const InvalidRRType&) {
98 [ - + ][ - + ]: 6 : isc_throw(InvalidRdataText, "Invalid RRtype in "
[ - + ][ - + ]
[ - + ]
99 : : << rrtype_name << " bitmap: " << type);
100 : : }
101 : 8043 : } while (!iss.eof());
102 : :
103 [ + + ]: 708549 : for (int window = 0; window < 256; ++window) {
104 : : int octet;
105 [ + + ]: 23274287 : for (octet = 31; octet >= 0; octet--) {
106 [ + + ]: 22571256 : if (bitmap[window * 32 + octet] != 0) {
107 : : break;
108 : : }
109 : : }
110 [ + + ]: 705792 : if (octet < 0) {
111 : 703031 : continue;
112 : : }
113 : 2761 : typebits.push_back(window);
114 : 2761 : typebits.push_back(octet + 1);
115 [ + + ]: 19610 : for (int i = 0; i <= octet; ++i) {
116 : 16849 : typebits.push_back(bitmap[window * 32 + i]);
117 : : }
118 : : }
119 : 2757 : }
120 : :
121 : : void
122 : 608 : bitmapsToText(const vector<uint8_t>& typebits, ostringstream& oss) {
123 : : // In the following loop we use string::at() rather than operator[].
124 : : // Since the index calculation is a bit complicated, it will be safer
125 : : // and easier to find a bug (if any). Note that this conversion method
126 : : // is generally not expected to be very efficient, so the slight overhead
127 : : // of at() should be acceptable.
128 : 608 : const size_t typebits_len = typebits.size();
129 : 608 : size_t len = 0;
130 [ + + ]: 1214 : for (size_t i = 0; i < typebits_len; i += len) {
131 [ - + ]: 606 : assert(i + 2 <= typebits.size());
132 : 606 : const unsigned int block = typebits.at(i);
133 : 606 : len = typebits.at(i + 1);
134 [ - + ]: 606 : assert(len > 0 && len <= 32);
135 : 606 : i += 2;
136 [ + + ]: 4785 : for (size_t j = 0; j < len; ++j) {
137 [ + + ]: 4179 : if (typebits.at(i + j) == 0) {
138 : 2984 : continue;
139 : : }
140 [ + + ]: 10755 : for (size_t k = 0; k < 8; ++k) {
141 [ + + ]: 9560 : if ((typebits.at(i + j) & (0x80 >> k)) == 0) {
142 : 8031 : continue;
143 : : }
144 : 1529 : const unsigned int t = block * 256 + j * 8 + k;
145 [ - + ]: 1529 : assert(t < 65536);
146 : 1529 : oss << " " << RRType(t);
147 : : }
148 : : }
149 : : }
150 : 608 : }
151 : : }
152 : : }
153 : : }
154 : : }
155 : : }
156 : 66614 : }
|