chiark / gitweb /
Found on chiark.
authorian <ian>
Sun, 27 Sep 1998 15:31:35 +0000 (15:31 +0000)
committerian <ian>
Sun, 27 Sep 1998 15:31:35 +0000 (15:31 +0000)
src/adns-internal.h [new file with mode: 0644]
src/adns.c [new file with mode: 0644]
src/adns.h [new file with mode: 0644]

diff --git a/src/adns-internal.h b/src/adns-internal.h
new file mode 100644 (file)
index 0000000..cabb271
--- /dev/null
@@ -0,0 +1,38 @@
+/**/
+
+#ifndef ADNS_INTERNAL_H_INCLUDED
+#define ADNS_INTERNAL_H_INCLUDED
+
+#include "adns.h"
+
+#define MAXSERVERS 5
+#define MAXUDPRETRIES 10
+#define UDPRETRYMS 2000
+#define TCPMS 20000
+
+struct adns__query {
+  adns_query next, back;
+  adns_query parent, child;
+  adns_rrtype type;
+  stuct adns_answer *answer;
+  int flags, udpretries, server;
+  struct timeval timeout;
+  void *context;
+  char owner[1];
+};
+
+struct adns__state {
+  struct { adns_query head, tail } input, timew, childw, output;
+  int udpsocket;
+  int qbufavail, tcpbufavail, tcpbufused, tcpbufdone;
+  char *qbuf, *tcpbuf;
+  int nservers;
+  struct {
+    struct in_addr addr;
+    int tcpsocket;
+    struct timeval timeout;
+    struct { adns_query head, tail } connw;
+  } servers[MAXSERVERS];
+};
+
+#endif
diff --git a/src/adns.c b/src/adns.c
new file mode 100644 (file)
index 0000000..381105d
--- /dev/null
@@ -0,0 +1,127 @@
+/**/
+
+#include <arpa/nameser.h>
+
+#include "adns-internal.h"
+
+#define LIST_UNLINK(list,node) \
+  do { \
+    if ((node)->back) (node)->back->next= (node)->next; \
+      else                   (list).head= (node)->next; \
+    if ((node)->next) (node)->next->back= (node)->back; \
+      else                   (list).tail= (node)->back; \
+  } while(0)
+
+#define LIST_LINK_TAIL(list,node) \
+  do { \
+    (node)->back= 0; \
+    (node)->next= (list).tail; \
+    if (list).tail (list).tail->back= (node); else (list).head= (node); \
+    (list).tail= (node); \
+  } while(0)
+
+void addserver(adns_state ads, struct in_addr addr) {
+  if (ads->nservers>=MAXSERVERS) {
+    if (ads->flags & adns_if_debug)
+      fprintf(stderr,"adns: too many nameservers, ignoring %s",
+             inet_ntoa(addr));
+  } else {
+    ads->servers[ads->nservers].addr= addr;
+    ads->servers[ads->nservers].tcpsocket= -1;
+    ads->nservers++;
+  }
+}
+
+void readconfig(adns_state ads, const char *filename) {
+}
+
+void readconfigenv(adns_state ads, const char *envvar) {
+  const char *filename;
+
+  if (flags & adns_if_noenv) return;
+  filename= getenv(envvar); if (!filename) return;
+  readconfig(ads,filename);
+}
+  
+int adns_init(adns_state *ads_r, int flags) {
+  adns_state ads;
+  const char *cfile;
+  
+  ads= malloc(sizeof(*ads)); if (!ads) return errno;
+  ads->queue.head= ads->queue.tail= 0;
+  ads->timew.head= ads->timew.tail= 0;
+  ads->child.head= ads->child.tail= 0;
+  ads->ready.head= ads->ready.tail= 0;
+  ads->udpsocket= -1;
+  ads->qbufavail= 0;
+  ads->qbuf= 0;
+  ads->tcpbufavail= ads->tcpbufused= ads->tcpbufdone= 0;
+  ads->tcpbuf= 0;
+  ads->flags= flags;
+  ads->nservers= 0;
+
+  readconfig(ads,"/etc/resolv.conf");
+  readconfigenv(ads,"RES_CONF");
+  readconfigenv(ads,"ADNS_RES_CONF");
+  if (!ads->nservers) {
+    if (ads->flags & adns_if_debug)
+      fprintf(stderr,"adns: no nameservers, using localhost\n");
+    addserver(ads,INADDR_LOOPBACK);
+  }
+  
+  *ads_r= ads;
+  return 0;
+}
+
+void query_fail(adns_state ads, adns_query qu, ands_status stat) {
+  struct adns_answer ans;
+  
+  ans= qu->answer;
+  if (!ans) ans= malloc(sizeof(*qu->answer));
+  if (ans) {
+    ans->status= stat;
+    ans->cname= 0;
+    ans->type= qu->type;
+    ans->nrrs= 0;
+  }
+  qu->answer= ans;
+  LIST_LINK_TAIL(ads.ready,qu);
+}
+
+void adns_event(adns_state ads,
+               fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+               int *maxfd, struct timeval *tv) {
+  for (
+}
+
+int adns_submit(adns_state ads,
+               const char *owner,
+               adns_rrtype type,
+               int flags,
+               void *context,
+               adns_query *query_r) {
+  adns_query qu;
+  adns_status stat;
+  int ol, r;
+
+  stat= 0;
+  ol= strlen(owner);
+  if (ol>MAXDNAME+1) { stat= ands_s_invaliddomain; ol= 0; }
+  if (ol>0 && owner[ol-1]=='.') { flags &= ~adns_f_search; ol--; }
+  qu= malloc(sizeof(*qu)+ol+1); if (!qu) return errno;
+  qu->next= qu->back= qu->parent= qu->child= 0;
+  qu->type= type;
+  qu->answer= 0;
+  qu->flags= flags;
+  qu->context= context;
+  qu->retries= 0;
+  qu->server= 0;
+  memcpy(qu->owner,owner,ol); qu->owner[ol]= 0;
+  if (stat) {
+    query_fail(ads,qu,stat);
+  } else {
+    LIST_LINK_TAIL(ads->input,qu);
+    adns_event(ads,0,0,0,0,0);
+  }
+  *query_r= qu;
+}
diff --git a/src/adns.h b/src/adns.h
new file mode 100644 (file)
index 0000000..61b3fc8
--- /dev/null
@@ -0,0 +1,160 @@
+/**/
+
+#ifndef ADNS_H_INCLUDED
+#define ADNS_H_INCLUDED
+
+typedef struct adns__state adns_state;
+typedef struct adns__query adns_query;
+
+typedef enum {
+  adns_if_noenv=      0x0001, /* do not look at environment */
+  adns_if_noerrprint= 0x0002, /* never print output to stderr */
+  adns_if_debug=      0x0004, /* print debugging output to stderr */
+} adns_initflags;
+
+typedef enum {
+  adns_f_search=     0x0001, /* use the searchlist */
+  adns_f_usevc=      0x0002, /* use a virtual circuit (TCP connection) */
+} adns_queryflags;
+
+typedef enum {
+  adns_rrttype_mask=  0x0fff,
+  adns_qtf_deref=     0x1000,
+  adns_qtf_mailconv=  0x2000,
+  adns_r_none=             0,
+  adns_r_a=                1,
+  adns_r_ns_raw=           2,
+  adns_r_ns=                  adns_r_ns_raw|adns_qtf_deref,
+  adns_r_cname=            5,
+  adns_r_soa_raw=          6,
+  adns_r_soa=                 adns_r_soa_raw|adns_qtf_mailconv,
+  adns_r_null=            10,
+  adns_r_ptr_raw=         12,
+  adns_r_ptr=                 adns_r_ptr_raw|adns_rf_deref,
+  adns_r_hinfo=           13,  
+  adns_r_mx_raw=          15,
+  adns_r_mx=                  adns_r_mx_raw|adns_qtf_deref,
+  adns_r_txt=             16,
+  adns_r_rp_raw           17,
+  adns_r_rp=                  adns_r_rp_raw|adns_qtf_mailconv
+} adns_rrtype;
+
+typedef enum {
+  adns_s_ok,
+  adns_s_notresponding,
+  adns_s_serverfailure,
+  adns_s_unknownqtype,
+  adns_s_remoteerror,
+  adns_s_max_tempfail= 99,
+  adns_s_nxdomain,
+  adns_s_norecord,
+  adns_s_invaliddomain
+} adns_status;
+
+/* In dereferenced answers, multiple addresses show up as multiple
+ * answers with all the dm pointers being the same.  If no
+ * address is available (permanent failure) then INADDR_NONE is
+ * used. */
+
+struct adns_answer {
+  adns_status status;
+  char *cname; /* always NULL if query was for CNAME records */
+  adns_rrtype type;
+  int nrrs;
+  union {
+    struct in_addr inaddr[1];                                          /* a */
+    char (*str)[1];                     /* ns_raw, cname, ptr, ptr_raw, txt */
+    struct { char *dm; struct in_addr addr; } dmaddr;                 /* ns */
+    struct { char *a, *b; } strpair[1];                /* hinfo, rp, rp_raw */
+    struct { int pref; char *dm; struct in_addr addr; } intdmaddr[1]; /* mx */
+    struct { int pref; char *str; } intstr[1]; /* mx_raw */
+    struct {
+      char *ns0, *rp;
+      unsigned long serial, refresh, retry, expire, minimum;
+    } soa[1]; /* soa, soa_raw */
+    /* NULL is empty */
+  } rrs;
+};
+
+/* Memory management:
+ *  adns_state and adns_query are actually pointers to malloc'd state;
+ *  On submission questions are copied, including the owner domain;
+ *  Answers are malloc'd as a single piece of memory.
+ * query_io:
+ *  Must always be non-null pointer;
+ *  If *query_io is 0 to start with then any query may be returned;
+ *  If *query_io is !0 adns_query then only that query may be returned.
+ * Errors:
+ *  Return values are 0 or an errno value;
+ *  Seriously fatal system errors (eg, failure to create sockets,
+ *  malloc failure, etc.) return errno values;
+ *  Other errors (nameserver failure, timed out connections, &c)
+ *  are returned in the status field of the answer.  If status is
+ *  nonzero then nrrs will be 0, otherwise it will be >0.
+ *  type will always be the type requested;
+ *  If no (appropriate) requests are done adns_query returns EWOULDBLOCK;
+ *  If no requests are outstanding adns_query and adns_wait return ESRCH;
+ *  If malloc failure occurs during internal allocation or processing
+ *  ands_query, _wait and _answer set *answer to 0.
+ */
+
+int adns_init(adns_state *newstate_r);
+
+int adns_synchronous(adns_state ads,
+                    const char *owner,
+                    adns_rrtype type,
+                    int flags,
+                    struct adns_answer *answer);
+
+int adns_submit(adns_state ads,
+               const char *owner,
+               adns_rrtype type,
+               int flags,
+               void *context,
+               const struct adns_query *query_r);
+
+int adns_query(adns_state ads,
+              adns_query *query_io,
+              struct adns_answer *answer,
+              void *context_r);
+
+int adns_wait(adns_state ads,
+             adns_query *query_io,
+             struct adns_answer *answer,
+              void *context_r);
+
+int adns_cancel(adns_state ads, adns_query query);
+
+int adns_finish(adns_state);
+
+void adns_event(adns_state, fd_set *readfds_mod,
+               fd_set *writefds_mod, fd_set *exceptfds_mod,
+               int *maxfd_mod, struct timeval *tv_mod);
+/* You may call this with *_mod=0 to have a simple callback,
+   or with *fds_mod=*maxfd_mod=0 but tv_mod!=0 if you are
+   not going to sleep, or with all !=0 if you are going to sleep. */
+
+/* Example expected/legal calling sequences:
+ *  adns_init
+ *  adns_submit 1
+ *  adns_submit 2
+ *  adns_submit 3
+ *  adns_wait 1
+ *  adns_query 3 -> EWOULDBLOCK
+ *  adns_wait 2
+ *  adns_wait 3
+ *  ....
+ *  adns_finish
+ *
+ *  adns_init
+ *  adns_submit ...
+ *  loop {
+ *   adns_query
+ *   adns_interest
+ *   select
+ *   adns_callback
+ *   other things
+ *  }
+ */
+
+#endif