static int __dns_gethostbyx_r_inner(const char* name, struct hostent* result, char *buf, size_t buflen, struct hostent **RESULT, int *h_errnop, int lookfor) { #else int __dns_gethostbyx_r(const char* name, struct hostent* result, char *buf, size_t buflen, struct hostent **RESULT, int *h_errnop, int lookfor) { #endif int names,ips; unsigned char *cur; unsigned char *max; unsigned char inpkg[1500]; char* tmp; int size; if (lookfor==1) { result->h_addrtype=AF_INET; result->h_length=4; } else { result->h_addrtype=AF_INET6; result->h_length=16; } result->h_aliases=(char**)(buf+8*sizeof(char*)); result->h_addr_list=(char**)buf; result->h_aliases[0]=0; cur=buf+16*sizeof(char*); max=buf+buflen; names=ips=0; if ((size=res_query(name,C_IN,lookfor,inpkg,512))<0) { invalidpacket: *h_errnop=HOST_NOT_FOUND; return -1; } { tmp=inpkg+12; { char Name[257]; unsigned short q=((unsigned short)inpkg[4]<<8)+inpkg[5]; while (q>0) { if (tmp>(char*)inpkg+size) goto invalidpacket; while (*tmp) { tmp+=*tmp+1; if (tmp>(char*)inpkg+size) goto invalidpacket; } tmp+=5; --q; } if (tmp>(char*)inpkg+size) goto invalidpacket; q=((unsigned short)inpkg[6]<<8)+inpkg[7]; if (q<1) goto nodata; while (q>0) { int decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),Name,256,inpkg+size); if (decofs<0) break; tmp=inpkg+decofs; --q; if (tmp[0]!=0 || tmp[1]!=lookfor || /* TYPE != A */ tmp[2]!=0 || tmp[3]!=1) { /* CLASS != IN */ if (tmp[1]==5) { /* CNAME */ tmp+=10; decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),Name,256,inpkg+size); if (decofs<0) break; tmp=inpkg+decofs; } else break; continue; } tmp+=10; /* skip type, class, TTL and length */ { int slen; if (lookfor==1 || lookfor==28) /* A or AAAA*/ { slen=strlen(Name); if (cur+slen+8+(lookfor==28?12:0)>=max) { *h_errnop=NO_RECOVERY; return -1; } } else if (lookfor==12) /* PTR */ { decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),Name,256,inpkg+size); if (decofs<0) break; tmp=inpkg+decofs; slen=strlen(Name); } else slen=strlen(Name); strcpy(cur,Name); if (names==0) result->h_name=cur; else result->h_aliases[names-1]=cur; result->h_aliases[names]=0; if (names<8) ++names; /* cur+=slen+1; */ cur+=(slen|3)+1; result->h_addr_list[ips++] = cur; if (lookfor==1) /* A */ { *(int*)cur=*(int*)tmp; cur+=4; result->h_addr_list[ips]=0; } else if (lookfor==28) /* AAAA */ { { int k; for (k=0; k<16; ++k) cur[k]=tmp[k]; } cur+=16; result->h_addr_list[ips]=0; } } /* puts(Name); */ } } } if (!names) { nodata: *h_errnop=NO_DATA; return -1; } *h_errnop=0; *RESULT=result; return 0; }
int dn_expand(unsigned char *msg, unsigned char *eomorig, unsigned char *comp_dn, unsigned char *exp_dn, int length) { return __dns_decodename(msg,comp_dn-msg,exp_dn,length,eomorig)-(comp_dn-msg); }