ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

transmit.c
Go to the documentation of this file.
00001 /*
00002  * transmit.c
00003  * - construct queries
00004  * - send queries
00005  */
00006 /*
00007  *  This file is
00008  *    Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk>
00009  *
00010  *  It is part of adns, which is
00011  *    Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk>
00012  *    Copyright (C) 1999-2000 Tony Finch <dot@dotat.at>
00013  *
00014  *  This program is free software; you can redistribute it and/or modify
00015  *  it under the terms of the GNU General Public License as published by
00016  *  the Free Software Foundation; either version 2, or (at your option)
00017  *  any later version.
00018  *
00019  *  This program is distributed in the hope that it will be useful,
00020  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  *  GNU General Public License for more details.
00023  *
00024  *  You should have received a copy of the GNU General Public License
00025  *  along with this program; if not, write to the Free Software Foundation,
00026  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00027  */
00028 
00029 #include <errno.h>
00030 
00031 #ifdef ADNS_JGAA_WIN32
00032 # include "adns_win32.h"
00033 #else
00034 # include <sys/types.h>
00035 # include <sys/uio.h>
00036 #endif
00037 
00038 #include "internal.h"
00039 #include "tvarith.h"
00040 
00041 #define MKQUERY_START(vb) (rqp= (vb)->buf+(vb)->used)
00042 #define MKQUERY_ADDB(b) *rqp++= (b)
00043 #define MKQUERY_ADDW(w) (MKQUERY_ADDB(((w)>>8)&0x0ff), MKQUERY_ADDB((w)&0x0ff))
00044 #define MKQUERY_STOP(vb) ((vb)->used= rqp-(vb)->buf)
00045 
00046 static adns_status mkquery_header(adns_state ads, vbuf *vb, int *id_r, int qdlen) {
00047   int id;
00048   byte *rqp;
00049 
00050   if (!adns__vbuf_ensure(vb,DNS_HDRSIZE+qdlen+4)) return adns_s_nomemory;
00051 
00052   vb->used= 0;
00053   MKQUERY_START(vb);
00054 
00055   *id_r= id= (ads->nextid++) & 0x0ffff;
00056   MKQUERY_ADDW(id);
00057   MKQUERY_ADDB(0x01); /* QR=Q(0), OPCODE=QUERY(0000), !AA, !TC, RD */
00058   MKQUERY_ADDB(0x00); /* !RA, Z=000, RCODE=NOERROR(0000) */
00059   MKQUERY_ADDW(1); /* QDCOUNT=1 */
00060   MKQUERY_ADDW(0); /* ANCOUNT=0 */
00061   MKQUERY_ADDW(0); /* NSCOUNT=0 */
00062   MKQUERY_ADDW(0); /* ARCOUNT=0 */
00063 
00064   MKQUERY_STOP(vb);
00065 
00066   return adns_s_ok;
00067 }
00068 
00069 static adns_status mkquery_footer(vbuf *vb, adns_rrtype type) {
00070   byte *rqp;
00071 
00072   MKQUERY_START(vb);
00073   MKQUERY_ADDW(type & adns__rrt_typemask); /* QTYPE */
00074   MKQUERY_ADDW(DNS_CLASS_IN); /* QCLASS=IN */
00075   MKQUERY_STOP(vb);
00076   assert(vb->used <= vb->avail);
00077 
00078   return adns_s_ok;
00079 }
00080 
00081 adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
00082               const char *owner, int ol,
00083               const typeinfo *typei, adns_queryflags flags) {
00084   int ll, c, nbytes;
00085   byte label[255], *rqp;
00086   const char *p, *pe;
00087   adns_status st;
00088 
00089   st= mkquery_header(ads,vb,id_r,ol+2); if (st) return st;
00090 
00091   MKQUERY_START(vb);
00092 
00093   p= owner; pe= owner+ol;
00094   nbytes= 0;
00095   while (p!=pe) {
00096     ll= 0;
00097     while (p!=pe && (c= *p++)!='.') {
00098       if (c=='\\') {
00099     if (!(flags & adns_qf_quoteok_query)) return adns_s_querydomaininvalid;
00100     if (ctype_digit(p[0])) {
00101       if (ctype_digit(p[1]) && ctype_digit(p[2])) {
00102         c= (p[0] - '0')*100 + (p[1] - '0')*10 + (p[2] - '0');
00103         p += 3;
00104         if (c >= 256) return adns_s_querydomaininvalid;
00105       } else {
00106         return adns_s_querydomaininvalid;
00107       }
00108     } else if (!(c= *p++)) {
00109       return adns_s_querydomaininvalid;
00110     }
00111       }
00112       if (!(flags & adns_qf_quoteok_query)) {
00113     if (c == '-') {
00114       if (!ll) return adns_s_querydomaininvalid;
00115     } else if (!ctype_alpha(c) && !ctype_digit(c)) {
00116       return adns_s_querydomaininvalid;
00117     }
00118       }
00119       if (ll == sizeof(label)) return adns_s_querydomaininvalid;
00120       label[ll++]= c;
00121     }
00122     if (!ll) return adns_s_querydomaininvalid;
00123     if (ll > DNS_MAXLABEL) return adns_s_querydomaintoolong;
00124     nbytes+= ll+1;
00125     if (nbytes >= DNS_MAXDOMAIN) return adns_s_querydomaintoolong;
00126     MKQUERY_ADDB(ll);
00127     memcpy(rqp,label,(size_t) ll); rqp+= ll;
00128   }
00129   MKQUERY_ADDB(0);
00130 
00131   MKQUERY_STOP(vb);
00132 
00133   st= mkquery_footer(vb,typei->type);
00134 
00135   return adns_s_ok;
00136 }
00137 
00138 adns_status adns__mkquery_frdgram(adns_state ads, vbuf *vb, int *id_r,
00139                   const byte *qd_dgram, int qd_dglen, int qd_begin,
00140                   adns_rrtype type, adns_queryflags flags) {
00141   byte *rqp;
00142   findlabel_state fls;
00143   int lablen, labstart;
00144   adns_status st;
00145 
00146   st= mkquery_header(ads,vb,id_r,qd_dglen); if (st) return st;
00147 
00148   MKQUERY_START(vb);
00149 
00150   adns__findlabel_start(&fls,ads,-1,0,qd_dgram,qd_dglen,qd_dglen,qd_begin,0);
00151   for (;;) {
00152     st= adns__findlabel_next(&fls,&lablen,&labstart); assert(!st);
00153     if (!lablen) break;
00154     assert(lablen<255);
00155     MKQUERY_ADDB(lablen);
00156     memcpy(rqp,qd_dgram+labstart, (size_t) lablen);
00157     rqp+= lablen;
00158   }
00159   MKQUERY_ADDB(0);
00160 
00161   MKQUERY_STOP(vb);
00162 
00163   st= mkquery_footer(vb,type);
00164 
00165   return adns_s_ok;
00166 }
00167 
00168 void adns__querysend_tcp(adns_query qu, struct timeval now) {
00169   byte length[2];
00170   struct iovec iov[2];
00171   int wr, r;
00172   adns_state ads;
00173 
00174   if (qu->ads->tcpstate != server_ok) return;
00175 
00176   assert(qu->state == query_tcpw);
00177 
00178   length[0]= (qu->query_dglen&0x0ff00U) >>8;
00179   length[1]= (qu->query_dglen&0x0ff);
00180 
00181   ads= qu->ads;
00182   if (!adns__vbuf_ensure(&ads->tcpsend,ads->tcpsend.used+qu->query_dglen+2)) return;
00183 
00184   qu->retries++;
00185 
00186   /* Reset idle timeout. */
00187   ads->tcptimeout.tv_sec= ads->tcptimeout.tv_usec= 0;
00188 
00189   if (ads->tcpsend.used) {
00190     wr= 0;
00191   } else {
00192     iov[0].iov_base= (char*)length;
00193     iov[0].iov_len= 2;
00194     iov[1].iov_base= (char*)qu->query_dgram;
00195     iov[1].iov_len= qu->query_dglen;
00196     adns__sigpipe_protect(qu->ads);
00197 
00198     ADNS_CLEAR_ERRNO;
00199     wr= writev(qu->ads->tcpsocket,iov,2);
00200     ADNS_CAPTURE_ERRNO;
00201     adns__sigpipe_unprotect(qu->ads);
00202     if (wr < 0) {
00203       if (!(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR || errno == ENOSPC ||
00204         errno == ENOBUFS || errno == ENOMEM)) {
00205     adns__tcp_broken(ads,"write",strerror(errno));
00206     return;
00207       }
00208       wr= 0;
00209     }
00210   }
00211 
00212   if (wr<2) {
00213     r= adns__vbuf_append(&ads->tcpsend,length,2-wr); assert(r);
00214     wr= 0;
00215   } else {
00216     wr-= 2;
00217   }
00218   if (wr<qu->query_dglen) {
00219     r= adns__vbuf_append(&ads->tcpsend,qu->query_dgram+wr,qu->query_dglen-wr); assert(r);
00220   }
00221 }
00222 
00223 static void query_usetcp(adns_query qu, struct timeval now) {
00224   qu->state= query_tcpw;
00225   qu->timeout= now;
00226   timevaladd(&qu->timeout,TCPWAITMS);
00227   LIST_LINK_TAIL(qu->ads->tcpw,qu);
00228   adns__querysend_tcp(qu,now);
00229   adns__tcp_tryconnect(qu->ads,now);
00230 }
00231 
00232 void adns__query_send(adns_query qu, struct timeval now) {
00233   struct sockaddr_in servaddr;
00234   int serv, r;
00235   adns_state ads;
00236 
00237   assert(qu->state == query_tosend);
00238   if ((qu->flags & adns_qf_usevc) || (qu->query_dglen > DNS_MAXUDP)) {
00239     query_usetcp(qu,now);
00240     return;
00241   }
00242 
00243   if (qu->retries >= UDPMAXRETRIES) {
00244     adns__query_fail(qu,adns_s_timeout);
00245     return;
00246   }
00247 
00248   serv= qu->udpnextserver;
00249   memset(&servaddr,0,sizeof(servaddr));
00250 
00251   ads= qu->ads;
00252   servaddr.sin_family= AF_INET;
00253   servaddr.sin_addr= ads->servers[serv].addr;
00254   servaddr.sin_port= htons(DNS_PORT);
00255 
00256   ADNS_CLEAR_ERRNO;
00257   r= sendto(ads->udpsocket,(char*)qu->query_dgram,qu->query_dglen,0,
00258         (const struct sockaddr*)&servaddr,sizeof(servaddr));
00259   ADNS_CAPTURE_ERRNO;
00260   if (r<0 && errno == EMSGSIZE) { qu->retries= 0; query_usetcp(qu,now); return; }
00261   if (r<0 && ((errno != EAGAIN) && (errno != EWOULDBLOCK))) adns__warn(ads,serv,0,"sendto failed: %s (%d)",strerror(errno), errno);
00262 
00263   qu->timeout= now;
00264   timevaladd(&qu->timeout,UDPRETRYMS);
00265   qu->udpsent |= (1<<serv);
00266   qu->udpnextserver= (serv+1)%ads->nservers;
00267   qu->retries++;
00268   LIST_LINK_TAIL(ads->udpw,qu);
00269 }

Generated on Fri May 25 2012 04:31:59 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.