Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DNS cache bug about ai_socktype and ai_protocol #9274

Closed
Cering opened this issue Aug 8, 2022 · 3 comments
Closed

DNS cache bug about ai_socktype and ai_protocol #9274

Cering opened this issue Aug 8, 2022 · 3 comments
Labels
HTTP/3 h3 or quic related

Comments

@Cering
Copy link
Contributor

Cering commented Aug 8, 2022

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
@bagder bagder added the HTTP/3 h3 or quic related label Aug 8, 2022
@bagder
Copy link
Member

bagder commented Aug 8, 2022

Ouch. Are you able to submit a PR for this or do you want me to have a look?

@Cering
Copy link
Contributor Author

Cering commented Aug 8, 2022

Already submit my solution in #9275

@bagder bagder linked a pull request Aug 8, 2022 that will close this issue
@Cering
Copy link
Contributor Author

Cering commented Aug 8, 2022

Thanks, #9276 is more graceful :)

@bagder bagder closed this as completed in 0f23341 Aug 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
HTTP/3 h3 or quic related
2 participants