* 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).
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");
--- /dev/null
+/*
+ * 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
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;
}
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; }
}
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;
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;
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);
#include <sys/time.h>
#include "adns.h"
+#include "dlist.h"
/* Configuration and constants */
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;
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);
(( ((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))
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,
}
query_simple(ads,qu, owner,ol, typei,flags, now);
}
+ adns__autosys(ads,now);
adns__consistency(ads,qu,cc_entex);
return 0;
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;