chiark / gitweb /
Do not invoke __autosys indirectly from __procdgram.
authorian <ian>
Tue, 12 Oct 1999 19:51:08 +0000 (19:51 +0000)
committerian <ian>
Tue, 12 Oct 1999 19:51:08 +0000 (19:51 +0000)
changelog
src/check.c
src/dlist.h [new file with mode: 0644]
src/event.c
src/internal.h
src/query.c
src/setup.c

index b2a249e..f24e3c3 100644 (file)
--- a/changelog
+++ b/changelog
@@ -13,12 +13,14 @@ adns (0.5) unstable; urgency=medium
   * Better usage messages (and no default query domain) for adnstest.
   
   Bugfixes:
+  * Do not invoke __autosys indirectly from __procdgram (result: coredump
+    usually in memmove, unless adns_if_noautosys was used).
+  * Do not scramble innards when a query on the output queue is cancelled.
   * Mailboxes containing spaces in their names are quoted.
   * adns_rr_hostaddr naddrs is -1 on temporary failure (as documented).
   * Reject TXT RRs with no strings.
-  * Do not scramble innards when a query on the output queue is cancelled.
   * Correct error messages for qname CNAME foo, foo CNAME bar.
-  * Fixed typo in adns.h.
+  * Fixed typos in adns.h.
 
   General improvements:
   * Promise not to change fds in adns_beforepoll (if now is specified).
index 25de10d..4d5e031 100644 (file)
@@ -83,11 +83,13 @@ static void checkc_global(adns_state ads) {
   case server_connecting:
     assert(ads->tcpsocket >= 0);
   case server_disconnected: /* fall through */
-    assert(!ads->tcprecv.used);
     assert(!ads->tcpsend.used);
+    assert(!ads->tcprecv.used);
+    assert(!ads->tcprecv_skip);
     break;
   case server_ok:
     assert(ads->tcpsocket >= 0);
+    assert(ads->tcprecv_skip <= ads->tcprecv.used);
     break;
   default:
     assert(!"ads->tcpstate value");
diff --git a/src/dlist.h b/src/dlist.h
new file mode 100644 (file)
index 0000000..de0268f
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * dlist.h
+ * - macros for handling doubly linked lists
+ */
+/*
+ *  This file is
+ *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *
+ *  It is part of adns, which is
+ *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *    Copyright (C) 1999 Tony Finch <dot@dotat.at>
+ *  
+ *  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, or (at your option)
+ *  any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+ */
+
+#ifndef ADNS_DLIST_H_INCLUDED
+#define ADNS_DLIST_H_INCLUDED
+
+#define LIST_INIT(list) ((list).head= (list).tail= 0)
+#define LINK_INIT(link) ((link).next= (link).back= 0)
+
+#define LIST_UNLINK_PART(list,node,part) \
+  do { \
+    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).head= (node); \
+    (list).tail= (node); \
+  } while(0)
+
+#define LIST_UNLINK(list,node) LIST_UNLINK_PART(list,node,)
+#define LIST_LINK_TAIL(list,node) LIST_LINK_TAIL_PART(list,node,)
+
+#endif
index fc8aa81..6ddf492 100644 (file)
@@ -48,7 +48,7 @@ void adns__tcp_closenext(adns_state ads) {
   serv= ads->tcpserver;
   close(ads->tcpsocket);
   ads->tcpstate= server_disconnected;
-  ads->tcprecv.used= ads->tcpsend.used= 0;
+  ads->tcprecv.used= ads->tcprecv_skip= ads->tcpsend.used= 0;
   ads->tcpserver= (serv+1)%ads->nservers;
 }
 
@@ -97,6 +97,7 @@ void adns__tcp_tryconnect(adns_state ads, struct timeval now) {
     assert(ads->tcpstate == server_disconnected);
     assert(!ads->tcpsend.used);
     assert(!ads->tcprecv.used);
+    assert(!ads->tcprecv_skip);
 
     proto= getprotobyname("tcp");
     if (!proto) { adns__diag(ads,-1,0,"unable to find protocol no. for TCP !"); return; }
@@ -240,7 +241,7 @@ int adns__pollfds(adns_state ads, struct pollfd pollfds_buf[MAX_POLLFDS]) {
 }
 
 int adns_processreadable(adns_state ads, int fd, const struct timeval *now) {
-  int skip, want, dgramlen, r, udpaddrlen, serv;
+  int want, dgramlen, r, udpaddrlen, serv, old_skip;
   byte udpbuf[DNS_MAXUDP];
   struct sockaddr_in udpaddr;
   
@@ -252,22 +253,26 @@ int adns_processreadable(adns_state ads, int fd, const struct timeval *now) {
     break;
   case server_ok:
     if (fd != ads->tcpsocket) break;
-    skip= 0;
+    assert(!ads->tcprecv_skip);
     for (;;) {
-      if (ads->tcprecv.used<skip+2) {
-       want= 2;
-      } else {
-       dgramlen= (ads->tcprecv.buf[skip]<<8) | ads->tcprecv.buf[skip+1];
-       if (ads->tcprecv.used<skip+2+dgramlen) {
-         want= 2+dgramlen;
+      if (ads->tcprecv.used >= ads->tcprecv_skip+2) {
+       dgramlen= ((ads->tcprecv.buf[ads->tcprecv_skip]<<8) |
+                  ads->tcprecv.buf[ads->tcprecv_skip+1]);
+       if (ads->tcprecv.used >= ads->tcprecv_skip+2+dgramlen) {
+         old_skip= ads->tcprecv_skip;
+         ads->tcprecv_skip += 2+dgramlen;
+         adns__procdgram(ads, ads->tcprecv.buf+old_skip+2,
+                         dgramlen, ads->tcpserver, 1,*now);
+         continue;
        } else {
-         adns__procdgram(ads,ads->tcprecv.buf+skip+2,dgramlen,ads->tcpserver,1,*now);
-         skip+= 2+dgramlen; continue;
+         want= 2+dgramlen;
        }
+      } else {
+       want= 2;
       }
-      ads->tcprecv.used -= skip;
-      memmove(ads->tcprecv.buf,ads->tcprecv.buf+skip,ads->tcprecv.used);
-      skip= 0;
+      ads->tcprecv.used -= ads->tcprecv_skip;
+      memmove(ads->tcprecv.buf,ads->tcprecv.buf+ads->tcprecv_skip,ads->tcprecv.used);
+      ads->tcprecv_skip= 0;
       if (!adns__vbuf_ensure(&ads->tcprecv,want)) { r= ENOMEM; goto xit; }
       assert(ads->tcprecv.used <= ads->tcprecv.avail);
       if (ads->tcprecv.used == ads->tcprecv.avail) continue;
@@ -345,6 +350,7 @@ int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) {
   case server_connecting:
     if (fd != ads->tcpsocket) break;
     assert(ads->tcprecv.used==0);
+    assert(ads->tcprecv_skip==0);
     for (;;) {
       if (!adns__vbuf_ensure(&ads->tcprecv,1)) { r= ENOMEM; goto xit; }
       r= read(ads->tcpsocket,&ads->tcprecv.buf,1);
index 89327ec..5fdea89 100644 (file)
@@ -43,6 +43,7 @@ typedef unsigned char byte;
 #include <sys/time.h>
 
 #include "adns.h"
+#include "dlist.h"
 
 /* Configuration and constants */
 
@@ -279,7 +280,7 @@ struct adns__state {
   adns_query forallnext;
   int nextid, udpsocket, tcpsocket;
   vbuf tcpsend, tcprecv;
-  int nservers, nsortlist, nsearchlist, searchndots, tcpserver;
+  int nservers, nsortlist, nsearchlist, searchndots, tcpserver, tcprecv_skip;
   enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate;
   struct timeval tcptimeout;
   struct sigaction stdsigpipe;
@@ -631,7 +632,10 @@ void adns__tcp_closenext(adns_state ads);
 void adns__tcp_tryconnect(adns_state ads, struct timeval now);
 
 void adns__autosys(adns_state ads, struct timeval now);
-/* Make all the system calls we want to if the application wants us to. */
+/* Make all the system calls we want to if the application wants us to.
+ * Must not be called from within adns internal processing functions,
+ * lest we end up in recursive descent !
+ */
 
 void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io,
                             struct timeval *tv_buf);
@@ -680,28 +684,6 @@ static inline int errno_resources(int e) { return e==ENOMEM || e==ENOBUFS; }
   (( ((sz)+sizeof(union maxalign)-1) / sizeof(union maxalign) ) \
    * sizeof(union maxalign) )
 
-#define LIST_INIT(list) ((list).head= (list).tail= 0)
-#define LINK_INIT(link) ((link).next= (link).back= 0)
-
-#define LIST_UNLINK_PART(list,node,part) \
-  do { \
-    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).head= (node); \
-    (list).tail= (node); \
-  } while(0)
-
-#define LIST_UNLINK(list,node) LIST_UNLINK_PART(list,node,)
-#define LIST_LINK_TAIL(list,node) LIST_LINK_TAIL_PART(list,node,)
-
 #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))
index 53eecd9..b9e6d4d 100644 (file)
@@ -105,7 +105,6 @@ static void query_submit(adns_state ads, adns_query qu,
   memcpy(qu->query_dgram,qu->vb.buf,qu->vb.used);
   
   adns__query_send(qu,now);
-  adns__autosys(ads,now);
 }
 
 adns_status adns__internal_submit(adns_state ads, adns_query *query_r,
@@ -243,6 +242,7 @@ int adns_submit(adns_state ads,
     }
     query_simple(ads,qu, owner,ol, typei,flags, now);
   }
+  adns__autosys(ads,now);
   adns__consistency(ads,qu,cc_entex);
   return 0;
 
index 8604f8e..0e3e7da 100644 (file)
@@ -469,6 +469,7 @@ static int init_begin(adns_state *ads_r, adns_initflags flags, FILE *diagfile) {
   ads->udpsocket= ads->tcpsocket= -1;
   adns__vbuf_init(&ads->tcpsend);
   adns__vbuf_init(&ads->tcprecv);
+  ads->tcprecv_skip= 0;
   ads->nservers= ads->nsortlist= ads->nsearchlist= ads->tcpserver= 0;
   ads->searchndots= 1;
   ads->tcpstate= server_disconnected;