1pub(crate) mod acl;
2pub(crate) mod address;
3pub(crate) mod nsupdate;
4pub(crate) mod soa;
5pub use bindizr_core::dns::txt;
6pub mod xfr;
7
8use std::{io::ErrorKind, net::SocketAddr, time::Duration};
9
10use acl::SecondaryAcl;
11pub(crate) use bindizr_core::{config, log_error, log_info, log_warn, model};
12pub(crate) use bindizr_service as service;
13use domain::base::iana::Rtype;
14use tokio::{
15 net::{TcpListener, TcpStream, UdpSocket},
16 time::timeout,
17};
18
19const TCP_IDLE_TIMEOUT: Duration = Duration::from_secs(30);
20
21enum QueryRoute {
22 Nsupdate,
23 Soa,
24 Xfr,
25 Other(Rtype),
26}
27
28pub async fn initialize() {
29 xfr::initialize().await;
30
31 let bindizr_config = config::get_bindizr_config();
32 let listen_addr = SocketAddr::new(
33 bindizr_config.dns.listen_addr,
34 bindizr_config.dns.listen_port,
35 );
36
37 let secondary_acl = acl::secondary_acl_from_config();
38 let tcp_secondary_acl = secondary_acl.clone();
39
40 tokio::spawn(async move {
41 if let Err(e) = run_tcp_server(listen_addr, tcp_secondary_acl).await {
42 log_error!("DNS TCP server error: {}", e);
43 }
44 });
45
46 tokio::spawn(async move {
47 if let Err(e) = run_udp_server(listen_addr, secondary_acl).await {
48 log_error!("DNS UDP server error: {}", e);
49 }
50 });
51}
52
53async fn run_tcp_server(
54 listen_addr: SocketAddr,
55 secondary_acl: SecondaryAcl,
56) -> Result<(), String> {
57 let listener = TcpListener::bind(listen_addr)
58 .await
59 .map_err(|e| format!("Failed to bind DNS TCP listener on {}: {}", listen_addr, e))?;
60
61 log_info!("DNS TCP server listening on {}", listen_addr);
62
63 loop {
64 match listener.accept().await {
65 Ok((stream, client_addr)) => {
66 let allowed = secondary_acl.clone();
67 tokio::spawn(async move {
68 if let Err(e) = handle_tcp_connection(stream, client_addr, allowed).await {
69 log_error!("DNS TCP connection error from {}: {}", client_addr, e);
70 }
71 });
72 }
73 Err(e) => {
74 log_error!("Failed to accept DNS TCP connection: {}", e);
75 }
76 }
77 }
78}
79
80async fn handle_tcp_connection(
81 mut stream: TcpStream,
82 client_addr: SocketAddr,
83 secondary_acl: SecondaryAcl,
84) -> Result<(), String> {
85 loop {
86 let query_data = match timeout(TCP_IDLE_TIMEOUT, xfr::wire::read_tcp_message(&mut stream))
87 .await
88 {
89 Ok(Ok(query_data)) => query_data,
90 Ok(Err(xfr::error::XfrError::IoError(e))) if e.kind() == ErrorKind::UnexpectedEof => {
91 break;
92 }
93 Ok(Err(e)) => return Err(format!("Failed to read DNS TCP message: {}", e)),
94 Err(_) => {
95 log_info!(
96 "Closing idle DNS TCP connection from {} after {:?}",
97 client_addr,
98 TCP_IDLE_TIMEOUT
99 );
100 break;
101 }
102 };
103
104 handle_tcp_query(&mut stream, client_addr, &secondary_acl, &query_data).await?;
105 }
106
107 Ok(())
108}
109
110async fn handle_tcp_query(
111 stream: &mut TcpStream,
112 client_addr: SocketAddr,
113 secondary_acl: &SecondaryAcl,
114 query_data: &[u8],
115) -> Result<(), String> {
116 match classify_query_route(query_data) {
117 Ok(QueryRoute::Nsupdate) => {
118 nsupdate::handle_tcp_nsupdate(stream, query_data, client_addr).await?;
119 }
120 Ok(QueryRoute::Soa) => {
121 soa::handle_tcp_soa(stream, client_addr, query_data)
122 .await
123 .map_err(|e| format!("Failed to handle SOA TCP query: {}", e))?;
124 }
125 Ok(QueryRoute::Xfr) => {
126 xfr::handle_tcp_query(stream, client_addr, secondary_acl, query_data)
127 .await
128 .map_err(|e| format!("Failed to handle XFR TCP query: {}", e))?;
129 }
130 Ok(QueryRoute::Other(qtype)) => {
131 log_info!(
132 "Ignoring non-XFR DNS TCP query from {} (qtype={:?})",
133 client_addr,
134 qtype
135 );
136 }
137 Err(e) => {
138 log_warn!("Failed to parse DNS TCP query from {}: {}", client_addr, e);
139 }
140 }
141
142 Ok(())
143}
144
145async fn run_udp_server(
146 listen_addr: SocketAddr,
147 secondary_acl: SecondaryAcl,
148) -> Result<(), String> {
149 let socket = UdpSocket::bind(listen_addr)
150 .await
151 .map_err(|e| format!("Failed to bind DNS UDP socket on {}: {}", listen_addr, e))?;
152
153 log_info!("DNS UDP server listening on {}", listen_addr);
154
155 let mut buf = vec![0u8; 65535];
156
157 loop {
158 let (len, client_addr) = match socket.recv_from(&mut buf).await {
159 Ok(v) => v,
160 Err(e) => {
161 log_error!("Failed to receive DNS UDP packet: {}", e);
162 continue;
163 }
164 };
165
166 let query_data = &buf[..len];
167
168 match classify_query_route(query_data) {
169 Ok(QueryRoute::Nsupdate) => {
170 if let Err(e) =
171 nsupdate::handle_udp_nsupdate(&socket, query_data, client_addr).await
172 {
173 log_error!("NSUPDATE UDP handler failed for {}: {}", client_addr, e);
174 }
175 }
176 Ok(QueryRoute::Soa) => {
177 if let Err(e) = soa::handle_udp_soa(&socket, client_addr, query_data).await {
178 log_warn!("Failed to handle SOA UDP query from {}: {}", client_addr, e);
179 }
180 }
181 Ok(QueryRoute::Xfr) => {
182 if let Err(e) = xfr::handle_udp_query(client_addr, &secondary_acl, query_data).await
183 {
184 log_warn!("Failed to handle XFR UDP query from {}: {}", client_addr, e);
185 }
186 }
187 Ok(QueryRoute::Other(_)) => {}
188 Err(_) => {}
189 }
190 }
191}
192
193fn classify_query_route(query_data: &[u8]) -> Result<QueryRoute, String> {
194 if nsupdate::is_nsupdate(query_data) {
195 return Ok(QueryRoute::Nsupdate);
196 }
197
198 let (_zone_name, qtype, _client_serial, _query_id) =
199 xfr::wire::parse_query(query_data).map_err(|e| e.to_string())?;
200
201 if qtype == Rtype::SOA {
202 Ok(QueryRoute::Soa)
203 } else if xfr::is_xfr_query_type(qtype) {
204 Ok(QueryRoute::Xfr)
205 } else {
206 Ok(QueryRoute::Other(qtype))
207 }
208}