Back to index

opendkim  2.6.4
Classes | Defines | Functions | Variables
vbr.c File Reference
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <resolv.h>
#include <varargs.h>
#include "vbr.h"

Go to the source code of this file.

Classes

struct  vbr_query
struct  vbr_handle

Defines

#define _REENTRANT
#define FALSE   0
#define TRUE   1
#define BUFRSZ   2048
#define DEFERRLEN   64
#define DEFTIMEOUT   10
#define MAXCNAMEDEPTH   3
#define MAXPACKET   8192
#define RES_UNC_T   unsigned char *
#define T_RRSIG   46
#define VBR_DNS_ERROR   (-1)
#define VBR_DNS_SUCCESS   0
#define VBR_DNS_REPLY   1
#define VBR_DNS_NOREPLY   2
#define VBR_DNS_EXPIRED   3
#define strlcpy(x, y, z)   vbr_strlcpy((x), (y), (z))
#define CLOBBER(x)

Functions

static void vbr_error __P ((VBR *, const char *,...))
size_t vbr_strlcpy (char *dst, const char *src, ssize_t size)
static void * vbr_malloc (VBR *vbr, void *closure, size_t nbytes)
static void vbr_free (VBR *vbr, void *closure, void *ptr)
static void vbr_verror (VBR *vbr, const char *format, va_list va)
static void vbr_error (VBR *vbr, const char *format,...)
static void vbr_timeouts (struct timeval *timeout, struct timeval *ctimeout, struct timeval *wstart, struct timeval *wstop, struct timeval **next)
static int vbr_res_cancel (void *srv, void *qh)
static int vbr_res_query (void *srv, int type, unsigned char *query, unsigned char *buf, size_t buflen, void **qh)
int vbr_res_waitreply (void *srv, void *qh, struct timeval *to, size_t *bytes, int *error, int *dnssec)
static _Bool vbr_txt_decode (u_char *ansbuf, size_t anslen, u_char *buf, size_t buflen)
VBR * vbr_init (void *(*caller_mallocf)(void *closure, size_t nbytes), void(*caller_freef)(void *closure, void *p), void *closure)
void vbr_options (VBR *vbr, unsigned int opts)
void vbr_close (VBR *vbr)
const u_char * vbr_geterror (VBR *vbr)
VBR_STAT vbr_settimeout (VBR *vbr, u_int timeout)
VBR_STAT vbr_setcallbackint (VBR *vbr, u_int cbint)
VBR_STAT vbr_setcallbackctx (VBR *vbr, void *ctx)
VBR_STAT vbr_setdnscallback (VBR *vbr, void(*func)(const void *context))
void vbr_setdomain (VBR *vbr, u_char *domain)
void vbr_setcert (VBR *vbr, u_char *cert)
void vbr_settype (VBR *vbr, u_char *type)
void vbr_trustedcerts (VBR *vbr, u_char **certs)
VBR_STAT vbr_query (VBR *vbr, u_char **res, u_char **cert)
VBR_STAT vbr_getheader (VBR *vbr, unsigned char *hdr, size_t len)
void * vbr_dns_set_query_service (VBR *vbr, void *h)
void vbr_dns_set_query_start (VBR *vbr, int(*func)(void *, int, unsigned char *, unsigned char *, size_t, void **))
void vbr_dns_set_query_cancel (VBR *vbr, int(*func)(void *, void *))
void vbr_dns_set_query_waitreply (VBR *vbr, int(*func)(void *, void *, struct timeval *, size_t *, int *, int *))

Variables

static char vbr_c_id [] = "@(#)$Id: vbr.c,v 1.5.2.1 2010/10/27 21:43:09 cm-msk Exp $"

Class Documentation

struct vbr_query

Definition at line 70 of file vbr.c.

Class Members
u_char vq_buf
size_t vq_buflen
int vq_error
void * vq_qh

Define Documentation

#define _REENTRANT

Definition at line 14 of file vbr.c.

#define BUFRSZ   2048

Definition at line 47 of file vbr.c.

#define CLOBBER (   x)
Value:
if ((x) != NULL) \
                     { \
                            vbr_free(vbr, vbr->vbr_closure, (x)); \
                            (x) = NULL; \
                     }

Definition at line 736 of file vbr.c.

#define DEFERRLEN   64

Definition at line 48 of file vbr.c.

#define DEFTIMEOUT   10

Definition at line 49 of file vbr.c.

#define FALSE   0

Definition at line 41 of file vbr.c.

#define MAXCNAMEDEPTH   3

Definition at line 50 of file vbr.c.

#define MAXPACKET   8192

Definition at line 53 of file vbr.c.

#define RES_UNC_T   unsigned char *

Definition at line 57 of file vbr.c.

#define strlcpy (   x,
  y,
 
)    vbr_strlcpy((x), (y), (z))

Definition at line 135 of file vbr.c.

#define T_RRSIG   46

Definition at line 60 of file vbr.c.

#define TRUE   1

Definition at line 44 of file vbr.c.

#define VBR_DNS_ERROR   (-1)

Definition at line 63 of file vbr.c.

#define VBR_DNS_EXPIRED   3

Definition at line 67 of file vbr.c.

#define VBR_DNS_NOREPLY   2

Definition at line 66 of file vbr.c.

#define VBR_DNS_REPLY   1

Definition at line 65 of file vbr.c.

#define VBR_DNS_SUCCESS   0

Definition at line 64 of file vbr.c.


Function Documentation

static void vbr_error __P ( (VBR *, const char *,...)  ) [static]
void vbr_close ( VBR *  vbr)

Definition at line 753 of file vbr.c.

{
       assert(vbr != NULL);

       CLOBBER(vbr->vbr_error);

       CLOBBER(vbr);
}

Here is the caller graph for this function:

void vbr_dns_set_query_cancel ( VBR *  vbr,
int(*)(void *, void *)  func 
)

Definition at line 1274 of file vbr.c.

{
       assert(vbr != NULL);

       vbr->vbr_dns_cancel = func;
}
void* vbr_dns_set_query_service ( VBR *  vbr,
void *  h 
)

Definition at line 1210 of file vbr.c.

{
       void *old;

       assert(vbr != NULL);

       old = vbr->vbr_dns_service;

       vbr->vbr_dns_service = h;

       return old;
}
void vbr_dns_set_query_start ( VBR *  vbr,
int(*)(void *, int, unsigned char *, unsigned char *, size_t, void **)  func 
)

Definition at line 1246 of file vbr.c.

{
       assert(vbr != NULL);

       vbr->vbr_dns_start = func;
}
void vbr_dns_set_query_waitreply ( VBR *  vbr,
int(*)(void *, void *, struct timeval *, size_t *, int *, int *)  func 
)

Definition at line 1303 of file vbr.c.

{
       assert(vbr != NULL);

       vbr->vbr_dns_waitreply = func;
}
static void vbr_error ( VBR *  vbr,
const char *  format,
  ... 
) [static]

Definition at line 310 of file vbr.c.

{
       va_list va;

       assert(vbr != NULL);
       assert(format != NULL);

       va_start(va, format);
       vbr_verror(vbr, format, va);
       va_end(va);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void vbr_free ( VBR *  vbr,
void *  closure,
void *  ptr 
) [static]

Definition at line 221 of file vbr.c.

{
       assert(vbr != NULL);

       if (vbr->vbr_free == NULL)
              free(ptr);
       else
              vbr->vbr_free(closure, ptr);
}

Here is the caller graph for this function:

const u_char* vbr_geterror ( VBR *  vbr)

Definition at line 774 of file vbr.c.

{
       assert(vbr != NULL);

       return vbr->vbr_error;
}

Here is the caller graph for this function:

VBR_STAT vbr_getheader ( VBR *  vbr,
unsigned char *  hdr,
size_t  len 
)

Definition at line 1172 of file vbr.c.

{
       size_t olen;

       assert(vbr != NULL);
       assert(hdr != NULL);

       if (vbr->vbr_cert == NULL || vbr->vbr_type == NULL)
       {
              vbr_error(vbr, "VBR certifiers or type missing");
              return VBR_STAT_INVALID;
       }

       olen = snprintf((char *) hdr, len, "md=%s; mc=%s; mv=%s",
                       vbr->vbr_domain, vbr->vbr_type, vbr->vbr_cert);
       if (olen >= len)
       {
              vbr_error(vbr, "VBR buffer too small");
              return VBR_STAT_NORESOURCE;
       }

       return VBR_STAT_OK;
}

Here is the call graph for this function:

VBR* vbr_init ( void *(*)(void *closure, size_t nbytes)  caller_mallocf,
void(*)(void *closure, void *p)  caller_freef,
void *  closure 
)

Definition at line 683 of file vbr.c.

{
       VBR *new;

       /* copy the parameters */
       new = (VBR *) malloc(sizeof(struct vbr_handle));
       if (new == NULL)
              return NULL;

       new->vbr_malloc = caller_mallocf;
       new->vbr_free = caller_freef;
       new->vbr_closure = closure;
       new->vbr_timeout = DEFTIMEOUT;
       new->vbr_callback_int = 0;
       new->vbr_dns_callback = NULL;
       new->vbr_user_context = NULL;
       new->vbr_errlen = 0;
       new->vbr_error = NULL;

       new->vbr_domain = NULL;
       new->vbr_type = NULL;
       new->vbr_cert = NULL;
       new->vbr_trusted = NULL;

       new->vbr_dns_service = NULL;
       new->vbr_dns_start = vbr_res_query;
       new->vbr_dns_waitreply = vbr_res_waitreply;
       new->vbr_dns_cancel = vbr_res_cancel;

       return new;
}

Here is the call graph for this function:

static void* vbr_malloc ( VBR *  vbr,
void *  closure,
size_t  nbytes 
) [static]

Definition at line 198 of file vbr.c.

{
       assert(vbr != NULL);

       if (vbr->vbr_malloc == NULL)
              return malloc(nbytes);
       else
              return vbr->vbr_malloc(closure, nbytes);
}

Here is the caller graph for this function:

void vbr_options ( VBR *  vbr,
unsigned int  opts 
)

Definition at line 729 of file vbr.c.

{
       assert(vbr != NULL);

       vbr->vbr_opts = opts;
}
VBR_STAT vbr_query ( VBR *  vbr,
u_char **  res,
u_char **  cert 
)

Definition at line 965 of file vbr.c.

{
       int c;
       int n;
       int status;
       int dnserr;
       struct vbr_query *vq;
       void *qh;
       u_char *p;
       u_char *last;
       u_char *last2;
       u_char *p2;
       struct timeval timeout;
       u_char certs[VBR_MAXHEADER + 1];
       u_char query[VBR_MAXHOSTNAMELEN + 1];
       unsigned char buf[BUFRSZ];

       assert(vbr != NULL);
       assert(res != NULL);
       assert(cert != NULL);

       if (vbr->vbr_type == NULL ||
           vbr->vbr_cert == NULL ||
           vbr->vbr_trusted == NULL)
       {
              vbr_error(vbr, "required data for VBR check missing");
              return VBR_STAT_INVALID;
       }

       strlcpy((char *) certs, vbr->vbr_cert, sizeof certs);

       if (vbr->vbr_malloc != NULL)
              vq = vbr->vbr_malloc(vbr->vbr_closure, sizeof(*vq));
       else
              vq = malloc(sizeof(*vq));

       if (vq == NULL)
              return VBR_STAT_NORESOURCE;

       memset(vq, '\0', sizeof *vq);

       for (c = 0; ; c++)
       {
              if ((vbr->vbr_opts & VBR_OPT_TRUSTEDONLY) != 0)
              {
                     /*
                     **  Query our trusted vouchers regardless of what the
                     **  sender said.
                     */

                     if (vbr->vbr_trusted[c] == NULL)
                            break;
                     else
                            p = vbr->vbr_trusted[c];
              }
              else
              {
                     /*
                     **  Query the sender's vouchers that also appear in our
                     **  trusted voucher list.
                     */

                     _Bool found;

                     p = (u_char *) strtok_r(c == 0 ? (char *) certs : NULL,
                                             ":", (char **) &last);
                     if (p == NULL)
                            break;

                     found = FALSE;

                     for (n = 0; vbr->vbr_trusted[n] != NULL; n++)
                     {
                            if (strcasecmp((char *) p,
                                           (char *) vbr->vbr_trusted[n]) == 0)
                            {
                                   found = TRUE;
                                   break;
                            }
                     }

                     if (!found)
                            continue;
              }      

              snprintf((char *) query, sizeof query, "%s.%s.%s",
                       vbr->vbr_domain, VBR_PREFIX, p);

              qh = NULL;

              status = vbr->vbr_dns_start(vbr->vbr_dns_service, T_TXT, query,
                                          vq->vq_buf, sizeof vq->vq_buf,
                                          &vq->vq_qh);

              if (status != VBR_STAT_OK)
              {
                     snprintf(vbr->vbr_error, sizeof vbr->vbr_error,
                              "unable to start query for '%s'",
                              query);
                     return VBR_STAT_DNSERROR;
              }

              timeout.tv_sec = vbr->vbr_timeout;
              timeout.tv_usec = 0;

              if (vbr->vbr_dns_callback == NULL)
              {
                     status = vbr->vbr_dns_waitreply(vbr->vbr_dns_service,
                                                     vq->vq_qh,
                                                     &timeout,
                                                     &vq->vq_buflen,
                                                     &dnserr,
                                                     NULL);
              }
              else
              {
                     struct timeval *to;
                     struct timeval wstart;
                     struct timeval wstop;
                     struct timeval ctimeout;

                     wstop.tv_sec = 0;
                     wstop.tv_usec = 0;

                     for (;;)
                     {
                            (void) gettimeofday(&wstart, NULL);

                            ctimeout.tv_sec = vbr->vbr_callback_int;
                            ctimeout.tv_usec = 0;

                            timeout.tv_sec = vbr->vbr_timeout;
                            timeout.tv_usec = 0;

                            vbr_timeouts(&timeout, &ctimeout,
                                         &wstart, &wstop,
                                         &to);

                            status = vbr->vbr_dns_waitreply(vbr->vbr_dns_service,
                                                            vq->vq_qh,
                                                            to,
                                                            &vq->vq_buflen,
                                                            &dnserr,
                                                            NULL);

                            (void) gettimeofday(&wstop, NULL);

                            if (status != VBR_DNS_NOREPLY ||
                                to == &timeout)
                                   break;

                            vbr->vbr_dns_callback(vbr->vbr_user_context);
                     }
              }

              vbr->vbr_dns_cancel(vbr->vbr_dns_service, vq->vq_qh);

              if (status == VBR_DNS_ERROR || status == VBR_DNS_EXPIRED)
              {
                     vbr_error(vbr, "failed to retrieve %s", query);
                     return VBR_STAT_DNSERROR;
              }

              /* try to decode the reply */
              if (!vbr_txt_decode(vq->vq_buf, vq->vq_buflen,
                                  buf, sizeof buf))
                     continue;

              /* see if there's a vouch match */
              for (p2 = (u_char *) strtok_r((char *) buf, " \t",
                                            (char **) &last2);
                   p2 != NULL;
                   p2 = (u_char *) strtok_r(NULL, " \t",
                                            (char **) &last2))
              {
                     if (strcasecmp((char *) p2, VBR_ALL) == 0 ||
                         strcasecmp((char *) p2,
                                    (char *) vbr->vbr_type) == 0)
                     {
                            /* we have a winner! */
                            *res = (u_char *) "pass";
                            *cert = p;
                            return VBR_STAT_OK;
                     }
              }
       }

       /* nobody vouched */
       *res = (u_char *) "fail";
       return VBR_STAT_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int vbr_res_cancel ( void *  srv,
void *  qh 
) [static]

Definition at line 409 of file vbr.c.

{
       if (qh != NULL)
              free(qh);

       return 0;
}

Here is the caller graph for this function:

static int vbr_res_query ( void *  srv,
int  type,
unsigned char *  query,
unsigned char *  buf,
size_t  buflen,
void **  qh 
) [static]

Definition at line 439 of file vbr.c.

{
       int n;
       int ret;
       struct vbr_query *vq;
       unsigned char qbuf[HFIXEDSZ + MAXPACKET];
#ifdef HAVE_RES_NINIT
       struct __res_state statp;
#endif /* HAVE_RES_NINIT */

#ifdef HAVE_RES_NINIT
       memset(&statp, '\0', sizeof statp);
       res_ninit(&statp);
#endif /* HAVE_RES_NINIT */

#ifdef HAVE_RES_NINIT
       n = res_nmkquery(&statp, QUERY, (char *) query, C_IN, type, NULL, 0,
                        NULL, qbuf, sizeof qbuf);
#else /* HAVE_RES_NINIT */
       n = res_mkquery(QUERY, (char *) query, C_IN, type, NULL, 0, NULL, qbuf,
                       sizeof qbuf);
#endif /* HAVE_RES_NINIT */
       if (n == (size_t) -1)
       {
#ifdef HAVE_RES_NINIT
              res_nclose(&statp);
#endif /* HAVE_RES_NINIT */
              return VBR_DNS_ERROR;
       }

#ifdef HAVE_RES_NINIT
       ret = res_nsend(&statp, qbuf, n, buf, buflen);
#else /* HAVE_RES_NINIT */
       ret = res_send(qbuf, n, buf, buflen);
#endif /* HAVE_RES_NINIT */
       if (ret == -1)
       {
#ifdef HAVE_RES_NINIT
              res_nclose(&statp);
#endif /* HAVE_RES_NINIT */
              return VBR_DNS_ERROR;
       }

#ifdef HAVE_RES_NINIT
       res_nclose(&statp);
#endif /* HAVE_RES_NINIT */

       vq = (struct vbr_query *) malloc(sizeof *vq);
       if (vq == NULL)
              return VBR_DNS_ERROR;

       if (ret == -1)
       {
              vq->vq_error = errno;
              vq->vq_buflen = 0;
       }
       else
       {
              vq->vq_error = 0;
              vq->vq_buflen = (size_t) ret;
       }

       *qh = (void *) vq;

       return VBR_DNS_SUCCESS;
}

Here is the caller graph for this function:

int vbr_res_waitreply ( void *  srv,
void *  qh,
struct timeval *  to,
size_t *  bytes,
int *  error,
int *  dnssec 
)

Definition at line 526 of file vbr.c.

{
       struct vbr_query *vq;

       assert(qh != NULL);

       vq = qh;

       if (bytes != NULL)
              *bytes = vq->vq_buflen;
       if (error != NULL)
              *error = vq->vq_error;

       return VBR_DNS_SUCCESS;
}

Here is the caller graph for this function:

VBR_STAT vbr_setcallbackctx ( VBR *  vbr,
void *  ctx 
)

Definition at line 835 of file vbr.c.

{
       assert(vbr != NULL);

       vbr->vbr_user_context = ctx;
       return VBR_STAT_OK;
}
VBR_STAT vbr_setcallbackint ( VBR *  vbr,
u_int  cbint 
)

Definition at line 815 of file vbr.c.

{
       assert(vbr != NULL);

       vbr->vbr_callback_int = cbint;
       return VBR_STAT_OK;
}
void vbr_setcert ( VBR *  vbr,
u_char *  cert 
)

Definition at line 895 of file vbr.c.

{
       assert(vbr != NULL);
       assert(cert != NULL);

       vbr->vbr_cert = cert;
}

Here is the caller graph for this function:

VBR_STAT vbr_setdnscallback ( VBR *  vbr,
void(*)(const void *context)  func 
)

Definition at line 855 of file vbr.c.

{
       assert(vbr != NULL);

       vbr->vbr_dns_callback = func;
       return VBR_STAT_OK;
}
void vbr_setdomain ( VBR *  vbr,
u_char *  domain 
)

Definition at line 875 of file vbr.c.

{
       assert(vbr != NULL);
       assert(domain != NULL);

       vbr->vbr_domain = domain;
}

Here is the caller graph for this function:

VBR_STAT vbr_settimeout ( VBR *  vbr,
u_int  timeout 
)

Definition at line 795 of file vbr.c.

{
       assert(vbr != NULL);

       vbr->vbr_timeout = timeout;
       return VBR_STAT_OK;
}
void vbr_settype ( VBR *  vbr,
u_char *  type 
)

Definition at line 915 of file vbr.c.

{
       assert(vbr != NULL);
       assert(type != NULL);

       vbr->vbr_type = type;
}

Here is the caller graph for this function:

size_t vbr_strlcpy ( char *  dst,
const char *  src,
ssize_t  size 
)

Definition at line 166 of file vbr.c.

{
       register ssize_t i;

       if (size-- <= 0)
              return strlen(src);
       for (i = 0; i < size && (dst[i] = src[i]) != 0; i++)
              continue;
       dst[i] = '\0';
       if (src[i] == '\0')
              return i;
       else
              return i + strlen(src + i);
}
static void vbr_timeouts ( struct timeval *  timeout,
struct timeval *  ctimeout,
struct timeval *  wstart,
struct timeval *  wstop,
struct timeval **  next 
) [static]

Definition at line 337 of file vbr.c.

{
       assert(timeout != NULL);
       assert(ctimeout != NULL);
       assert(wstart != NULL);
       assert(wstop != NULL);
       assert(next != NULL);

       if (wstop->tv_sec == 0 && wstop->tv_usec == 0)
       {
              /* first pass */
              if (timeout->tv_sec < ctimeout->tv_sec ||
                  (timeout->tv_sec == ctimeout->tv_sec &&
                   timeout->tv_usec < ctimeout->tv_usec))
                     *next = timeout;
              else
                     *next = ctimeout;
       }
       else
       {
              struct timeval to1;
              struct timeval to2;

              /* compute start through overall timeout */
              memcpy(&to1, wstart, sizeof to1);
              to1.tv_sec += timeout->tv_sec;
              to1.tv_usec += timeout->tv_usec;
              if (to1.tv_usec > 1000000)
              {
                     to1.tv_sec += (to1.tv_usec / 1000000);
                     to1.tv_usec = (to1.tv_usec % 1000000);
              }

              /* compute stop through callback timeout */
              memcpy(&to2, wstop, sizeof to2);
              to2.tv_sec += ctimeout->tv_sec;
              to2.tv_usec += ctimeout->tv_usec;
              if (to2.tv_usec > 1000000)
              {
                     to2.tv_sec += (to2.tv_usec / 1000000);
                     to2.tv_usec = (to2.tv_usec % 1000000);
              }

              /* ...and decide */
              if (to1.tv_sec < to2.tv_sec ||
                  (to1.tv_sec == to2.tv_sec &&
                   to1.tv_usec < to2.tv_usec))
                     *next = timeout;
              else
                     *next = ctimeout;
       }
}

Here is the caller graph for this function:

void vbr_trustedcerts ( VBR *  vbr,
u_char **  certs 
)

Definition at line 935 of file vbr.c.

{
       assert(vbr != NULL);
       assert(certs != NULL);

       vbr->vbr_trusted = certs;
}
static _Bool vbr_txt_decode ( u_char *  ansbuf,
size_t  anslen,
u_char *  buf,
size_t  buflen 
) [static]

Definition at line 557 of file vbr.c.

{
       int type = -1;
       int class = -1;
       int qdcount;
       int ancount;
       int n;
       int c;
       u_char *cp;
       u_char *eom;
       u_char *p;
       HEADER hdr;
       char qname[VBR_MAXHOSTNAMELEN + 1];

       assert(ansbuf != NULL);
       assert(buf != NULL);

       /* set up pointers */
       memcpy(&hdr, ansbuf, sizeof hdr);
       cp = ansbuf + HFIXEDSZ;
       eom = ansbuf + anslen;

       /* skip over the name at the front of the answer */
       for (qdcount = ntohs((unsigned short) hdr.qdcount);
            qdcount > 0;
            qdcount--)
       {
              /* copy it first */
              (void) dn_expand(ansbuf, eom, cp, qname, sizeof qname);

              if ((n = dn_skipname(cp, eom)) < 0)
                     return FALSE;
              cp += n;

              /* extract the type and class */
              if (cp + INT16SZ + INT16SZ > eom)
                     return FALSE;

              GETSHORT(type, cp);
              GETSHORT(class, cp);
       }

       if (type != T_TXT || class != C_IN)
              return FALSE;

       if (hdr.rcode == NXDOMAIN)
              return FALSE;

       /* get the answer count */
       ancount = ntohs((unsigned short) hdr.ancount);
       if (ancount == 0)
              return FALSE;

       /* if truncated, we can't do it */
       if (hdr.tc)
              return FALSE;

       /* grab the label, even though we know what we asked... */
       if ((n = dn_expand(ansbuf, eom, cp, (RES_UNC_T) qname,
                          sizeof qname)) < 0)
              return FALSE;
       /* ...and move past it */
       cp += n;

       /* extract the type and class */
       if (cp + INT16SZ + INT16SZ > eom)
              return FALSE;
       GETSHORT(type, cp);
       GETSHORT(class, cp);

       /* reject anything that's not valid (stupid wildcards) */
       if (type != T_TXT || class != C_IN)
              return FALSE;

       /* skip the TTL */
       cp += INT32SZ;

       /* get payload length */
       if (cp + INT16SZ > eom)
              return FALSE;
       GETSHORT(n, cp);

       /* XXX -- maybe deal with a partial reply rather than require it all */
       if (cp + n > eom)
              return FALSE;

       if (n > buflen)
              return FALSE;

       /* extract the payload */
       memset(buf, '\0', buflen);
       p = buf;
       while (n > 0)
       {
              c = *cp++;
              n--;
              while (c > 0)
              {
                     *p++ = *cp++;
                     c--;
                     n--;
              }
       }

       return TRUE;
}

Here is the caller graph for this function:

static void vbr_verror ( VBR *  vbr,
const char *  format,
va_list  va 
) [static]

Definition at line 244 of file vbr.c.

{
       int flen;
       int saverr;
       u_char *new;

       assert(vbr != NULL);
       assert(format != NULL);

       saverr = errno;

       if (vbr->vbr_error == NULL)
       {
              vbr->vbr_error = vbr_malloc(vbr, vbr->vbr_closure, DEFERRLEN);
              if (vbr->vbr_error == NULL)
              {
                     errno = saverr;
                     return;
              }
              vbr->vbr_errlen = DEFERRLEN;
       }

       for (;;)
       {
              flen = vsnprintf((char *) vbr->vbr_error, vbr->vbr_errlen,
                               format, va);

              /* compensate for broken vsnprintf() implementations */
              if (flen == -1)
                     flen = vbr->vbr_errlen * 2;

              if (flen >= vbr->vbr_errlen)
              {
                     new = vbr_malloc(vbr, vbr->vbr_closure, flen + 1);
                     if (new == NULL)
                     {
                            errno = saverr;
                            return;
                     }

                     vbr_free(vbr, vbr->vbr_closure, vbr->vbr_error);
                     vbr->vbr_error = new;
                     vbr->vbr_errlen = flen + 1;
              }
              else
              {
                     break;
              }
       }

       errno = saverr;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char vbr_c_id[] = "@(#)$Id: vbr.c,v 1.5.2.1 2010/10/27 21:43:09 cm-msk Exp $" [static]

Definition at line 9 of file vbr.c.