This is the mail archive of the libc-help@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Tune global _res variable to bypass /etc/resolv.conf? If not, how to bypass /etc/resolv.conf in a C program using glibc?


Based on various examples I've found from various sources regarding
using the resolver in libc, the code example below is presumably
supposed to force the resolver use the DNS server of my choice.  It
appears that changing _res in this way has no impact on glibc; it always
uses the list of DNS servers from /etc/resolv.conf.

Is there a different way that _res should be changed to bypass
/etc/resolv.conf and set the DNS server to something else at the C
programming level?

I have tried calling res_init() both before and after I muck with _res
and I get the same results -- the entries in /etc/resolv.conf are used
rather than my settings via:
    _res.nscount = 1; _res.nsaddr_list[0] = serverSock;

FWIW, the seminal source for information online about using _res in this
way appears to be the DNS & Bind book:
        http://docstore.mik.ua/orelly/networking_2ndEd/dns/ch15_02.htm 
which I realize is quite old and perhaps inaccurate.

If anyone can point to a README or FAQ that explains how to stop the
glibc resolver from falling back to /etc/resolv.conf (i.e., how to
control what DNS servers are used completely via the libc API), I'd much
appreciate it.  I've searched around and been unable to find any
suggestions other than the aforementioned suggestions about modifying
_res.

If anyone is interested in why I'm asking, it's because I'm trying to
close this bug in BusyBox: https://bugs.busybox.net/show_bug.cgi?id=675

I apologize if this is a dumb question; it's my first time posting to this
list.

Thanks for your help!  Code example is below:

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <resolv.h>
#include <netdb.h>
#include <string.h>

int main(int argc, char **argv) {
  struct  in_addr server;
  struct sockaddr_in serverSock;
  struct addrinfo hint;
  struct addrinfo *result = NULL;

  if (argc != 3) {
    fprintf(stderr, "usage: %s <HOST> <DNS_SERVER>\n", argv[0]);
    return(1);
  }


  if (inet_pton(AF_INET, argv[2], &server) > 0) {
    serverSock.sin_family = AF_INET;
    serverSock.sin_port = htons(53);
    serverSock.sin_addr = server;

    _res.nscount = 1;
    _res.nsaddr_list[0] = serverSock;

    printf("res.nscount before res_init() call: %d\n", _res.nscount);
    res_init();
    printf("res.nscount after res_init() call: %d\n", _res.nscount);

    /* Do it again?  res_init seems to put things back to match
    ** /etc/resolv.conf! */
    _res.nscount = 1;
    _res.nsaddr_list[0] = serverSock;

  } else {
    printf("unable to inet_pton: %s\n", argv[2]);
    return(1);
  }
  memset(&hint, 0 , sizeof(hint));
  if (!getaddrinfo(argv[1], NULL /*service*/, &hint, &result)) {
    struct addrinfo *cur = result;
    unsigned cnt = 0;

    while (cur) {
      char host[128];
      char serv[16];

      if (!getnameinfo(cur->ai_addr, sizeof(struct sockaddr_in),
                      host, sizeof(host), serv, sizeof(serv),
                      NI_NUMERICHOST | NI_NUMERICSERV)) {
        printf("Host: %s, Serv: %s\n", host, serv);
      } else {
        printf("Unable to getnameinfo\n");
      }
      cur = cur->ai_next;
    }
  } else {
    printf("getaddrinfo() on %s failed.\n", argv[1]);
  }
  return(0);
}


-- 

   -- bkuhn


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]