1 use crate::dnscrypt_certs::*;
2 use crate::errors::*;
3
4 use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
5 use std::net::IpAddr;
6 use std::sync::Arc;
7
8 pub const DNS_MAX_HOSTNAME_SIZE: usize = 256;
9 pub const DNS_HEADER_SIZE: usize = 12;
10 pub const DNS_OFFSET_FLAGS: usize = 2;
11 pub const DNS_MAX_PACKET_SIZE: usize = 0x1600;
12
13 const DNS_MAX_INDIRECTIONS: usize = 16;
14 const DNS_FLAGS_TC: u16 = 1u16 << 9;
15 const DNS_FLAGS_QR: u16 = 1u16 << 15;
16 const DNS_FLAGS_RA: u16 = 1u16 << 7;
17 const DNS_FLAGS_RD: u16 = 1u16 << 8;
18 const DNS_FLAGS_CD: u16 = 1u16 << 4;
19 const DNS_OFFSET_QUESTION: usize = DNS_HEADER_SIZE;
20
21 pub const DNS_TYPE_A: u16 = 1;
22 pub const DNS_TYPE_AAAA: u16 = 28;
23 pub const DNS_TYPE_OPT: u16 = 41;
24 pub const DNS_TYPE_TXT: u16 = 16;
25 pub const DNS_TYPE_HINFO: u16 = 13;
26 pub const DNS_CLASS_INET: u16 = 1;
27
28 pub const DNS_RCODE_SERVFAIL: u8 = 2;
29 pub const DNS_RCODE_NXDOMAIN: u8 = 3;
30 pub const DNS_RCODE_REFUSED: u8 = 5;
31
32 #[inline]
rcode(packet: &[u8]) -> u833 pub fn rcode(packet: &[u8]) -> u8 {
34 packet[3] & 0x0f
35 }
36
37 #[inline]
set_rcode(packet: &mut [u8], rcode: u8)38 pub fn set_rcode(packet: &mut [u8], rcode: u8) {
39 packet[3] = (packet[3] & !0x0f) | rcode;
40 }
41
42 #[inline]
rcode_servfail(packet: &[u8]) -> bool43 pub fn rcode_servfail(packet: &[u8]) -> bool {
44 rcode(packet) == DNS_RCODE_SERVFAIL
45 }
46
47 #[inline]
set_rcode_servfail(packet: &mut [u8])48 pub fn set_rcode_servfail(packet: &mut [u8]) {
49 set_rcode(packet, DNS_RCODE_SERVFAIL)
50 }
51
52 #[inline]
rcode_refused(packet: &[u8]) -> bool53 pub fn rcode_refused(packet: &[u8]) -> bool {
54 rcode(packet) == DNS_RCODE_REFUSED
55 }
56
57 #[inline]
set_rcode_refused(packet: &mut [u8])58 pub fn set_rcode_refused(packet: &mut [u8]) {
59 set_rcode(packet, DNS_RCODE_REFUSED)
60 }
61
62 #[inline]
rcode_nxdomain(packet: &[u8]) -> bool63 pub fn rcode_nxdomain(packet: &[u8]) -> bool {
64 rcode(packet) == DNS_RCODE_NXDOMAIN
65 }
66
67 #[inline]
set_rcode_nxdomain(packet: &mut [u8])68 pub fn set_rcode_nxdomain(packet: &mut [u8]) {
69 set_rcode(packet, DNS_RCODE_NXDOMAIN)
70 }
71
72 #[inline]
qdcount(packet: &[u8]) -> u1673 pub fn qdcount(packet: &[u8]) -> u16 {
74 BigEndian::read_u16(&packet[4..])
75 }
76
77 #[inline]
ancount(packet: &[u8]) -> u1678 pub fn ancount(packet: &[u8]) -> u16 {
79 BigEndian::read_u16(&packet[6..])
80 }
81
ancount_inc(packet: &mut [u8]) -> Result<(), Error>82 fn ancount_inc(packet: &mut [u8]) -> Result<(), Error> {
83 let mut ancount = ancount(packet);
84 ensure!(ancount < 0xffff, "Too many answer records");
85 ancount += 1;
86 BigEndian::write_u16(&mut packet[6..], ancount);
87 Ok(())
88 }
89
90 #[inline]
nscount(packet: &[u8]) -> u1691 fn nscount(packet: &[u8]) -> u16 {
92 BigEndian::read_u16(&packet[8..])
93 }
94
95 #[inline]
arcount(packet: &[u8]) -> u1696 pub fn arcount(packet: &[u8]) -> u16 {
97 BigEndian::read_u16(&packet[10..])
98 }
99
arcount_inc(packet: &mut [u8]) -> Result<(), Error>100 fn arcount_inc(packet: &mut [u8]) -> Result<(), Error> {
101 let mut arcount = arcount(packet);
102 ensure!(arcount < 0xffff, "Too many additional records");
103 arcount += 1;
104 BigEndian::write_u16(&mut packet[10..], arcount);
105 Ok(())
106 }
107
108 #[inline]
arcount_clear(packet: &mut [u8]) -> Result<(), Error>109 fn arcount_clear(packet: &mut [u8]) -> Result<(), Error> {
110 BigEndian::write_u16(&mut packet[10..], 0);
111 Ok(())
112 }
113
114 #[inline]
an_ns_ar_count_clear(packet: &mut [u8])115 pub fn an_ns_ar_count_clear(packet: &mut [u8]) {
116 packet[6..12].iter_mut().for_each(|x| *x = 0);
117 }
118
119 #[inline]
tid(packet: &[u8]) -> u16120 pub fn tid(packet: &[u8]) -> u16 {
121 BigEndian::read_u16(&packet[0..])
122 }
123
124 #[inline]
set_tid(packet: &mut [u8], tid: u16)125 pub fn set_tid(packet: &mut [u8], tid: u16) {
126 BigEndian::write_u16(&mut packet[0..], tid);
127 }
128
129 #[inline]
set_flags(packet: &mut [u8], flags: u16)130 pub fn set_flags(packet: &mut [u8], flags: u16) {
131 BigEndian::write_u16(&mut packet[DNS_OFFSET_FLAGS..], flags);
132 }
133
134 #[inline]
authoritative_response(packet: &mut [u8])135 pub fn authoritative_response(packet: &mut [u8]) {
136 let current_rd_cd_flags =
137 BigEndian::read_u16(&packet[DNS_OFFSET_FLAGS..]) & (DNS_FLAGS_CD | DNS_FLAGS_RD);
138 set_flags(packet, current_rd_cd_flags | DNS_FLAGS_QR | DNS_FLAGS_RA);
139 }
140
141 #[inline]
truncate(packet: &mut [u8])142 pub fn truncate(packet: &mut [u8]) {
143 let current_flags = BigEndian::read_u16(&packet[DNS_OFFSET_FLAGS..]);
144 BigEndian::write_u16(
145 &mut packet[DNS_OFFSET_FLAGS..],
146 current_flags | DNS_FLAGS_TC | DNS_FLAGS_QR | DNS_FLAGS_RA,
147 );
148 }
149
150 #[inline]
is_response(packet: &[u8]) -> bool151 pub fn is_response(packet: &[u8]) -> bool {
152 BigEndian::read_u16(&packet[DNS_OFFSET_FLAGS..]) & DNS_FLAGS_QR == DNS_FLAGS_QR
153 }
154
155 #[inline]
is_truncated(packet: &[u8]) -> bool156 pub fn is_truncated(packet: &[u8]) -> bool {
157 BigEndian::read_u16(&packet[DNS_OFFSET_FLAGS..]) & DNS_FLAGS_TC == DNS_FLAGS_TC
158 }
159
qname(packet: &[u8]) -> Result<Vec<u8>, Error>160 pub fn qname(packet: &[u8]) -> Result<Vec<u8>, Error> {
161 debug_assert!(std::usize::MAX > 0xffff);
162 debug_assert!(DNS_MAX_HOSTNAME_SIZE > 0xff);
163 let packet_len = packet.len();
164 ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
165 ensure!(qdcount(packet) == 1, "Unexpected query count");
166 let mut offset = DNS_HEADER_SIZE;
167 let mut qname = Vec::with_capacity(DNS_MAX_HOSTNAME_SIZE);
168 loop {
169 ensure!(offset < packet_len, "Short packet");
170 match packet[offset] as usize {
171 label_len if label_len & 0xc0 == 0xc0 => bail!("Indirections"),
172 0 => {
173 if qname.is_empty() {
174 qname.push(b'.')
175 }
176 break;
177 }
178 label_len => {
179 ensure!(label_len < 0x40, "Long label");
180 ensure!(packet_len - offset > 1, "Short packet");
181 offset += 1;
182 ensure!(packet_len - offset > label_len, "Short packet");
183 if !qname.is_empty() {
184 qname.push(b'.')
185 }
186 ensure!(
187 qname.len() < DNS_MAX_HOSTNAME_SIZE - label_len,
188 "Name too long"
189 );
190 qname.extend_from_slice(&packet[offset..offset + label_len]);
191 offset += label_len;
192 }
193 }
194 }
195 Ok(qname)
196 }
197
normalize_qname(packet: &mut [u8]) -> Result<(), Error>198 pub fn normalize_qname(packet: &mut [u8]) -> Result<(), Error> {
199 debug_assert!(std::usize::MAX > 0xffff);
200 debug_assert!(DNS_MAX_HOSTNAME_SIZE > 0xff);
201 let packet_len = packet.len();
202 ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
203 ensure!(qdcount(packet) == 1, "Unexpected query count");
204 let mut offset = DNS_HEADER_SIZE;
205 loop {
206 ensure!(offset < packet_len, "Short packet");
207 match packet[offset] as usize {
208 label_len if label_len & 0xc0 == 0xc0 => bail!("Indirections"),
209 0 => {
210 break;
211 }
212 label_len => {
213 ensure!(label_len < 0x40, "Long label");
214 ensure!(packet_len - offset > 1, "Short packet");
215 offset += 1;
216 ensure!(packet_len - offset > label_len, "Short packet");
217 ensure!(
218 offset - DNS_HEADER_SIZE < DNS_MAX_HOSTNAME_SIZE - label_len,
219 "Name too long"
220 );
221 packet[offset..offset + label_len]
222 .iter_mut()
223 .for_each(|x| *x = x.to_ascii_lowercase());
224 offset += label_len;
225 }
226 }
227 }
228 Ok(())
229 }
230
qname_tld(qname: &[u8]) -> &[u8]231 pub fn qname_tld(qname: &[u8]) -> &[u8] {
232 qname.rsplit(|c| *c == b'.').next().unwrap_or_default()
233 }
234
recase_qname(packet: &mut [u8], qname: &[u8]) -> Result<(), Error>235 pub fn recase_qname(packet: &mut [u8], qname: &[u8]) -> Result<(), Error> {
236 debug_assert!(std::usize::MAX > 0xffff);
237 let packet_len = packet.len();
238 ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
239 ensure!(qdcount(packet) == 1, "Unexpected query count");
240 let qname_len = qname.len();
241 let mut offset = DNS_HEADER_SIZE;
242 let mut qname_offset = 0;
243 loop {
244 ensure!(offset < packet_len, "Short packet");
245 match packet[offset] as usize {
246 label_len if label_len & 0xc0 == 0xc0 => bail!("Indirections"),
247 0 => {
248 ensure!(
249 (qname_len == 1 && qname[0] == b'.') || qname_offset == qname_len,
250 "Unterminated reference qname"
251 );
252 break;
253 }
254 label_len => {
255 ensure!(label_len < 0x40, "Long label");
256 ensure!(packet_len - offset > 1, "Short packet");
257 ensure!(qname_offset < qname_len, "Short reference qname");
258 offset += 1;
259 if qname_offset != 0 {
260 ensure!(qname[qname_offset] == b'.', "Non-matching reference qname");
261 qname_offset += 1;
262 }
263 ensure!(packet_len - offset > label_len, "Short packet");
264 ensure!(
265 qname_len - qname_offset >= label_len,
266 "Short reference qname"
267 );
268 packet[offset..offset + label_len]
269 .iter_mut()
270 .zip(&qname[qname_offset..qname_offset + label_len])
271 .for_each(|(a, b)| {
272 debug_assert!(a.eq_ignore_ascii_case(b));
273 *a = *b
274 });
275 offset += label_len;
276 qname_offset += label_len;
277 }
278 }
279 }
280 Ok(())
281 }
282
skip_name(packet: &[u8], offset: usize) -> Result<usize, Error>283 fn skip_name(packet: &[u8], offset: usize) -> Result<usize, Error> {
284 let packet_len = packet.len();
285 ensure!(offset < packet_len - 1, "Short packet");
286 let mut qname_len: usize = 0;
287 let mut offset = offset;
288 loop {
289 let label_len = match packet[offset] as usize {
290 label_len if label_len & 0xc0 == 0xc0 => {
291 ensure!(packet_len - offset >= 2, "Incomplete offset");
292 offset += 2;
293 break;
294 }
295 label_len => label_len,
296 } as usize;
297 ensure!(label_len < 0x40, "Long label");
298 ensure!(
299 packet_len - offset - 1 > label_len,
300 "Malformed packet with an out-of-bounds name"
301 );
302 qname_len += label_len + 1;
303 ensure!(qname_len <= DNS_MAX_HOSTNAME_SIZE, "Name too long");
304 offset += label_len + 1;
305 if label_len == 0 {
306 break;
307 }
308 }
309 Ok(offset)
310 }
311
traverse_rrs<F: FnMut(usize) -> Result<(), Error>>( packet: &[u8], mut offset: usize, rrcount: usize, mut cb: F, ) -> Result<usize, Error>312 fn traverse_rrs<F: FnMut(usize) -> Result<(), Error>>(
313 packet: &[u8],
314 mut offset: usize,
315 rrcount: usize,
316 mut cb: F,
317 ) -> Result<usize, Error> {
318 let packet_len = packet.len();
319 for _ in 0..rrcount {
320 offset = skip_name(packet, offset)?;
321 ensure!(packet_len - offset >= 10, "Short packet");
322 let rdlen = BigEndian::read_u16(&packet[offset + 8..]) as usize;
323 ensure!(
324 packet_len - offset >= 10 + rdlen,
325 "Record length would exceed packet length"
326 );
327 cb(offset)?;
328 offset += 10;
329 offset += rdlen;
330 }
331 Ok(offset)
332 }
333
traverse_rrs_mut<F: FnMut(&mut [u8], usize) -> Result<(), Error>>( packet: &mut [u8], mut offset: usize, rrcount: usize, mut cb: F, ) -> Result<usize, Error>334 fn traverse_rrs_mut<F: FnMut(&mut [u8], usize) -> Result<(), Error>>(
335 packet: &mut [u8],
336 mut offset: usize,
337 rrcount: usize,
338 mut cb: F,
339 ) -> Result<usize, Error> {
340 let packet_len = packet.len();
341 for _ in 0..rrcount {
342 offset = skip_name(packet, offset)?;
343 ensure!(packet_len - offset >= 10, "Short packet");
344 let rdlen = BigEndian::read_u16(&packet[offset + 8..]) as usize;
345 ensure!(
346 packet_len - offset >= 10 + rdlen,
347 "Record length would exceed packet length"
348 );
349 cb(packet, offset)?;
350 offset += 10;
351 offset += rdlen;
352 }
353 Ok(offset)
354 }
355
min_ttl(packet: &[u8], min_ttl: u32, max_ttl: u32, failure_ttl: u32) -> Result<u32, Error>356 pub fn min_ttl(packet: &[u8], min_ttl: u32, max_ttl: u32, failure_ttl: u32) -> Result<u32, Error> {
357 let packet_len = packet.len();
358 ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
359 ensure!(packet_len <= DNS_MAX_PACKET_SIZE, "Large packet");
360 ensure!(qdcount(packet) == 1, "No question");
361 let mut offset = skip_name(packet, DNS_OFFSET_QUESTION)?;
362 assert!(offset > DNS_OFFSET_QUESTION);
363 ensure!(packet_len - offset > 4, "Short packet");
364 offset += 4;
365 let (ancount, nscount, arcount) = (ancount(packet), nscount(packet), arcount(packet));
366 let rrcount = ancount as usize + nscount as usize + arcount as usize;
367 let mut found_min_ttl = if rrcount > 0 { max_ttl } else { failure_ttl };
368
369 offset = traverse_rrs(packet, offset, rrcount, |offset| {
370 let qtype = BigEndian::read_u16(&packet[offset..]);
371 let ttl = BigEndian::read_u32(&packet[offset + 4..]);
372 if qtype != DNS_TYPE_OPT && ttl < found_min_ttl {
373 found_min_ttl = ttl;
374 }
375 Ok(())
376 })?;
377 if found_min_ttl < min_ttl {
378 found_min_ttl = min_ttl;
379 }
380 ensure!(packet_len == offset, "Garbage after packet");
381 Ok(found_min_ttl)
382 }
383
set_ttl(packet: &mut [u8], ttl: u32) -> Result<(), Error>384 pub fn set_ttl(packet: &mut [u8], ttl: u32) -> Result<(), Error> {
385 let packet_len = packet.len();
386 ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
387 ensure!(packet_len <= DNS_MAX_PACKET_SIZE, "Large packet");
388 ensure!(qdcount(packet) == 1, "No question");
389 let mut offset = skip_name(packet, DNS_OFFSET_QUESTION)?;
390 assert!(offset > DNS_OFFSET_QUESTION);
391 ensure!(packet_len - offset > 4, "Short packet");
392 offset += 4;
393 let (ancount, nscount, arcount) = (ancount(packet), nscount(packet), arcount(packet));
394 let rrcount = ancount as usize + nscount as usize + arcount as usize;
395 offset = traverse_rrs_mut(packet, offset, rrcount, |packet, offset| {
396 let qtype = BigEndian::read_u16(&packet[offset..]);
397 if qtype != DNS_TYPE_OPT {
398 BigEndian::write_u32(&mut packet[offset + 4..], ttl)
399 }
400 Ok(())
401 })?;
402 ensure!(packet_len == offset, "Garbage after packet");
403 Ok(())
404 }
405
add_edns_section(packet: &mut Vec<u8>, max_payload_size: u16) -> Result<(), Error>406 fn add_edns_section(packet: &mut Vec<u8>, max_payload_size: u16) -> Result<(), Error> {
407 let opt_rr: [u8; 11] = [
408 0,
409 (DNS_TYPE_OPT >> 8) as u8,
410 DNS_TYPE_OPT as u8,
411 (max_payload_size >> 8) as u8,
412 max_payload_size as u8,
413 0,
414 0,
415 0,
416 0,
417 0,
418 0,
419 ];
420 ensure!(
421 DNS_MAX_PACKET_SIZE - packet.len() >= opt_rr.len(),
422 "Packet would be too large to add a new record"
423 );
424 arcount_inc(packet)?;
425 packet.extend(&opt_rr);
426 Ok(())
427 }
428
set_edns_max_payload_size(packet: &mut Vec<u8>, max_payload_size: u16) -> Result<(), Error>429 pub fn set_edns_max_payload_size(packet: &mut Vec<u8>, max_payload_size: u16) -> Result<(), Error> {
430 let packet_len = packet.len();
431 ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
432 ensure!(packet_len <= DNS_MAX_PACKET_SIZE, "Large packet");
433 ensure!(qdcount(packet) == 1, "No question");
434 let mut offset = skip_name(packet, DNS_OFFSET_QUESTION)?;
435 assert!(offset > DNS_OFFSET_QUESTION);
436 ensure!(packet_len - offset >= 4, "Short packet");
437 offset += 4;
438 let (ancount, nscount, arcount) = (ancount(packet), nscount(packet), arcount(packet));
439 offset = traverse_rrs(
440 packet,
441 offset,
442 ancount as usize + nscount as usize,
443 |_offset| Ok(()),
444 )?;
445 let mut edns_payload_set = false;
446 traverse_rrs_mut(packet, offset, arcount as _, |packet, offset| {
447 let qtype = BigEndian::read_u16(&packet[offset..]);
448 if qtype == DNS_TYPE_OPT {
449 ensure!(!edns_payload_set, "Duplicate OPT RR found");
450 BigEndian::write_u16(&mut packet[offset + 2..], max_payload_size);
451 edns_payload_set = true;
452 }
453 Ok(())
454 })?;
455 if edns_payload_set {
456 return Ok(());
457 }
458 add_edns_section(packet, max_payload_size)?;
459 Ok(())
460 }
461
serve_certificates<'t>( client_packet: &[u8], expected_qname: &str, dnscrypt_encryption_params_set: impl IntoIterator<Item = &'t Arc<DNSCryptEncryptionParams>>, ) -> Result<Option<Vec<u8>>, Error>462 pub fn serve_certificates<'t>(
463 client_packet: &[u8],
464 expected_qname: &str,
465 dnscrypt_encryption_params_set: impl IntoIterator<Item = &'t Arc<DNSCryptEncryptionParams>>,
466 ) -> Result<Option<Vec<u8>>, Error> {
467 ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet");
468 ensure!(qdcount(client_packet) == 1, "No question");
469 ensure!(
470 !is_response(client_packet),
471 "Question expected, but got a response instead"
472 );
473 let offset = skip_name(client_packet, DNS_HEADER_SIZE)?;
474 ensure!(client_packet.len() - offset >= 4, "Short packet");
475 let qtype = BigEndian::read_u16(&client_packet[offset..]);
476 let qclass = BigEndian::read_u16(&client_packet[offset + 2..]);
477 if qtype != DNS_TYPE_TXT || qclass != DNS_CLASS_INET {
478 return Ok(None);
479 }
480 let qname_v = qname(client_packet)?;
481 let qname = std::str::from_utf8(&qname_v)?;
482 if !qname.eq_ignore_ascii_case(expected_qname) {
483 return Ok(None);
484 }
485 let mut packet = (&client_packet[..offset + 4]).to_vec();
486 an_ns_ar_count_clear(&mut packet);
487 authoritative_response(&mut packet);
488 let dnscrypt_encryption_params = dnscrypt_encryption_params_set
489 .into_iter()
490 .max_by_key(|x| x.dnscrypt_cert().ts_end())
491 .ok_or_else(|| anyhow!("No certificates"))?;
492 let cert_bin = dnscrypt_encryption_params.dnscrypt_cert().as_bytes();
493 ensure!(cert_bin.len() <= 0xff, "Certificate too long");
494 ancount_inc(&mut packet)?;
495 packet.write_u16::<BigEndian>(0xc000 + DNS_HEADER_SIZE as u16)?;
496 packet.write_u16::<BigEndian>(DNS_TYPE_TXT)?;
497 packet.write_u16::<BigEndian>(DNS_CLASS_INET)?;
498 packet.write_u32::<BigEndian>(DNSCRYPT_CERTS_RENEWAL)?;
499 packet.write_u16::<BigEndian>(1 + cert_bin.len() as u16)?;
500 packet.write_u8(cert_bin.len() as u8)?;
501 packet.extend_from_slice(cert_bin);
502 ensure!(packet.len() < DNS_MAX_PACKET_SIZE, "Packet too large");
503
504 Ok(Some(packet))
505 }
506
serve_truncated_response(client_packet: Vec<u8>) -> Result<Vec<u8>, Error>507 pub fn serve_truncated_response(client_packet: Vec<u8>) -> Result<Vec<u8>, Error> {
508 ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet");
509 ensure!(qdcount(&client_packet) == 1, "No question");
510 ensure!(
511 !is_response(&client_packet),
512 "Question expected, but got a response instead"
513 );
514 let offset = skip_name(&client_packet, DNS_HEADER_SIZE)?;
515 let mut packet = client_packet;
516 ensure!(packet.len() - offset >= 4, "Short packet");
517 packet.truncate(offset + 4);
518 an_ns_ar_count_clear(&mut packet);
519 authoritative_response(&mut packet);
520 truncate(&mut packet);
521 Ok(packet)
522 }
523
qtype_qclass(packet: &[u8]) -> Result<(u16, u16), Error>524 pub fn qtype_qclass(packet: &[u8]) -> Result<(u16, u16), Error> {
525 ensure!(packet.len() >= DNS_HEADER_SIZE, "Short packet");
526 ensure!(qdcount(packet) == 1, "No question");
527 let offset = skip_name(packet, DNS_HEADER_SIZE)?;
528 ensure!(packet.len() - offset >= 4, "Short packet");
529 let qtype = BigEndian::read_u16(&packet[offset..]);
530 let qclass = BigEndian::read_u16(&packet[offset + 2..]);
531 Ok((qtype, qclass))
532 }
533
parse_txt_rrdata<F: FnMut(&str) -> Result<(), Error>>( rrdata: &[u8], mut cb: F, ) -> Result<(), Error>534 fn parse_txt_rrdata<F: FnMut(&str) -> Result<(), Error>>(
535 rrdata: &[u8],
536 mut cb: F,
537 ) -> Result<(), Error> {
538 let rrdata_len = rrdata.len();
539 let mut offset = 0;
540 while offset < rrdata_len {
541 let part_len = rrdata[offset] as usize;
542 if part_len == 0 {
543 break;
544 }
545 ensure!(rrdata_len - offset > part_len, "Short TXT RR data");
546 offset += 1;
547 let part_bin = &rrdata[offset..offset + part_len];
548 let part = std::str::from_utf8(part_bin)?;
549 cb(part)?;
550 offset += part_len;
551 }
552 Ok(())
553 }
554
query_meta(packet: &mut Vec<u8>) -> Result<Option<String>, Error>555 pub fn query_meta(packet: &mut Vec<u8>) -> Result<Option<String>, Error> {
556 let packet_len = packet.len();
557 ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
558 ensure!(packet_len <= DNS_MAX_PACKET_SIZE, "Large packet");
559 ensure!(qdcount(packet) == 1, "No question");
560 let mut offset = skip_name(packet, DNS_OFFSET_QUESTION)?;
561 assert!(offset > DNS_OFFSET_QUESTION);
562 ensure!(packet_len - offset >= 4, "Short packet");
563 offset += 4;
564 let (ancount, nscount, arcount) = (ancount(packet), nscount(packet), arcount(packet));
565 offset = traverse_rrs(
566 packet,
567 offset,
568 ancount as usize + nscount as usize,
569 |_offset| Ok(()),
570 )?;
571 let mut token = None;
572 traverse_rrs(packet, offset, arcount as _, |mut offset| {
573 let qtype = BigEndian::read_u16(&packet[offset..]);
574 let qclass = BigEndian::read_u16(&packet[offset + 2..]);
575 if qtype != DNS_TYPE_TXT || qclass != DNS_CLASS_INET {
576 return Ok(());
577 }
578 let len = BigEndian::read_u16(&packet[offset + 8..]) as usize;
579 offset += 10;
580 ensure!(packet_len - offset >= len, "Short packet");
581 let rrdata = &packet[offset..offset + len];
582 parse_txt_rrdata(rrdata, |txt| {
583 if txt.len() < 7 || !txt.starts_with("token:") {
584 return Ok(());
585 }
586 ensure!(token.is_none(), "Duplicate token");
587 let found_token = &txt[6..];
588 let found_token = found_token.to_owned();
589 token = Some(found_token);
590 Ok(())
591 })?;
592 Ok(())
593 })?;
594 if token.is_some() {
595 arcount_clear(packet)?;
596 packet.truncate(offset);
597 }
598 Ok(token)
599 }
600
serve_nxdomain_response(client_packet: Vec<u8>) -> Result<Vec<u8>, Error>601 pub fn serve_nxdomain_response(client_packet: Vec<u8>) -> Result<Vec<u8>, Error> {
602 ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet");
603 ensure!(qdcount(&client_packet) == 1, "No question");
604 ensure!(
605 !is_response(&client_packet),
606 "Question expected, but got a response instead"
607 );
608 let offset = skip_name(&client_packet, DNS_HEADER_SIZE)?;
609 let mut packet = client_packet;
610 ensure!(packet.len() - offset >= 4, "Short packet");
611 packet.truncate(offset + 4);
612 an_ns_ar_count_clear(&mut packet);
613 authoritative_response(&mut packet);
614 set_rcode_nxdomain(&mut packet);
615 Ok(packet)
616 }
617
serve_blocked_response(client_packet: Vec<u8>) -> Result<Vec<u8>, Error>618 pub fn serve_blocked_response(client_packet: Vec<u8>) -> Result<Vec<u8>, Error> {
619 ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet");
620 ensure!(qdcount(&client_packet) == 1, "No question");
621 ensure!(
622 !is_response(&client_packet),
623 "Question expected, but got a response instead"
624 );
625 let offset = skip_name(&client_packet, DNS_HEADER_SIZE)?;
626 let mut packet = client_packet;
627 ensure!(packet.len() - offset >= 4, "Short packet");
628 packet.truncate(offset + 4);
629 an_ns_ar_count_clear(&mut packet);
630 authoritative_response(&mut packet);
631 let hinfo_cpu = b"Query blocked";
632 let hinfo_rdata = b"by the DNS server";
633 let rdata_len = 1 + hinfo_cpu.len() + 1 + hinfo_rdata.len();
634 ancount_inc(&mut packet)?;
635 packet.write_u16::<BigEndian>(0xc000 + DNS_HEADER_SIZE as u16)?;
636 packet.write_u16::<BigEndian>(DNS_TYPE_HINFO)?;
637 packet.write_u16::<BigEndian>(DNS_CLASS_INET)?;
638 packet.write_u32::<BigEndian>(60)?;
639 packet.write_u16::<BigEndian>(rdata_len as _)?;
640 packet.push(hinfo_cpu.len() as u8);
641 packet.extend_from_slice(hinfo_cpu);
642 packet.push(hinfo_rdata.len() as u8);
643 packet.extend_from_slice(hinfo_rdata);
644 Ok(packet)
645 }
646
serve_ip_response(client_packet: Vec<u8>, ip: IpAddr, ttl: u32) -> Result<Vec<u8>, Error>647 pub fn serve_ip_response(client_packet: Vec<u8>, ip: IpAddr, ttl: u32) -> Result<Vec<u8>, Error> {
648 ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet");
649 ensure!(qdcount(&client_packet) == 1, "No question");
650 ensure!(
651 !is_response(&client_packet),
652 "Question expected, but got a response instead"
653 );
654 let offset = skip_name(&client_packet, DNS_HEADER_SIZE)?;
655 let mut packet = client_packet;
656 ensure!(packet.len() - offset >= 4, "Short packet");
657 packet.truncate(offset + 4);
658 an_ns_ar_count_clear(&mut packet);
659 authoritative_response(&mut packet);
660 ancount_inc(&mut packet)?;
661 packet.write_u16::<BigEndian>(0xc000 + DNS_HEADER_SIZE as u16)?;
662 match ip {
663 IpAddr::V4(ip) => {
664 packet.write_u16::<BigEndian>(DNS_TYPE_A)?;
665 packet.write_u16::<BigEndian>(DNS_CLASS_INET)?;
666 packet.write_u32::<BigEndian>(ttl)?;
667 packet.write_u16::<BigEndian>(4)?;
668 packet.extend_from_slice(&ip.octets());
669 }
670 IpAddr::V6(ip) => {
671 packet.write_u16::<BigEndian>(DNS_TYPE_AAAA)?;
672 packet.write_u16::<BigEndian>(DNS_CLASS_INET)?;
673 packet.write_u32::<BigEndian>(ttl)?;
674 packet.write_u16::<BigEndian>(16)?;
675 packet.extend_from_slice(&ip.octets());
676 }
677 };
678 Ok(packet)
679 }
680