1

I open a GSM connection over ppp and try to download a file from a URL with curl.

With few devices I get a CURLE_COULDNT_RESOLVE_HOST error from curl and getaddrinfo results in EAI_AGAIN.

In route my ppp0 interface is registered correct. resolv.conf contains the google DNS and manually executing nslookup in terminal is working.

I got no idea why it is not working. The only thing I know: IPv6 is not possible.

This is my code for getaddrinfo

int checkINet(std::string address)
{
   struct addrinfo hints, *servinfo, *p;
   memset(&hints, 0, sizeof(hints));
   hints.ai_family = AF_INET;
   hints.ai_socktype = SOCK_STREAM;
   char ip_addr[INET6_ADDRSTRLEN];

   int s = getaddrinfo(address.c_str(), NULL, &hints, &servinfo);

   if (s != 0)
   {
      std::cout << "No connection possible: " << address << "\n";
      std::cout << "getaddrinfo: " << s << " " << gai_strerror(s) << "\n";
      return -1;
   }
   else
   {
      std::cout << "Conection successful: " << address << "\n";

      for (p = servinfo; p != NULL; p = p->ai_next)
      {
         void *addr;
         if (p->ai_family == AF_INET)
         {
            struct sockaddr_in *ipv4 =(struct sockaddr_in *)p->ai_addr;
            addr = &(ipv4->sin_addr);
         }
         else
         {
            struct sockaddr_in6 *ipv6 =(struct sockaddr_in6 *)p->ai_addr;
            addr = &(ipv6->sin6_addr);
         }

         inet_ntop(p->ai_family, addr, ip_addr, sizeof ip_addr);
         std::cout << addr << "\n";
      }

   }
   freeaddrinfo(servinfo);
   return 0;
}

And for curl:

   CURL *curl;
   FILE *fp;
   CURLcode res;

   // initialise a connection to the server
   curl = curl_easy_init();
   if (curl)
   {
      fp = fopen(UPDATE_ZIP, "wb");
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
      curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
      curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
      curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
      curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
      res = curl_easy_perform(curl);
      curl_easy_cleanup(curl);
      fclose(fp);

      if (CURLE_OK != res)
      {
          std::out << "curl failed with: " << res << "\n";
          return res;
      }
      return 0;
   }
   return -1;
yakana
  • 41
  • 5
  • `nslookup` bypasses NSS and connects to the DNS servers itself. Assuming Glibc, `getaddrinfo` does go through NSS. Can you compare with the behavior of `getent hosts $address` and what the contents of `/etc/nsswitch.conf` are? – ephemient Nov 02 '17 at 15:54
  • Also, you say IPv6 is not possible, so you limit `getaddrinfo()` to IPv4, but the rest of your code is looking for IPv6. Are you planning in enabling IPv6 in the future? Also, you can replace `inet_ntop() ` with `getnameinfo()` and get rid of your `addr` variable: `getnameinfo(p->ai_addr, p->ai_addrlen, ip_addr, sizeof ip_addr, NULL, 0, NI_NUMERICHOST);` – Remy Lebeau Nov 02 '17 at 16:22
  • IPv6 is a leftover until I discovered, that the GSM provider only supplys IPv4.I think NSS is the hint I searched. I will keep this updated – yakana Nov 06 '17 at 08:09

1 Answers1

0

ephemient tipp is right. Changed order inside /etc/nsswitch.con from hosts: files dns to hosts: dns files

yakana
  • 41
  • 5