chiark / gitweb /
+ * Referrals with RD+RA set, or RCODE=Refused, don't generate warnings,
[adns.git] / src / transmit.c
index 4590a16c7f74c95eb3b0dce8b84aeb827c628eaf..08e49d01577f760cf78b4c4d58f08bcab8805de5 100644 (file)
@@ -5,10 +5,10 @@
  */
 /*
  *  This file is
- *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *    Copyright (C) 1997-2000 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) 1997-2000 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
@@ -32,6 +32,7 @@
 #include <sys/uio.h>
 
 #include "internal.h"
+#include "tvarith.h"
 
 #define MKQUERY_START(vb) (rqp= (vb)->buf+(vb)->used)
 #define MKQUERY_ADDB(b) *rqp++= (b)
@@ -76,17 +77,17 @@ static adns_status mkquery_footer(vbuf *vb, adns_rrtype type) {
 adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
                          const char *owner, int ol,
                          const typeinfo *typei, adns_queryflags flags) {
-  int ll, c, nlabs;
+  int ll, c, nbytes;
   byte label[255], *rqp;
   const char *p, *pe;
   adns_status st;
 
-  st= mkquery_header(ads,vb,id_r,strlen(owner)+2); if (st) return st;
+  st= mkquery_header(ads,vb,id_r,ol+2); if (st) return st;
   
   MKQUERY_START(vb);
 
   p= owner; pe= owner+ol;
-  nlabs= 0;
+  nbytes= 0;
   while (p!=pe) {
     ll= 0;
     while (p!=pe && (c= *p++)!='.') {
@@ -114,7 +115,9 @@ adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
       label[ll++]= c;
     }
     if (!ll) return adns_s_querydomaininvalid;
-    if (nlabs++ > 63) return adns_s_querydomaintoolong;
+    if (ll > DNS_MAXLABEL) return adns_s_querydomaintoolong;
+    nbytes+= ll+1;
+    if (nbytes >= DNS_MAXDOMAIN) return adns_s_querydomaintoolong;
     MKQUERY_ADDB(ll);
     memcpy(rqp,label,ll); rqp+= ll;
   }
@@ -157,7 +160,7 @@ adns_status adns__mkquery_frdgram(adns_state ads, vbuf *vb, int *id_r,
   return adns_s_ok;
 }
 
-void adns__query_tcp(adns_query qu, struct timeval now) {
+void adns__querysend_tcp(adns_query qu, struct timeval now) {
   byte length[2];
   struct iovec iov[2];
   int wr, r;
@@ -165,15 +168,18 @@ void adns__query_tcp(adns_query qu, struct timeval now) {
 
   if (qu->ads->tcpstate != server_ok) return;
 
+  assert(qu->state == query_tcpw);
+
   length[0]= (qu->query_dglen&0x0ff00U) >>8;
   length[1]= (qu->query_dglen&0x0ff);
 
   ads= qu->ads;
   if (!adns__vbuf_ensure(&ads->tcpsend,ads->tcpsend.used+qu->query_dglen+2)) return;
 
-  timevaladd(&now,TCPMS);
-  qu->timeout= now;
-  qu->state= query_tcpsent;
+  qu->retries++;
+
+  /* Reset idle timeout. */
+  ads->tcptimeout.tv_sec= ads->tcptimeout.tv_usec= 0;
 
   if (ads->tcpsend.used) {
     wr= 0;
@@ -207,11 +213,11 @@ void adns__query_tcp(adns_query qu, struct timeval now) {
 }
 
 static void query_usetcp(adns_query qu, struct timeval now) {
-  timevaladd(&now,TCPMS);
+  qu->state= query_tcpw;
   qu->timeout= now;
-  qu->state= query_tcpwait;
-  LIST_LINK_TAIL(qu->ads->timew,qu);
-  adns__query_tcp(qu,now);
+  timevaladd(&qu->timeout,TCPWAITMS);
+  LIST_LINK_TAIL(qu->ads->tcpw,qu);
+  adns__querysend_tcp(qu,now);
   adns__tcp_tryconnect(qu->ads,now);
 }
 
@@ -226,7 +232,7 @@ void adns__query_send(adns_query qu, struct timeval now) {
     return;
   }
 
-  if (qu->udpretries >= UDPMAXRETRIES) {
+  if (qu->retries >= UDPMAXRETRIES) {
     adns__query_fail(qu,adns_s_timeout);
     return;
   }
@@ -241,13 +247,13 @@ void adns__query_send(adns_query qu, struct timeval now) {
   
   r= sendto(ads->udpsocket,qu->query_dgram,qu->query_dglen,0,
            (const struct sockaddr*)&servaddr,sizeof(servaddr));
-  if (r<0 && errno == EMSGSIZE) { query_usetcp(qu,now); return; }
-  if (r<0) adns__warn(ads,serv,0,"sendto failed: %s",strerror(errno));
+  if (r<0 && errno == EMSGSIZE) { qu->retries= 0; query_usetcp(qu,now); return; }
+  if (r<0 && errno != EAGAIN) adns__warn(ads,serv,0,"sendto failed: %s",strerror(errno));
   
-  timevaladd(&now,UDPRETRYMS);
   qu->timeout= now;
+  timevaladd(&qu->timeout,UDPRETRYMS);
   qu->udpsent |= (1<<serv);
   qu->udpnextserver= (serv+1)%ads->nservers;
-  qu->udpretries++;
-  LIST_LINK_TAIL(ads->timew,qu);
+  qu->retries++;
+  LIST_LINK_TAIL(ads->udpw,qu);
 }