Loading Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,10 @@ aidl_interface { cc_defaults { name: "resolv_test_defaults", cflags: [ // networkCreatePhysical and networkCreateVpn were deprecated from netd_aidl_interface v6. "-Wno-error=deprecated-declarations", ], // Note that, static link liblog and libbase is a hard requirement for resolv related tests // because libbase is not compatible between Q and R for general platform build due // to its log revelant functions changing. And most of resolv related tests must be able to run Loading doh.rs +44 −27 Original line number Diff line number Diff line Loading @@ -53,7 +53,6 @@ const MAX_INCOMING_BUFFER_SIZE_WHOLE: u64 = 10000000; const MAX_INCOMING_BUFFER_SIZE_EACH: u64 = 1000000; const MAX_CONCURRENT_STREAM_SIZE: u64 = 100; const MAX_DATAGRAM_SIZE: usize = 1350; const MAX_DATAGRAM_SIZE_U64: u64 = 1350; const DOH_PORT: u16 = 443; const QUICHE_IDLE_TIMEOUT_MS: u64 = 180000; const SYSTEM_CERT_PATH: &str = "/system/etc/security/cacerts"; Loading @@ -78,19 +77,19 @@ pub struct DohDispatcher { join_handle: task::JoinHandle<Result<()>>, } fn make_doh_udp_socket(ip_addr: &str, mark: u32) -> Result<std::net::UdpSocket> { let sock_addr = SocketAddr::new(IpAddr::from_str(&ip_addr)?, DOH_PORT); let bind_addr = match sock_addr { fn make_doh_udp_socket(ip_addr: &str, mark: u32) -> Result<(SocketAddr, std::net::UdpSocket)> { let peer_addr = SocketAddr::new(IpAddr::from_str(&ip_addr)?, DOH_PORT); let bind_addr = match peer_addr { std::net::SocketAddr::V4(_) => "0.0.0.0:0", std::net::SocketAddr::V6(_) => "[::]:0", }; let udp_sk = std::net::UdpSocket::bind(bind_addr)?; udp_sk.set_nonblocking(true)?; mark_socket(udp_sk.as_raw_fd(), mark)?; udp_sk.connect(sock_addr)?; udp_sk.connect(peer_addr)?; debug!("connecting to {:} from {:}", sock_addr, udp_sk.local_addr()?); Ok(udp_sk) debug!("connecting to {:} from {:}", peer_addr, udp_sk.local_addr()?); Ok((peer_addr, udp_sk)) } // DoH dispatcher Loading @@ -102,13 +101,14 @@ impl DohDispatcher { cert_path: Option<&str>, ) -> Result<Box<DohDispatcher>> { // Setup socket let udp_sk = make_doh_udp_socket(&ip_addr, mark)?; DohDispatcher::new_with_socket(url, ip_addr, mark, cert_path, udp_sk) let (peer_addr, udp_sk) = make_doh_udp_socket(&ip_addr, mark)?; DohDispatcher::new_with_socket(url, ip_addr, peer_addr, mark, cert_path, udp_sk) } fn new_with_socket( url: &str, ip_addr: &str, peer_addr: SocketAddr, mark: u32, cert_path: Option<&str>, udp_sk: std::net::UdpSocket, Loading @@ -128,8 +128,15 @@ impl DohDispatcher { "Creating a doh handler task: url={}, ip_addr={}, mark={:#x}, scid {:x?}", url, ip_addr, mark, &scid ); let join_handle = RUNTIME_STATIC.spawn(doh_handler(url, udp_sk, config, h3_config, scid, cmd_receiver)); let join_handle = RUNTIME_STATIC.spawn(doh_handler( url, peer_addr, udp_sk, config, h3_config, scid, cmd_receiver, )); Ok(Box::new(DohDispatcher { query_sender: cmd_sender, join_handle })) } Loading @@ -145,6 +152,7 @@ impl DohDispatcher { async fn doh_handler( url: url::Url, peer_addr: SocketAddr, udp_sk: std::net::UdpSocket, mut config: quiche::Config, h3_config: h3::Config, Loading @@ -153,8 +161,10 @@ async fn doh_handler( ) -> Result<()> { debug!("doh_handler: url={:?}", url); let connid = quiche::ConnectionId::from_ref(&scid); let sk = UdpSocket::from_std(udp_sk)?; let mut conn = quiche::connect(url.domain(), &scid, &mut config)?; let mut conn = quiche::connect(url.domain(), &connid, peer_addr, &mut config)?; let recv_info = quiche::RecvInfo { from: peer_addr }; let mut quic_conn_start = std::time::Instant::now(); let mut h3_conn: Option<h3::Connection> = None; let mut is_idle = false; Loading @@ -170,7 +180,7 @@ async fn doh_handler( debug!("recv {:?} ", size); match size { Ok(size) => { let processed = match conn.recv(&mut buf[..size]) { let processed = match conn.recv(&mut buf[..size], recv_info) { Ok(l) => l, Err(e) => { error!("quic recv failed: {:?}", e); Loading Loading @@ -207,7 +217,7 @@ async fn doh_handler( // If there is any pending query, resume the quic connection. if !pending_cmds.is_empty() { info!("still some pending queries but connection is not avaiable, resume it"); conn = quiche::connect(url.domain(), &scid, &mut config)?; conn = quiche::connect(url.domain(), &connid, peer_addr, &mut config)?; quic_conn_start = std::time::Instant::now(); h3_conn = None; is_idle = false; Loading Loading @@ -264,15 +274,15 @@ fn send_dns_query( path.push_str("?dns="); path.push_str(std::str::from_utf8(&query)?); let _req = vec![ quiche::h3::Header::new(":method", "GET"), quiche::h3::Header::new(":scheme", "https"), quiche::h3::Header::new(b":method", b"GET"), quiche::h3::Header::new(b":scheme", b"https"), quiche::h3::Header::new( ":authority", url.host_str().ok_or_else(|| anyhow!("failed to get host"))?, b":authority", url.host_str().ok_or_else(|| anyhow!("failed to get host"))?.as_bytes(), ), quiche::h3::Header::new(":path", &path), quiche::h3::Header::new("user-agent", "quiche"), quiche::h3::Header::new("accept", "application/dns-message"), quiche::h3::Header::new(b":path", path.as_bytes()), quiche::h3::Header::new(b"user-agent", b"quiche"), quiche::h3::Header::new(b"accept", b"application/dns-message"), // TODO: is content-length required? ]; Loading Loading @@ -334,7 +344,7 @@ async fn recv_query( async fn flush_tx(sk: &UdpSocket, conn: &mut quiche::Connection) -> Result<()> { let mut out = [0; MAX_DATAGRAM_SIZE]; loop { let write = match conn.send(&mut out) { let (write, _) = match conn.send(&mut out) { Ok(v) => v, Err(quiche::Error::Done) => { debug!("done writing"); Loading @@ -358,7 +368,7 @@ fn create_quiche_config(cert_path: Option<&str>) -> Result<quiche::Config> { config.load_verify_locations_from_directory(cert_path.unwrap_or(SYSTEM_CERT_PATH))?; // Some of these configs are necessary, or the server can't respond the HTTP/3 request. config.set_max_idle_timeout(QUICHE_IDLE_TIMEOUT_MS); config.set_max_udp_payload_size(MAX_DATAGRAM_SIZE_U64); config.set_max_recv_udp_payload_size(MAX_DATAGRAM_SIZE); config.set_initial_max_data(MAX_INCOMING_BUFFER_SIZE_WHOLE); config.set_initial_max_stream_data_bidi_local(MAX_INCOMING_BUFFER_SIZE_EACH); config.set_initial_max_stream_data_bidi_remote(MAX_INCOMING_BUFFER_SIZE_EACH); Loading Loading @@ -516,7 +526,7 @@ mod tests { assert!(super::make_doh_udp_socket(ip, 0).is_err(), "udp socket should not be created"); } // Make a socket connecting to loopback with a test mark. let sk = super::make_doh_udp_socket(LOOPBACK_ADDR, TEST_MARK).unwrap(); let (_, sk) = super::make_doh_udp_socket(LOOPBACK_ADDR, TEST_MARK).unwrap(); // Check if the socket is connected to loopback. assert_eq!( sk.peer_addr().unwrap(), Loading Loading @@ -568,9 +578,16 @@ mod tests { const SAMPLE_QUERY: &str = "q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB"; #[test] fn close_doh() { let udp_sk = super::make_doh_udp_socket(LOOPBACK_ADDR, TEST_MARK).unwrap(); let doh = DohDispatcher::new_with_socket(GOOGLE_DNS_URL, GOOGLE_DNS_IP, 0, None, udp_sk).unwrap(); let (peer_socket, udp_sk) = super::make_doh_udp_socket(LOOPBACK_ADDR, TEST_MARK).unwrap(); let doh = DohDispatcher::new_with_socket( GOOGLE_DNS_URL, GOOGLE_DNS_IP, peer_socket, 0, None, udp_sk, ) .unwrap(); let (resp_tx, resp_rx) = oneshot::channel(); let cmd = Command::DohQuery { query: SAMPLE_QUERY.as_bytes().to_vec(), resp: resp_tx }; assert!(doh.query(cmd).is_ok(), "Send query failed"); Loading gethnamaddr.cpp +16 −57 Original line number Diff line number Diff line Loading @@ -82,16 +82,6 @@ using android::net::NetworkDnsEventReported; // NetBSD uses _DIAGASSERT to null-check arguments and the like, // but it's clear from the number of mistakes in their assertions // that they don't actually test or ship with this. #define _DIAGASSERT(e) /* nothing */ // TODO: unify macro ALIGNBYTES and ALIGN for all possible data type alignment of hostent // buffer. #define ALIGNBYTES (sizeof(uintptr_t) - 1) #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES) constexpr int MAXADDRS = 35; typedef union { Loading @@ -99,16 +89,7 @@ typedef union { uint8_t buf[MAXPACKET]; } querybuf; typedef union { int32_t al; char ac; } align; static void convert_v4v6_hostent(struct hostent* hp, char** bpp, char* ep, const std::function<void(struct hostent* hp)>& mapping_param, const std::function<void(char* src, char* dst)>& mapping_addr); static void pad_v4v6_hostent(struct hostent* hp, char** bpp, char* ep); static int dns_gethtbyaddr(const unsigned char* uaddr, int len, int af, const android_net_context* netcontext, getnamaddr* info, NetworkDnsEventReported* event); Loading @@ -125,8 +106,9 @@ static int dns_gethtbyname(ResState* res, const char* name, int af, getnamaddr* if (eom - (ptr) < (count)) goto no_recovery; \ } while (0) static struct hostent* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype, struct hostent* hent, char* buf, size_t buflen, int* he) { static struct hostent* getanswer(const querybuf* _Nonnull answer, int anslen, const char* _Nonnull qname, int qtype, struct hostent* hent, char* buf, size_t buflen, int* he) { const HEADER* hp; const uint8_t* cp; int n; Loading @@ -141,9 +123,6 @@ static struct hostent* getanswer(const querybuf* answer, int anslen, const char* const char* tname; std::vector<char*> aliases; _DIAGASSERT(answer != NULL); _DIAGASSERT(qname != NULL); tname = qname; hent->h_name = NULL; eom = answer->buf + anslen; Loading Loading @@ -324,7 +303,7 @@ static struct hostent* getanswer(const querybuf* answer, int anslen, const char* bp += nn; } bp += sizeof(align) - (size_t)((uintptr_t)bp % sizeof(align)); bp = align_ptr<sizeof(int32_t)>(bp); if (bp + n >= ep) { LOG(DEBUG) << __func__ << ": size (" << n << ") too big"; Loading Loading @@ -364,7 +343,7 @@ no_recovery: *he = NO_RECOVERY; return NULL; success: bp = (char*) ALIGN(bp); bp = align_ptr(bp); aliases.push_back(nullptr); qlen = aliases.size() * sizeof(*hent->h_aliases); if ((size_t)(ep - bp) < qlen) goto nospc; Loading Loading @@ -474,15 +453,13 @@ fake: return 0; } int resolv_gethostbyaddr(const void* addr, socklen_t len, int af, hostent* hp, char* buf, int resolv_gethostbyaddr(const void* _Nonnull addr, socklen_t len, int af, hostent* hp, char* buf, size_t buflen, const struct android_net_context* netcontext, hostent** result, NetworkDnsEventReported* event) { const uint8_t* uaddr = (const uint8_t*)addr; socklen_t size; struct getnamaddr info; _DIAGASSERT(addr != NULL); if (af == AF_INET6 && len == NS_IN6ADDRSZ && (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr*) addr) || IN6_IS_ADDR_SITELOCAL((const struct in6_addr*) addr))) { Loading Loading @@ -614,42 +591,24 @@ nospc: return NULL; } static void convert_v4v6_hostent(struct hostent* hp, char** bpp, char* ep, const std::function<void(struct hostent* hp)>& map_param, const std::function<void(char* src, char* dst)>& map_addr) { _DIAGASSERT(hp != NULL); _DIAGASSERT(bpp != NULL); _DIAGASSERT(ep != NULL); /* Reserve space for mapping IPv4 address to IPv6 address in place */ static void pad_v4v6_hostent(struct hostent* _Nonnull hp, char** _Nonnull bpp, char* _Nonnull ep) { if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ) return; map_param(hp); for (char** ap = hp->h_addr_list; *ap; ap++) { int i = (int)(sizeof(align) - (size_t)((uintptr_t)*bpp % sizeof(align))); char* const bp = align_ptr<sizeof(int32_t)>(*bpp); if (ep - *bpp < (i + NS_IN6ADDRSZ)) { /* Out of memory. Truncate address list here. XXX */ *ap = NULL; if (ep - bp < NS_IN6ADDRSZ) { // Out of space. Truncate address list here. *ap = nullptr; return; } *bpp += i; map_addr(*ap, *bpp); *ap = *bpp; *bpp += NS_IN6ADDRSZ; memcpy(bp, *ap, NS_INADDRSZ); memcpy(bp + NS_INADDRSZ, NAT64_PAD, sizeof(NAT64_PAD)); *ap = bp; *bpp = bp + NS_IN6ADDRSZ; } } /* Reserve space for mapping IPv4 address to IPv6 address in place */ static void pad_v4v6_hostent(struct hostent* hp, char** bpp, char* ep) { convert_v4v6_hostent(hp, bpp, ep, [](struct hostent* hp) { (void) hp; /* unused */ }, [](char* src, char* dst) { memcpy(dst, src, NS_INADDRSZ); memcpy(dst + NS_INADDRSZ, NAT64_PAD, sizeof(NAT64_PAD)); }); } static int dns_gethtbyname(ResState* res, const char* name, int addr_type, getnamaddr* info) { int n, type; info->hp->h_addrtype = addr_type; Loading resolv_private.h +27 −0 Original line number Diff line number Diff line Loading @@ -194,6 +194,33 @@ Dest saturate_cast(int64_t x) { return static_cast<Dest>(x); } constexpr bool is_power_of_2(size_t n) { return n != 0 && (n & (n - 1)) == 0; } // Rounds up a pointer to a char buffer |p| to a multiple of |Alignment| bytes. // Requirements: // |p| must be a pointer to a byte-sized type (e.g.: uint8_t) // |Alignment| must be a power of 2 template<uintptr_t Alignment = sizeof(void*), typename T> requires (sizeof(T) == 1) && (is_power_of_2(Alignment)) constexpr T* align_ptr(T* const p) { // Written this way to sidestep the performance-no-int-to-ptr clang-tidy warning. constexpr uintptr_t mask = Alignment - 1; const uintptr_t uintptr = reinterpret_cast<uintptr_t>(p); const uintptr_t aligned = (uintptr + mask) & ~mask; const uintptr_t bias = aligned - uintptr; return p + bias; } // Testcases for align_ptr() // TODO: enable when libc++ has std::bit_cast - reinterpret_cast isn't allowed in consteval context // static_assert(align_ptr((char*)1000) == (char*)1000); // static_assert(align_ptr((char*)1001) == (char*)1000 + sizeof(void*)); // static_assert(align_ptr((char*)1003) == (char*)1000 + sizeof(void*)); // static_assert(align_ptr<sizeof(uint32_t)>((char*)1004) == (char*)1004); // static_assert(align_ptr<sizeof(uint64_t)>((char*)1004) == (char*)1008); android::net::NsType getQueryType(const uint8_t* msg, size_t msgLen); android::net::IpVersion ipFamilyToIPVersion(int ipFamily); Loading sethostent.cpp +1 −4 Original line number Diff line number Diff line Loading @@ -46,9 +46,6 @@ constexpr int MAXALIASES = 35; constexpr int MAXADDRS = 35; #define ALIGNBYTES (sizeof(uintptr_t) - 1) #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES) static void sethostent_r(FILE** hf) { if (!*hf) *hf = fopen(_PATH_HOSTS, "re"); Loading Loading @@ -121,7 +118,7 @@ int _hf_gethtbyname2(const char* name, int af, getnamaddr* info) { if (anum >= MAXALIASES) goto nospc; HENT_SCOPY(aliases[anum], hp->h_aliases[anum], ptr, len); } ptr = (char*) ALIGN(ptr); ptr = align_ptr(ptr); if ((size_t)(ptr - buf) >= info->buflen) goto nospc; } Loading Loading
Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,10 @@ aidl_interface { cc_defaults { name: "resolv_test_defaults", cflags: [ // networkCreatePhysical and networkCreateVpn were deprecated from netd_aidl_interface v6. "-Wno-error=deprecated-declarations", ], // Note that, static link liblog and libbase is a hard requirement for resolv related tests // because libbase is not compatible between Q and R for general platform build due // to its log revelant functions changing. And most of resolv related tests must be able to run Loading
doh.rs +44 −27 Original line number Diff line number Diff line Loading @@ -53,7 +53,6 @@ const MAX_INCOMING_BUFFER_SIZE_WHOLE: u64 = 10000000; const MAX_INCOMING_BUFFER_SIZE_EACH: u64 = 1000000; const MAX_CONCURRENT_STREAM_SIZE: u64 = 100; const MAX_DATAGRAM_SIZE: usize = 1350; const MAX_DATAGRAM_SIZE_U64: u64 = 1350; const DOH_PORT: u16 = 443; const QUICHE_IDLE_TIMEOUT_MS: u64 = 180000; const SYSTEM_CERT_PATH: &str = "/system/etc/security/cacerts"; Loading @@ -78,19 +77,19 @@ pub struct DohDispatcher { join_handle: task::JoinHandle<Result<()>>, } fn make_doh_udp_socket(ip_addr: &str, mark: u32) -> Result<std::net::UdpSocket> { let sock_addr = SocketAddr::new(IpAddr::from_str(&ip_addr)?, DOH_PORT); let bind_addr = match sock_addr { fn make_doh_udp_socket(ip_addr: &str, mark: u32) -> Result<(SocketAddr, std::net::UdpSocket)> { let peer_addr = SocketAddr::new(IpAddr::from_str(&ip_addr)?, DOH_PORT); let bind_addr = match peer_addr { std::net::SocketAddr::V4(_) => "0.0.0.0:0", std::net::SocketAddr::V6(_) => "[::]:0", }; let udp_sk = std::net::UdpSocket::bind(bind_addr)?; udp_sk.set_nonblocking(true)?; mark_socket(udp_sk.as_raw_fd(), mark)?; udp_sk.connect(sock_addr)?; udp_sk.connect(peer_addr)?; debug!("connecting to {:} from {:}", sock_addr, udp_sk.local_addr()?); Ok(udp_sk) debug!("connecting to {:} from {:}", peer_addr, udp_sk.local_addr()?); Ok((peer_addr, udp_sk)) } // DoH dispatcher Loading @@ -102,13 +101,14 @@ impl DohDispatcher { cert_path: Option<&str>, ) -> Result<Box<DohDispatcher>> { // Setup socket let udp_sk = make_doh_udp_socket(&ip_addr, mark)?; DohDispatcher::new_with_socket(url, ip_addr, mark, cert_path, udp_sk) let (peer_addr, udp_sk) = make_doh_udp_socket(&ip_addr, mark)?; DohDispatcher::new_with_socket(url, ip_addr, peer_addr, mark, cert_path, udp_sk) } fn new_with_socket( url: &str, ip_addr: &str, peer_addr: SocketAddr, mark: u32, cert_path: Option<&str>, udp_sk: std::net::UdpSocket, Loading @@ -128,8 +128,15 @@ impl DohDispatcher { "Creating a doh handler task: url={}, ip_addr={}, mark={:#x}, scid {:x?}", url, ip_addr, mark, &scid ); let join_handle = RUNTIME_STATIC.spawn(doh_handler(url, udp_sk, config, h3_config, scid, cmd_receiver)); let join_handle = RUNTIME_STATIC.spawn(doh_handler( url, peer_addr, udp_sk, config, h3_config, scid, cmd_receiver, )); Ok(Box::new(DohDispatcher { query_sender: cmd_sender, join_handle })) } Loading @@ -145,6 +152,7 @@ impl DohDispatcher { async fn doh_handler( url: url::Url, peer_addr: SocketAddr, udp_sk: std::net::UdpSocket, mut config: quiche::Config, h3_config: h3::Config, Loading @@ -153,8 +161,10 @@ async fn doh_handler( ) -> Result<()> { debug!("doh_handler: url={:?}", url); let connid = quiche::ConnectionId::from_ref(&scid); let sk = UdpSocket::from_std(udp_sk)?; let mut conn = quiche::connect(url.domain(), &scid, &mut config)?; let mut conn = quiche::connect(url.domain(), &connid, peer_addr, &mut config)?; let recv_info = quiche::RecvInfo { from: peer_addr }; let mut quic_conn_start = std::time::Instant::now(); let mut h3_conn: Option<h3::Connection> = None; let mut is_idle = false; Loading @@ -170,7 +180,7 @@ async fn doh_handler( debug!("recv {:?} ", size); match size { Ok(size) => { let processed = match conn.recv(&mut buf[..size]) { let processed = match conn.recv(&mut buf[..size], recv_info) { Ok(l) => l, Err(e) => { error!("quic recv failed: {:?}", e); Loading Loading @@ -207,7 +217,7 @@ async fn doh_handler( // If there is any pending query, resume the quic connection. if !pending_cmds.is_empty() { info!("still some pending queries but connection is not avaiable, resume it"); conn = quiche::connect(url.domain(), &scid, &mut config)?; conn = quiche::connect(url.domain(), &connid, peer_addr, &mut config)?; quic_conn_start = std::time::Instant::now(); h3_conn = None; is_idle = false; Loading Loading @@ -264,15 +274,15 @@ fn send_dns_query( path.push_str("?dns="); path.push_str(std::str::from_utf8(&query)?); let _req = vec![ quiche::h3::Header::new(":method", "GET"), quiche::h3::Header::new(":scheme", "https"), quiche::h3::Header::new(b":method", b"GET"), quiche::h3::Header::new(b":scheme", b"https"), quiche::h3::Header::new( ":authority", url.host_str().ok_or_else(|| anyhow!("failed to get host"))?, b":authority", url.host_str().ok_or_else(|| anyhow!("failed to get host"))?.as_bytes(), ), quiche::h3::Header::new(":path", &path), quiche::h3::Header::new("user-agent", "quiche"), quiche::h3::Header::new("accept", "application/dns-message"), quiche::h3::Header::new(b":path", path.as_bytes()), quiche::h3::Header::new(b"user-agent", b"quiche"), quiche::h3::Header::new(b"accept", b"application/dns-message"), // TODO: is content-length required? ]; Loading Loading @@ -334,7 +344,7 @@ async fn recv_query( async fn flush_tx(sk: &UdpSocket, conn: &mut quiche::Connection) -> Result<()> { let mut out = [0; MAX_DATAGRAM_SIZE]; loop { let write = match conn.send(&mut out) { let (write, _) = match conn.send(&mut out) { Ok(v) => v, Err(quiche::Error::Done) => { debug!("done writing"); Loading @@ -358,7 +368,7 @@ fn create_quiche_config(cert_path: Option<&str>) -> Result<quiche::Config> { config.load_verify_locations_from_directory(cert_path.unwrap_or(SYSTEM_CERT_PATH))?; // Some of these configs are necessary, or the server can't respond the HTTP/3 request. config.set_max_idle_timeout(QUICHE_IDLE_TIMEOUT_MS); config.set_max_udp_payload_size(MAX_DATAGRAM_SIZE_U64); config.set_max_recv_udp_payload_size(MAX_DATAGRAM_SIZE); config.set_initial_max_data(MAX_INCOMING_BUFFER_SIZE_WHOLE); config.set_initial_max_stream_data_bidi_local(MAX_INCOMING_BUFFER_SIZE_EACH); config.set_initial_max_stream_data_bidi_remote(MAX_INCOMING_BUFFER_SIZE_EACH); Loading Loading @@ -516,7 +526,7 @@ mod tests { assert!(super::make_doh_udp_socket(ip, 0).is_err(), "udp socket should not be created"); } // Make a socket connecting to loopback with a test mark. let sk = super::make_doh_udp_socket(LOOPBACK_ADDR, TEST_MARK).unwrap(); let (_, sk) = super::make_doh_udp_socket(LOOPBACK_ADDR, TEST_MARK).unwrap(); // Check if the socket is connected to loopback. assert_eq!( sk.peer_addr().unwrap(), Loading Loading @@ -568,9 +578,16 @@ mod tests { const SAMPLE_QUERY: &str = "q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB"; #[test] fn close_doh() { let udp_sk = super::make_doh_udp_socket(LOOPBACK_ADDR, TEST_MARK).unwrap(); let doh = DohDispatcher::new_with_socket(GOOGLE_DNS_URL, GOOGLE_DNS_IP, 0, None, udp_sk).unwrap(); let (peer_socket, udp_sk) = super::make_doh_udp_socket(LOOPBACK_ADDR, TEST_MARK).unwrap(); let doh = DohDispatcher::new_with_socket( GOOGLE_DNS_URL, GOOGLE_DNS_IP, peer_socket, 0, None, udp_sk, ) .unwrap(); let (resp_tx, resp_rx) = oneshot::channel(); let cmd = Command::DohQuery { query: SAMPLE_QUERY.as_bytes().to_vec(), resp: resp_tx }; assert!(doh.query(cmd).is_ok(), "Send query failed"); Loading
gethnamaddr.cpp +16 −57 Original line number Diff line number Diff line Loading @@ -82,16 +82,6 @@ using android::net::NetworkDnsEventReported; // NetBSD uses _DIAGASSERT to null-check arguments and the like, // but it's clear from the number of mistakes in their assertions // that they don't actually test or ship with this. #define _DIAGASSERT(e) /* nothing */ // TODO: unify macro ALIGNBYTES and ALIGN for all possible data type alignment of hostent // buffer. #define ALIGNBYTES (sizeof(uintptr_t) - 1) #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES) constexpr int MAXADDRS = 35; typedef union { Loading @@ -99,16 +89,7 @@ typedef union { uint8_t buf[MAXPACKET]; } querybuf; typedef union { int32_t al; char ac; } align; static void convert_v4v6_hostent(struct hostent* hp, char** bpp, char* ep, const std::function<void(struct hostent* hp)>& mapping_param, const std::function<void(char* src, char* dst)>& mapping_addr); static void pad_v4v6_hostent(struct hostent* hp, char** bpp, char* ep); static int dns_gethtbyaddr(const unsigned char* uaddr, int len, int af, const android_net_context* netcontext, getnamaddr* info, NetworkDnsEventReported* event); Loading @@ -125,8 +106,9 @@ static int dns_gethtbyname(ResState* res, const char* name, int af, getnamaddr* if (eom - (ptr) < (count)) goto no_recovery; \ } while (0) static struct hostent* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype, struct hostent* hent, char* buf, size_t buflen, int* he) { static struct hostent* getanswer(const querybuf* _Nonnull answer, int anslen, const char* _Nonnull qname, int qtype, struct hostent* hent, char* buf, size_t buflen, int* he) { const HEADER* hp; const uint8_t* cp; int n; Loading @@ -141,9 +123,6 @@ static struct hostent* getanswer(const querybuf* answer, int anslen, const char* const char* tname; std::vector<char*> aliases; _DIAGASSERT(answer != NULL); _DIAGASSERT(qname != NULL); tname = qname; hent->h_name = NULL; eom = answer->buf + anslen; Loading Loading @@ -324,7 +303,7 @@ static struct hostent* getanswer(const querybuf* answer, int anslen, const char* bp += nn; } bp += sizeof(align) - (size_t)((uintptr_t)bp % sizeof(align)); bp = align_ptr<sizeof(int32_t)>(bp); if (bp + n >= ep) { LOG(DEBUG) << __func__ << ": size (" << n << ") too big"; Loading Loading @@ -364,7 +343,7 @@ no_recovery: *he = NO_RECOVERY; return NULL; success: bp = (char*) ALIGN(bp); bp = align_ptr(bp); aliases.push_back(nullptr); qlen = aliases.size() * sizeof(*hent->h_aliases); if ((size_t)(ep - bp) < qlen) goto nospc; Loading Loading @@ -474,15 +453,13 @@ fake: return 0; } int resolv_gethostbyaddr(const void* addr, socklen_t len, int af, hostent* hp, char* buf, int resolv_gethostbyaddr(const void* _Nonnull addr, socklen_t len, int af, hostent* hp, char* buf, size_t buflen, const struct android_net_context* netcontext, hostent** result, NetworkDnsEventReported* event) { const uint8_t* uaddr = (const uint8_t*)addr; socklen_t size; struct getnamaddr info; _DIAGASSERT(addr != NULL); if (af == AF_INET6 && len == NS_IN6ADDRSZ && (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr*) addr) || IN6_IS_ADDR_SITELOCAL((const struct in6_addr*) addr))) { Loading Loading @@ -614,42 +591,24 @@ nospc: return NULL; } static void convert_v4v6_hostent(struct hostent* hp, char** bpp, char* ep, const std::function<void(struct hostent* hp)>& map_param, const std::function<void(char* src, char* dst)>& map_addr) { _DIAGASSERT(hp != NULL); _DIAGASSERT(bpp != NULL); _DIAGASSERT(ep != NULL); /* Reserve space for mapping IPv4 address to IPv6 address in place */ static void pad_v4v6_hostent(struct hostent* _Nonnull hp, char** _Nonnull bpp, char* _Nonnull ep) { if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ) return; map_param(hp); for (char** ap = hp->h_addr_list; *ap; ap++) { int i = (int)(sizeof(align) - (size_t)((uintptr_t)*bpp % sizeof(align))); char* const bp = align_ptr<sizeof(int32_t)>(*bpp); if (ep - *bpp < (i + NS_IN6ADDRSZ)) { /* Out of memory. Truncate address list here. XXX */ *ap = NULL; if (ep - bp < NS_IN6ADDRSZ) { // Out of space. Truncate address list here. *ap = nullptr; return; } *bpp += i; map_addr(*ap, *bpp); *ap = *bpp; *bpp += NS_IN6ADDRSZ; memcpy(bp, *ap, NS_INADDRSZ); memcpy(bp + NS_INADDRSZ, NAT64_PAD, sizeof(NAT64_PAD)); *ap = bp; *bpp = bp + NS_IN6ADDRSZ; } } /* Reserve space for mapping IPv4 address to IPv6 address in place */ static void pad_v4v6_hostent(struct hostent* hp, char** bpp, char* ep) { convert_v4v6_hostent(hp, bpp, ep, [](struct hostent* hp) { (void) hp; /* unused */ }, [](char* src, char* dst) { memcpy(dst, src, NS_INADDRSZ); memcpy(dst + NS_INADDRSZ, NAT64_PAD, sizeof(NAT64_PAD)); }); } static int dns_gethtbyname(ResState* res, const char* name, int addr_type, getnamaddr* info) { int n, type; info->hp->h_addrtype = addr_type; Loading
resolv_private.h +27 −0 Original line number Diff line number Diff line Loading @@ -194,6 +194,33 @@ Dest saturate_cast(int64_t x) { return static_cast<Dest>(x); } constexpr bool is_power_of_2(size_t n) { return n != 0 && (n & (n - 1)) == 0; } // Rounds up a pointer to a char buffer |p| to a multiple of |Alignment| bytes. // Requirements: // |p| must be a pointer to a byte-sized type (e.g.: uint8_t) // |Alignment| must be a power of 2 template<uintptr_t Alignment = sizeof(void*), typename T> requires (sizeof(T) == 1) && (is_power_of_2(Alignment)) constexpr T* align_ptr(T* const p) { // Written this way to sidestep the performance-no-int-to-ptr clang-tidy warning. constexpr uintptr_t mask = Alignment - 1; const uintptr_t uintptr = reinterpret_cast<uintptr_t>(p); const uintptr_t aligned = (uintptr + mask) & ~mask; const uintptr_t bias = aligned - uintptr; return p + bias; } // Testcases for align_ptr() // TODO: enable when libc++ has std::bit_cast - reinterpret_cast isn't allowed in consteval context // static_assert(align_ptr((char*)1000) == (char*)1000); // static_assert(align_ptr((char*)1001) == (char*)1000 + sizeof(void*)); // static_assert(align_ptr((char*)1003) == (char*)1000 + sizeof(void*)); // static_assert(align_ptr<sizeof(uint32_t)>((char*)1004) == (char*)1004); // static_assert(align_ptr<sizeof(uint64_t)>((char*)1004) == (char*)1008); android::net::NsType getQueryType(const uint8_t* msg, size_t msgLen); android::net::IpVersion ipFamilyToIPVersion(int ipFamily); Loading
sethostent.cpp +1 −4 Original line number Diff line number Diff line Loading @@ -46,9 +46,6 @@ constexpr int MAXALIASES = 35; constexpr int MAXADDRS = 35; #define ALIGNBYTES (sizeof(uintptr_t) - 1) #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES) static void sethostent_r(FILE** hf) { if (!*hf) *hf = fopen(_PATH_HOSTS, "re"); Loading Loading @@ -121,7 +118,7 @@ int _hf_gethtbyname2(const char* name, int af, getnamaddr* info) { if (anum >= MAXALIASES) goto nospc; HENT_SCOPY(aliases[anum], hp->h_aliases[anum], ptr, len); } ptr = (char*) ALIGN(ptr); ptr = align_ptr(ptr); if ((size_t)(ptr - buf) >= info->buflen) goto nospc; } Loading