"Fossies" - the Fresh Open Source Software Archive

Member "nss_ldap-265/resolve.c" (6 Nov 2009, 8859 Bytes) of package /linux/privat/old/nss_ldap-265.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.

    1 /*
    2  * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hvgskolan
    3  * (Royal Institute of Technology, Stockholm, Sweden).
    4  * All rights reserved.
    5  * 
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed by the Kungliga Tekniska
   20  *      Hvgskolan and its contributors.
   21  * 
   22  * 4. Neither the name of the Institute nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  * 
   26  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  */
   38 
   39 #include "config.h"
   40 
   41 #include <stdio.h>
   42 #include <stdlib.h>
   43 #include <sys/types.h>
   44 #include <netinet/in.h>
   45 #include <arpa/nameser.h>
   46 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
   47 #include <arpa/nameser_compat.h>
   48 #endif
   49 #include <string.h>
   50 #ifdef HAVE_STRINGS_H
   51 #include <strings.h>
   52 #endif
   53 
   54 #include <resolv.h>
   55 
   56 #include "resolve.h"
   57 
   58 static char rcsId[] = "$Id: resolve.c,v 2.11 2009/05/26 07:25:12 lukeh Exp $";
   59 
   60 #if defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND)
   61 
   62 #define DECL(X) {#X, T_##X}
   63 
   64 static struct stot
   65 {
   66   char *name;
   67   int type;
   68 }
   69 stot[] =
   70 {
   71   DECL (A),
   72     DECL (NS),
   73     DECL (CNAME), DECL (PTR), DECL (MX), DECL (TXT), DECL (AFSDB), DECL (SRV),
   74   {
   75   NULL, 0}
   76 };
   77 
   78 static int
   79 string_to_type (const char *name)
   80 {
   81   struct stot *p = stot;
   82   for (p = stot; p->name; p++)
   83     if (strcasecmp (name, p->name) == 0)
   84       return p->type;
   85   return -1;
   86 }
   87 
   88 #if 0
   89 static char *
   90 type_to_string (int type)
   91 {
   92   struct stot *p = stot;
   93   for (p = stot; p->name; p++)
   94     if (type == p->type)
   95       return p->name;
   96   return NULL;
   97 }
   98 #endif
   99 
  100 void
  101 dns_free_data (struct dns_reply *r)
  102 {
  103   struct resource_record *rr;
  104   if (r->q.domain)
  105     free (r->q.domain);
  106   for (rr = r->head; rr;)
  107     {
  108       struct resource_record *tmp = rr;
  109       if (rr->domain)
  110     free (rr->domain);
  111       if (rr->u.data)
  112     free (rr->u.data);
  113       rr = rr->next;
  114       free (tmp);
  115     }
  116   free (r);
  117 }
  118 
  119 static struct dns_reply *
  120 parse_reply (unsigned char *data, int len)
  121 {
  122   unsigned char *p;
  123   char host[128];
  124   int status;
  125   int query, response;
  126 
  127   struct dns_reply *r;
  128   struct resource_record **rr;
  129 
  130   r = (struct dns_reply *) malloc (sizeof (struct dns_reply));
  131   memset (r, 0, sizeof (struct dns_reply));
  132   r->q.domain = NULL;
  133 
  134   p = data;
  135   memcpy (&r->h, p, sizeof (HEADER));
  136   p += sizeof (HEADER);
  137   for (query = 0; query < ntohs(r->h.qdcount); query++)
  138     {
  139       status = dn_expand (data, data + len, p, host, sizeof (host));
  140       if (status < 0)
  141         {
  142           dns_free_data (r);
  143           return NULL;
  144         }
  145       p += status;
  146       if (p + 4 > data + len)
  147         {
  148           dns_free_data (r);
  149           return NULL;
  150         }
  151       if (r->q.domain == NULL)
  152         {
  153           r->q.domain = strdup (host);
  154           r->q.type = (p[0] << 8 | p[1]);
  155           r->q.class = (p[2] << 8 | p[3]);
  156         }
  157       p += 4;
  158     }
  159   rr = &r->head;
  160   for (response = 0; (response < ntohs(r->h.ancount)) && (p < data + len); response++)
  161     {
  162       unsigned int type, class, ttl, size;
  163       status = dn_expand (data, data + len, p, host, sizeof (host));
  164       if (status < 0)
  165     {
  166       dns_free_data (r);
  167       return NULL;
  168     }
  169       p += status;
  170       if (p + 10 > data + len)
  171         {
  172           dns_free_data (r);
  173           return NULL;
  174         }
  175       type = (p[0] << 8) | p[1];
  176       p += 2;
  177       class = (p[0] << 8) | p[1];
  178       p += 2;
  179       ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
  180       p += 4;
  181       size = (p[0] << 8) | p[1];
  182       p += 2;
  183       if (p + size > data + len)
  184         {
  185           dns_free_data (r);
  186           return NULL;
  187         }
  188       *rr = (struct resource_record *) calloc (1,
  189                            sizeof (struct
  190                                resource_record));
  191       (*rr)->domain = strdup (host);
  192       (*rr)->type = type;
  193       (*rr)->class = class;
  194       (*rr)->ttl = ttl;
  195       (*rr)->size = size;
  196       switch (type)
  197     {
  198     case T_NS:
  199     case T_CNAME:
  200     case T_PTR:
  201       status = dn_expand (data, data + len, p, host, sizeof (host));
  202       if (status < 0)
  203         {
  204           dns_free_data (r);
  205           return NULL;
  206         }
  207       (*rr)->u.txt = strdup (host);
  208       break;
  209     case T_MX:
  210     case T_AFSDB:
  211       {
  212             if (p + 2 > data + len)
  213               {
  214                 dns_free_data (r);
  215                 return NULL;
  216               }
  217         status = dn_expand (data, data + len, p + 2, host, sizeof (host));
  218         if (status < 0)
  219           {
  220         dns_free_data (r);
  221         return NULL;
  222           }
  223 
  224         (*rr)->u.mx =
  225           (struct mx_record *) malloc (sizeof (struct mx_record) +
  226                        strlen (host));
  227         (*rr)->u.mx->preference = (p[0] << 8) | p[1];
  228         strcpy ((*rr)->u.mx->domain, host);
  229         break;
  230       }
  231     case T_SRV:
  232       {
  233             if (p + 6 > data + len)
  234               {
  235                 dns_free_data (r);
  236                 return NULL;
  237               }
  238         status = dn_expand (data, data + len, p + 6, host, sizeof (host));
  239         if (status < 0)
  240           {
  241         dns_free_data (r);
  242         return NULL;
  243           }
  244         (*rr)->u.srv =
  245           (struct srv_record *) malloc (sizeof (struct srv_record) +
  246                         strlen (host));
  247         (*rr)->u.srv->priority = (p[0] << 8) | p[1];
  248         (*rr)->u.srv->weight = (p[2] << 8) | p[3];
  249         (*rr)->u.srv->port = (p[4] << 8) | p[5];
  250         strcpy ((*rr)->u.srv->target, host);
  251         break;
  252       }
  253     case T_TXT:
  254       {
  255             if (p + *p > data + len)
  256               {
  257                 dns_free_data (r);
  258                 return NULL;
  259               }
  260         (*rr)->u.txt = (char *) malloc (size + 1);
  261         strncpy ((*rr)->u.txt, (char *) p + 1, *p);
  262         (*rr)->u.txt[*p] = 0;
  263         break;
  264       }
  265 
  266     default:
  267       (*rr)->u.data = (unsigned char *) malloc (size);
  268       memcpy ((*rr)->u.data, p, size);
  269     }
  270       p += size;
  271       rr = &(*rr)->next;
  272     }
  273   *rr = NULL;
  274   return r;
  275 }
  276 
  277 
  278 
  279 struct dns_reply *
  280 dns_lookup (const char *domain, const char *type_name)
  281 {
  282   unsigned char *reply = NULL;
  283   int len, rlen;
  284   int type;
  285   struct dns_reply *r = NULL;
  286 
  287   type = string_to_type (type_name);
  288   rlen = 1024;
  289   reply = malloc(rlen);
  290   do
  291     {
  292       len = res_search (domain, C_IN, type, reply, rlen);
  293       if ((len == -1) || (len < rlen))
  294         {
  295           break;
  296         }
  297       reply = realloc (reply, len + 1024);
  298       rlen = len + 1024;
  299     }
  300   while (1);
  301   if (len >= 0)
  302     r = parse_reply (reply, len);
  303   free(reply);
  304   return r;
  305 }
  306 
  307 #else /* defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */
  308 
  309 struct dns_reply *
  310 dns_lookup (const char *domain, const char *type_name)
  311 {
  312   return NULL;
  313 }
  314 
  315 void
  316 dns_free_data (struct dns_reply *r)
  317 {
  318 }
  319 
  320 #endif
  321 
  322 #ifdef TEST
  323 
  324 int
  325 main (int argc, char **argv)
  326 {
  327   struct dns_reply *r;
  328   struct resource_record *rr;
  329   r = dns_lookup (argv[1], argv[2]);
  330   if (r == NULL)
  331     {
  332       printf ("No reply.\n");
  333       return 1;
  334     }
  335   for (rr = r->head; rr; rr = rr->next)
  336     {
  337       printf ("%s %s %d ", rr->domain, type_to_string (rr->type), rr->ttl);
  338       switch (rr->type)
  339     {
  340     case T_NS:
  341       printf ("%s\n", (char *) rr->data);
  342       break;
  343     case T_A:
  344       printf ("%d.%d.%d.%d\n",
  345           ((unsigned char *) rr->data)[0],
  346           ((unsigned char *) rr->data)[1],
  347           ((unsigned char *) rr->data)[2],
  348           ((unsigned char *) rr->data)[3]);
  349       break;
  350     case T_MX:
  351     case T_AFSDB:
  352       {
  353         struct mx_record *mx = (struct mx_record *) rr->data;
  354         printf ("%d %s\n", mx->preference, mx->domain);
  355         break;
  356       }
  357     case T_SRV:
  358       {
  359         struct srv_record *srv = (struct srv_record *) rr->data;
  360         printf ("%d %d %d %s\n", srv->priority, srv->weight,
  361             srv->port, srv->target);
  362         break;
  363       }
  364     default:
  365       printf ("\n");
  366       break;
  367     }
  368     }
  369 
  370   return 0;
  371 }
  372 #endif