1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use dnssector::DNS_MAX_COMPRESSED_SIZE;
use std::{
io::{self, Read, Write},
net::{SocketAddr, TcpStream, UdpSocket},
time::Duration,
};
pub fn query_raw_udp(
local: &SocketAddr,
upstream: &SocketAddr,
packet: &[u8],
timeout: Duration,
) -> io::Result<Vec<u8>> {
let socket = UdpSocket::bind(local)?;
let _ = socket.set_read_timeout(Some(timeout));
socket.connect(upstream)?;
socket.send(packet)?;
let mut response = vec![0; DNS_MAX_COMPRESSED_SIZE];
let response_len = socket.recv(&mut response)?;
response.truncate(response_len);
Ok(response)
}
pub fn query_raw_tcp(
upstream: &SocketAddr,
packet: &[u8],
timeout: Duration,
) -> io::Result<Vec<u8>> {
let mut stream = TcpStream::connect_timeout(upstream, timeout)?;
let _ = stream.set_read_timeout(Some(timeout));
let _ = stream.set_write_timeout(Some(timeout));
let _ = stream.set_nodelay(true);
let query_len = packet.len();
let mut tcp_query = Vec::with_capacity(2 + query_len);
tcp_query.push((query_len >> 8) as u8);
tcp_query.push(query_len as u8);
tcp_query.extend_from_slice(packet);
stream.write_all(&tcp_query)?;
let mut response_len_bytes = [0u8; 2];
stream.read_exact(&mut response_len_bytes)?;
let response_len = ((response_len_bytes[0] as usize) << 8) | (response_len_bytes[1] as usize);
let mut response = vec![0; response_len];
stream.read_exact(&mut response)?;
Ok(response)
}