"Fossies" - the Fresh Open Source Software Archive

Member "udns-0.4/udns_init.c" (5 Jul 2011, 6842 Bytes) of package /linux/misc/dns/udns-0.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "udns_init.c" see the Fossies "Dox" file reference documentation.

    1 /* udns_init.c
    2    resolver initialisation stuff
    3 
    4    Copyright (C) 2006  Michael Tokarev <mjt@corpit.ru>
    5    This file is part of UDNS library, an async DNS stub resolver.
    6 
    7    This library is free software; you can redistribute it and/or
    8    modify it under the terms of the GNU Lesser General Public
    9    License as published by the Free Software Foundation; either
   10    version 2.1 of the License, or (at your option) any later version.
   11 
   12    This library is distributed in the hope that it will be useful,
   13    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15    Lesser General Public License for more details.
   16 
   17    You should have received a copy of the GNU Lesser General Public
   18    License along with this library, in file named COPYING.LGPL; if not,
   19    write to the Free Software Foundation, Inc., 59 Temple Place,
   20    Suite 330, Boston, MA  02111-1307  USA
   21 
   22  */
   23 
   24 #ifdef HAVE_CONFIG_H
   25 # include "config.h"
   26 #endif
   27 #ifdef WINDOWS
   28 # include <winsock2.h>          /* includes <windows.h> */
   29 # include <iphlpapi.h>      /* for dns server addresses etc */
   30 #else
   31 # include <sys/types.h>
   32 # include <unistd.h>
   33 # include <fcntl.h>
   34 #endif  /* !WINDOWS */
   35 
   36 #include <stdlib.h>
   37 #include <string.h>
   38 #include "udns.h"
   39 
   40 #define ISSPACE(x) (x == ' ' || x == '\t' || x == '\r' || x == '\n')
   41 
   42 static const char space[] = " \t\r\n";
   43 
   44 static void dns_set_serv_internal(struct dns_ctx *ctx, char *serv) {
   45   dns_add_serv(ctx, NULL);
   46   for(serv = strtok(serv, space); serv; serv = strtok(NULL, space))
   47     dns_add_serv(ctx, serv);
   48 }
   49 
   50 static void dns_set_srch_internal(struct dns_ctx *ctx, char *srch) {
   51   dns_add_srch(ctx, NULL);
   52   for(srch = strtok(srch, space); srch; srch = strtok(NULL, space))
   53     dns_add_srch(ctx, srch);
   54 }
   55 
   56 #ifdef WINDOWS
   57 
   58 #ifndef NO_IPHLPAPI
   59 /* Apparently, some systems does not have proper headers for IPHLPAIP to work.
   60  * The best is to upgrade headers, but here's another, ugly workaround for
   61  * this: compile with -DNO_IPHLPAPI.
   62  */
   63 
   64 typedef DWORD (WINAPI *GetAdaptersAddressesFunc)(
   65   ULONG Family, DWORD Flags, PVOID Reserved,
   66   PIP_ADAPTER_ADDRESSES pAdapterAddresses,
   67   PULONG pOutBufLen);
   68 
   69 static int dns_initns_iphlpapi(struct dns_ctx *ctx) {
   70   HANDLE h_iphlpapi;
   71   GetAdaptersAddressesFunc pfnGetAdAddrs;
   72   PIP_ADAPTER_ADDRESSES pAddr, pAddrBuf;
   73   PIP_ADAPTER_DNS_SERVER_ADDRESS pDnsAddr;
   74   ULONG ulOutBufLen;
   75   DWORD dwRetVal;
   76   int ret = -1;
   77 
   78   h_iphlpapi = LoadLibrary("iphlpapi.dll");
   79   if (!h_iphlpapi)
   80     return -1;
   81   pfnGetAdAddrs = (GetAdaptersAddressesFunc)
   82     GetProcAddress(h_iphlpapi, "GetAdaptersAddresses");
   83   if (!pfnGetAdAddrs) goto freelib;
   84   ulOutBufLen = 0;
   85   dwRetVal = pfnGetAdAddrs(AF_UNSPEC, 0, NULL, NULL, &ulOutBufLen);
   86   if (dwRetVal != ERROR_BUFFER_OVERFLOW) goto freelib;
   87   pAddrBuf = malloc(ulOutBufLen);
   88   if (!pAddrBuf) goto freelib;
   89   dwRetVal = pfnGetAdAddrs(AF_UNSPEC, 0, NULL, pAddrBuf, &ulOutBufLen);
   90   if (dwRetVal != ERROR_SUCCESS) goto freemem;
   91   for (pAddr = pAddrBuf; pAddr; pAddr = pAddr->Next)
   92     for (pDnsAddr = pAddr->FirstDnsServerAddress;
   93      pDnsAddr;
   94      pDnsAddr = pDnsAddr->Next)
   95       dns_add_serv_s(ctx, pDnsAddr->Address.lpSockaddr);
   96   ret = 0;
   97 freemem:
   98   free(pAddrBuf);
   99 freelib:
  100   FreeLibrary(h_iphlpapi);
  101   return ret;
  102 }
  103 
  104 #else /* NO_IPHLPAPI */
  105 
  106 #define dns_initns_iphlpapi(ctx) (-1)
  107 
  108 #endif /* NO_IPHLPAPI */
  109 
  110 static int dns_initns_registry(struct dns_ctx *ctx) {
  111   LONG res;
  112   HKEY hk;
  113   DWORD type = REG_EXPAND_SZ | REG_SZ;
  114   DWORD len;
  115   char valBuf[1024];
  116 
  117 #define REGKEY_WINNT "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"
  118 #define REGKEY_WIN9x "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP"
  119   res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WINNT, 0, KEY_QUERY_VALUE, &hk);
  120   if (res != ERROR_SUCCESS)
  121     res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WIN9x,
  122                        0, KEY_QUERY_VALUE, &hk);
  123   if (res != ERROR_SUCCESS)
  124     return -1;
  125   len = sizeof(valBuf) - 1;
  126   res = RegQueryValueEx(hk, "NameServer", NULL, &type, (BYTE*)valBuf, &len);
  127   if (res != ERROR_SUCCESS || !len || !valBuf[0]) {
  128     len = sizeof(valBuf) - 1;
  129     res = RegQueryValueEx(hk, "DhcpNameServer", NULL, &type,
  130                           (BYTE*)valBuf, &len);
  131   }
  132   RegCloseKey(hk);
  133   if (res != ERROR_SUCCESS || !len || !valBuf[0])
  134     return -1;
  135   valBuf[len] = '\0';
  136   /* nameservers are stored as a whitespace-seperate list:
  137    * "192.168.1.1 123.21.32.12" */
  138   dns_set_serv_internal(ctx, valBuf);
  139   return 0;
  140 }
  141 
  142 #else /* !WINDOWS */
  143 
  144 static int dns_init_resolvconf(struct dns_ctx *ctx) {
  145   char *v;
  146   char buf[2049];   /* this buffer is used to hold /etc/resolv.conf */
  147   int has_srch = 0;
  148 
  149   /* read resolv.conf... */
  150   { int fd = open("/etc/resolv.conf", O_RDONLY);
  151     if (fd >= 0) {
  152       int l = read(fd, buf, sizeof(buf) - 1);
  153       close(fd);
  154       buf[l < 0 ? 0 : l] = '\0';
  155     }
  156     else
  157       buf[0] = '\0';
  158   }
  159   if (buf[0]) { /* ...and parse it */
  160     char *line, *nextline;
  161     line = buf;
  162     do {
  163       nextline = strchr(line, '\n');
  164       if (nextline) *nextline++ = '\0';
  165       v = line;
  166       while(*v && !ISSPACE(*v)) ++v;
  167       if (!*v) continue;
  168       *v++ = '\0';
  169       while(ISSPACE(*v)) ++v;
  170       if (!*v) continue;
  171       if (strcmp(line, "domain") == 0) {
  172         dns_set_srch_internal(ctx, strtok(v, space));
  173     has_srch = 1;
  174       }
  175       else if (strcmp(line, "search") == 0) {
  176         dns_set_srch_internal(ctx, v);
  177     has_srch = 1;
  178       }
  179       else if (strcmp(line, "nameserver") == 0)
  180         dns_add_serv(ctx, strtok(v, space));
  181       else if (strcmp(line, "options") == 0)
  182         dns_set_opts(ctx, v);
  183     } while((line = nextline) != NULL);
  184   }
  185 
  186   buf[sizeof(buf)-1] = '\0';
  187 
  188   /* get list of nameservers from env. vars. */
  189   if ((v = getenv("NSCACHEIP")) != NULL ||
  190       (v = getenv("NAMESERVERS")) != NULL) {
  191     strncpy(buf, v, sizeof(buf) - 1);
  192     dns_set_serv_internal(ctx, buf);
  193   }
  194   /* if $LOCALDOMAIN is set, use it for search list */
  195   if ((v = getenv("LOCALDOMAIN")) != NULL) {
  196     strncpy(buf, v, sizeof(buf) - 1);
  197     dns_set_srch_internal(ctx, buf);
  198     has_srch = 1;
  199   }
  200   if ((v = getenv("RES_OPTIONS")) != NULL)
  201     dns_set_opts(ctx, v);
  202 
  203   /* if still no search list, use local domain name */
  204   if (has_srch &&
  205       gethostname(buf, sizeof(buf) - 1) == 0 &&
  206       (v = strchr(buf, '.')) != NULL &&
  207       *++v != '\0')
  208     dns_add_srch(ctx, v);
  209 
  210   return 0;
  211 }
  212 
  213 #endif /* !WINDOWS */
  214 
  215 int dns_init(struct dns_ctx *ctx, int do_open) {
  216   if (!ctx)
  217     ctx = &dns_defctx;
  218   dns_reset(ctx);
  219 
  220 #ifdef WINDOWS
  221   if (dns_initns_iphlpapi(ctx) != 0)
  222     dns_initns_registry(ctx);
  223   /*XXX WINDOWS: probably good to get default domain and search list too...
  224    * And options.  Something is in registry. */
  225   /*XXX WINDOWS: maybe environment variables are also useful? */
  226 #else
  227   dns_init_resolvconf(ctx);
  228 #endif
  229 
  230   return do_open ? dns_open(ctx) : 0;
  231 }