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:

  1. 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
  2. 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.
  3. 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.
  4. 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: 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:

  1. The service handle pointer is NULL.
  2. 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.
  3. The query cancel function deallocates the state handle. It always returns 0.
  4. 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:

  1. The service handle pointer is the return value from ar_init(), which creates an instance of the libar service.
  2. The query start function passes the query to ar_addquery() and returns the query handle generated by that function.
  3. The query cancel function merely passes the service handle and the query handle to ar_cancelquery().
  4. 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.