diff options
author | Paul Holzinger <pholzing@redhat.com> | 2024-07-22 20:28:27 +0200 |
---|---|---|
committer | Paul Holzinger <pholzing@redhat.com> | 2024-07-23 12:19:02 +0200 |
commit | 78e0c0eb75e9f8967e94bea15282fbb056335d83 (patch) | |
tree | 522bef3a3b1e8c88bc986aa7e940bf36d160e7c9 | |
parent | 75d37ff559d6e2c9a30990c8aebafbc303ef9839 (diff) |
coredns: move main code out of select!
This removes several layers of nesting and most importantly the
formatter can run on the function which results in much more readable
code.
Signed-off-by: Paul Holzinger <pholzing@redhat.com>
-rw-r--r-- | src/dns/coredns.rs | 290 |
1 files changed, 154 insertions, 136 deletions
diff --git a/src/dns/coredns.rs b/src/dns/coredns.rs index 6062a58..f9e2893 100644 --- a/src/dns/coredns.rs +++ b/src/dns/coredns.rs @@ -18,6 +18,7 @@ use resolv_conf::ScopedIp; use std::convert::TryInto; use std::env; use std::fs::File; +use std::io::Error; use std::io::Read; use std::net::{IpAddr, SocketAddr}; use std::sync::Arc; @@ -110,158 +111,175 @@ impl CoreDns { v = receiver.next() => { let msg_received = match v { Some(value) => value, - _ => { + None => { // None received, nothing to process so continue debug!("None recevied from stream, continue the loop"); continue; } }; - match msg_received { - Ok(msg) => { - let backend = self.backend.load(); - let src_address = msg.addr(); - let mut dns_resolver = self.resolv_conf.clone(); - let sender = sender_original.clone().with_remote_addr(src_address); - let (request_name, record_type, mut req) = match parse_dns_msg(msg) { - Some((name, record_type, req)) => (name, record_type, req), - _ => { - error!("None received while parsing dns message, this is not expected server will ignore this message"); - continue; - } - }; - let request_name_string = request_name.to_string(); - - let mut resolved_ip_list: Vec<IpAddr> = Vec::new(); - let mut nameservers_scoped: Vec<ScopedIp> = Vec::new(); - // Add resolvers configured for container - if let Some(Some(dns_servers)) = backend.ctr_dns_server.get(&src_address.ip()) { - if !dns_servers.is_empty() { - for dns_server in dns_servers.iter() { - nameservers_scoped.push(ScopedIp::from(*dns_server)); - } - } - // Add network scoped resolvers only if container specific resolvers were not configured - } else if let Some(network_dns_servers) = backend.get_network_scoped_resolvers(&src_address.ip()) { - for dns_server in network_dns_servers.iter() { - nameservers_scoped.push(ScopedIp::from(*dns_server)); - } - } - // Override host resolvers with custom resolvers if any were - // configured for container or network. - if !nameservers_scoped.is_empty() { - dns_resolver = resolv_conf::Config::new(); - dns_resolver.nameservers = nameservers_scoped; - } + self.process_message(msg_received, &sender_original, no_proxy); + }, + } + } + Ok(()) + } - // Create debug and trace info for key parameters. - trace!("server name: {:?}", self.name.to_ascii()); - debug!("request source address: {:?}", src_address); - trace!("requested record type: {:?}", record_type); - debug!("checking if backend has entry for: {:?}", &request_name_string); - trace!( - "server backend.name_mappings: {:?}", - backend.name_mappings - ); - trace!("server backend.ip_mappings: {:?}", backend.ip_mappings); - - - // if record type is PTR try resolving early and return if record found - if record_type == RecordType::PTR { - if let Some(msg) = reply_ptr(&request_name_string, &backend, src_address, &req) { - reply(sender, src_address, &msg); - continue; - } - } + fn process_message( + &self, + msg_received: Result<SerialMessage, Error>, + sender_original: &BufDnsStreamHandle, + no_proxy: bool, + ) { + match msg_received { + Ok(msg) => { + let backend = self.backend.load(); + let src_address = msg.addr(); + let mut dns_resolver = self.resolv_conf.clone(); + let sender = sender_original.with_remote_addr(src_address); + let (request_name, record_type, mut req) = match parse_dns_msg(msg) { + Some((name, record_type, req)) => (name, record_type, req), + _ => { + error!("None received while parsing dns message, this is not expected server will ignore this message"); + return; + } + }; + let request_name_string = request_name.to_string(); + + let mut resolved_ip_list: Vec<IpAddr> = Vec::new(); + let mut nameservers_scoped: Vec<ScopedIp> = Vec::new(); + // Add resolvers configured for container + if let Some(Some(dns_servers)) = backend.ctr_dns_server.get(&src_address.ip()) { + if !dns_servers.is_empty() { + for dns_server in dns_servers.iter() { + nameservers_scoped.push(ScopedIp::from(*dns_server)); + } + } + // Add network scoped resolvers only if container specific resolvers were not configured + } else if let Some(network_dns_servers) = + backend.get_network_scoped_resolvers(&src_address.ip()) + { + for dns_server in network_dns_servers.iter() { + nameservers_scoped.push(ScopedIp::from(*dns_server)); + } + } + // Override host resolvers with custom resolvers if any were + // configured for container or network. + if !nameservers_scoped.is_empty() { + dns_resolver = resolv_conf::Config::new(); + dns_resolver.nameservers = nameservers_scoped; + } - // attempt intra network resolution - match backend.lookup(&src_address.ip(), &request_name_string) { - // If we go success from backend lookup - DNSResult::Success(_ip_vec) => { - debug!("Found backend lookup"); - resolved_ip_list = _ip_vec; + // Create debug and trace info for key parameters. + trace!("server name: {:?}", self.name.to_ascii()); + debug!("request source address: {:?}", src_address); + trace!("requested record type: {:?}", record_type); + debug!( + "checking if backend has entry for: {:?}", + &request_name_string + ); + trace!("server backend.name_mappings: {:?}", backend.name_mappings); + trace!("server backend.ip_mappings: {:?}", backend.ip_mappings); + + // if record type is PTR try resolving early and return if record found + if record_type == RecordType::PTR { + if let Some(msg) = reply_ptr(&request_name_string, &backend, src_address, &req) + { + reply(sender, src_address, &msg); + return; + } + } - } - // For everything else assume the src_address was not in ip_mappings - _ => { - debug!("No backend lookup found, try resolving in current resolvers entry"); - if let Some(container_mappings) = backend.name_mappings.get(&self.network_name) { - if let Some(ips) = container_mappings.get(&request_name_string) { - resolved_ip_list.clone_from(ips); - } - } - } + // attempt intra network resolution + match backend.lookup(&src_address.ip(), &request_name_string) { + // If we go success from backend lookup + DNSResult::Success(_ip_vec) => { + debug!("Found backend lookup"); + resolved_ip_list = _ip_vec; + } + // For everything else assume the src_address was not in ip_mappings + _ => { + debug!("No backend lookup found, try resolving in current resolvers entry"); + if let Some(container_mappings) = + backend.name_mappings.get(&self.network_name) + { + if let Some(ips) = container_mappings.get(&request_name_string) { + resolved_ip_list.clone_from(ips); } - if !resolved_ip_list.is_empty() { - if record_type == RecordType::A { - for record_addr in resolved_ip_list { - if let IpAddr::V4(ipv4) = record_addr { - req.add_answer( - Record::new() - .set_name(request_name.clone()) - .set_ttl(CONTAINER_TTL) - .set_rr_type(RecordType::A) - .set_dns_class(DNSClass::IN) - .set_data(Some(RData::A(rdata::A(ipv4)))) - .clone(), - ); - } - } - } else if record_type == RecordType::AAAA { - for record_addr in resolved_ip_list { - if let IpAddr::V6(ipv6) = record_addr { - req.add_answer( - Record::new() - .set_name(request_name.clone()) - .set_ttl(CONTAINER_TTL) - .set_rr_type(RecordType::AAAA) - .set_dns_class(DNSClass::IN) - .set_data(Some(RData::AAAA(rdata::AAAA(ipv6)))) - .clone(), - ); + } + } + } + if !resolved_ip_list.is_empty() { + if record_type == RecordType::A { + for record_addr in resolved_ip_list { + if let IpAddr::V4(ipv4) = record_addr { + req.add_answer( + Record::new() + .set_name(request_name.clone()) + .set_ttl(CONTAINER_TTL) + .set_rr_type(RecordType::A) + .set_dns_class(DNSClass::IN) + .set_data(Some(RData::A(rdata::A(ipv4)))) + .clone(), + ); + } + } + } else if record_type == RecordType::AAAA { + for record_addr in resolved_ip_list { + if let IpAddr::V6(ipv6) = record_addr { + req.add_answer( + Record::new() + .set_name(request_name.clone()) + .set_ttl(CONTAINER_TTL) + .set_rr_type(RecordType::AAAA) + .set_dns_class(DNSClass::IN) + .set_data(Some(RData::AAAA(rdata::AAAA(ipv6)))) + .clone(), + ); + } + } + } + reply(sender, src_address, &req); + } else { + debug!( + "Not found, forwarding dns request for {:?}", + &request_name_string + ); + if no_proxy + || backend.ctr_is_internal(&src_address.ip()) + || request_name_string.ends_with(&backend.search_domain) + || request_name_string.matches('.').count() == 1 + { + let mut nx_message = req.clone(); + nx_message.set_response_code(ResponseCode::NXDomain); + reply(sender.clone(), src_address, &nx_message); + } else { + let nameservers = dns_resolver.nameservers.clone(); + tokio::spawn(async move { + // forward dns request to hosts's /etc/resolv.conf + for nameserver in nameservers { + let connection = UdpClientStream::<UdpSocket>::new( + SocketAddr::new(nameserver.into(), 53), + ); + + if let Ok((cl, req_sender)) = AsyncClient::connect(connection).await + { + tokio::spawn(req_sender); + if let Some(resp) = forward_dns_req(cl, req.clone()).await { + if reply(sender.clone(), src_address, &resp).is_some() { + // request resolved from following resolver so + // break and don't try other resolvers + break; } } } - reply(sender, src_address, &req); - } else { - debug!("Not found, forwarding dns request for {:?}", &request_name_string); - if no_proxy || backend.ctr_is_internal(&src_address.ip()) || - request_name_string.ends_with(&backend.search_domain) || request_name_string.matches('.').count() == 1 { - let mut nx_message = req.clone(); - nx_message.set_response_code(ResponseCode::NXDomain); - reply(sender.clone(), src_address, &nx_message); - } else { - let nameservers = dns_resolver.nameservers.clone(); - tokio::spawn(async move { - // forward dns request to hosts's /etc/resolv.conf - for nameserver in nameservers { - let connection = UdpClientStream::<UdpSocket>::new(SocketAddr::new( - nameserver.into(), - 53, - )); - - if let Ok((cl, req_sender)) = AsyncClient::connect(connection).await { - tokio::spawn(req_sender); - if let Some(resp) = forward_dns_req(cl, req.clone()).await { - if reply(sender.clone(), src_address, &resp).is_some() { - // request resolved from following resolver so - // break and don't try other resolvers - break; - } - } - } - } - }); - } } - } - - Err(e) => error!("Error parsing dns message {:?}", e), + }); } - }, + } } - } - Ok(()) //TODO: My IDE sees this as unreachable code. Fix when refactoring + Err(e) => error!("Error parsing dns message {:?}", e), + } } } |