minires 0.97

Pierre A. Humblet
September 2003

Copyright (c) 2001 - 2003 Pierre A. Humblet
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version

The file minires.c contains a simple implementation of resolver functions
(found e.g. in the bind package) commonly used in clients, adapted to the
Cygwin environment. It was written from scratch as a weekend project,
starting from man page API definitions.  Currently it works as a simple
synchronous non caching stub resolver.  A planned version will interface to
the built-in caching resolver on Windows 2000 and XP.

Instead of querying a local bind daemon, the routines try to reach
predefined name servers. Their addresses are obtained directly from Windows
(except on Win95 with DHCP) or from /etc/resolv.conf or from the LOCALDOMAIN
environment variable.

The API conforms to the following resolver(3) man page, with some 
variations noted below. See also resolver(5) and hostname(7).

Recent versions of bind include many functions not implemented here.

The resolv.h, arpa/nameser.h and arpa/nameser_compat.h files are included 
as they are not in the current standard Cygwin. They were taken from 
bind 9.2.1.
Note that resolv.h redefines the function names to have a "__" prefix.
This can lead to problems with some configure scripts, see
http://www.openldap.org/lists/openldap-bugs/199907/msg00021.html

THESE INCLUDE FILES MUST BE INSTALLED MANUALLY (not done by make install)
under /usr/local/include (or /usr/include).  
Verify that you do not already have such files under /usr/include from 
some other source.

Similarly the package creates the library libminires.dll.a (and
libminires.a). Standard makefiles expect libresolv.dll.a
MAKE A SYMBOLIC LINK FROM ONE TO THE OTHER:
ln -s /usr/local/lib/libminires.dll.a /usr/local/lib/libresolv.dll.a

resolv.h changed with release 0.94. Applications compiled with
the old (new) version WILL NOT RUN with newer (older) dll's.

*********************************************************
#include <sys/types.h> 
#include <netinet/in.h> 
#include <arpa/nameser.h> 
#include <resolv.h> 

res_query(dname, class, type, answer, anslen) 
const char *dname; 
int class, type; 
u_char *answer; 
int anslen; 

res_search(dname, class, type, answer, anslen) 
const char *dname; 
int class, type; 
u_char *answer;
int anslen; 

res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen) 
int op; 
const char *dname; 
int class, type; 
const char *data; 
int datalen; 
struct rrec *newrr; 
u_char *buf; 
int buflen; 

int res_querydomain( const char * Name, const char * DomName, int Class,
		     int Type, unsigned char * AnsPtr, int AnsLength)

res_send(msg, msglen, answer, anslen) 
const u_char *msg; 
int msglen; 
u_char *answer; 
int anslen; 

res_init() 

res_close()

dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) 
const char *exp_dn; 
u_char *comp_dn; 
int length; 
u_char **dnptrs, **lastdnptr; 

dn_expand(msg, eomorig, comp_dn, exp_dn, length) 
const u_char *msg, *eomorig, *comp_dn; 
char *exp_dn; 
int length; 

int dn_skipname(const unsigned char *comp_dn, const unsigned char *eom)

The res_xx functions listed above are not thread safe as they access 
a common structure, struct __res_state _res (see below) and set the
global variable h_errno.

The functions res_nquery, res_nsearch, res_nmkquery, res_nsend, 
res_ninit and res_nclose are thread safe. They all have an extra 
initial argument of type res_state and set the element res_h_errno.

DESCRIPTION

These routines are used for making, sending and interpreting query and reply
messages with Internet domain name servers.

Global configuration and state information that is used by the resolver
routines is kept in the structure _res. Most of the values have reasonable
defaults and can be ignored. Options stored in _res.options are defined in
resolv.h and are as follows. Options are stored as a simple bit mask
containing the bitwise ``or'' of the options enabled.

RES_INIT 
True if the initial name server address and default domain name are
initialized (i.e., res_init has been called).

RES_DEBUG 
Print debugging messages. 

RES_AAONLY 
Accept authoritative answers only. With this option, res_send should
continue until it finds an authoritative answer or finds an error. Currently
this is not implemented.

RES_USEVC 
Use TCP connections for queries instead of UDP datagrams. 

RES_STAYOPEN 
Used with RES_USEVC to keep the TCP connection open between queries. This is
useful only in programs that regularly do many queries. UDP should be the
normal mode used.

RES_IGNTC 
Unused currently (ignore truncation errors, i.e., don't retry with TCP). 

RES_RECURSE 
Set the recursion-desired bit in queries. This is the default. ( res_send
does not do iterative queries and expects the name server to handle
recursion.)

RES_DEFNAMES 
If set, res_search will append the default domain name to single-component
names (those that do not contain a dot). This option is enabled by default.

RES_DNSRCH
If this option is set, res_search will search for host names in the current
domain and in parent domains; see hostname(7). This is used by the standard
host lookup routine gethostbyname(3). This option is enabled by default.

RES_NOALIASES
This option turns off the user level aliasing feature controlled by the
HOSTALIASES environment variable. Network daemons should set this option.

The res_init routine reads the configuration file (if any; see resolver(5))
to get the default domain name, search list and the Internet address of the
local name server(s). If no server is configured, the host running the
resolver is tried. The current domain name is defined by the hostname if not
specified in the configuration file; it can be overridden by the environment
variable LOCALDOMAIN. This environment variable may contain several
blank-separated tokens if you wish to override the search list on a
per-process basis. This is similar to the search command in the
configuration file. Another environment variable (``RES_OPTIONS'') can be
set to override certain internal resolver options which are otherwise set by
changing fields in the _res structure or are inherited from the
configuration file's options command. The syntax of the ``RES_OPTIONS''
environment variable is explained in resolver(5). Initialization normally
occurs on the first call to one of the other resolver routines.  

The res_query function provides an interface to the server query
mechanism. It constructs a query, sends it to the local server, awaits a
response, and makes preliminary checks on the reply. The query requests
information of the specified type and class for the specified
fully-qualified domain name dname . The reply message is left in the answer
buffer with length anslen supplied by the caller.

The res_querydomain queries the concatenation of Name and DomName.

The res_search routine makes a query and awaits a response like res_query,
but in addition, it implements the default and search rules controlled by
the RES_DEFNAMES and RES_DNSRCH options. It returns the first successful
reply.

The remaining routines are lower-level routines used by res_query. The
res_mkquery function constructs a standard query message and places it in
buf. It returns the size of the query, or -1 if the query is larger than
buflen. The query type op is usually QUERY, but can be any of the query
types defined in <arpa/nameser.h>. The domain name for the query is given by
dname. Newrr is currently unused but is intended for making update messages.

The res_send routine sends a pre-formatted query and returns an answer. It
will call res_init if RES_INIT is not set, send the query to the local name
server, and handle timeouts and retries. The length of the reply message is
returned, or -1 if there were errors.

The res_close routine closes all sockets opened by res_send.
 
The dn_comp function compresses the domain name exp_dn and stores it in
comp_dn. The size of the compressed name is returned or -1 if there were
errors. The size of the array pointed to by comp_dn is given by length. The
compression uses an array of pointers dnptrs to previously-compressed names
in the current message. The first pointer points to to the beginning of the
message and the list ends with NULL. The limit to the array is specified by
lastdnptr. A side effect of dn_comp is to update the list of pointers for
labels inserted into the message as the name is compressed. If dnptr is
NULL, names are not compressed. If lastdnptr is NULL, the list of labels is
not updated.

The dn_expand entry expands the compressed domain name comp_dn to a full
domain name. The compressed name is contained in a query or reply message;
msg is a pointer to the beginning of the message. The uncompressed name is
placed in the buffer indicated by exp_dn which is of size length. The size
of compressed name is returned or -1 if there was an error.

The dn_skipname entry returns the size of the compressed name, as does 
dn_expand, or -1 if there was an error.

***********************************************************************************

Non conformance

Functions
--------
res_comp():    not implemented
res_mkquery(): implemented only for op == QUERY
res_search():  always looks up first, even with RES_DNSRCH and RES_DEFNAMES,
               no matter the number of dots in the domain.

Options:
-------
RES_USEVC:     not implemented
RES_STAYOPEN:  not implemented
RES_RECURSE:   always applied
RES_NOALIASES: not implemented
Options other than RES_DEBUG are set by res_init(). They
can be modified after calling that function.

Environment
----------
RES_OPTIONS:   not implemented

Windows extensions 
------------------
The domain name or search list are obtained as follows, 
in order of increasing priorities:
1) From Windows (only domain name)
2) From /etc/resolv.conf 
3) From the environment variable LOCALDOMAIN

The DNS servers are obtained as follows, 
in order of increasing priorities:
1) From Windows [except on Win95 with DHCP]
2) From /etc/resolv.conf [mandatory on Win95 with DHCP]

Build instructions
------------------
1) Download the source package
2) make 
3) make install
   (see remark above about the include files)
