DNS Callback Overview
[back to index]
By default, libopendkim will use the standard UNIX resolver for
retrieving keys and policies that are stored in the DNS. Where an application
has some need for use of a resolver other than the standard one, a mechanism
is provided for instructing the library to make use of that other
package. This is done by using registration functions to pass pointers
to the application-provided package to act as primitives for asking questions
and getting answers.
The four functions provided are as follows:
- dkim_dns_set_query_service() --
Provides libopendkim with a handle representing the DNS resolver package
to be used, such as a handle to an instantiation of a library
- dkim_dns_set_query_start() --
Provides libopendkim with a function that it should call when it
wishes to make a request of the DNS. This function should expect to
receive from libopendkim the handle provided above, the name and type
to be requested from the DNS, a buffer into which to write the
answer once it arrives and the length of that buffer. The function
should return zero on success or non-zero on failure, and will also
return (via reference) a pointer to a handle that represents the
initiated query so that it can be passed to other functions. This
function is responsible for establishing whatever state it will need
to satisfy the other functions' requirements and provide a pointer to
that state, including whatever synchronization mechanism is desired.
See the page link for this function to view the actual function
prototype.
- dkim_dns_set_query_cancel() --
Provides libopendkim with a function that it should call when it
wishes to cancel a request of the DNS previously initiated by the
previous function. This function should expect to receive from
libopendkim the service handle provided above and the handle that
represents the query to be canceled. This function will be called
for all queries exactly once, including completed queries, to give
the libraries a chance to deallocate memory. See the page link for
this function to view the actual function prototype.
- dkim_dns_set_query_waitreply() --
Provides libopendkim with a function that it should call when it
wishes to check for or wait on a reply to a previously initiated
DNS query. This function should expect to receive from libopendkim
the service handle provided above, the handle that represents the query
of interest, an optional timeout via a pointer to a
struct timeval, an optional pointer to a size_t that
will receive the number of bytes returned, an optional pointer to an
int to receive any error code, and an optional pointer to an
int to receive a
DKIM_DNSSEC constant if the
resolver package supports such queries. The function should return
a value as follows:
- If an answer is available, the provided function should populate
the optional values and the buffer provided when the query was
initiated, and return the constant DKIM_DNS_SUCCESS.
- If not, and no timeout is provided, it should wait indefinitely
for an answer, returning DKIM_DNS_SUCCESS and populating
values and the buffer once an answer arrives. The implementation
of this waiting/wakeup mechanism is unspecified.
- If a timeout is provided and no reply arrives in that time, the
function should return DKIM_DNS_NOREPLY. If a reply does
arrive in that time, it should populate the values and buffer
and return DKIM_DNS_SUCCESS,
- In case of any transport or other permanent error in resolving
the request, the function should return DKIM_DNS_ERROR.
- If the resolver decides it will no longer wait for the reply even
if the application asks, it should return
DKIM_DNS_EXPIRED.
See the page link for this function to view the actual function
prototype.
For the purposes of illustration, libopendkim includes a set of the above
as defaults that point to the standard UNIX resolver. They are:
- The service handle pointer is NULL.
- The query start function passes the query to res_query() and
then creates a small state handle that stores the return value
from that function, which is the length of the reply.
res_query() populates the buffer provided, and doesn't return
until it completes (i.e. it is synchronous) so in fact a final result
is already available. It returns 0, unless res_query()
returns an error in which case it returns -1.
- The query cancel function deallocates the state handle. It always
returns 0.
- The query waitreply function copies the reply length and error code
from the state handle to the provided integer pointers and returns
DKIM_DNS_SUCCESS immediately.
So from libopendkim's perspective, it starts a query and then asks for a
reply, but the reply has actually already completed so the wait stage is
almost a no-op except to get the length of the reply.
Looking at a slightly more complicated case, we consider how it would work
with libar:
- The service handle pointer is the return value from ar_init(),
which creates an instance of the libar service.
- The query start function passes the query to ar_addquery() and
returns the query handle generated by that function.
- The query cancel function merely passes the service handle and the query
handle to ar_cancelquery().
- The query wait function passes the service and query handles to
ar_waitreply() with whatever the requested timeout was.
On return it copies the returned number of bytes to the caller, or any
appropriate error code. If waiting is required, this is implemented
inside ar_waitreply() using POSIX condition variables.
In this case, operation is fairly straightforward until the wait operation.
If libar has a reply available, the wait function above would get
AR_STAT_SUCCESS back immediately, and can thus return
DKIM_DNS_SUCCESS to libopendkim immediately. If the reply is
still pending, libopendkim will get DKIM_DNS_NOREPLY back and can
do other work while libar is still waiting. If libopendkim wishes to wait,
the timeout it provides is turned into a POSIX condition wait and the libar
dispatcher thread will signal it when a reply arrives.
Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set
forth in the respective licenses.