Back to index

opendkim  2.6.4
Defines | Typedefs | Functions | Variables
async-resolv.h File Reference
#include <sys/types.h>
#include <sys/time.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define NULL   0
#define FALSE   0
#define TRUE   1
#define AR_FLAG_USETCP   0x01 /* use TCP instead of UDP */
#define AR_FLAG_DEAD   0x02 /* service now unavailable */
#define AR_FLAG_TRUNCCHECK   0x04 /* limited truncation checks */
#define AR_FLAG_RECONNECT   0x08 /* pending reconnect */
#define AR_FLAG_TRACELOGGING   0x10 /* debug logging */
#define AR_STAT_ERROR   (-1) /* error in transit */
#define AR_STAT_SUCCESS   0 /* reply available */
#define AR_STAT_NOREPLY   1 /* reply not available (yet) */
#define AR_STAT_EXPIRED   2 /* no reply, query expired */
#define QUERY_ERRNO_TOOBIG   (-1) /* query too large */
#define QUERY_ERRNO_RETRIES   (-2) /* too many retries */
#define QUERY_ERRNO_SERVICE   (-3) /* lost contact with DNS */
#define AR_DEFREVIVIFY   2 /* how long to play dead */
#define AR_MAXTIMEOUT   10000000 /* max. allowed timeout (s) */

Typedefs

typedef struct ar_libhandleAR_LIB
typedef struct ar_queryAR_QUERY
typedef void * ar_malloc_t (void *, size_t)
typedef void ar_free_t (void *, void *)

Functions

AR_QUERY ar_addquery (AR_LIB, char *, int, int, int, unsigned char *, size_t, int *, struct timeval *)
int ar_cancelquery (AR_LIB, AR_QUERY)
char * ar_strerror (int)
int ar_waitreply (AR_LIB, AR_QUERY, size_t *, struct timeval *)
AR_LIB ar_init (ar_malloc_t *, ar_free_t *, void *, int)
void ar_recycle (AR_LIB, AR_QUERY)
int ar_resend (AR_LIB, AR_QUERY)
void ar_setmaxretry (AR_LIB, int, int *)
void ar_setretry (AR_LIB, struct timeval *, struct timeval *)
int ar_shutdown (AR_LIB)

Variables

static char async_resolv_h_id [] = "@(#)$Id: ar.h,v 1.4 2010/09/02 05:10:57 cm-msk Exp $"

Define Documentation

#define AR_DEFREVIVIFY   2 /* how long to play dead */

Definition at line 57 of file async-resolv.h.

#define AR_FLAG_DEAD   0x02 /* service now unavailable */

Definition at line 43 of file async-resolv.h.

#define AR_FLAG_RECONNECT   0x08 /* pending reconnect */

Definition at line 45 of file async-resolv.h.

#define AR_FLAG_TRACELOGGING   0x10 /* debug logging */

Definition at line 46 of file async-resolv.h.

#define AR_FLAG_TRUNCCHECK   0x04 /* limited truncation checks */

Definition at line 44 of file async-resolv.h.

#define AR_FLAG_USETCP   0x01 /* use TCP instead of UDP */

Definition at line 42 of file async-resolv.h.

#define AR_MAXTIMEOUT   10000000 /* max. allowed timeout (s) */

Definition at line 58 of file async-resolv.h.

#define AR_STAT_ERROR   (-1) /* error in transit */

Definition at line 48 of file async-resolv.h.

#define AR_STAT_EXPIRED   2 /* no reply, query expired */

Definition at line 51 of file async-resolv.h.

#define AR_STAT_NOREPLY   1 /* reply not available (yet) */

Definition at line 50 of file async-resolv.h.

#define AR_STAT_SUCCESS   0 /* reply available */

Definition at line 49 of file async-resolv.h.

#define FALSE   0

Definition at line 24 of file async-resolv.h.

#define NULL   0

Definition at line 21 of file async-resolv.h.

#define QUERY_ERRNO_RETRIES   (-2) /* too many retries */

Definition at line 54 of file async-resolv.h.

#define QUERY_ERRNO_SERVICE   (-3) /* lost contact with DNS */

Definition at line 55 of file async-resolv.h.

#define QUERY_ERRNO_TOOBIG   (-1) /* query too large */

Definition at line 53 of file async-resolv.h.

#define TRUE   1

Definition at line 27 of file async-resolv.h.


Typedef Documentation

typedef void ar_free_t(void *, void *)

Definition at line 39 of file async-resolv.h.

typedef struct ar_libhandle* AR_LIB

Definition at line 32 of file async-resolv.h.

typedef void* ar_malloc_t(void *, size_t)

Definition at line 38 of file async-resolv.h.

typedef struct ar_query* AR_QUERY

Definition at line 35 of file async-resolv.h.


Function Documentation

AR_QUERY ar_addquery ( AR_LIB  ,
char *  ,
int  ,
int  ,
int  ,
unsigned char *  ,
size_t  ,
int *  ,
struct timeval *   
)

Definition at line 2283 of file ar.c.

{
       char prev;
       int status;
       size_t wlen;
       AR_QUERY q;
       char *p;

       assert(lib != NULL);
       assert(name != NULL);

       /*
       **  Sanity-check the name.  Look for invalid characters or patterns
       **  that will make res_mkquery() return -1 for reasons other than
       **  "buffer too short".
       **
       **  In particular, look for:
       **     - non-ASCII characters
       **     - non-printable characters
       **     - things that start with "."
       **     - things that contain adjacent "."s
       */

       wlen = 0;
       prev = '\0';
       for (p = name; *p != '\0'; p++)
       {
              if (!isascii(*p) || !isprint(*p) ||
                  (*p == '.' && (prev == '.' || prev == '\0')))
              {
                     if (err != NULL)
                            *err = EINVAL;
                     errno = EINVAL;
                     return NULL;
              }

              prev = *p;
       }

       /* sanity-check the timeout, if provided */
       if (timeout != NULL)
       {
              if (timeout->tv_sec < 0 || timeout->tv_sec > AR_MAXTIMEOUT ||
                  timeout->tv_usec < 0 || timeout->tv_usec >= 1000000)
              {
                     if (err != NULL)
                            *err = EINVAL;
                     errno = EINVAL;
                     return NULL;
              }
       }

       pthread_mutex_lock(&lib->ar_lock);

       /* start the dispatcher if it's not already running */
       if (lib->ar_drun == 0)
       {
              status = pthread_create(&lib->ar_dispatcher, NULL,
                                      ar_dispatcher, lib);
              if (status != 0)
              {
                     if (err != NULL)
                            *err = status;
                     errno = status;
                     pthread_mutex_unlock(&lib->ar_lock);
                     return NULL;
              }

              lib->ar_drun = 1;
       }

       if ((lib->ar_flags & AR_FLAG_DEAD) != 0)
       {
              if (err != NULL)
                     *err = lib->ar_deaderrno;
              errno = lib->ar_deaderrno;
              pthread_mutex_unlock(&lib->ar_lock);
              return NULL;
       }

       if (lib->ar_recycle != NULL)
       {
              q = lib->ar_recycle;
              lib->ar_recycle = q->q_next;
              pthread_mutex_unlock(&lib->ar_lock);
       }
       else
       {
              pthread_mutex_unlock(&lib->ar_lock);
              q = ar_malloc(lib, sizeof(struct ar_query));
              if (q == NULL)
              {
                     if (err != NULL)
                            *err = errno;
                     return NULL;
              }
              memset(q, '\0', sizeof(struct ar_query));
              pthread_mutex_init(&q->q_lock, NULL);
              pthread_cond_init(&q->q_reply, NULL);
       }

       /* construct the query */
       q->q_class = class;
       q->q_type = type;
       q->q_flags = 0;
       q->q_depth = depth;
       q->q_errno = err;
       q->q_next = NULL;
       q->q_buf = buf;
       q->q_buflen = buflen;
       q->q_tries = 0;
       if (timeout == NULL)
       {
              q->q_flags |= QUERY_INFINIWAIT;
              q->q_timeout.tv_sec = 0;
              q->q_timeout.tv_usec = 0;
       }
       else
       {
              (void) gettimeofday(&q->q_timeout, NULL);
              q->q_timeout.tv_sec += timeout->tv_sec;
              q->q_timeout.tv_usec += timeout->tv_usec;
              if (q->q_timeout.tv_usec >= 1000000)
              {
                     q->q_timeout.tv_sec += 1;
                     q->q_timeout.tv_usec -= 1000000;
              }
       }
       strlcpy(q->q_name, name, sizeof q->q_name);

       /* enqueue the query and signal the dispatcher */
       pthread_mutex_lock(&lib->ar_lock);
       if (lib->ar_pending == NULL)
       {
              lib->ar_pending = q;
              lib->ar_pendingtail = q;
       }
       else
       {
              lib->ar_pendingtail->q_next = q;
              lib->ar_pendingtail = q;
       }

       wlen = ar_poke(lib);

       if ((lib->ar_flags & AR_FLAG_TRACELOGGING) != 0)
       {
              syslog(LOG_DEBUG, "arlib: added query %p %d/%d '%s'",
                     q, q->q_class, q->q_type, q->q_name);
       }

       pthread_mutex_unlock(&lib->ar_lock);

       switch (wlen)
       {
         case sizeof q:
              return q;

         default:
              ar_recycle(lib, q);
              return NULL;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ar_cancelquery ( AR_LIB  ,
AR_QUERY   
)

Definition at line 2462 of file ar.c.

{
       AR_QUERY q;
       AR_QUERY last;

       assert(lib != NULL);
       assert(query != NULL);

       pthread_mutex_lock(&lib->ar_lock);

       if ((lib->ar_flags & AR_FLAG_TRACELOGGING) != 0)
              syslog(LOG_DEBUG, "arlib: canceling query %p", query);

       /* first, look in pending queries */
       for (q = lib->ar_pending, last = NULL;
            q != NULL;
            last = q, q = q->q_next)
       {
              if (query == q)
              {
                     if (last == NULL)
                     {
                            lib->ar_pending = q->q_next;
                            if (lib->ar_pending == NULL)
                                   lib->ar_pendingtail = NULL;
                     }
                     else
                     {
                            last->q_next = q->q_next;
                            if (lib->ar_pendingtail == q)
                                   lib->ar_pendingtail = last;
                     }

                     q->q_next = lib->ar_recycle;
                     if ((q->q_flags & QUERY_RESEND) != 0)
                            lib->ar_resend--;
                     lib->ar_recycle = q;

                     pthread_mutex_unlock(&lib->ar_lock);
                     return 0;
              }
       }
       
       /* next, look in active queries */
       for (q = lib->ar_queries, last = NULL;
            q != NULL;
            last = q, q = q->q_next)
       {
              if (query == q)
              {
                     if (last == NULL)
                     {
                            lib->ar_queries = q->q_next;
                            if (lib->ar_queries == NULL)
                                   lib->ar_queriestail = NULL;

                     }
                     else
                     {
                            last->q_next = q->q_next;
                            if (lib->ar_queriestail == q)
                                   lib->ar_queriestail = last;
                     }

                     q->q_next = lib->ar_recycle;
                     if ((q->q_flags & QUERY_RESEND) != 0)
                            lib->ar_resend--;
                     lib->ar_recycle = q;

                     pthread_mutex_unlock(&lib->ar_lock);
                     return 0;
              }
       }

       pthread_mutex_unlock(&lib->ar_lock);

       if ((lib->ar_flags & AR_FLAG_TRACELOGGING) != 0)
              syslog(LOG_DEBUG, "arlib: cancel failed for query %p", query);

       return 1;
}

Here is the caller graph for this function:

AR_LIB ar_init ( ar_malloc_t ,
ar_free_t ,
void *  ,
int   
)
void ar_recycle ( AR_LIB  ,
AR_QUERY   
)

Definition at line 2738 of file ar.c.

{
       assert(lib != NULL);
       assert(query != NULL);

       pthread_mutex_lock(&lib->ar_lock);
       query->q_next = lib->ar_recycle;
       lib->ar_recycle = query;
       pthread_mutex_unlock(&lib->ar_lock);
}

Here is the caller graph for this function:

int ar_resend ( AR_LIB  ,
AR_QUERY   
)

Definition at line 2761 of file ar.c.

{
       size_t wlen;

       assert(lib != NULL);
       assert(query != NULL);

       wlen = write(lib->ar_control[1], query, sizeof query);
       return (wlen == 4 ? 0 : -1);
}
void ar_setmaxretry ( AR_LIB  ,
int  ,
int *   
)

Definition at line 2210 of file ar.c.

{
       assert(lib != NULL);

       if (old != NULL)
              *old = lib->ar_retries;

       if (new != -1)
              lib->ar_retries = new;
}
void ar_setretry ( AR_LIB  ,
struct timeval *  ,
struct timeval *   
)

Definition at line 2186 of file ar.c.

{
       assert(lib != NULL);

       if (old != NULL)
              memcpy(old, &lib->ar_retry, sizeof lib->ar_retry);

       if (new != NULL)
              memcpy(&lib->ar_retry, new, sizeof lib->ar_retry);
}
int ar_shutdown ( AR_LIB  )

Definition at line 2120 of file ar.c.

{
       int status;

       assert(lib != NULL);

       close(lib->ar_control[0]);

       if ((lib->ar_flags & AR_FLAG_TRACELOGGING) != 0)
              syslog(LOG_DEBUG, "arlib: shutting down");

       status = 0;

       if (lib->ar_drun != 0)
              status = pthread_join(lib->ar_dispatcher, NULL);

       if (status == 0)
       {
              void *closure;
              void (*user_free)(void *, void *);

              close(lib->ar_nsfd);
              close(lib->ar_control[1]);
              pthread_mutex_destroy(&lib->ar_lock);

              ar_smashqueue(lib, lib->ar_pending);
              ar_smashqueue(lib, lib->ar_queries);
              ar_smashqueue(lib, lib->ar_recycle);

              if (lib->ar_tcpbuf != NULL)
                     ar_free(lib, lib->ar_tcpbuf);
              ar_free(lib, lib->ar_querybuf);
              ar_free(lib, lib->ar_nsaddrs);

              closure = lib->ar_closure;
              user_free = lib->ar_free;

              ar_socket_free(lib->ar_css);
              ar_socket_free(lib->ar_dss);

              if (user_free != NULL)
                     user_free(closure, lib);
              else
                     free(lib);
       }

#ifdef ARDEBUG
       ar_debug_stop();
#endif /* ARDEBUG */

       return status;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* ar_strerror ( int  )

Definition at line 2783 of file ar.c.

{
       switch (err)
       {
         case QUERY_ERRNO_RETRIES:
              return "Too many retries";

         case QUERY_ERRNO_TOOBIG:
              return "Unable to construct query";

         default:
              return strerror(errno);
       }
}
int ar_waitreply ( AR_LIB  ,
AR_QUERY  ,
size_t *  ,
struct timeval *   
)

Definition at line 2568 of file ar.c.

{
       _Bool infinite;
       _Bool maintimeout = FALSE;
       int status;
       struct timespec until;
       struct timeval now;

       assert(lib != NULL);
       assert(query != NULL);

       if ((lib->ar_flags & AR_FLAG_TRACELOGGING) != 0)
              syslog(LOG_DEBUG, "arlib: waiting for query %p", query);

       pthread_mutex_lock(&query->q_lock);

       if ((query->q_flags & QUERY_REPLY) != 0)
       {
              if (len != NULL)
                     *len = query->q_replylen;
              pthread_mutex_unlock(&query->q_lock);

              if ((lib->ar_flags & AR_FLAG_TRACELOGGING) != 0)
              {
                     syslog(LOG_DEBUG, "arlib: wait for %p successful",
                            query);
              }

              return AR_STAT_SUCCESS;
       }
       else if ((query->q_flags & QUERY_ERROR) != 0)
       {
              pthread_mutex_unlock(&query->q_lock);

              if ((lib->ar_flags & AR_FLAG_TRACELOGGING) != 0)
              {
                     syslog(LOG_DEBUG, "arlib: wait for %p error [1]",
                            query);
              }

              return AR_STAT_ERROR;
       }
       else if ((query->q_flags & QUERY_NOREPLY) != 0)
       {
              if (query->q_errno != NULL)
                     *query->q_errno = ETIMEDOUT;
              pthread_mutex_unlock(&query->q_lock);

              if ((lib->ar_flags & AR_FLAG_TRACELOGGING) != 0)
              {
                     syslog(LOG_DEBUG, "arlib: wait for %p expired",
                            query);
              }

              return AR_STAT_EXPIRED;
       }

       /*
       **  Pick the soonest of:
       **  - timeout specified above
       **  - timeout specified on the query
       **  - forever
       */

       (void) gettimeofday(&now, NULL);
       infinite = FALSE;
       until.tv_sec = 0;
       until.tv_nsec = 0;

       if (timeout == NULL && (query->q_flags & QUERY_INFINIWAIT) != 0)
       {
              infinite = TRUE;
       }
       else
       {
              /* if a timeout was specified above */
              if (timeout != NULL)
              {
                     until.tv_sec = now.tv_sec + timeout->tv_sec;
                     until.tv_nsec = now.tv_usec + timeout->tv_usec;
                     if (until.tv_nsec >= 1000000)
                     {
                            until.tv_sec += 1;
                            until.tv_nsec -= 1000000;
                     }
                     until.tv_nsec *= 1000;
              }

              /* if a timeout was specified on the query */
              if ((query->q_flags & QUERY_INFINIWAIT) == 0)
              {
                     if (until.tv_sec == 0 ||
                         until.tv_sec > query->q_timeout.tv_sec ||
                         (until.tv_sec == query->q_timeout.tv_sec &&
                          until.tv_nsec > query->q_timeout.tv_usec * 1000))
                     {
                            until.tv_sec = query->q_timeout.tv_sec;
                            until.tv_nsec = query->q_timeout.tv_usec * 1000;
                            maintimeout = TRUE;
                     }
              }
       }

       while ((query->q_flags & (QUERY_REPLY|QUERY_NOREPLY|QUERY_ERROR)) == 0)
       {
              if (infinite)
              {
                     status = pthread_cond_wait(&query->q_reply,
                                                &query->q_lock);
              }
              else
              {
                     status = pthread_cond_timedwait(&query->q_reply,
                                                     &query->q_lock,
                                                     &until);
                     if (status == ETIMEDOUT)
                            break;
              }
       }

       /* recheck flags */
       if ((query->q_flags & QUERY_ERROR) != 0)
       {
              pthread_mutex_unlock(&query->q_lock);

              if ((lib->ar_flags & AR_FLAG_TRACELOGGING) != 0)
              {
                     syslog(LOG_DEBUG, "arlib: wait for %p error [2]",
                            query);
              }

              return AR_STAT_ERROR;
       }
       else if ((query->q_flags & QUERY_REPLY) == 0)
       {
              if (maintimeout && query->q_errno != NULL)
                     *query->q_errno = ETIMEDOUT;
              pthread_mutex_unlock(&query->q_lock);

              if ((lib->ar_flags & AR_FLAG_TRACELOGGING) != 0)
              {
                     syslog(LOG_DEBUG, "arlib: wait for %p timeout (%s)",
                            query, maintimeout ? "expired" : "no reply");
              }

              return (maintimeout ? AR_STAT_EXPIRED : AR_STAT_NOREPLY);
       }

       if (len != NULL)
              *len = query->q_replylen;
       pthread_mutex_unlock(&query->q_lock);

       if ((lib->ar_flags & AR_FLAG_TRACELOGGING) != 0)
              syslog(LOG_DEBUG, "arlib: wait for %p succeeded", query);

       return AR_STAT_SUCCESS;
}

Here is the caller graph for this function:


Variable Documentation

char async_resolv_h_id[] = "@(#)$Id: ar.h,v 1.4 2010/09/02 05:10:57 cm-msk Exp $" [static]

Definition at line 12 of file async-resolv.h.