chiark / gitweb /
Use struct sockaddr in several places; distinguish various places where
[adns.git] / src / general.c
index 7c42eb6e6b76ec9f1c42436935354422c52de1a5..8311dd7d5eb1d0f3559475c15c93f546fce6e18f 100644 (file)
  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
  */
 
+#include <stdlib.h>
+
+#include <arpa/inet.h>
+
 #include "internal.h"
 
 /* Core diagnostic functions */
 
 void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
-                int serv, const char *fmt, adns_query qu, va_list al) {
+                int serv, adns_query qu, const char *fmt, va_list al) {
   const char *bef, *aft;
   vbuf vb;
   if (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))) return;
@@ -42,8 +46,11 @@ void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
     adns__vbuf_init(&vb);
     fprintf(stderr,"%sQNAME=%s, QTYPE=%s",
            bef,
-           adns__diag_domain(ads,-1,0,&vb,qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
-           qu->typei ? qu->typei->name : "<unknown>");
+           adns__diag_domain(qu->ads,-1,0, &vb,
+                             qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
+           qu->typei ? qu->typei->rrtname : "<unknown>");
+    if (qu->typei && qu->typei->fmtname)
+      fprintf(stderr,"(%s)",qu->typei->fmtname);
     bef=", "; aft=")\n";
   }
   
@@ -106,9 +113,10 @@ int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
 
   newlen= vb->used+len;
   if (vb->avail < newlen) {
+    if (newlen<20) newlen= 20;
     newlen <<= 1;
     nb= realloc(vb->buf,newlen);
-    if (!nb) { newlen >>= 1; nb= realloc(vb->buf,newlen); }
+    if (!nb) { newlen= vb->used+len; nb= realloc(vb->buf,newlen); }
     if (!nb) return 0;
     vb->buf= nb;
     vb->avail= newlen;
@@ -117,14 +125,25 @@ int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
   return 1;
 }
 
+int adns__vbuf_appendstr(vbuf *vb, const char *data) {
+  int l;
+  l= strlen(data);
+  return adns__vbuf_append(vb,data,l);
+}
+
+void adns__vbuf_free(vbuf *vb) {
+  free(vb->buf);
+  adns__vbuf_init(vb);
+}
+
 /* Additional diagnostic functions */
 
-const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, vbuf *vb,
-                             int flags, const byte *dgram, int dglen, int cbyte) {
+const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
+                             vbuf *vb, const byte *dgram, int dglen, int cbyte) {
   adns_status st;
 
-  st= adns__parse_domain(ads,serv,vb,qu->flags, dgram,dglen, &cbyte,dglen);
-  if (st == adns_s_nomemory) {
+  st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen);
+  if (st == adns_s_nolocalmem) {
     return "<cannot report domain... out of memory>";
   }
   if (st) {
@@ -136,15 +155,86 @@ const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, vbuf *vb,
       return "<cannot report bad format... out of memory>";
     }
   }
-  if (!vb.used) {
+  if (!vb->used) {
     adns__vbuf_appendstr(vb,"<truncated ...>");
     adns__vbuf_append(vb,"",1);
   }
   return vb->buf;
 }
-    
+
+adns_status adns_rr_info(adns_rrtype type,
+                        const char **rrtname_r, const char **fmtname_r,
+                        int *len_r,
+                        const void *datap, char **data_r) {
+  const typeinfo *typei;
+  vbuf vb;
+  adns_status st;
+
+  typei= adns__findtype(type);
+  if (!typei) return adns_s_notimplemented;
+
+  if (rrtname_r) *rrtname_r= typei->rrtname;
+  if (fmtname_r) *fmtname_r= typei->fmtname;
+  if (len_r) *len_r= typei->rrsz;
+
+  if (!datap) return adns_s_ok;
+  
+  adns__vbuf_init(&vb);
+  st= typei->convstring(&vb,datap);
+  if (st) goto x_freevb;
+  if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nolocalmem; goto x_freevb; }
+  assert(strlen(vb.buf) == vb.used-1);
+  *data_r= realloc(vb.buf,vb.used);
+  if (!*data_r) *data_r= vb.buf;
+  return adns_s_ok;
+
+ x_freevb:
+  adns__vbuf_free(&vb);
+  return st;
+}
+
+#define SINFO(n,s) { adns_s_##n, s }
+
+static const struct sinfo {
+  adns_status st;
+  const char *string;
+} sinfos[]= {
+  SINFO(  ok,                  "OK"                                    ),
+  SINFO(  timeout,             "Timed out"                             ),
+  SINFO(  nolocalmem,          "Out of memory"                         ),
+  SINFO(  allservfail,         "No working nameservers"                ),
+  SINFO(  servfail,            "Nameserver failure"                    ),
+  SINFO(  notimplemented,      "Query not implemented"                 ),
+  SINFO(  refused,             "Refused by nameserver"                 ),
+  SINFO(  reasonunknown,       "Reason unknown"                        ),
+  SINFO(  norecurse,           "Recursion denied by nameserver"        ),
+  SINFO(  serverfaulty,        "Nameserver sent bad data"              ),
+  SINFO(  unknownreply,        "Reply from nameserver not understood"  ),
+  SINFO(  invaliddata,         "Invalid data"                          ),
+  SINFO(  inconsistent,        "Inconsistent data"                     ),
+  SINFO(  cname,               "RR refers to an alias"                 ),
+  SINFO(  invalidanswerdomain, "Received syntactically invalid domain" ),
+  SINFO(  nxdomain,            "No such domain"                        ),
+  SINFO(  nodata,              "No such data"                          ),
+  SINFO(  invalidquerydomain,  "Domain syntactically invalid"          ),
+  SINFO(  domaintoolong,       "Domain name too long"                  )
+};
+
+static int si_compar(const void *key, const void *elem) {
+  const adns_status *st= key;
+  const struct sinfo *si= elem;
+
+  return *st < si->st ? -1 : *st > si->st ? 1 : 0;
+}
+
 const char *adns_strerror(adns_status st) {
   static char buf[100];
+
+  const struct sinfo *si;
+
+  si= bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*si),sizeof(*si),si_compar);
+  if (si) return si->string;
+  
   snprintf(buf,sizeof(buf),"code %d",st);
   return buf;
 }