Branch data Line data Source code
1 : : // Copyright (C) 2010 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 <config.h>
16 : :
17 : : #include <sys/types.h>
18 : : #include <netinet/in.h>
19 : :
20 : : #include <dns/message.h>
21 : : #include <dns/rcode.h>
22 : :
23 : : #include <asiolink/asiolink.h>
24 : :
25 : : #include <dns/tests/unittest_util.h>
26 : :
27 : : #include <testutils/dnsmessage_test.h>
28 : : #include <testutils/srv_test.h>
29 : :
30 : : using namespace isc::dns;
31 : : using namespace isc::util;
32 : : using namespace isc::asiolink;
33 : :
34 : : namespace isc {
35 : : namespace testutils {
36 : : const char* const DEFAULT_REMOTE_ADDRESS = "192.0.2.1";
37 : :
38 : 69 : SrvTestBase::SrvTestBase() : request_message(Message::RENDER),
39 [ + - ]: 69 : parse_message(new Message(Message::PARSE)),
40 [ + - ]: 69 : response_message(new Message(Message::RENDER)),
41 : : default_qid(0x1035),
42 [ + - ]: 69 : opcode(Opcode(Opcode::QUERY())),
43 : : qname("www.example.com"),
44 : 69 : qclass(RRClass::IN()),
45 : 69 : qtype(RRType::A()), io_sock(NULL),
46 : : io_message(NULL), endpoint(NULL),
47 [ + - ][ + - ]: 414 : response_obuffer(new OutputBuffer(0))
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
48 : 69 : {}
49 : :
50 [ + - ][ + - ]: 207 : SrvTestBase::~SrvTestBase() {
[ + - ]
51 : 69 : delete io_message;
52 [ + + ][ + - ]: 69 : delete endpoint;
53 : 69 : }
54 : :
55 : : void
56 : 53 : SrvTestBase::createDataFromFile(const char* const datafile,
57 : : const int protocol)
58 : : {
59 : 53 : delete io_message;
60 : 53 : data.clear();
61 : :
62 [ + + ]: 53 : delete endpoint;
63 : :
64 : : endpoint = IOEndpoint::create(protocol,
65 [ + - ][ + - ]: 53 : IOAddress(DEFAULT_REMOTE_ADDRESS), 53210);
66 : 53 : UnitTestUtil::readWireData(datafile, data);
67 : : io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
68 [ + - ]: 53 : &IOSocket::getDummyTCPSocket();
69 : 53 : io_message = new IOMessage(&data[0], data.size(), *io_sock, *endpoint);
70 : 53 : }
71 : :
72 : : void
73 : 67 : SrvTestBase::createRequestPacket(Message& message,
74 : : const int protocol, TSIGContext* context)
75 : : {
76 [ + + ]: 67 : if (context == NULL) {
77 : 63 : message.toWire(request_renderer);
78 : : } else {
79 : 4 : message.toWire(request_renderer, *context);
80 : : }
81 : :
82 : 67 : delete io_message;
83 : :
84 : : endpoint = IOEndpoint::create(protocol,
85 [ + - ][ + - ]: 67 : IOAddress(DEFAULT_REMOTE_ADDRESS), 53210);
86 : : io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
87 [ + + ]: 67 : &IOSocket::getDummyTCPSocket();
88 : :
89 : : io_message = new IOMessage(request_renderer.getData(),
90 : : request_renderer.getLength(),
91 : 67 : *io_sock, *endpoint);
92 : 67 : }
93 : :
94 : : // Unsupported requests. Should result in NOTIMP.
95 : : void
96 : 2 : SrvTestBase::unsupportedRequest() {
97 [ + + ]: 34 : for (unsigned int i = 0; i < 16; ++i) {
98 : : // set Opcode to 'i', which iterators over all possible codes except
99 : : // the standard query and notify
100 [ + + ][ + + ]: 64 : if (i == isc::dns::Opcode::QUERY().getCode() ||
[ + + ]
101 : 30 : i == isc::dns::Opcode::NOTIFY().getCode()) {
102 : 4 : continue;
103 : : }
104 : 28 : createDataFromFile("simplequery_fromWire.wire");
105 : 28 : data[2] = ((i << 3) & 0xff);
106 : :
107 : 28 : parse_message->clear(isc::dns::Message::PARSE);
108 : 28 : processMessage();
109 [ - + ][ # # ]: 28 : EXPECT_TRUE(dnsserv.hasAnswer());
[ # # ][ # # ]
[ # # ][ # # ]
110 : 28 : headerCheck(*parse_message, default_qid, isc::dns::Rcode::NOTIMP(), i,
111 : 28 : QR_FLAG, 0, 0, 0, 0);
112 : : }
113 : 2 : }
114 : :
115 : : // Multiple questions. Should result in FORMERR.
116 : : void
117 : 2 : SrvTestBase::multiQuestion() {
118 : 2 : createDataFromFile("multiquestion_fromWire.wire");
119 : 2 : processMessage();
120 [ - + ][ # # ]: 2 : EXPECT_TRUE(dnsserv.hasAnswer());
[ # # ][ # # ]
[ # # ][ # # ]
121 : 2 : headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
122 : 2 : opcode.getCode(), QR_FLAG, 2, 0, 0, 0);
123 : :
124 : 4 : isc::dns::QuestionIterator qit = parse_message->beginQuestion();
125 [ + - ][ + - ]: 4 : EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
126 [ + - ][ - + ]: 4 : EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
127 [ + - ][ - + ]: 4 : EXPECT_EQ(isc::dns::RRType::A(), (*qit)->getType());
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
128 [ + - ]: 2 : ++qit;
129 [ + - ][ + - ]: 4 : EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
130 [ + - ][ - + ]: 4 : EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
131 [ + - ][ - + ]: 4 : EXPECT_EQ(isc::dns::RRType::AAAA(), (*qit)->getType());
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
132 [ + - ]: 2 : ++qit;
133 [ + - ][ + - ]: 2 : EXPECT_TRUE(qit == parse_message->endQuestion());
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + - ]
134 : 2 : }
135 : :
136 : : // Incoming data doesn't even contain the complete header. Must be silently
137 : : // dropped.
138 : : void
139 : 2 : SrvTestBase::shortMessage() {
140 : 2 : createDataFromFile("shortmessage_fromWire");
141 : 2 : processMessage();
142 [ - + ][ # # ]: 2 : EXPECT_FALSE(dnsserv.hasAnswer());
[ # # ][ # # ]
[ # # ][ # # ]
143 : 2 : }
144 : :
145 : : // Response messages. Must be silently dropped, whether it's a valid response
146 : : // or malformed or could otherwise cause a protocol error.
147 : : void
148 : 2 : SrvTestBase::response() {
149 : : // A valid (although unusual) response
150 : 2 : createDataFromFile("simpleresponse_fromWire.wire");
151 : 2 : processMessage();
152 [ - + ][ # # ]: 2 : EXPECT_FALSE(dnsserv.hasAnswer());
[ # # ][ # # ]
[ # # ][ # # ]
153 : :
154 : : // A response with a broken question section. must be dropped rather than
155 : : //returning FORMERR.
156 : 2 : createDataFromFile("shortresponse_fromWire");
157 : 2 : processMessage();
158 [ - + ][ # # ]: 2 : EXPECT_FALSE(dnsserv.hasAnswer());
[ # # ][ # # ]
[ # # ][ # # ]
159 : :
160 : : // A response to iquery. must be dropped rather than returning NOTIMP.
161 : 2 : createDataFromFile("iqueryresponse_fromWire.wire");
162 : 2 : processMessage();
163 [ - + ][ # # ]: 2 : EXPECT_FALSE(dnsserv.hasAnswer());
[ # # ][ # # ]
[ # # ][ # # ]
164 : 2 : }
165 : :
166 : : // Query with a broken question
167 : : void
168 : 2 : SrvTestBase::shortQuestion() {
169 : 2 : createDataFromFile("shortquestion_fromWire");
170 : 2 : processMessage();
171 [ - + ][ # # ]: 2 : EXPECT_TRUE(dnsserv.hasAnswer());
[ # # ][ # # ]
[ # # ][ # # ]
172 : : // Since the query's question is broken, the question section of the
173 : : // response should be empty.
174 : 2 : headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
175 : 2 : opcode.getCode(), QR_FLAG, 0, 0, 0, 0);
176 : 2 : }
177 : :
178 : : // Query with a broken answer section
179 : : void
180 : 2 : SrvTestBase::shortAnswer() {
181 : 2 : createDataFromFile("shortanswer_fromWire.wire");
182 : 2 : processMessage();
183 [ - + ][ # # ]: 2 : EXPECT_TRUE(dnsserv.hasAnswer());
[ # # ][ # # ]
[ # # ][ # # ]
184 : :
185 : : // This is a bogus query, but question section is valid. So the response
186 : : // should copy the question section.
187 : 2 : headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
188 : 2 : opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
189 : :
190 : 4 : isc::dns::QuestionIterator qit = parse_message->beginQuestion();
191 [ + - ][ + - ]: 4 : EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
192 [ + - ][ - + ]: 4 : EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
193 [ + - ][ - + ]: 4 : EXPECT_EQ(isc::dns::RRType::A(), (*qit)->getType());
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
194 [ + - ]: 2 : ++qit;
195 [ + - ][ + - ]: 2 : EXPECT_TRUE(qit == parse_message->endQuestion());
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + - ]
196 : 2 : }
197 : :
198 : : // Query with unsupported version of EDNS.
199 : : void
200 : 2 : SrvTestBase::ednsBadVers() {
201 : 2 : createDataFromFile("queryBadEDNS_fromWire.wire");
202 : 2 : processMessage();
203 [ - + ][ # # ]: 2 : EXPECT_TRUE(dnsserv.hasAnswer());
[ # # ][ # # ]
[ # # ][ # # ]
204 : :
205 : : // The response must have an EDNS OPT RR in the additional section,
206 : : // it will be added automatically at the render time.
207 : : // Note that the DNSSEC DO bit is cleared even if this bit in the query
208 : : // is set. This is a limitation of the current implementation.
209 : 2 : headerCheck(*parse_message, default_qid, isc::dns::Rcode::BADVERS(),
210 : 2 : opcode.getCode(), QR_FLAG, 1, 0, 0, 1);
211 [ - + ][ # # ]: 4 : EXPECT_FALSE(parse_message->getEDNS()); // EDNS isn't added at this point
[ # # ][ # # ]
[ # # ][ # # ]
212 : :
213 : : InputBuffer ib(response_obuffer->getData(),
214 : 2 : response_obuffer->getLength());
215 : 4 : isc::dns::Message parsed(isc::dns::Message::PARSE);
216 [ + - ]: 2 : parsed.fromWire(ib);
217 [ + - ][ + - ]: 4 : EXPECT_EQ(isc::dns::Rcode::BADVERS(), parsed.getRcode());
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ + - ]
218 [ + - ]: 2 : isc::dns::ConstEDNSPtr edns(parsed.getEDNS());
219 [ - + ][ # # ]: 4 : ASSERT_TRUE(edns);
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ][ # # ]
220 [ - + ][ # # ]: 2 : EXPECT_FALSE(edns->getDNSSECAwareness());
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
221 : : }
222 : :
223 : : void
224 : 2 : SrvTestBase::axfrOverUDP() {
225 : : // AXFR over UDP is invalid and should result in FORMERR.
226 : : UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
227 : 2 : isc::dns::Name("example.com"),
228 : 2 : isc::dns::RRClass::IN(),
229 [ + - ][ + - ]: 2 : isc::dns::RRType::AXFR());
230 : 2 : createRequestPacket(request_message, IPPROTO_UDP);
231 : 2 : processMessage();
232 [ - + ][ # # ]: 2 : EXPECT_TRUE(dnsserv.hasAnswer());
[ # # ][ # # ]
[ # # ][ # # ]
233 : 2 : headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
234 : 2 : opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
235 : 2 : }
236 : : } // end of namespace testutils
237 : 2 : } // end of namespace isc
238 : :
239 : :
240 : : // Local Variables:
241 : : // mode: c++
242 : : // End:
|