Skip to content

DNS cache bug about ai_socktype and ai_protocol #9274

Closed
@Cering

Description

@Cering

I did this

  • Send an http3 request first and set CURLOPT_FRESH_CONNECT and CURLOPT_FORBID_REUSE to 1, for avoid reusing http3 connection
  • After that, send an http(tcp) request. This will not reuse the http3 connection, but will use the dns cache
  • However, the second request return fail because of error 7(Couldn't connect to server)
  • The demo code is demo.cpp.txt, and major output info:
New Request[0]: https://www.google.com
curl_debug[0]: STATE: INIT => CONNECT handle 0x13c2a68; line 1833 (connection #-5000)
curl_debug[0]: Added connection 0. The cache now contains 1 members
curl_debug[0]: STATE: CONNECT => RESOLVING handle 0x13c2a68; line 1879 (connection #0)
curl_debug[0]: family0 == v4, family1 == v6
curl_debug[0]:   Trying 142.251.42.228:443...
curl_debug[0]:  CAfile: /etc/pki/tls/certs/ca-bundle.crt
curl_debug[0]:  CApath: none
curl_debug[0]: Connect socket 5 over QUIC to 142.251.42.228:443
curl_debug[0]: Sent QUIC client Initial, ALPN: h3,h3-29,h3-28,h3-27
...
curl_debug[0]: multi_done: status: 0 prem: 0 done: 0
curl_debug[0]: The cache now contains 0 members
curl_debug[0]: Closing connection 2
curl_debug[0]: Expire cleared (transfer 0x13c2a68)
mycurl_process: https://www.google.com.hk/, curl_code: 0(No error), http_version: 30, total_time: 0.760068, connect_time: 0.618590, download_bytes: 49727, download_speed: 65424


New Request[1]: https://www.google.com
curl_debug[0]: STATE: INIT => CONNECT handle 0x13c2a68; line 1833 (connection #-5000)
curl_debug[0]: Added connection 3. The cache now contains 1 members
curl_debug[0]: Hostname www.google.com was found in DNS cache
curl_debug[0]: family0 == v4, family1 == v6
curl_debug[0]: The cache now contains 0 members
curl_debug[0]: Closing connection 3
curl_debug[0]: Expire cleared (transfer 0x13c2a68)
mycurl_process: https://www.google.com/, curl_code: 7(Couldn't connect to server), http_version: 0, total_time: 0.000000, connect_time: 0.000000, download_bytes: 0, download_speed: 0

I expected the following

  • I add some output and find the error occured in Curl_socket():
if(*sockfd == CURL_SOCKET_BAD) {
  int err = errno;
  const char* errinfo = strerror(err);
  //output is 'error socket: 93, Protocol not supported'
  infof(conn->data, "error socket: %d, %s\n", err, errinfo);  
  /* no socket, no connection */
  return CURLE_COULDNT_CONNECT;
}
  • Then output the dns cache info in Curl_resolv() and Curl_socket()
//in Curl_resolv()
if(dns) {
  infof(data, "Hostname %s was found in DNS cache\n", hostname);
  dns->inuse++; /* we use it! */
  rc = CURLRESOLV_RESOLVED;

  const struct Curl_addrinfo *ai = dns->addr;
  while(ai)
  {
      char buf[INET6_ADDRSTRLEN];
      Curl_printable_address(ai, buf, sizeof(buf));
      //output is 'dns cache ai_info[111.206.72.219] - flags: 0, family: 2, socktype: 2, protocol: 17'
      infof(data, "dns cache ai_info[%s] - flags: %d, family: %d, socktype: %d, protocol: %d\n", buf, ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol);
      ai = ai->ai_next;
  }
}

//in Curl_socket()
memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);

{
    char ipaddress[MAX_IPADR_LEN];
    long port;
    Curl_addr2string((struct sockaddr*)&addr->sa_addr, addr->addrlen, ipaddress, &port);
    //output is 'create socket[111.206.72.219] - ai_family: 2, socktype: 1, protocol: 17'
    infof(conn->data, "create socket[%s] - ai_family: %d, socktype: %d, protocol: %d\n", ipaddress, addr->family, addr->socktype, addr->protocol);
}

if(data->set.fopensocket) {
  • It seems that when send an http3 request firstly, the dns result is ai_socktype=1(SOCK_DGRAM) and ai_protocol=17(IPPROTO_UDP) and was cached. Then use this dns cache to create a tcp socket, the params is ai_socktype=1(SOCK_STREAM) and ai_protocol=17(IPPROTO_UDP), which is an error input(a stream socket can't use for udp protocol). So system return error - Protocol not supported.

curl/libcurl version

curl 7.83.0 (x86_64-pc-linux-gnu) libcurl/7.83.0 BoringSSL zlib/1.2.7 brotli/1.0.9 nghttp2/1.41.0 quiche/0.12.0 OpenLDAP/2.4.44
Release-Date: 2022-04-27
Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS brotli Debug HSTS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TrackMemory UnixSockets

operating system

Linux mylinux 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    HTTP/3h3 or quic related

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions