chiark / gitweb /
Mailbox quoting seems to work.
[adns.git] / src / internal.h
index 7b12237f3d5bbb066bdb701064c931c6dd984555..5e42adeb0cc963a2a5bb6606f22d73417386ac2d 100644 (file)
@@ -5,7 +5,7 @@
  * - comments regarding library data structures
  */
 /*
- *  This file is part of adns, which is Copyright (C) 1997, 1998 Ian Jackson
+ *  This file is part of adns, which is Copyright (C) 1997-1999 Ian Jackson
  *  
  *  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
@@ -25,7 +25,7 @@
 #ifndef ADNS_INTERNAL_H_INCLUDED
 #define ADNS_INTERNAL_H_INCLUDED
 
-#define PRINTFFORMAT(a,b) __attribute__((format(printf,a,b)))
+#include "config.h"
 typedef unsigned char byte;
 
 #include <stdarg.h>
@@ -39,10 +39,12 @@ typedef unsigned char byte;
 /* Configuration and constants */
 
 #define MAXSERVERS 5
-#define UDPMAXRETRIES /*15*/5
+#define MAXSORTLIST 15
+#define UDPMAXRETRIES 15
 #define UDPRETRYMS 2000
 #define TCPMS 30000
 #define LOCALRESOURCEMS 20
+#define MAXTTLBELIEVE (7*86400) /* any TTL > 7 days is capped */
 
 #define DNS_PORT 53
 #define DNS_MAXUDP 512
@@ -50,6 +52,8 @@ typedef unsigned char byte;
 #define DNS_HDRSIZE 12
 #define DNS_CLASS_IN 1
 
+#define DNS_INADDR_ARPA "in-addr", "arpa"
+
 typedef enum {
   rcode_noerror,
   rcode_formaterror,
@@ -75,15 +79,13 @@ typedef struct {
   byte *buf;
 } vbuf;
 
-typedef union {
-  void *ext;
-  int dmaddr_index;
-} qcontext;
-
 typedef struct {
+  adns_state ads;
   adns_query qu;
+  int serv;
   const byte *dgram;
-  int serv, dglen, max, nsstart;
+  int dglen, nsstart, nscount, arcount;
+  struct timeval now;
 } parseinfo;
 
 typedef struct {
@@ -103,7 +105,7 @@ typedef struct {
    * and will not be null-terminated by convstring.
    */
 
-  adns_status (*parse)(const struct parseinfo *pai, int cbyte, void *store_r);
+  adns_status (*parse)(const parseinfo *pai, int cbyte, int max, void *store_r);
   /* Parse one RR, in dgram of length dglen, starting at cbyte and
    * extending until at most max.
    *
@@ -115,14 +117,14 @@ typedef struct {
    * nsstart is the offset of the authority section.
    */
 
-  int (*diff_needswap)(const void *datap_a, const void *datap_b);
+  int (*diff_needswap)(adns_state ads, const void *datap_a, const void *datap_b);
   /* Returns !0 if RR a should be strictly after RR b in the sort order,
    * 0 otherwise.  Must not fail.
    */
 } typeinfo;
 
 typedef struct allocnode {
-  struct allocnode *next;
+  struct allocnode *next, *back;
 } allocnode;
 
 union maxalign {
@@ -134,13 +136,22 @@ union maxalign {
   union maxalign *up;
 } data;
 
+typedef struct {
+  void *ext;
+  void (*callback)(adns_query parent, adns_query child);
+  union {
+    adns_rr_addr ptr_parent_addr;
+    adns_rr_hostaddr *hostaddr;
+  } info;
+} qcontext;
+
 struct adns__query {
   adns_state ads;
   enum { query_udp, query_tcpwait, query_tcpsent, query_child, query_done } state;
   adns_query back, next, parent;
   struct { adns_query head, tail; } children;
   struct { adns_query back, next; } siblings;
-  struct allocnode *allocations;
+  struct { allocnode *head, *tail; } allocations;
   int interim_allocd;
   void *final_allocspace;
   
@@ -171,7 +182,9 @@ struct adns__query {
   int udpnextserver;
   unsigned long udpsent, tcpfailed; /* bitmap indexed by server */
   struct timeval timeout;
-  qcontext context;
+  time_t expires; /* Earliest expiry time of any record we used. */
+
+  qcontext ctx;
 
   /* Possible states:
    *
@@ -229,15 +242,19 @@ struct adns__query {
 struct adns__state {
   adns_initflags iflags;
   FILE *diagfile;
+  int configerrno;
   struct { adns_query head, tail; } timew, childw, output;
   int nextid, udpsocket, tcpsocket;
   vbuf tcpsend, tcprecv;
-  int nservers, tcpserver;
+  int nservers, nsortlist, tcpserver;
   enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate;
   struct timeval tcptimeout;
   struct server {
     struct in_addr addr;
   } servers[MAXSERVERS];
+  struct sortlist {
+    struct in_addr base, mask;
+  } sortlist[MAXSORTLIST];
 };
 
 /* From setup.c: */
@@ -278,7 +295,8 @@ const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
  */
   
 void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
-                int (*needswap)(const void *a, const void *b));
+                int (*needswap)(void *context, const void *a, const void *b),
+                void *context);
 /* Does an insertion sort of array which must contain nobjs objects
  * each sz bytes long.  tempbuf must point to a buffer at least
  * sz bytes long.  needswap should return !0 if a>b (strictly, ie
@@ -335,7 +353,7 @@ int adns__internal_submit(adns_state ads, adns_query *query_r,
  * If failstat is nonzero then if we are successful in creating the query
  * it is immediately failed with code failstat (but _submit still succeds).
  *
- * ctx is copied byte-for-byte into the query.
+ * *ctx is copied byte-for-byte into the query.
  */
 
 void *adns__alloc_interim(adns_query qu, size_t sz);
@@ -355,6 +373,20 @@ void *adns__alloc_interim(adns_query qu, size_t sz);
  * but it will not necessarily return a distinct pointer each time.
  */
 
+void adns__transfer_interim(adns_query from, adns_query to, void *block, size_t sz);
+/* Transfers an interim allocation from one query to another, so that
+ * the `to' query will have room for the data when we get to makefinal
+ * and so that the free will happen when the `to' query is freed
+ * rather than the `from' query.
+ *
+ * It is legal to call adns__transfer_interim with a null pointer; this
+ * has no effect.
+ *
+ * _transfer_interim also ensures that the expiry time of the `to' query
+ * is no later than that of the `from' query, so that child queries'
+ * TTLs get inherited by their parents.
+ */
+
 void *adns__alloc_mine(adns_query qu, size_t sz);
 /* Like _interim, but does not record the length for later
  * copying into the answer.  This just ensures that the memory
@@ -450,18 +482,28 @@ adns_status adns__parse_domain(adns_state ads, int serv, adns_query qu,
  * serv may be -1 and qu may be 0 - they are used for error reporting only.
  */
 
+adns_status adns__parse_domain_more(findlabel_state *fls, adns_state ads,
+                                   adns_query qu, vbuf *vb, parsedomain_flags flags,
+                                   const byte *dgram);
+/* Like adns__parse_domain, but you pass it a pre-initialised findlabel_state,
+ * for continuing an existing domain or some such of some kind.  Also, unlike
+ * _parse_domain, the domain data will be appended to vb, rather than replacing
+ * the existing contents.
+ */
+
 adns_status adns__findrr(adns_query qu, int serv,
                         const byte *dgram, int dglen, int *cbyte_io,
-                        int *type_r, int *class_r, int *rdlen_r, int *rdstart_r,
+                        int *type_r, int *class_r, unsigned long *ttl_r,
+                        int *rdlen_r, int *rdstart_r,
                         int *ownermatchedquery_r);
 /* Finds the extent and some of the contents of an RR in a datagram
  * and does some checks.  The datagram is *dgram, length dglen, and
  * the RR starts at *cbyte_io (which is updated afterwards to point
  * to the end of the RR).
  *
- * The type, class and RRdata length and start are returned iff
- * the corresponding pointer variables are not null.  type_r and
- * class_r may not be null.
+ * The type, class, TTL and RRdata length and start are returned iff
+ * the corresponding pointer variables are not null.  type_r, class_r
+ * and ttl_r may not be null.  The TTL will be capped.
  *
  * If ownermatchedquery_r != 0 then the owner domain of this
  * RR will be compared with that in the query (or, if the query
@@ -478,11 +520,12 @@ adns_status adns__findrr(adns_query qu, int serv,
  * If an error is returned then *type_r will be undefined too.
  */
 
-static adns_status findrr_anychk(adns_query qu, int serv,
-                                const byte *dgram, int dglen, int *cbyte_io,
-                                int *type_r, int *class_r, int *rdlen_r, int *rdstart_r,
-                                const byte *eo_dgram, int eo_dglen, int eo_cbyte,
-                                int *eo_matched_r);
+adns_status adns__findrr_anychk(adns_query qu, int serv,
+                               const byte *dgram, int dglen, int *cbyte_io,
+                               int *type_r, int *class_r, unsigned long *ttl_r,
+                               int *rdlen_r, int *rdstart_r,
+                               const byte *eo_dgram, int eo_dglen, int eo_cbyte,
+                               int *eo_matched_r);
 /* Like adns__findrr_checked, except that the datagram and
  * owner to compare with can be specified explicitly.
  *
@@ -497,6 +540,11 @@ static adns_status findrr_anychk(adns_query qu, int serv,
  * untruncated.
  */
 
+void adns__update_expires(adns_query qu, unsigned long ttl, struct timeval now);
+/* Updates the `expires' field in the query, so that it doesn't exceed
+ * now + ttl.
+ */
+
 int vbuf__append_quoted1035(vbuf *vb, const byte *buf, int len);
 
 /* From event.c: */
@@ -535,17 +583,17 @@ static inline int ctype_alpha(int c) {
 
 #define LIST_UNLINK_PART(list,node,part) \
   do { \
-    if ((node)->back) (node)->back->part next= (node)->part next; \
-      else                        (list).head= (node)->part next; \
-    if ((node)->next) (node)->next->part back= (node)->part back; \
-      else                        (list).tail= (node)->part back; \
+    if ((node)->part back) (node)->part back->part next= (node)->part next; \
+      else                                  (list).head= (node)->part next; \
+    if ((node)->part next) (node)->part next->part back= (node)->part back; \
+      else                                  (list).tail= (node)->part back; \
   } while(0)
 
 #define LIST_LINK_TAIL_PART(list,node,part) \
   do { \
     (node)->part next= 0; \
     (node)->part back= (list).tail; \
-    if ((list).tail) (list).tail->part next= (node); else (list).part head= (node); \
+    if ((list).tail) (list).tail->part next= (node); else (list).head= (node); \
     (list).tail= (node); \
   } while(0)
 
@@ -555,5 +603,11 @@ static inline int ctype_alpha(int c) {
 #define GETIL_B(cb) (((dgram)[(cb)++]) & 0x0ff)
 #define GET_B(cb,tv) ((tv)= GETIL_B((cb)))
 #define GET_W(cb,tv) ((tv)=0, (tv)|=(GETIL_B((cb))<<8), (tv)|=GETIL_B(cb), (tv))
+#define GET_L(cb,tv) ( (tv)=0, \
+                      (tv)|=(GETIL_B((cb))<<24), \
+                      (tv)|=(GETIL_B((cb))<<16), \
+                      (tv)|=(GETIL_B((cb))<<8), \
+                      (tv)|=GETIL_B(cb), \
+                      (tv) )
 
 #endif