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

types.c
Go to the documentation of this file.
00001 /*
00002  * types.c
00003  * - RR-type-specific code, and the machinery to call it
00004  */
00005 /*
00006  *  This file is
00007  *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
00008  *
00009  *  It is part of adns, which is
00010  *    Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk>
00011  *    Copyright (C) 1999-2000 Tony Finch <dot@dotat.at>
00012  *
00013  *  This program is free software; you can redistribute it and/or modify
00014  *  it under the terms of the GNU General Public License as published by
00015  *  the Free Software Foundation; either version 2, or (at your option)
00016  *  any later version.
00017  *
00018  *  This program is distributed in the hope that it will be useful,
00019  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  *  GNU General Public License for more details.
00022  *
00023  *  You should have received a copy of the GNU General Public License
00024  *  along with this program; if not, write to the Free Software Foundation,
00025  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00026  */
00027 
00028 #ifdef ADNS_JGAA_WIN32
00029 # include "adns_win32.h"
00030 #else
00031 # include <stdlib.h>
00032 # include <sys/types.h>
00033 # include <sys/socket.h>
00034 # include <netinet/in.h>
00035 # include <arpa/inet.h>
00036 #endif
00037 
00038 #include "internal.h"
00039 
00040 #define R_NOMEM           return adns_s_nomemory
00041 #define CSP_ADDSTR(s)     do { if (!adns__vbuf_appendstr(vb,(s))) R_NOMEM; } while (0)
00042 
00043 /*
00044  * order of sections:
00045  *
00046  * _string                    (pap)
00047  * _textdata, _qstring        (csp)
00048  * _str                       (mf,cs)
00049  * _intstr                    (mf,csp,cs)
00050  * _manyistr                  (mf,cs)
00051  * _txt                       (pa)
00052  * _inaddr                    (pa,dip,di)
00053  * _addr                      (pa,di,csp,cs)
00054  * _domain                    (pap)
00055  * _host_raw                  (pa)
00056  * _hostaddr                  (pap,pa,dip,di,mfp,mf,csp,cs +pap_findaddrs)
00057  * _mx_raw                    (pa,di)
00058  * _mx                        (pa,di)
00059  * _inthostaddr               (mf,cs)
00060  * _ptr                       (pa)
00061  * _strpair                   (mf,cs)
00062  * _intstrpair                (mf,cs)
00063  * _hinfo                     (pa)
00064  * _mailbox                   (pap +pap_mailbox822)
00065  * _rp                        (pa)
00066  * _soa                       (pa,mf,cs)
00067  * _flat                      (mf)
00068  *
00069  * within each section:
00070  *    pap_*
00071  *    pa_*
00072  *    dip_*
00073  *    di_*
00074  *    mfp_*
00075  *    mf_*
00076  *    csp_*
00077  *    cs_*
00078  */
00079 
00080 /*
00081  * _qstring               (pap,csp)
00082  */
00083 
00084 static adns_status pap_qstring(const parseinfo *pai, int *cbyte_io, int max,
00085                   int *len_r, char **str_r) {
00086   /* Neither len_r nor str_r may be null.
00087    * End of datagram (overrun) is indicated by returning adns_s_invaliddata;
00088    */
00089   const byte *dgram= pai->dgram;
00090   int l, cbyte;
00091   char *str;
00092 
00093   cbyte= *cbyte_io;
00094 
00095   if (cbyte >= max) return adns_s_invaliddata;
00096   GET_B(cbyte,l);
00097   if (cbyte+l > max) return adns_s_invaliddata;
00098 
00099   str= adns__alloc_interim(pai->qu, (size_t)l+1);
00100   if (!str) R_NOMEM;
00101 
00102   str[l]= 0;
00103   memcpy(str,dgram+cbyte,(size_t)l);
00104 
00105   *len_r= l;
00106   *str_r= str;
00107   *cbyte_io= cbyte+l;
00108 
00109   return adns_s_ok;
00110 }
00111 
00112 static adns_status csp_qstring(vbuf *vb, const char *dp, int len) {
00113   unsigned char ch;
00114   char buf[10];
00115   int cn;
00116 
00117   CSP_ADDSTR("\"");
00118   for (cn=0; cn<len; cn++) {
00119     ch= *dp++;
00120     if (ch == '\\') {
00121       CSP_ADDSTR("\\\\");
00122     } else if (ch == '"') {
00123       CSP_ADDSTR("\\\"");
00124     } else if (ch >= 32 && ch <= 126) {
00125       if (!adns__vbuf_append(vb,&ch,1)) R_NOMEM;
00126     } else {
00127       sprintf(buf,"\\x%02x",ch);
00128       CSP_ADDSTR(buf);
00129     }
00130   }
00131   CSP_ADDSTR("\"");
00132 
00133   return adns_s_ok;
00134 }
00135 
00136 /*
00137  * _str  (mf)
00138  */
00139 
00140 static void mf_str(adns_query qu, void *datap) {
00141   char **rrp= datap;
00142 
00143   adns__makefinal_str(qu,rrp);
00144 }
00145 
00146 /*
00147  * _intstr  (mf)
00148  */
00149 
00150 static void mf_intstr(adns_query qu, void *datap) {
00151   adns_rr_intstr *rrp= datap;
00152 
00153   adns__makefinal_str(qu,&rrp->str);
00154 }
00155 
00156 /*
00157  * _manyistr   (mf)
00158  */
00159 
00160 static void mf_manyistr(adns_query qu, void *datap) {
00161   adns_rr_intstr **rrp= datap;
00162   adns_rr_intstr *te, *table;
00163   void *tablev;
00164   int tc;
00165 
00166   for (tc=0, te= *rrp; te->i >= 0; te++, tc++);
00167   tablev= *rrp;
00168   adns__makefinal_block(qu,&tablev,sizeof(*te)*(tc+1));
00169   *rrp= table= tablev;
00170   for (te= *rrp; te->i >= 0; te++)
00171     adns__makefinal_str(qu,&te->str);
00172 }
00173 
00174 /*
00175  * _txt   (pa,cs)
00176  */
00177 
00178 static adns_status pa_txt(const parseinfo *pai, int cbyte, int max, void *datap) {
00179   adns_rr_intstr **rrp= datap, *table, *te;
00180   const byte *dgram= pai->dgram;
00181   int ti, tc, l, startbyte;
00182   adns_status st;
00183 
00184   startbyte= cbyte;
00185   if (cbyte >= max) return adns_s_invaliddata;
00186   tc= 0;
00187   while (cbyte < max) {
00188     GET_B(cbyte,l);
00189     cbyte+= l;
00190     tc++;
00191   }
00192   if (cbyte != max || !tc) return adns_s_invaliddata;
00193 
00194   table= adns__alloc_interim(pai->qu,sizeof(*table)*(tc+1));
00195   if (!table) R_NOMEM;
00196 
00197   for (cbyte=startbyte, ti=0, te=table; ti<tc; ti++, te++) {
00198     st= pap_qstring(pai, &cbyte, max, &te->i, &te->str);
00199     if (st) return st;
00200   }
00201   assert(cbyte == max);
00202 
00203   te->i= -1;
00204   te->str= 0;
00205 
00206   *rrp= table;
00207   return adns_s_ok;
00208 }
00209 
00210 static adns_status cs_txt(vbuf *vb, const void *datap) {
00211   const adns_rr_intstr *const *rrp= datap;
00212   const adns_rr_intstr *current;
00213   adns_status st;
00214   int spc;
00215 
00216   for (current= *rrp, spc=0;  current->i >= 0;  current++, spc=1) {
00217     if (spc) CSP_ADDSTR(" ");
00218     st= csp_qstring(vb,current->str,current->i); if (st) return st;
00219   }
00220   return adns_s_ok;
00221 }
00222 
00223 /*
00224  * _hinfo   (cs)
00225  */
00226 
00227 static adns_status cs_hinfo(vbuf *vb, const void *datap) {
00228   const adns_rr_intstrpair *rrp= datap;
00229   adns_status st;
00230 
00231   st= csp_qstring(vb,rrp->array[0].str,rrp->array[0].i);  if (st) return st;
00232   CSP_ADDSTR(" ");
00233   st= csp_qstring(vb,rrp->array[1].str,rrp->array[1].i);  if (st) return st;
00234   return adns_s_ok;
00235 }
00236 
00237 /*
00238  * _inaddr   (pa,dip,di)
00239  */
00240 
00241 static adns_status pa_inaddr(const parseinfo *pai, int cbyte, int max, void *datap) {
00242   struct in_addr *storeto= datap;
00243 
00244   if (max-cbyte != 4) return adns_s_invaliddata;
00245   memcpy(storeto, pai->dgram + cbyte, 4);
00246   return adns_s_ok;
00247 }
00248 
00249 static int search_sortlist(adns_state ads, struct in_addr ad) {
00250   const struct sortlist *slp;
00251   int i;
00252 
00253   for (i=0, slp=ads->sortlist;
00254        i<ads->nsortlist && !((ad.s_addr & slp->mask.s_addr) == slp->base.s_addr);
00255        i++, slp++);
00256   return i;
00257 }
00258 
00259 static int dip_inaddr(adns_state ads, struct in_addr a, struct in_addr b) {
00260   int ai, bi;
00261 
00262   if (!ads->nsortlist) return 0;
00263 
00264   ai= search_sortlist(ads,a);
00265   bi= search_sortlist(ads,b);
00266   return bi<ai;
00267 }
00268 
00269 static int di_inaddr(adns_state ads, const void *datap_a, const void *datap_b) {
00270   const struct in_addr *ap= datap_a, *bp= datap_b;
00271 
00272   return dip_inaddr(ads,*ap,*bp);
00273 }
00274 
00275 static adns_status cs_inaddr(vbuf *vb, const void *datap) {
00276   const struct in_addr *rrp= datap, rr= *rrp;
00277   const char *ia;
00278 
00279   ia= inet_ntoa(rr); assert(ia);
00280   CSP_ADDSTR(ia);
00281   return adns_s_ok;
00282 }
00283 
00284 /*
00285  * _addr   (pa,di,csp,cs)
00286  */
00287 
00288 static adns_status pa_addr(const parseinfo *pai, int cbyte, int max, void *datap) {
00289   adns_rr_addr *storeto= datap;
00290   const byte *dgram= pai->dgram;
00291 
00292   if (max-cbyte != 4) return adns_s_invaliddata;
00293   storeto->len= sizeof(storeto->addr.inet);
00294   memset(&storeto->addr,0,sizeof(storeto->addr.inet));
00295   storeto->addr.inet.sin_family= AF_INET;
00296   memcpy(&storeto->addr.inet.sin_addr,dgram+cbyte,4);
00297   return adns_s_ok;
00298 }
00299 
00300 static int di_addr(adns_state ads, const void *datap_a, const void *datap_b) {
00301   const adns_rr_addr *ap= datap_a, *bp= datap_b;
00302 
00303   assert(ap->addr.sa.sa_family == AF_INET);
00304   return dip_inaddr(ads, ap->addr.inet.sin_addr, bp->addr.inet.sin_addr);
00305 }
00306 
00307 static int div_addr(void *context, const void *datap_a, const void *datap_b) {
00308   const adns_state ads= context;
00309 
00310   return di_addr(ads, datap_a, datap_b);
00311 }
00312 
00313 static adns_status csp_addr(vbuf *vb, const adns_rr_addr *rrp) {
00314   const char *ia;
00315   static char buf[30];
00316 
00317   switch (rrp->addr.inet.sin_family) {
00318   case AF_INET:
00319     CSP_ADDSTR("INET ");
00320     ia= inet_ntoa(rrp->addr.inet.sin_addr); assert(ia);
00321     CSP_ADDSTR(ia);
00322     break;
00323   default:
00324     sprintf(buf,"AF=%u",rrp->addr.sa.sa_family);
00325     CSP_ADDSTR(buf);
00326     break;
00327   }
00328   return adns_s_ok;
00329 }
00330 
00331 static adns_status cs_addr(vbuf *vb, const void *datap) {
00332   const adns_rr_addr *rrp= datap;
00333 
00334   return csp_addr(vb,rrp);
00335 }
00336 
00337 /*
00338  * _domain      (pap,csp,cs)
00339  * _dom_raw     (pa)
00340  */
00341 
00342 static adns_status pap_domain(const parseinfo *pai, int *cbyte_io, int max,
00343                   char **domain_r, parsedomain_flags flags) {
00344   adns_status st;
00345   char *dm;
00346 
00347   st= adns__parse_domain(pai->qu->ads, pai->serv, pai->qu, &pai->qu->vb, flags,
00348              pai->dgram,pai->dglen, cbyte_io, max);
00349   if (st) return st;
00350   if (!pai->qu->vb.used) return adns_s_invaliddata;
00351 
00352   dm= adns__alloc_interim(pai->qu, (size_t) pai->qu->vb.used+1);
00353   if (!dm) R_NOMEM;
00354 
00355   dm[pai->qu->vb.used]= 0;
00356   memcpy(dm,pai->qu->vb.buf, (size_t) pai->qu->vb.used);
00357 
00358   *domain_r= dm;
00359   return adns_s_ok;
00360 }
00361 
00362 static adns_status csp_domain(vbuf *vb, const char *domain) {
00363   CSP_ADDSTR(domain);
00364   if (!*domain) CSP_ADDSTR(".");
00365   return adns_s_ok;
00366 }
00367 
00368 static adns_status cs_domain(vbuf *vb, const void *datap) {
00369   const char *const *domainp= datap;
00370   return csp_domain(vb,*domainp);
00371 }
00372 
00373 static adns_status pa_dom_raw(const parseinfo *pai, int cbyte, int max, void *datap) {
00374   char **rrp= datap;
00375   adns_status st;
00376 
00377   st= pap_domain(pai, &cbyte, max, rrp, pdf_quoteok);
00378   if (st) return st;
00379 
00380   if (cbyte != max) return adns_s_invaliddata;
00381   return adns_s_ok;
00382 }
00383 
00384 /*
00385  * _host_raw   (pa)
00386  */
00387 
00388 static adns_status pa_host_raw(const parseinfo *pai, int cbyte, int max, void *datap) {
00389   char **rrp= datap;
00390   adns_status st;
00391 
00392   st= pap_domain(pai, &cbyte, max, rrp,
00393          pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
00394   if (st) return st;
00395 
00396   if (cbyte != max) return adns_s_invaliddata;
00397   return adns_s_ok;
00398 }
00399 
00400 /*
00401  * _hostaddr   (pap,pa,dip,di,mfp,mf,csp,cs +icb_hostaddr, pap_findaddrs)
00402  */
00403 
00404 static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha,
00405                  int *cbyte_io, int count, int dmstart) {
00406   int rri, naddrs;
00407   int type, class, rdlen, rdstart, ownermatched;
00408   unsigned long ttl;
00409   adns_status st;
00410 
00411   for (rri=0, naddrs=-1; rri<count; rri++) {
00412     st= adns__findrr_anychk(pai->qu, pai->serv, pai->dgram, pai->dglen, cbyte_io,
00413                 &type, &class, &ttl, &rdlen, &rdstart,
00414                 pai->dgram, pai->dglen, dmstart, &ownermatched);
00415     if (st) return st;
00416     if (!ownermatched || class != DNS_CLASS_IN || type != adns_r_a) {
00417       if (naddrs>0) break; else continue;
00418     }
00419     if (naddrs == -1) {
00420       naddrs= 0;
00421     }
00422     if (!adns__vbuf_ensure(&pai->qu->vb, (int) ((naddrs+1)*sizeof(adns_rr_addr)))) R_NOMEM;
00423     adns__update_expires(pai->qu,ttl,pai->now);
00424     st= pa_addr(pai, rdstart,rdstart+rdlen,
00425         pai->qu->vb.buf + naddrs*sizeof(adns_rr_addr));
00426     if (st) return st;
00427     naddrs++;
00428   }
00429   if (naddrs >= 0) {
00430     ha->addrs= adns__alloc_interim(pai->qu, naddrs*sizeof(adns_rr_addr));
00431     if (!ha->addrs) R_NOMEM;
00432     memcpy(ha->addrs, pai->qu->vb.buf, naddrs*sizeof(adns_rr_addr));
00433     ha->naddrs= naddrs;
00434     ha->astatus= adns_s_ok;
00435 
00436     adns__isort(ha->addrs, naddrs, sizeof(adns_rr_addr), pai->qu->vb.buf,
00437         div_addr, pai->ads);
00438   }
00439   return adns_s_ok;
00440 }
00441 
00442 static void icb_hostaddr(adns_query parent, adns_query child) {
00443   adns_answer *cans= child->answer;
00444   adns_rr_hostaddr *rrp= child->ctx.info.hostaddr;
00445   adns_state ads= parent->ads;
00446   adns_status st;
00447 
00448   st= cans->status;
00449   rrp->astatus= st;
00450   rrp->naddrs= (st>0 && st<=adns_s_max_tempfail) ? -1 : cans->nrrs;
00451   rrp->addrs= cans->rrs.addr;
00452   adns__transfer_interim(child, parent, rrp->addrs, rrp->naddrs*sizeof(adns_rr_addr));
00453 
00454   if (parent->children.head) {
00455     LIST_LINK_TAIL(ads->childw,parent);
00456   } else {
00457     adns__query_done(parent);
00458   }
00459 }
00460 
00461 static adns_status pap_hostaddr(const parseinfo *pai, int *cbyte_io,
00462                 int max, adns_rr_hostaddr *rrp) {
00463   adns_status st;
00464   int dmstart, cbyte;
00465   qcontext ctx;
00466   int id;
00467   adns_query nqu;
00468   adns_queryflags nflags;
00469 
00470   dmstart= cbyte= *cbyte_io;
00471   st= pap_domain(pai, &cbyte, max, &rrp->host,
00472          pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
00473   if (st) return st;
00474   *cbyte_io= cbyte;
00475 
00476   rrp->astatus= adns_s_ok;
00477   rrp->naddrs= -1;
00478   rrp->addrs= 0;
00479 
00480   cbyte= pai->nsstart;
00481 
00482   st= pap_findaddrs(pai, rrp, &cbyte, pai->nscount, dmstart);
00483   if (st) return st;
00484   if (rrp->naddrs != -1) return adns_s_ok;
00485 
00486   st= pap_findaddrs(pai, rrp, &cbyte, pai->arcount, dmstart);
00487   if (st) return st;
00488   if (rrp->naddrs != -1) return adns_s_ok;
00489 
00490   st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
00491                 pai->dgram, pai->dglen, dmstart,
00492                 adns_r_addr, adns_qf_quoteok_query);
00493   if (st) return st;
00494 
00495   ctx.ext= 0;
00496   ctx.callback= icb_hostaddr;
00497   ctx.info.hostaddr= rrp;
00498 
00499   nflags= adns_qf_quoteok_query;
00500   if (!(pai->qu->flags & adns_qf_cname_loose)) nflags |= adns_qf_cname_forbid;
00501 
00502   st= adns__internal_submit(pai->ads, &nqu, adns__findtype(adns_r_addr),
00503                 &pai->qu->vb, id, nflags, pai->now, &ctx);
00504   if (st) return st;
00505 
00506   nqu->parent= pai->qu;
00507   LIST_LINK_TAIL_PART(pai->qu->children,nqu,siblings.);
00508 
00509   return adns_s_ok;
00510 }
00511 
00512 static adns_status pa_hostaddr(const parseinfo *pai, int cbyte, int max, void *datap) {
00513   adns_rr_hostaddr *rrp= datap;
00514   adns_status st;
00515 
00516   st= pap_hostaddr(pai, &cbyte, max, rrp);
00517   if (st) return st;
00518   if (cbyte != max) return adns_s_invaliddata;
00519 
00520   return adns_s_ok;
00521 }
00522 
00523 static int dip_hostaddr(adns_state ads, const adns_rr_hostaddr *ap, const adns_rr_hostaddr *bp) {
00524   if (ap->astatus != bp->astatus) return ap->astatus;
00525   if (ap->astatus) return 0;
00526 
00527   assert(ap->addrs[0].addr.sa.sa_family == AF_INET);
00528   assert(bp->addrs[0].addr.sa.sa_family == AF_INET);
00529   return dip_inaddr(ads,
00530             ap->addrs[0].addr.inet.sin_addr,
00531             bp->addrs[0].addr.inet.sin_addr);
00532 }
00533 
00534 static int di_hostaddr(adns_state ads, const void *datap_a, const void *datap_b) {
00535   const adns_rr_hostaddr *ap= datap_a, *bp= datap_b;
00536 
00537   return dip_hostaddr(ads, ap,bp);
00538 }
00539 
00540 static void mfp_hostaddr(adns_query qu, adns_rr_hostaddr *rrp) {
00541   void *tablev;
00542 
00543   adns__makefinal_str(qu,&rrp->host);
00544   tablev= rrp->addrs;
00545   adns__makefinal_block(qu, &tablev, rrp->naddrs*sizeof(*rrp->addrs));
00546   rrp->addrs= tablev;
00547 }
00548 
00549 static void mf_hostaddr(adns_query qu, void *datap) {
00550   adns_rr_hostaddr *rrp= datap;
00551 
00552   mfp_hostaddr(qu,rrp);
00553 }
00554 
00555 static adns_status csp_hostaddr(vbuf *vb, const adns_rr_hostaddr *rrp) {
00556   const char *errstr;
00557   adns_status st;
00558   char buf[20];
00559   int i;
00560 
00561   st= csp_domain(vb,rrp->host);  if (st) return st;
00562 
00563   CSP_ADDSTR(" ");
00564   CSP_ADDSTR(adns_errtypeabbrev(rrp->astatus));
00565 
00566   sprintf(buf," %d ",rrp->astatus);
00567   CSP_ADDSTR(buf);
00568 
00569   CSP_ADDSTR(adns_errabbrev(rrp->astatus));
00570   CSP_ADDSTR(" ");
00571 
00572   errstr= adns_strerror(rrp->astatus);
00573   st= csp_qstring(vb,errstr,(int)strlen(errstr));  if (st) return st;
00574 
00575   if (rrp->naddrs >= 0) {
00576     CSP_ADDSTR(" (");
00577     for (i=0; i<rrp->naddrs; i++) {
00578       CSP_ADDSTR(" ");
00579       st= csp_addr(vb,&rrp->addrs[i]);
00580     }
00581     CSP_ADDSTR(" )");
00582   } else {
00583     CSP_ADDSTR(" ?");
00584   }
00585   return adns_s_ok;
00586 }
00587 
00588 static adns_status cs_hostaddr(vbuf *vb, const void *datap) {
00589   const adns_rr_hostaddr *rrp= datap;
00590 
00591   return csp_hostaddr(vb,rrp);
00592 }
00593 
00594 /*
00595  * _mx_raw   (pa,di)
00596  */
00597 
00598 static adns_status pa_mx_raw(const parseinfo *pai, int cbyte, int max, void *datap) {
00599   const byte *dgram= pai->dgram;
00600   adns_rr_intstr *rrp= datap;
00601   adns_status st;
00602   int pref;
00603 
00604   if (cbyte+2 > max) return adns_s_invaliddata;
00605   GET_W(cbyte,pref);
00606   rrp->i= pref;
00607   st= pap_domain(pai, &cbyte, max, &rrp->str,
00608          pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
00609   if (st) return st;
00610 
00611   if (cbyte != max) return adns_s_invaliddata;
00612   return adns_s_ok;
00613 }
00614 
00615 static int di_mx_raw(adns_state ads, const void *datap_a, const void *datap_b) {
00616   const adns_rr_intstr *ap= datap_a, *bp= datap_b;
00617 
00618   if (ap->i < bp->i) return 0;
00619   if (ap->i > bp->i) return 1;
00620   return 0;
00621 }
00622 
00623 /*
00624  * _mx   (pa,di)
00625  */
00626 
00627 static adns_status pa_mx(const parseinfo *pai, int cbyte, int max, void *datap) {
00628   const byte *dgram= pai->dgram;
00629   adns_rr_inthostaddr *rrp= datap;
00630   adns_status st;
00631   int pref;
00632 
00633   if (cbyte+2 > max) return adns_s_invaliddata;
00634   GET_W(cbyte,pref);
00635   rrp->i= pref;
00636   st= pap_hostaddr(pai, &cbyte, max, &rrp->ha);
00637   if (st) return st;
00638 
00639   if (cbyte != max) return adns_s_invaliddata;
00640   return adns_s_ok;
00641 }
00642 
00643 static int di_mx(adns_state ads, const void *datap_a, const void *datap_b) {
00644   const adns_rr_inthostaddr *ap= datap_a, *bp= datap_b;
00645 
00646   if (ap->i < bp->i) return 0;
00647   if (ap->i > bp->i) return 1;
00648   return dip_hostaddr(ads, &ap->ha, &bp->ha);
00649 }
00650 
00651 /*
00652  * _inthostaddr  (mf,cs)
00653  */
00654 
00655 static void mf_inthostaddr(adns_query qu, void *datap) {
00656   adns_rr_inthostaddr *rrp= datap;
00657 
00658   mfp_hostaddr(qu,&rrp->ha);
00659 }
00660 
00661 static adns_status cs_inthostaddr(vbuf *vb, const void *datap) {
00662   const adns_rr_inthostaddr *rrp= datap;
00663   char buf[10];
00664 
00665   sprintf(buf,"%u ",rrp->i);
00666   CSP_ADDSTR(buf);
00667 
00668   return csp_hostaddr(vb,&rrp->ha);
00669 }
00670 
00671 /*
00672  * _inthost  (cs)
00673  */
00674 
00675 static adns_status cs_inthost(vbuf *vb, const void *datap) {
00676   const adns_rr_intstr *rrp= datap;
00677   char buf[10];
00678 
00679   sprintf(buf,"%u ",rrp->i);
00680   CSP_ADDSTR(buf);
00681   return csp_domain(vb,rrp->str);
00682 }
00683 
00684 /*
00685  * _ptr   (pa, +icb_ptr)
00686  */
00687 
00688 static void icb_ptr(adns_query parent, adns_query child) {
00689   adns_answer *cans= child->answer;
00690   const adns_rr_addr *queried, *found;
00691   adns_state ads= parent->ads;
00692   int i;
00693 
00694   if (cans->status == adns_s_nxdomain || cans->status == adns_s_nodata) {
00695     adns__query_fail(parent,adns_s_inconsistent);
00696     return;
00697   } else if (cans->status) {
00698     adns__query_fail(parent,cans->status);
00699     return;
00700   }
00701 
00702   queried= &parent->ctx.info.ptr_parent_addr;
00703   for (i=0, found=cans->rrs.addr; i<cans->nrrs; i++, found++) {
00704     if (queried->len == found->len &&
00705     !memcmp(&queried->addr,&found->addr,(size_t) queried->len)) {
00706       if (!parent->children.head) {
00707     adns__query_done(parent);
00708     return;
00709       } else {
00710     LIST_LINK_TAIL(ads->childw,parent);
00711     return;
00712       }
00713     }
00714   }
00715 
00716   adns__query_fail(parent,adns_s_inconsistent);
00717 }
00718 
00719 static adns_status pa_ptr(const parseinfo *pai, int dmstart, int max, void *datap) {
00720   static const char *(expectdomain[])= { DNS_INADDR_ARPA };
00721 
00722   char **rrp= datap;
00723   adns_status st;
00724   adns_rr_addr *ap;
00725   findlabel_state fls;
00726   char *ep;
00727   byte ipv[4];
00728   char labbuf[4];
00729   int cbyte, i, lablen, labstart, l, id;
00730   adns_query nqu;
00731   qcontext ctx;
00732 
00733   cbyte= dmstart;
00734   st= pap_domain(pai, &cbyte, max, rrp,
00735          pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
00736   if (st) return st;
00737   if (cbyte != max) return adns_s_invaliddata;
00738 
00739   ap= &pai->qu->ctx.info.ptr_parent_addr;
00740   if (!ap->len) {
00741     adns__findlabel_start(&fls, pai->ads, -1, pai->qu,
00742               pai->qu->query_dgram, pai->qu->query_dglen,
00743               pai->qu->query_dglen, DNS_HDRSIZE, 0);
00744     for (i=0; i<4; i++) {
00745       st= adns__findlabel_next(&fls,&lablen,&labstart); assert(!st);
00746       if (lablen<=0 || lablen>3) return adns_s_querydomainwrong;
00747       memcpy(labbuf, pai->qu->query_dgram + labstart, (size_t) lablen);  labbuf[lablen]= 0;
00748       ipv[3-i]= (unsigned char)strtoul(labbuf,&ep,10);  if (*ep) return adns_s_querydomainwrong;
00749       if (lablen>1 && pai->qu->query_dgram[labstart]=='0')
00750     return adns_s_querydomainwrong;
00751     }
00752     for (i=0; i<(int)sizeof(expectdomain)/(int)sizeof(*expectdomain); i++) {
00753       st= adns__findlabel_next(&fls,&lablen,&labstart); assert(!st);
00754       l= strlen(expectdomain[i]);
00755       if (lablen != l || memcmp(pai->qu->query_dgram + labstart, expectdomain[i], (size_t)l))
00756     return adns_s_querydomainwrong;
00757     }
00758     st= adns__findlabel_next(&fls,&lablen,0); assert(!st);
00759     if (lablen) return adns_s_querydomainwrong;
00760 
00761     ap->len= sizeof(struct sockaddr_in);
00762     memset(&ap->addr,0,sizeof(ap->addr.inet));
00763     ap->addr.inet.sin_family= AF_INET;
00764     ap->addr.inet.sin_addr.s_addr=
00765       htonl((u_long)(ipv[0]<<24) | (ipv[1]<<16) | (ipv[2]<<8) | (ipv[3]));
00766   }
00767 
00768   st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
00769                 pai->dgram, pai->dglen, dmstart,
00770                 adns_r_addr, adns_qf_quoteok_query);
00771   if (st) return st;
00772 
00773   ctx.ext= 0;
00774   ctx.callback= icb_ptr;
00775   memset(&ctx.info,0,(size_t) sizeof(ctx.info));
00776   st= adns__internal_submit(pai->ads, &nqu, adns__findtype(adns_r_addr),
00777                 &pai->qu->vb, id,
00778                 adns_qf_quoteok_query, pai->now, &ctx);
00779   if (st) return st;
00780 
00781   nqu->parent= pai->qu;
00782   LIST_LINK_TAIL_PART(pai->qu->children,nqu,siblings.);
00783   return adns_s_ok;
00784 }
00785 
00786 /*
00787  * _strpair   (mf)
00788  */
00789 
00790 static void mf_strpair(adns_query qu, void *datap) {
00791   adns_rr_strpair *rrp= datap;
00792 
00793   adns__makefinal_str(qu,&rrp->array[0]);
00794   adns__makefinal_str(qu,&rrp->array[1]);
00795 }
00796 
00797 /*
00798  * _intstrpair   (mf)
00799  */
00800 
00801 static void mf_intstrpair(adns_query qu, void *datap) {
00802   adns_rr_intstrpair *rrp= datap;
00803 
00804   adns__makefinal_str(qu,&rrp->array[0].str);
00805   adns__makefinal_str(qu,&rrp->array[1].str);
00806 }
00807 
00808 /*
00809  * _hinfo   (pa)
00810  */
00811 
00812 static adns_status pa_hinfo(const parseinfo *pai, int cbyte, int max, void *datap) {
00813   adns_rr_intstrpair *rrp= datap;
00814   adns_status st;
00815   int i;
00816 
00817   for (i=0; i<2; i++) {
00818     st= pap_qstring(pai, &cbyte, max, &rrp->array[i].i, &rrp->array[i].str);
00819     if (st) return st;
00820   }
00821 
00822   if (cbyte != max) return adns_s_invaliddata;
00823 
00824   return adns_s_ok;
00825 }
00826 
00827 /*
00828  * _mailbox   (pap,cs)
00829  */
00830 
00831 static adns_status pap_mailbox822(const parseinfo *pai, int *cbyte_io, int max,
00832                   char **mb_r) {
00833   int lablen, labstart, i, needquote, c, r, neednorm;
00834   const unsigned char *p;
00835   char *str;
00836   findlabel_state fls;
00837   adns_status st;
00838   vbuf *vb;
00839 
00840   vb= &pai->qu->vb;
00841   vb->used= 0;
00842   adns__findlabel_start(&fls, pai->ads,
00843             -1, pai->qu,
00844             pai->dgram, pai->dglen, max,
00845             *cbyte_io, cbyte_io);
00846   st= adns__findlabel_next(&fls,&lablen,&labstart);
00847   if (!lablen) {
00848     adns__vbuf_appendstr(vb,".");
00849     goto x_ok;
00850   }
00851 
00852   neednorm= 1;
00853   for (i=0, needquote=0, p= pai->dgram+labstart; i<lablen; i++) {
00854     c= *p++;
00855     if ((c&~128) < 32 || (c&~128) == 127) return adns_s_invaliddata;
00856     if (c == '.' && !neednorm) neednorm= 1;
00857     else if (c==' ' || c>=127 || ctype_822special(c)) needquote++;
00858     else neednorm= 0;
00859   }
00860 
00861   if (needquote || neednorm) {
00862     r= adns__vbuf_ensure(vb, lablen+needquote+4); if (!r) R_NOMEM;
00863     adns__vbuf_appendq(vb,(byte*)"\"",1);
00864     for (i=0, needquote=0, p= pai->dgram+labstart; i<lablen; i++, p++) {
00865       c= *p;
00866       if (c == '"' || c=='\\') adns__vbuf_appendq(vb,(byte*)"\\",1);
00867       adns__vbuf_appendq(vb,p,1);
00868     }
00869     adns__vbuf_appendq(vb,(byte*)"\"",1);
00870   } else {
00871     r= adns__vbuf_append(vb, pai->dgram+labstart, lablen); if (!r) R_NOMEM;
00872   }
00873 
00874   r= adns__vbuf_appendstr(vb,"@"); if (!r) R_NOMEM;
00875 
00876   st= adns__parse_domain_more(&fls,pai->ads, pai->qu,vb,0, pai->dgram);
00877   if (st) return st;
00878 
00879  x_ok:
00880   str= adns__alloc_interim(pai->qu, (size_t) vb->used+1); if (!str) R_NOMEM;
00881   memcpy(str,vb->buf,(size_t) vb->used);
00882   str[vb->used]= 0;
00883   *mb_r= str;
00884   return adns_s_ok;
00885 }
00886 
00887 static adns_status pap_mailbox(const parseinfo *pai, int *cbyte_io, int max,
00888                    char **mb_r) {
00889   if (pai->qu->typei->type & adns__qtf_mail822) {
00890     return pap_mailbox822(pai, cbyte_io, max, mb_r);
00891   } else {
00892     return pap_domain(pai, cbyte_io, max, mb_r, pdf_quoteok);
00893   }
00894 }
00895 
00896 static adns_status csp_mailbox(vbuf *vb, const char *mailbox) {
00897   return csp_domain(vb,mailbox);
00898 }
00899 
00900 /*
00901  * _rp   (pa,cs)
00902  */
00903 
00904 static adns_status pa_rp(const parseinfo *pai, int cbyte, int max, void *datap) {
00905   adns_rr_strpair *rrp= datap;
00906   adns_status st;
00907 
00908   st= pap_mailbox(pai, &cbyte, max, &rrp->array[0]);
00909   if (st) return st;
00910 
00911   st= pap_domain(pai, &cbyte, max, &rrp->array[1], pdf_quoteok);
00912   if (st) return st;
00913 
00914   if (cbyte != max) return adns_s_invaliddata;
00915   return adns_s_ok;
00916 }
00917 
00918 static adns_status cs_rp(vbuf *vb, const void *datap) {
00919   const adns_rr_strpair *rrp= datap;
00920   adns_status st;
00921 
00922   st= csp_mailbox(vb,rrp->array[0]);  if (st) return st;
00923   CSP_ADDSTR(" ");
00924   st= csp_domain(vb,rrp->array[1]);  if (st) return st;
00925 
00926   return adns_s_ok;
00927 }
00928 
00929 /*
00930  * _soa   (pa,mf,cs)
00931  */
00932 
00933 static adns_status pa_soa(const parseinfo *pai, int cbyte, int max, void *datap) {
00934   adns_rr_soa *rrp= datap;
00935   const byte *dgram= pai->dgram;
00936   adns_status st;
00937   int msw, lsw, i;
00938 
00939   st= pap_domain(pai, &cbyte, max, &rrp->mname,
00940          pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
00941   if (st) return st;
00942 
00943   st= pap_mailbox(pai, &cbyte, max, &rrp->rname);
00944   if (st) return st;
00945 
00946   if (cbyte+20 != max) return adns_s_invaliddata;
00947 
00948   for (i=0; i<5; i++) {
00949     GET_W(cbyte,msw);
00950     GET_W(cbyte,lsw);
00951     (&rrp->serial)[i]= (msw<<16) | lsw;
00952   }
00953 
00954   return adns_s_ok;
00955 }
00956 
00957 static void mf_soa(adns_query qu, void *datap) {
00958   adns_rr_soa *rrp= datap;
00959 
00960   adns__makefinal_str(qu,&rrp->mname);
00961   adns__makefinal_str(qu,&rrp->rname);
00962 }
00963 
00964 static adns_status cs_soa(vbuf *vb, const void *datap) {
00965   const adns_rr_soa *rrp= datap;
00966   char buf[20];
00967   int i;
00968   adns_status st;
00969 
00970   st= csp_domain(vb,rrp->mname);  if (st) return st;
00971   CSP_ADDSTR(" ");
00972   st= csp_mailbox(vb,rrp->rname);  if (st) return st;
00973 
00974   for (i=0; i<5; i++) {
00975     sprintf(buf," %lu",(&rrp->serial)[i]);
00976     CSP_ADDSTR(buf);
00977   }
00978 
00979   return adns_s_ok;
00980 }
00981 
00982 /*
00983  * _flat   (mf)
00984  */
00985 
00986 static void mf_flat(adns_query qu, void *data) { }
00987 
00988 /*
00989  * Now the table.
00990  */
00991 
00992 #define TYPESZ_M(member)           (sizeof(*((adns_answer*)0)->rrs.member))
00993 
00994 #define DEEP_MEMB(memb) TYPESZ_M(memb), mf_##memb, cs_##memb
00995 #define FLAT_MEMB(memb) TYPESZ_M(memb), mf_flat, cs_##memb
00996 
00997 #define DEEP_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \
00998  { adns_r_##code, rrt, fmt, TYPESZ_M(memb), mf_##memb, printer, parser, comparer }
00999 #define FLAT_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \
01000  { adns_r_##code, rrt, fmt, TYPESZ_M(memb), mf_flat, printer, parser, comparer }
01001 
01002 static const typeinfo typeinfos[] = {
01003 /* Must be in ascending order of rrtype ! */
01004 /* mem-mgmt code  rrt     fmt     member      parser      comparer    printer       */
01005 
01006 FLAT_TYPE(a,      "A",     0,     inaddr,     pa_inaddr,  di_inaddr,  cs_inaddr     ),
01007 DEEP_TYPE(ns_raw, "NS",   "raw",  str,        pa_host_raw,0,          cs_domain     ),
01008 DEEP_TYPE(cname,  "CNAME", 0,     str,        pa_dom_raw, 0,          cs_domain     ),
01009 DEEP_TYPE(soa_raw,"SOA",  "raw",  soa,        pa_soa,     0,          cs_soa        ),
01010 DEEP_TYPE(ptr_raw,"PTR",  "raw",  str,        pa_host_raw,0,          cs_domain     ),
01011 DEEP_TYPE(hinfo,  "HINFO", 0,     intstrpair, pa_hinfo,   0,          cs_hinfo      ),
01012 DEEP_TYPE(mx_raw, "MX",   "raw",  intstr,     pa_mx_raw,  di_mx_raw,  cs_inthost    ),
01013 DEEP_TYPE(txt,    "TXT",   0,     manyistr,   pa_txt,     0,          cs_txt        ),
01014 DEEP_TYPE(rp_raw, "RP",   "raw",  strpair,    pa_rp,      0,          cs_rp         ),
01015 
01016 FLAT_TYPE(addr,   "A",  "addr",   addr,       pa_addr,    di_addr,    cs_addr       ),
01017 DEEP_TYPE(ns,     "NS", "+addr",  hostaddr,   pa_hostaddr,di_hostaddr,cs_hostaddr   ),
01018 DEEP_TYPE(ptr,    "PTR","checked",str,        pa_ptr,     0,          cs_domain     ),
01019 DEEP_TYPE(mx,     "MX", "+addr",  inthostaddr,pa_mx,      di_mx,      cs_inthostaddr),
01020 
01021 DEEP_TYPE(soa,    "SOA","822",    soa,        pa_soa,     0,          cs_soa        ),
01022 DEEP_TYPE(rp,     "RP", "822",    strpair,    pa_rp,      0,          cs_rp         ),
01023 };
01024 
01025 const typeinfo *adns__findtype(adns_rrtype type) {
01026   const typeinfo *begin, *end, *mid;
01027 
01028   begin= typeinfos;  end= typeinfos+(sizeof(typeinfos)/sizeof(typeinfo));
01029 
01030   while (begin < end) {
01031     mid= begin + ((end-begin)>>1);
01032     if (mid->type == type) return mid;
01033     if (type > mid->type) begin= mid+1;
01034     else end= mid;
01035   }
01036   return 0;
01037 }

Generated on Thu May 24 2012 04:33:51 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.