Back to index

opendkim  2.6.2
dkim-dns.c
Go to the documentation of this file.
00001 /*
00002 **  Copyright (c) 2010, 2011, The OpenDKIM Project.  All rights reserved.
00003 **
00004 **  $Id: dkim-dns.c,v 1.6.4.1 2010/10/27 21:43:08 cm-msk Exp $
00005 */
00006 
00007 #ifndef lint
00008 static char dkim_dns_c_id[] = "@(#)$Id: dkim-dns.c,v 1.6.4.1 2010/10/27 21:43:08 cm-msk Exp $";
00009 #endif /* !lint */
00010 
00011 /* for Solaris */
00012 #ifndef _REENTRANT
00013 # define _REENTRANT
00014 #endif /* ! REENTRANT */
00015 
00016 /* system includes */
00017 #include <sys/param.h>
00018 #include <sys/types.h>
00019 #include <netinet/in.h>
00020 #include <arpa/nameser.h>
00021 #include <resolv.h>
00022 #include <netdb.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <assert.h>
00026 #include <errno.h>
00027 
00028 /* libopendkim includes */
00029 #include "dkim.h"
00030 #include "dkim-dns.h"
00031 
00032 /* OpenDKIM includes */
00033 #include "build-config.h"
00034 
00035 /* macros, limits, etc. */
00036 #ifndef MAXPACKET
00037 # define MAXPACKET      8192
00038 #endif /* ! MAXPACKET */
00039 
00040 /*
00041 **  Standard UNIX resolver stub functions
00042 */
00043 
00044 struct dkim_res_qh
00045 {
00046        int           rq_error;
00047        int           rq_dnssec;
00048        size_t        rq_buflen;
00049 };
00050 
00051 /*
00052 **  DKIM_RES_CANCEL -- cancel a pending resolver query
00053 **
00054 **  Parameters:
00055 **     srv -- query service handle (ignored)
00056 **     qh -- query handle (ignored)
00057 **
00058 **  Return value:
00059 **     0 on success, !0 on error
00060 **
00061 **  Notes:
00062 **     The standard UNIX resolver is synchronous, so in theory this can
00063 **     never get called.  We have not yet got any use cases for one thread
00064 **     canceling another thread's pending queries, so for now just return 0.
00065 */
00066 
00067 int
00068 dkim_res_cancel(void *srv, void *qh)
00069 {
00070        if (qh != NULL)
00071               free(qh);
00072 
00073        return 0;
00074 }
00075 
00076 /*
00077 **  DKIM_RES_QUERY -- initiate a DNS query
00078 **
00079 **  Parameters:
00080 **     srv -- service handle (ignored)
00081 **     type -- RR type to query
00082 **     query -- the question to ask
00083 **     buf -- where to write the answer
00084 **     buflen -- bytes at "buf"
00085 **     qh -- query handle, used with dkim_res_waitreply
00086 **
00087 **  Return value:
00088 **     0 on success, -1 on error
00089 **
00090 **  Notes:
00091 **     This is a stub for the stock UNIX resolver (res_) functions, which
00092 **     are synchronous so no handle needs to be created, so "qh" is set to
00093 **     "buf".  "buf" is actually populated before this returns (unless
00094 **     there's an error).
00095 */
00096 
00097 int
00098 dkim_res_query(void *srv, int type, unsigned char *query, unsigned char *buf,
00099                size_t buflen, void **qh)
00100 {
00101        int n;
00102        int ret;
00103        struct dkim_res_qh *rq;
00104        unsigned char qbuf[HFIXEDSZ + MAXPACKET];
00105 #ifdef HAVE_RES_NINIT
00106        struct __res_state statp;
00107 #endif /* HAVE_RES_NINIT */
00108 
00109 #ifdef HAVE_RES_NINIT
00110        memset(&statp, '\0', sizeof statp);
00111        res_ninit(&statp);
00112 #endif /* HAVE_RES_NINIT */
00113 
00114 #ifdef HAVE_RES_NINIT
00115        n = res_nmkquery(&statp, QUERY, (char *) query, C_IN, type, NULL, 0,
00116                         NULL, qbuf, sizeof qbuf);
00117 #else /* HAVE_RES_NINIT */
00118        n = res_mkquery(QUERY, (char *) query, C_IN, type, NULL, 0, NULL, qbuf,
00119                        sizeof qbuf);
00120 #endif /* HAVE_RES_NINIT */
00121        if (n == (size_t) -1)
00122        {
00123 #ifdef HAVE_RES_NINIT
00124               res_nclose(&statp);
00125 #endif /* HAVE_RES_NINIT */
00126               return DKIM_DNS_ERROR;
00127        }
00128 
00129 #ifdef HAVE_RES_NINIT
00130        ret = res_nsend(&statp, qbuf, n, buf, buflen);
00131 #else /* HAVE_RES_NINIT */
00132        ret = res_send(qbuf, n, buf, buflen);
00133 #endif /* HAVE_RES_NINIT */
00134        if (ret == -1)
00135        {
00136 #ifdef HAVE_RES_NINIT
00137               res_nclose(&statp);
00138 #endif /* HAVE_RES_NINIT */
00139               return DKIM_DNS_ERROR;
00140        }
00141 
00142 #ifdef HAVE_RES_NINIT
00143        res_nclose(&statp);
00144 #endif /* HAVE_RES_NINIT */
00145 
00146        rq = (struct dkim_res_qh *) malloc(sizeof *rq);
00147        if (rq == NULL)
00148               return DKIM_DNS_ERROR;
00149 
00150        rq->rq_dnssec = DKIM_DNSSEC_UNKNOWN;
00151        if (ret == -1)
00152        {
00153               rq->rq_error = errno;
00154               rq->rq_buflen = 0;
00155        }
00156        else
00157        {
00158               rq->rq_error = 0;
00159               rq->rq_buflen = (size_t) ret;
00160        }
00161 
00162        *qh = (void *) rq;
00163 
00164        return DKIM_DNS_SUCCESS;
00165 }
00166 
00167 /*
00168 **  DKIM_RES_WAITREPLY -- wait for a reply to a pending query
00169 **
00170 **  Parameters:
00171 **     srv -- service handle
00172 **     qh -- query handle
00173 **     to -- timeout
00174 **     bytes -- number of bytes in the reply (returned)
00175 **     error -- error code (returned)
00176 **
00177 **  Return value:
00178 **     A DKIM_DNS_* code.
00179 **
00180 **  Notes:
00181 **     Since the stock UNIX resolver is synchronous, the reply was completed
00182 **     before dkim_res_query() returned, and thus this is almost a no-op.
00183 */
00184 
00185 int
00186 dkim_res_waitreply(void *srv, void *qh, struct timeval *to, size_t *bytes,
00187                    int *error, int *dnssec)
00188 {
00189        struct dkim_res_qh *rq;
00190 
00191        assert(qh != NULL);
00192 
00193        rq = qh;
00194 
00195        if (bytes != NULL)
00196               *bytes = rq->rq_buflen;
00197        if (error != NULL)
00198               *error = rq->rq_error;
00199        if (dnssec != NULL)
00200               *dnssec = rq->rq_dnssec;
00201 
00202        return DKIM_DNS_SUCCESS;
00203 }