Back to index

glibc  2.9
Classes | Defines | Typedefs | Functions | Variables
dns-canon.c File Reference
#include <errno.h>
#include <netdb.h>
#include <resolv.h>
#include <stdlib.h>
#include <arpa/nameser.h>
#include <nsswitch.h>

Go to the source code of this file.

Classes

union  querybuf

Defines

#define MAXPACKET   65536
#define nqtypes   (sizeof (qtypes) / sizeof (qtypes[0]))

Typedefs

typedef union querybuf querybuf

Functions

enum nss_status _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen, char **result, int *errnop, int *h_errnop)

Variables

static const short int qtypes [] = { ns_t_a, ns_t_aaaa }

Class Documentation

union querybuf

Definition at line 36 of file dns-canon.c.

Collaboration diagram for querybuf:
Class Members
unsigned char buf
u_char buf
HEADER hdr

Define Documentation

#define MAXPACKET   65536

Definition at line 31 of file dns-canon.c.

#define nqtypes   (sizeof (qtypes) / sizeof (qtypes[0]))

Definition at line 44 of file dns-canon.c.


Typedef Documentation

typedef union querybuf querybuf

Function Documentation

enum nss_status _nss_dns_getcanonname_r ( const char *  name,
char *  buffer,
size_t  buflen,
char **  result,
int errnop,
int h_errnop 
)

Definition at line 48 of file dns-canon.c.

{
  /* Just an alibi buffer, res_nquery will allocate a real buffer for
     us.  */
  unsigned char buf[20];
  union
  {
    querybuf *buf;
    unsigned char *ptr;
  } ansp = { .ptr = buf };
  enum nss_status status = NSS_STATUS_UNAVAIL;

  for (int i = 0; i < nqtypes; ++i)
    {
      int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i],
                             buf, sizeof (buf), &ansp.ptr, NULL, NULL,
                             NULL);
      if (r > 0)
       {
         /* We need to decode the response.  Just one question record.
            And if we got no answers we bail out, too.  */
         if (ansp.buf->hdr.qdcount != htons (1))
           continue;

         /* Number of answers.   */
         unsigned int ancount = ntohs (ansp.buf->hdr.ancount);

         /* Beginning and end of the buffer with query, answer, and the
            rest.  */
         unsigned char *ptr = &ansp.buf->buf[sizeof (HEADER)];
         unsigned char *endptr = ansp.ptr + r;

         /* Skip over the query.  This is the name, type, and class.  */
         int s = __dn_skipname (ptr, endptr);
         if (s < 0)
           {
           unavail:
             status = NSS_STATUS_UNAVAIL;
             break;
           }

         /* Skip over the name and the two 16-bit values containing type
            and class.  */
         ptr += s + 2 * sizeof (uint16_t);

         while (ancount-- > 0)
           {
             /* Now the reply.  First again the name from the query,
               then type, class, TTL, and the length of the RDATA.
               We remember the name start.  */
             unsigned char *namestart = ptr;
             s = __dn_skipname (ptr, endptr);
             if (s < 0)
              goto unavail;

             ptr += s;

             /* Check whether type and class match.  */
             uint_fast16_t type;
             NS_GET16 (type, ptr);
             if (type == qtypes[i])
              {
                /* We found the record.  */
                s = __dn_expand (ansp.buf->buf, endptr, namestart,
                               buffer, buflen);
                if (s < 0)
                  {
                    if (errno != EMSGSIZE)
                     goto unavail;

                    /* The buffer is too small.  */
                    *errnop = ERANGE;
                    status = NSS_STATUS_TRYAGAIN;
                    h_errno = NETDB_INTERNAL;
                  }
                else
                  {
                    /* Success.  */
                    *result = buffer;
                    status = NSS_STATUS_SUCCESS;
                  }

                goto out;
              }

             if (type != ns_t_cname)
              goto unavail;

             if (__ns_get16 (ptr) != ns_c_in)
              goto unavail;

             /* Also skip over the TTL.  */
             ptr += sizeof (uint16_t) + sizeof (uint32_t);

             /* Skip over the data length and data.  */
             ptr += sizeof (uint16_t) + __ns_get16 (ptr);
           }
       }
    }

 out:
  *h_errnop = h_errno;

  if (ansp.ptr != buf)
    free (ansp.ptr);

  return status;
}

Here is the call graph for this function:


Variable Documentation

const short int qtypes[] = { ns_t_a, ns_t_aaaa } [static]

Definition at line 43 of file dns-canon.c.