-/**/
+/*
+ * dtest.c
+ * - simple test program, not part of the library
+ */
+/*
+ * This file is part of adns, which is Copyright (C) 1997, 1998 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
+ * 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.
+ */
#include <stdio.h>
#include <unistd.h>
--- /dev/null
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <sys/uio.h>
+# This file is part of adns, which is Copyright (C) 1997, 1998 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
+# 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.
+
CC=gcc $(WARNS) $(WERROR) $(OPTIMISE) $(DEBUG)
DEBUG=-g
OPTIMISE=-O2
-Wcast-qual -Wpointer-arith
WERROR=-Werror
+LIBOBJS= event.o query.o setup.o transmit.o general.o reply.o parse.o
+ALLOBJS= $(LIBOBJS) dtest.o
+
all: dtest
-dtest: dtest.o event.o query.o setup.o submit.o reply.o parse.o
+dtest: $(ALLOBJS)
clean:
rm -f dtest *.o
-dtest.o: adns.h
-
-event.o query.o setup.o submit.o reply.o parse.o: internal.h adns.h
-
+dtest.o: adns.h
+$(LIBOBJS): adns.h internal.h
+# This file is part of adns, which is Copyright (C) 1997, 1998 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
+# 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.
+
CC=gcc $(WARNS) $(WERROR) $(OPTIMISE) $(DEBUG)
DEBUG=-g
OPTIMISE=-O2
-Wcast-qual -Wpointer-arith
WERROR=-Werror
+LIBOBJS= event.o query.o setup.o transmit.o general.o reply.o parse.o
+ALLOBJS= $(LIBOBJS) dtest.o
+
all: dtest
-dtest: dtest.o event.o query.o setup.o submit.o reply.o parse.o
+dtest: $(ALLOBJS)
clean:
rm -f dtest *.o
-dtest.o: adns.h
-
-event.o query.o setup.o submit.o reply.o parse.o: internal.h adns.h
-
+dtest.o: adns.h
+$(LIBOBJS): adns.h internal.h
*
* $Id$
*/
+/*
+ * This file is part of adns, which is Copyright (C) 1997, 1998 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
+ * 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_H_INCLUDED
#define ADNS_H_INCLUDED
void adns_cancel(adns_state ads, adns_query query);
int adns_finish(adns_state);
+/* You may call this even if you have queries outstanding;
+ * they will be cancelled.
+ */
int adns_callback(adns_state, int maxfd, const fd_set *readfds, const fd_set *writefds,
const fd_set *exceptfds);
-/**/
+/*
+ * event.c
+ * - event loop core
+ * - TCP connection management
+ * - user-visible check/wait and event-loop-related functions
+ */
+/*
+ * This file is part of adns, which is Copyright (C) 1997, 1998 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
+ * 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.
+ */
#include <string.h>
#include <errno.h>
--- /dev/null
+/*
+ * general.c
+ * - diagnostic functions
+ * - vbuf handling
+ */
+/*
+ * This file is part of adns, which is Copyright (C) 1997, 1998 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
+ * 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.
+ */
+
+#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) {
+ const char *bef, *aft;
+ vbuf vb;
+ if (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))) return;
+
+ fprintf(stderr,"adns%s: ",pfx);
+
+ vfprintf(stderr,fmt,al);
+
+ bef= " (";
+ aft= "\n";
+
+ if (qu && qu->query_dgram) {
+ 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>");
+ bef=", "; aft=")\n";
+ }
+
+ if (serv>=0) {
+ fprintf(stderr,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
+ bef=", "; aft=")\n";
+ }
+
+ fputs(aft,stderr);
+}
+
+void adns__debug(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
+ va_list al;
+
+ va_start(al,fmt);
+ adns__vdiag(ads," debug",0,serv,qu,fmt,al);
+ va_end(al);
+}
+
+void adns__warn(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
+ va_list al;
+
+ va_start(al,fmt);
+ adns__vdiag(ads," warning",adns_if_noerrprint|adns_if_noserverwarn,serv,qu,fmt,al);
+ va_end(al);
+}
+
+void adns__diag(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
+ va_list al;
+
+ va_start(al,fmt);
+ adns__vdiag(ads,"",adns_if_noerrprint,serv,qu,fmt,al);
+ va_end(al);
+}
+
+/* vbuf functions */
+
+void adns__vbuf_init(vbuf *vb) {
+ vb->used= vb->avail= 0; vb->buf= 0;
+}
+
+int adns__vbuf_ensure(vbuf *vb, int want) {
+ void *nb;
+
+ if (vb->avail >= want) return 1;
+ nb= realloc(vb->buf,want); if (!nb) return 0;
+ vb->buf= nb;
+ vb->avail= want;
+ return 1;
+}
+
+void adns__vbuf_appendq(vbuf *vb, const byte *data, int len) {
+ memcpy(vb->buf+vb->used,data,len);
+ vb->used+= len;
+}
+
+int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
+ int newlen;
+ void *nb;
+
+ newlen= vb->used+len;
+ if (vb->avail < newlen) {
+ newlen <<= 1;
+ nb= realloc(vb->buf,newlen);
+ if (!nb) { newlen >>= 1; nb= realloc(vb->buf,newlen); }
+ if (!nb) return 0;
+ vb->buf= nb;
+ vb->avail= newlen;
+ }
+ adns__vbuf_appendq(vb,data,len);
+ return 1;
+}
+
+/* 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) {
+ adns_status st;
+
+ st= adns__parse_domain(ads,serv,vb,qu->flags, dgram,dglen, &cbyte,dglen);
+ if (st == adns_s_nomemory) {
+ return "<cannot report domain... out of memory>";
+ }
+ if (st) {
+ vb->used= 0;
+ if (!(adns__vbuf_appendstr(vb,"<bad format... ") &&
+ adns__vbuf_appendstr(vb,adns_strerror(st)) &&
+ adns__vbuf_appendstr(vb,">") &&
+ adns__vbuf_append(vb,"",1))) {
+ return "<cannot report bad format... out of memory>";
+ }
+ }
+ if (!vb.used) {
+ adns__vbuf_appendstr(vb,"<truncated ...>");
+ adns__vbuf_append(vb,"",1);
+ }
+ return vb->buf;
+}
+
+const char *adns_strerror(adns_status st) {
+ static char buf[100];
+ snprintf(buf,sizeof(buf),"code %d",st);
+ return buf;
+}
-/**/
+/*
+ * internal.h
+ * - declarations of private objects with external linkage (adns__*)
+ * - definitons of internal macros
+ * - comments regarding library data structures
+ */
+/*
+ * This file is part of adns, which is Copyright (C) 1997, 1998 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
+ * 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_INTERNAL_H_INCLUDED
#define ADNS_INTERNAL_H_INCLUDED
/* From setup.c: */
+int adns__setnonblock(adns_state ads, int fd); /* => errno value */
+
+/* From general.c: */
+
void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
int serv, adns_query qu, const char *fmt, va_list al);
void adns__vbuf_init(vbuf *vb);
void adns__vbuf_free(vbuf *vb);
-int adns__setnonblock(adns_state ads, int fd); /* => errno value */
+const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, vbuf *vb,
+ int flags, const byte *dgram, int dglen, int cbyte);
+/* Unpicks a domain in a datagram and returns a string suitable for
+ * printing it as. Never fails - if an error occurs, it will
+ * return some kind of string describing the error.
+ *
+ * serv may be -1, qu may be 0. vb must have been initialised,
+ * and will be left in an arbitrary consistent state.
+ *
+ * Returns either vb->buf, or a pointer to a string literal. Do not modify
+ * vb before using the return value.
+ */
+
+/* From transmit.c: */
-/* From submit.c: */
+adns_status adns__mkquery(adns_state ads, vbuf *vb,
+ const char *owner, int ol, int *id_r,
+ const typeinfo *typei, adns_queryflags flags);
+/* Assembles a query packet in vb, and returns id at *id_r. */
+
+void adns__query_tcp(adns_state ads, adns_query qu, struct timeval now);
+/* Query must be in state tcpwait/timew; it will be moved to a new state
+ * if possible and no further processing can be done on it for now.
+ * (Resulting state is one of tcpwait/timew (if server not connected),
+ * tcpsent/timew, child/childw or done/output.)
+ *
+ * adns__tcp_tryconnect should already have been called - _tcp
+ * will only use an existing connection (if there is one), which it
+ * may break. If the conn list lost then the caller is responsible for any
+ * reestablishment and retry.
+ */
+
+void adns__query_udp(adns_state ads, adns_query qu, struct timeval now);
+/* Query must be in state udp/NONE; it will be moved to a new state,
+ * and no further processing can be done on it for now.
+ * (Resulting state is one of udp/timew, tcpwait/timew (if server not connected),
+ * tcpsent/timew, child/childw or done/output.)
+ */
+
+/* From query.c: */
int adns__internal_submit(adns_state ads, adns_query *query_r,
adns_rrtype type, vbuf *qumsg_vb, int id,
void adns__makefinal_block(adns_query qu, void **blpp, size_t sz);
void adns__makefinal_str(adns_query qu, char **strp);
-/* From query.c: */
-
-void adns__query_udp(adns_state ads, adns_query qu, struct timeval now);
-void adns__query_tcp(adns_state ads, adns_query qu, struct timeval now);
-adns_status adns__mkquery(adns_state ads, vbuf *vb,
- const char *owner, int ol, int *id_r,
- const typeinfo *typei, adns_queryflags flags);
-/* Assembles a query packet in vb, and returns id at *id_r. */
-
-void adns__query_ok(adns_state ads, adns_query qu);
-void adns__query_fail(adns_state ads, adns_query qu, adns_status stat);
-
void adns__reset_cnameonly(adns_state ads, adns_query qu);
/* Resets all of the memory management stuff etc. to
* take account of only the CNAME. Used when we find an error somewhere
* when we're halfway through RRs in a datagram and discover that we
* need to retry the query.
*/
+
+void adns__query_done(adns_state ads, adns_query qu);
+void adns__query_fail(adns_state ads, adns_query qu, adns_status stat);
/* From reply.c: */
void adns__tcp_broken(adns_state ads, const char *what, const char *why);
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. */
/* Useful static inline functions: */
-/**/
+/*
+ * parse.c
+ * - parsing assistance functions (mainly for domains inside datagrams)
+ */
+/*
+ * This file is part of adns, which is Copyright (C) 1997, 1998 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
+ * 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.
+ */
#include "internal.h"
return adns_s_ok;
}
-const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, vbuf *vb,
- int flags, 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) {
- return "<cannot report domain... out of memory>";
- }
- if (st) {
- vb->used= 0;
- if (!(adns__vbuf_appendstr(vb,"<bad format... ") &&
- adns__vbuf_appendstr(vb,adns_strerror(st)) &&
- adns__vbuf_appendstr(vb,">") &&
- adns__vbuf_append(vb,"",1))) {
- return "<cannot report bad format... out of memory>";
- }
- }
- if (!vb.used) {
- adns__vbuf_appendstr(vb,"<truncated ...>");
- adns__vbuf_append(vb,"",1);
- }
- return vb->buf;
-}
-
adns_status adns__findrr(adns_state ads, int serv,
const byte *dgram, int dglen, int *cbyte_io,
int *type_r, int *class_r, int *rdlen_r, int *rdstart_r,
-/**/
-
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <sys/uio.h>
+/*
+ * query.c
+ * - overall query management (allocation, completion)
+ * - per-query memory management
+ * - query submission and cancellation (user-visible and internal)
+ */
+/*
+ * This file is part of adns, which is Copyright (C) 1997, 1998 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
+ * 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.
+ */
#include "internal.h"
-adns_status adns__mkquery(adns_state ads, vbuf *vb,
- const char *owner, int ol, int *id_r,
- const typeinfo *typei, adns_queryflags flags) {
- int ll, c, nlabs, id;
- byte label[255], *rqp;
- const char *p, *pe;
-
-#define MKQUERY_ADDB(b) *rqp++= (b)
-#define MKQUERY_ADDW(w) (MKQUERY_ADDB(((w)>>8)&0x0ff), MKQUERY_ADDB((w)&0x0ff))
-
- vb->used= 0;
- if (!adns__vbuf_ensure(vb,DNS_HDRSIZE+strlen(owner)+1+5))
- return adns_s_nolocalmem;
- rqp= vb->buf;
-
- *id_r= id= (ads->nextid++) & 0x0ffff;
-
- MKQUERY_ADDW(id);
- MKQUERY_ADDB(0x01); /* QR=Q(0), OPCODE=QUERY(0000), !AA, !TC, RD */
- MKQUERY_ADDB(0x00); /* !RA, Z=000, RCODE=NOERROR(0000) */
- MKQUERY_ADDW(1); /* QDCOUNT=1 */
- MKQUERY_ADDW(0); /* ANCOUNT=0 */
- MKQUERY_ADDW(0); /* NSCOUNT=0 */
- MKQUERY_ADDW(0); /* ARCOUNT=0 */
- p= owner; pe= owner+ol;
- nlabs= 0;
- if (!*p) return adns_s_invaliddomain;
- do {
- ll= 0;
- while (p!=pe && (c= *p++)!='.') {
- if (c=='\\') {
- if (!(flags & adns_qf_anyquote)) return adns_s_invaliddomain;
- if (ctype_digit(p[0])) {
- if (ctype_digit(p[1]) && ctype_digit(p[2])) {
- c= (*p++ - '0')*100 + (*p++ - '0')*10 + (*p++ - '0');
- if (c >= 256) return adns_s_invaliddomain;
- } else {
- return adns_s_invaliddomain;
- }
- } else if (!(c= *p++)) {
- return adns_s_invaliddomain;
- }
- }
- if (!(flags & adns_qf_anyquote)) {
- if (ctype_digit(c) || c == '-') {
- if (!ll) return adns_s_invaliddomain;
- } else if (!ctype_alpha(c)) {
- return adns_s_invaliddomain;
- }
- }
- if (ll == sizeof(label)) return adns_s_invaliddomain;
- label[ll++]= c;
- }
- if (!ll) return adns_s_invaliddomain;
- if (nlabs++ > 63) return adns_s_invaliddomain;
- MKQUERY_ADDB(ll);
- memcpy(rqp,label,ll); rqp+= ll;
- } while (p!=pe);
-
- MKQUERY_ADDB(0);
- MKQUERY_ADDW(typei->type & adns__rrt_typemask); /* QTYPE */
- MKQUERY_ADDW(DNS_CLASS_IN); /* QCLASS=IN */
-
- vb->used= rqp - vb->buf;
- assert(vb->used <= vb->avail);
-
- return adns_s_ok;
-}
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
-void adns__query_tcp(adns_state ads, adns_query qu, struct timeval now) {
- /* Query must be in state tcpwait/timew; it will be moved to a new state
- * if possible and no further processing can be done on it for now.
- * (Resulting state is one of tcpwait/timew (if server not connected),
- * tcpsent/timew, child/childw or done/output.)
- *
- * adns__tcp_tryconnect should already have been called - _tcp
- * will only use an existing connection (if there is one), which it
- * may break. If the conn list lost then the caller is responsible for any
- * reestablishment and retry.
- */
- byte length[2];
- struct iovec iov[2];
- int wr, r;
+#include <sys/time.h>
- if (ads->tcpstate != server_ok) return;
+#include "internal.h"
- length[0]= (qu->query_dglen&0x0ff00U) >>8;
- length[1]= (qu->query_dglen&0x0ff);
+int adns__internal_submit(adns_state ads, adns_query *query_r,
+ adns_rrtype type, vbuf *qumsg_vb, int id,
+ adns_queryflags flags, struct timeval now,
+ adns_status failstat, const qcontext *ctx) {
+ adns_query qu;
+ adns_status stat;
+ int ol, id, r;
+ struct timeval now;
+ const typeinfo *typei;
+ adns_query qu;
+
+ qu= malloc(sizeof(*qu)); if (!qu) goto x_nomemory;
+ qu->answer= malloc(sizeof(*qu->answer)); if (!qu->answer) goto x_freequ_nomemory;
+
+ qu->state= query_udp;
+ qu->back= qu->next= qu->parent= 0;
+ LIST_INIT(qu->children);
+ qu->siblings.next= qu->siblings.back= 0;
+ qu->allocations= 0;
+ qu->interim_allocd= 0;
+ qu->perm_used= 0;
+
+ qu->typei= adns__findtype(type);
+ adns__vbuf_init(&qu->vb);
+
+ qu->cname_dgram= 0;
+ qu->cname_dglen= qu->cname_begin= 0;
- if (!adns__vbuf_ensure(&ads->tcpsend,ads->tcpsend.used+qu->query_dglen+2)) return;
-
- timevaladd(&now,TCPMS);
- qu->timeout= now;
- qu->state= query_tcpsent;
- LIST_LINK_TAIL(ads->timew,qu);
+ qu->id= id;
+ qu->flags= flags;
+ qu->udpretries= 0;
+ qu->udpnextserver= 0;
+ qu->udpsent= qu->tcpfailed= 0;
+ timerclear(&qu->timeout);
+ memcpy(&qu->context,ctx,sizeof(qu->context));
+ memcpy(qu->owner,owner,ol); qu->owner[ol]= 0;
+
+ qu->answer->status= adns_s_ok;
+ qu->answer->cname= 0;
+ qu->answer->type= type;
+ qu->answer->nrrs= 0;
+ qu->answer->rrs= 0;
- if (ads->tcpsend.used) {
- wr= 0;
+ if (qu->typei) {
+ qu->answer->rrsz= qu->rrsz;
} else {
- iov[0].iov_base= length;
- iov[0].iov_len= 2;
- iov[1].iov_base= qu->query_dgram;
- iov[1].iov_len= qu->query_dglen;
- wr= writev(ads->tcpsocket,iov,2);
- if (wr < 0) {
- if (!(errno == EAGAIN || errno == EINTR || errno == ENOSPC ||
- errno == ENOBUFS || errno == ENOMEM)) {
- adns__tcp_broken(ads,"write",strerror(errno));
- return;
- }
- wr= 0;
- }
+ qu->answer->rrsz= -1;
+ failstat= adns_s_notimplemented;
}
+
+ *query_r= qu;
- if (wr<2) {
- r= adns__vbuf_append(&ads->tcpsend,length,2-wr); assert(r);
- wr= 0;
- } else {
- wr-= 2;
+ qu->query_dgram= malloc(qumsg_vb->used);
+ if (!qu->query_dgram) {
+ adns__query_fail(ads,qu,adns_s_nomemory);
+ return;
}
- if (wr<qu->query_dglen) {
- r= adns__vbuf_append(&ads->tcpsend,qu->query_dgram+wr,qu->query_dglen-wr); assert(r);
+ memcpy(qu->query_dgram,qumsg_vb->buf,qumsg_vb->used);
+ qu->vb= *qumsg_vb;
+ adns__vbuf_init(qumsg_vb);
+
+ if (failstat) {
+ adns__query_fail(ads,qu,failstat);
+ return;
}
+ adns__query_udp(ads,qu,now);
+ adns__autosys(ads,now);
+
+ return 0;
+
+ x_freequ_nomemory:
+ free(qu);
+ x_nomemory:
+ free(query_dgram);
+ return adns_s_nomemory;
}
-static void query_usetcp(adns_state ads, adns_query qu, struct timeval now) {
- timevaladd(&now,TCPMS);
- qu->timeout= now;
- qu->state= query_tcpwait;
- LIST_LINK_TAIL(ads->timew,qu);
- adns__query_tcp(ads,qu,now);
- adns__tcp_tryconnect(ads,now);
+int adns_submit(adns_state ads,
+ const char *owner,
+ adns_rrtype type,
+ adns_queryflags flags,
+ void *context,
+ adns_query *query_r) {
+ qcontext ctx;
+ int id;
+ vbuf vb;
+
+ ctx.ext= context;
+ r= gettimeofday(&now,0); if (r) return errno;
+ id= 0;
+
+ adns__vbuf_init(&vb);
+
+ ol= strlen(owner);
+ if (ol<=1 || ol>DNS_MAXDOMAIN+1) { stat= adns_s_invaliddomain; goto xit; }
+
+ if (owner[ol-1]=='.' && owner[ol-2]!='\\') { flags &= ~adns_qf_search; ol--; }
+
+ stat= adns__mkquery(ads,&vb, &id, owner,ol, typei,flags);
+
+ xit:
+ return adns__internal_submit(ads,query_r, type,&vb,id, flags,now, stat,&ctx);
}
-void adns__query_udp(adns_state ads, adns_query qu, struct timeval now) {
- /* Query must be in state udp/NONE; it will be moved to a new state,
- * and no further processing can be done on it for now.
- * (Resulting state is one of udp/timew, tcpwait/timew (if server not connected),
- * tcpsent/timew, child/childw or done/output.)
- */
- struct sockaddr_in servaddr;
- int serv, r;
+int adns_synchronous(adns_state ads,
+ const char *owner,
+ adns_rrtype type,
+ adns_queryflags flags,
+ adns_answer **answer_r) {
+ adns_query qu;
+ int r;
+
+ r= adns_submit(ads,owner,type,flags,0,&qu);
+ if (r) return r;
- assert(qu->state == query_udp);
- if ((qu->flags & adns_qf_usevc) || (qu->query_dglen > DNS_MAXUDP)) {
- query_usetcp(ads,qu,now);
- return;
- }
+ do {
+ r= adns_wait(ads,&qu,answer_r,0);
+ } while (r==EINTR);
+ if (r) adns_cancel(ads,qu);
+ return r;
+}
- if (qu->udpretries >= UDPMAXRETRIES) {
- adns__query_fail(ads,qu,adns_s_timeout);
- return;
+void adns_cancel(adns_state ads, adns_query query) {
+ abort(); /* fixme */
+}
+
+void *adns__alloc_interim(adns_state ads, adns_query qu, size_t sz) {
+ allocnode *an;
+
+ assert(!qu->final_allocspace);
+ sz= MEM_ROUND(sz);
+ an= malloc(MEM_ROUND(MEM_ROUND(sizeof(*an)) + sz));
+ if (!an) {
+ adns__query_fail(ads,qu,adns_s_nolocalmem);
+ return 0;
}
+ qu->permalloclen += sz;
+ an->next= qu->allocations;
+ qu->allocations= an;
+ return (byte*)an + MEM_ROUND(sizeof(*an));
+}
- serv= qu->udpnextserver;
- memset(&servaddr,0,sizeof(servaddr));
- servaddr.sin_family= AF_INET;
- servaddr.sin_addr= ads->servers[serv].addr;
- servaddr.sin_port= htons(DNS_PORT);
-
- r= sendto(ads->udpsocket,qu->query_dgram,qu->query_dglen,0,&servaddr,sizeof(servaddr));
- if (r<0 && errno == EMSGSIZE) { query_usetcp(ads,qu,now); return; }
- if (r<0) adns__warn(ads,serv,0,"sendto failed: %s",strerror(errno));
-
- timevaladd(&now,UDPRETRYMS);
- qu->timeout= now;
- qu->udpsent |= (1<<serv);
- qu->udpnextserver= (serv+1)%ads->nservers;
- qu->udpretries++;
- LIST_LINK_TAIL(ads->timew,qu);
+void *adns__alloc_final(adns_query qu, size_t sz) {
+ /* When we're in the _final stage, we _subtract_ from interim_alloc'd
+ * each allocation, and use final_allocspace to point to the next free
+ * bit.
+ */
+ void *rp;
+
+ sz= MEM_ROUND(sz);
+ rp= qu->final_allocspace;
+ assert(rp);
+ qu->interim_allocd -= sz;
+ assert(qu->interim_allocd>=0);
+ qu->final_allocspace= (byte*)rp + sz;
+ return rp;
+}
+
+void adns__reset_cnameonly(adns_state ads, adns_query qu) {
+ assert(qu->final_allocspace);
+ qu->answer->nrrs= 0;
+ qu->answer->rrs= 0;
+ qu->interim_allocd= qu->answer->cname ? MEM_ROUND(strlen(qu->answer->cname)+1) : 0;
}
static void adns__query_done(adns_state ads, adns_query qu) {
LIST_LINK_TAIL(ads->output,qu);
}
-void adns__reset_cnameonly(adns_state ads, adns_query qu) {
- assert(qu->final_allocspace);
- qu->answer->nrrs= 0;
- qu->answer->rrs= 0;
- qu->interim_allocd= qu->answer->cname ? MEM_ROUND(strlen(qu->answer->cname)+1) : 0;
-}
-
void adns__query_fail(adns_state ads, adns_query qu, adns_status stat) {
adns__reset_cnameonly(ads,qu);
qu->answer->status= stat;
adns__query_done(ads,qu);
}
+
+void adns__makefinal_str(adns_query qu, char **strp) {
+ int l;
+ char *before, *after;
+
+ before= *strp;
+ l= strlen(before)+1;
+ after= adns__alloc_final(qu,l);
+ memcpy(after,before,l);
+ *strp= after;
+}
+
+void adns__makefinal_block(adns__query qu, void **blpp, size_t sz) {
+ void *after;
+
+ after= adns__alloc_final(qu,sz);
+ memcpy(after,*blpp,sz);
+ *blpp= after;
+}
+
-/**/
+/*
+ * reply.c
+ * - main handling and parsing routine for received datagrams
+ */
+/*
+ * This file is part of adns, which is Copyright (C) 1997, 1998 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
+ * 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.
+ */
#include "internal.h"
adns__query_finish(ads,qu,adns_s_ok);
return;
-x_truncated:
+ x_truncated:
if (!flg_tc) {
adns__diag(ads,serv,qu,"server sent datagram which points outside itself");
adns__query_fail(ads,qu,adns_s_serverfaulty);
-/**/
+/*
+ * setup.c
+ * - configuration file parsing
+ * - management of global state
+ */
+/*
+ * This file is part of adns, which is Copyright (C) 1997, 1998 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
+ * 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.
+ */
#include <stdlib.h>
#include <errno.h>
#include "internal.h"
-void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
- int serv, const char *fmt, adns_query qu, va_list al) {
- const char *bef, *aft;
- vbuf vb;
- if (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))) return;
-
- fprintf(stderr,"adns%s: ",pfx);
-
- vfprintf(stderr,fmt,al);
-
- bef= " (";
- aft= "\n";
-
- if (qu && qu->query_dgram) {
- 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>");
- bef=", "; aft=")\n";
- }
-
- if (serv>=0) {
- fprintf(stderr,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
- bef=", "; aft=")\n";
- }
-
- fputs(aft,stderr);
-}
-
-void adns__debug(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
- va_list al;
-
- va_start(al,fmt);
- adns__vdiag(ads," debug",0,serv,qu,fmt,al);
- va_end(al);
-}
-
-void adns__warn(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
- va_list al;
-
- va_start(al,fmt);
- adns__vdiag(ads," warning",adns_if_noerrprint|adns_if_noserverwarn,serv,qu,fmt,al);
- va_end(al);
-}
-
-void adns__diag(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
- va_list al;
-
- va_start(al,fmt);
- adns__vdiag(ads,"",adns_if_noerrprint,serv,qu,fmt,al);
- va_end(al);
-}
-
-
-void adns__vbuf_init(vbuf *vb) {
- vb->used= vb->avail= 0; vb->buf= 0;
-}
-
-int adns__vbuf_ensure(vbuf *vb, int want) {
- void *nb;
-
- if (vb->avail >= want) return 1;
- nb= realloc(vb->buf,want); if (!nb) return 0;
- vb->buf= nb;
- vb->avail= want;
- return 1;
-}
-
-void adns__vbuf_appendq(vbuf *vb, const byte *data, int len) {
- memcpy(vb->buf+vb->used,data,len);
- vb->used+= len;
-}
-
-int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
- int newlen;
- void *nb;
-
- newlen= vb->used+len;
- if (vb->avail < newlen) {
- newlen <<= 1;
- nb= realloc(vb->buf,newlen);
- if (!nb) { newlen >>= 1; nb= realloc(vb->buf,newlen); }
- if (!nb) return 0;
- vb->buf= nb;
- vb->avail= newlen;
- }
- adns__vbuf_appendq(vb,data,len);
- return 1;
-}
-
-
static void addserver(adns_state ads, struct in_addr addr) {
int i;
struct server *ss;
int adns_finish(adns_state ads) {
abort(); /* fixme */
}
-
-const char *adns_strerror(adns_status st) {
- static char buf[100];
- snprintf(buf,sizeof(buf),"code %d",st);
- return buf;
-}
+++ /dev/null
-/**/
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <sys/time.h>
-
-#include "internal.h"
-
-int adns__internal_submit(adns_state ads, adns_query *query_r,
- adns_rrtype type, vbuf *qumsg_vb, int id,
- adns_queryflags flags, struct timeval now,
- adns_status failstat, const qcontext *ctx) {
- adns_query qu;
- adns_status stat;
- int ol, id, r;
- struct timeval now;
- const typeinfo *typei;
- adns_query qu;
-
- qu= malloc(sizeof(*qu)); if (!qu) goto x_nomemory;
- qu->answer= malloc(sizeof(*qu->answer)); if (!qu->answer) goto x_freequ_nomemory;
-
- qu->state= query_udp;
- qu->back= qu->next= qu->parent= 0;
- LIST_INIT(qu->children);
- qu->siblings.next= qu->siblings.back= 0;
- qu->allocations= 0;
- qu->interim_allocd= 0;
- qu->perm_used= 0;
-
- qu->typei= adns__findtype(type);
- adns__vbuf_init(&qu->vb);
-
- qu->cname_dgram= 0;
- qu->cname_dglen= qu->cname_begin= 0;
-
- qu->id= id;
- qu->flags= flags;
- qu->udpretries= 0;
- qu->udpnextserver= 0;
- qu->udpsent= qu->tcpfailed= 0;
- timerclear(&qu->timeout);
- memcpy(&qu->context,ctx,sizeof(qu->context));
- memcpy(qu->owner,owner,ol); qu->owner[ol]= 0;
-
- qu->answer->status= adns_s_ok;
- qu->answer->cname= 0;
- qu->answer->type= type;
- qu->answer->nrrs= 0;
- qu->answer->rrs= 0;
-
- if (qu->typei) {
- qu->answer->rrsz= qu->rrsz;
- } else {
- qu->answer->rrsz= -1;
- failstat= adns_s_notimplemented;
- }
-
- *query_r= qu;
-
- qu->query_dgram= malloc(qumsg_vb->used);
- if (!qu->query_dgram) {
- adns__query_fail(ads,qu,adns_s_nomemory);
- return;
- }
- memcpy(qu->query_dgram,qumsg_vb->buf,qumsg_vb->used);
- qu->vb= *qumsg_vb;
- adns__vbuf_init(qumsg_vb);
-
- if (failstat) {
- adns__query_fail(ads,qu,failstat);
- return;
- }
- adns__query_udp(ads,qu,now);
- adns__autosys(ads,now);
-
- return 0;
-
- x_freequ_nomemory:
- free(qu);
- x_nomemory:
- free(query_dgram);
- return adns_s_nomemory;
-}
-
-int adns_submit(adns_state ads,
- const char *owner,
- adns_rrtype type,
- adns_queryflags flags,
- void *context,
- adns_query *query_r) {
- qcontext ctx;
- int id;
- vbuf vb;
-
- ctx.ext= context;
- r= gettimeofday(&now,0); if (r) return errno;
- id= 0;
-
- adns__vbuf_init(&vb);
-
- ol= strlen(owner);
- if (ol<=1 || ol>DNS_MAXDOMAIN+1) { stat= adns_s_invaliddomain; goto xit; }
-
- if (owner[ol-1]=='.' && owner[ol-2]!='\\') { flags &= ~adns_qf_search; ol--; }
-
- stat= adns__mkquery(ads,&vb, &id, owner,ol, typei,flags);
-
- xit:
- return adns__internal_submit(ads,query_r, type,&vb,id, flags,now, stat,&ctx);
-}
-
-int adns_synchronous(adns_state ads,
- const char *owner,
- adns_rrtype type,
- adns_queryflags flags,
- adns_answer **answer_r) {
- adns_query qu;
- int r;
-
- r= adns_submit(ads,owner,type,flags,0,&qu);
- if (r) return r;
-
- do {
- r= adns_wait(ads,&qu,answer_r,0);
- } while (r==EINTR);
- if (r) adns_cancel(ads,qu);
- return r;
-}
-
-void adns_cancel(adns_state ads, adns_query query) {
- abort(); /* fixme */
-}
-
-void adns__makefinal_str(adns_query qu, char **strp) {
- int l;
- char *before, *after;
-
- before= *strp;
- l= strlen(before)+1;
- after= adns__alloc_final(qu,l);
- memcpy(after,before,l);
- *strp= after;
-}
-
-void adns__makefinal_block(adns__query qu, void **blpp, size_t sz) {
- void *after;
-
- after= adns__alloc_final(qu,sz);
- memcpy(after,*blpp,sz);
- *blpp= after;
-}
-
-void *adns__alloc_interim(adns_state ads, adns_query qu, size_t sz) {
- allocnode *an;
-
- assert(!qu->final_allocspace);
- sz= MEM_ROUND(sz);
- an= malloc(MEM_ROUND(MEM_ROUND(sizeof(*an)) + sz));
- if (!an) {
- adns__query_fail(ads,qu,adns_s_nolocalmem);
- return 0;
- }
- qu->permalloclen += sz;
- an->next= qu->allocations;
- qu->allocations= an;
- return (byte*)an + MEM_ROUND(sizeof(*an));
-}
-
-void *adns__alloc_final(adns_query qu, size_t sz) {
- /* When we're in the _final stage, we _subtract_ from interim_alloc'd
- * each allocation, and use final_allocspace to point to the next free
- * bit.
- */
- void *rp;
-
- sz= MEM_ROUND(sz);
- rp= qu->final_allocspace;
- assert(rp);
- qu->interim_allocd -= sz;
- assert(qu->interim_allocd>=0);
- qu->final_allocspace= (byte*)rp + sz;
- return rp;
-}
--- /dev/null
+/*
+ * transmit.c
+ * - construct queries
+ * - send queries
+ */
+/*
+ * This file is part of adns, which is Copyright (C) 1997, 1998 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
+ * 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.
+ */
+
+#include "internal.h"
+
+adns_status adns__mkquery(adns_state ads, vbuf *vb,
+ const char *owner, int ol, int *id_r,
+ const typeinfo *typei, adns_queryflags flags) {
+ int ll, c, nlabs, id;
+ byte label[255], *rqp;
+ const char *p, *pe;
+
+#define MKQUERY_ADDB(b) *rqp++= (b)
+#define MKQUERY_ADDW(w) (MKQUERY_ADDB(((w)>>8)&0x0ff), MKQUERY_ADDB((w)&0x0ff))
+
+ vb->used= 0;
+ if (!adns__vbuf_ensure(vb,DNS_HDRSIZE+strlen(owner)+1+5))
+ return adns_s_nolocalmem;
+ rqp= vb->buf;
+
+ *id_r= id= (ads->nextid++) & 0x0ffff;
+
+ MKQUERY_ADDW(id);
+ MKQUERY_ADDB(0x01); /* QR=Q(0), OPCODE=QUERY(0000), !AA, !TC, RD */
+ MKQUERY_ADDB(0x00); /* !RA, Z=000, RCODE=NOERROR(0000) */
+ MKQUERY_ADDW(1); /* QDCOUNT=1 */
+ MKQUERY_ADDW(0); /* ANCOUNT=0 */
+ MKQUERY_ADDW(0); /* NSCOUNT=0 */
+ MKQUERY_ADDW(0); /* ARCOUNT=0 */
+ p= owner; pe= owner+ol;
+ nlabs= 0;
+ if (!*p) return adns_s_invaliddomain;
+ do {
+ ll= 0;
+ while (p!=pe && (c= *p++)!='.') {
+ if (c=='\\') {
+ if (!(flags & adns_qf_anyquote)) return adns_s_invaliddomain;
+ if (ctype_digit(p[0])) {
+ if (ctype_digit(p[1]) && ctype_digit(p[2])) {
+ c= (*p++ - '0')*100 + (*p++ - '0')*10 + (*p++ - '0');
+ if (c >= 256) return adns_s_invaliddomain;
+ } else {
+ return adns_s_invaliddomain;
+ }
+ } else if (!(c= *p++)) {
+ return adns_s_invaliddomain;
+ }
+ }
+ if (!(flags & adns_qf_anyquote)) {
+ if (ctype_digit(c) || c == '-') {
+ if (!ll) return adns_s_invaliddomain;
+ } else if (!ctype_alpha(c)) {
+ return adns_s_invaliddomain;
+ }
+ }
+ if (ll == sizeof(label)) return adns_s_invaliddomain;
+ label[ll++]= c;
+ }
+ if (!ll) return adns_s_invaliddomain;
+ if (nlabs++ > 63) return adns_s_invaliddomain;
+ MKQUERY_ADDB(ll);
+ memcpy(rqp,label,ll); rqp+= ll;
+ } while (p!=pe);
+
+ MKQUERY_ADDB(0);
+ MKQUERY_ADDW(typei->type & adns__rrt_typemask); /* QTYPE */
+ MKQUERY_ADDW(DNS_CLASS_IN); /* QCLASS=IN */
+
+ vb->used= rqp - vb->buf;
+ assert(vb->used <= vb->avail);
+
+ return adns_s_ok;
+}
+
+void adns__query_tcp(adns_state ads, adns_query qu, struct timeval now) {
+ byte length[2];
+ struct iovec iov[2];
+ int wr, r;
+
+ if (ads->tcpstate != server_ok) return;
+
+ length[0]= (qu->query_dglen&0x0ff00U) >>8;
+ length[1]= (qu->query_dglen&0x0ff);
+
+ if (!adns__vbuf_ensure(&ads->tcpsend,ads->tcpsend.used+qu->query_dglen+2)) return;
+
+ timevaladd(&now,TCPMS);
+ qu->timeout= now;
+ qu->state= query_tcpsent;
+ LIST_LINK_TAIL(ads->timew,qu);
+
+ if (ads->tcpsend.used) {
+ wr= 0;
+ } else {
+ iov[0].iov_base= length;
+ iov[0].iov_len= 2;
+ iov[1].iov_base= qu->query_dgram;
+ iov[1].iov_len= qu->query_dglen;
+ wr= writev(ads->tcpsocket,iov,2);
+ if (wr < 0) {
+ if (!(errno == EAGAIN || errno == EINTR || errno == ENOSPC ||
+ errno == ENOBUFS || errno == ENOMEM)) {
+ adns__tcp_broken(ads,"write",strerror(errno));
+ return;
+ }
+ wr= 0;
+ }
+ }
+
+ if (wr<2) {
+ r= adns__vbuf_append(&ads->tcpsend,length,2-wr); assert(r);
+ wr= 0;
+ } else {
+ wr-= 2;
+ }
+ if (wr<qu->query_dglen) {
+ r= adns__vbuf_append(&ads->tcpsend,qu->query_dgram+wr,qu->query_dglen-wr); assert(r);
+ }
+}
+
+static void query_usetcp(adns_state ads, adns_query qu, struct timeval now) {
+ timevaladd(&now,TCPMS);
+ qu->timeout= now;
+ qu->state= query_tcpwait;
+ LIST_LINK_TAIL(ads->timew,qu);
+ adns__query_tcp(ads,qu,now);
+ adns__tcp_tryconnect(ads,now);
+}
+
+void adns__query_udp(adns_state ads, adns_query qu, struct timeval now) {
+ struct sockaddr_in servaddr;
+ int serv, r;
+
+ assert(qu->state == query_udp);
+ if ((qu->flags & adns_qf_usevc) || (qu->query_dglen > DNS_MAXUDP)) {
+ query_usetcp(ads,qu,now);
+ return;
+ }
+
+ if (qu->udpretries >= UDPMAXRETRIES) {
+ adns__query_fail(ads,qu,adns_s_timeout);
+ return;
+ }
+
+ serv= qu->udpnextserver;
+ memset(&servaddr,0,sizeof(servaddr));
+ servaddr.sin_family= AF_INET;
+ servaddr.sin_addr= ads->servers[serv].addr;
+ servaddr.sin_port= htons(DNS_PORT);
+
+ r= sendto(ads->udpsocket,qu->query_dgram,qu->query_dglen,0,&servaddr,sizeof(servaddr));
+ if (r<0 && errno == EMSGSIZE) { query_usetcp(ads,qu,now); return; }
+ if (r<0) adns__warn(ads,serv,0,"sendto failed: %s",strerror(errno));
+
+ timevaladd(&now,UDPRETRYMS);
+ qu->timeout= now;
+ qu->udpsent |= (1<<serv);
+ qu->udpnextserver= (serv+1)%ads->nservers;
+ qu->udpretries++;
+ LIST_LINK_TAIL(ads->timew,qu);
+}
-/**/
+/*
+ * types.c
+ * - RR-type-specific code, and the machinery to call it
+ */
+/*
+ * This file is part of adns, which is Copyright (C) 1997, 1998 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
+ * 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.
+ */
#include "internal.h"