Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentypes.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
1.7.6.1
|