| Anonymous | Login | Signup for a new account | 11-10-2008 10:41 PST |
| Main | My View | View Issues | Change Log | Docs |
| Viewing Issue Simple Details [ Jump to Notes ] | [ View Advanced ] [ Issue History ] [ Print ] | ||||||||
| ID | Category | Severity | Reproducibility | Date Submitted | Last Update | ||||
| 0000104 | [uClibc] Networking Support | minor | always | 02-15-05 11:26 | 04-28-05 14:26 | ||||
| Reporter | dasi | View Status | public | ||||||
| Assigned To | uClibc | ||||||||
| Priority | normal | Resolution | fixed | ||||||
| Status | closed | Product Version | 0.9.26 | ||||||
| Summary | 0000104: resolv.c patch: returning multiple ip in h_addr_list | ||||||||
| Description |
I noticed that uClibc doesn't fill up struct hostent -> h_addr_list member with a multiple IP's if available. Here is a patch attached, which provides such functionality. I used it with v0.9.26. It worked fine. I also tried this path with v0.9.27: patch is aplying succesfuly, but i wont work because of modifications made in order to support h_aliases. This path is also IPv6 ready, but i didin't finished it because i don't use IPv6 at the moment. see patch in the "Additional Information" |
||||||||
| Additional Information |
Index: resolv.c =================================================================== --- resolv.c (revision 1000) +++ resolv.c (working copy) @@ -212,7 +212,10 @@ int ttl; int rdlength; unsigned char * rdata; - int rdoffset; + int rdoffset; + char* buf; + size_t buflen; + size_t add_count; }; enum etc_hosts_action { @@ -665,7 +668,9 @@ struct timeval tv; fd_set fds; struct resolv_header h; - struct resolv_question q; + struct resolv_question q; + struct resolv_answer ma; + int first_answer = 1; int retries = 0; unsigned char * packet = malloc(PACKETSZ); char *dns, *lookup = malloc(MAXDNAME); @@ -828,21 +833,55 @@ } DPRINTF("Decoding answer at pos %d\n", pos); - for (j=0;j<h.ancount;j++) + first_answer = 1; + for (j=0;j<h.ancount;j++,pos += i) { - i = __decode_answer(packet, pos, a); + i = __decode_answer(packet, pos, &ma); if (i<0) { DPRINTF("failed decode %d\n", i); goto again; } - /* For all but T_SIG, accept first answer */ - if (a->atype != T_SIG) - break; - DPRINTF("skipping T_SIG %d\n", i); - free(a->dotted); - pos += i; + if ( first_answer ) + { + ma.buf = a->buf; + ma.buflen = a->buflen; + ma.add_count = a->add_count; + memcpy(a, &ma, sizeof(ma)); + if (a->atype != T_SIG && (0 == a->buf || (type != T_A && type != T_AAAA))) + { + break; + } + if (a->atype != type) + { + free(a->dotted); + continue; + } + a->add_count = h.ancount - j - 1; + if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen) + { + break; + } + a->add_count = 0; + first_answer = 0; + } + else + { + free(ma.dotted); + if (ma.atype != type) + { + continue; + } + if (a->rdlength != ma.rdlength) + { + free(a->dotted); + DPRINTF("Answer address len(%u) differs from original(%u)\n", ma.rdlength, a->rdlength); + goto again; + } + memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength); + ++a->add_count; + } } DPRINTF("Answer name = |%s|\n", a->dotted); @@ -1711,8 +1750,11 @@ BIGLOCK; __nameserversXX=__nameservers; __nameserverXX=__nameserver; - BIGUNLOCK; - i = __dns_lookup(buf, T_A, __nameserversXX, __nameserverXX, &packet, &a); + BIGUNLOCK; + a.buf = buf; + a.buflen = buflen; + a.add_count = 0; + i = __dns_lookup(name, T_A, __nameserversXX, __nameserverXX, &packet, &a); if (i < 0) { *h_errnop = HOST_NOT_FOUND; @@ -1720,26 +1762,30 @@ return TRY_AGAIN; } + if ((a.rdlength + sizeof(struct in_addr*)) * a.add_count + 256 > buflen) + { + free(a.dotted); + free(packet); + *h_errnop = NETDB_INTERNAL; + DPRINTF("buffer to small(multiple addresses)\n"); + return ERANGE; + } + else if(a.add_count > 0) + { + memmove(buf - sizeof(struct in_addr*)*2, buf, a.add_count * a.rdlength); + addr_list = (struct in_addr**)(buf + a.add_count * a.rdlength); + addr_list[0] = in; + for (i = 0; i<a.add_count; ++i) + addr_list[i+1] = (struct in_addr*)(buf - sizeof(struct in_addr*)*2 + a.rdlength * i); + addr_list[a.add_count + 1] = 0; + buflen -= (((char*)&(addr_list[a.add_count + 2])) - buf); + buf = (char*)&addr_list[a.add_count + 2]; + } + strncpy(buf, a.dotted, buflen); free(a.dotted); - if (a.atype == T_CNAME) { /* CNAME */ - DPRINTF("Got a CNAME in gethostbyname()\n"); - i = __decode_dotted(packet, a.rdoffset, buf, buflen); - free(packet); - - if (i < 0) { - *h_errnop = NO_RECOVERY; - DPRINTF("__decode_dotted\n"); - return -1; - } - if (++nest > MAX_RECURSE) { - *h_errnop = NO_RECOVERY; - DPRINTF("recursion\n"); - return -1; - } - continue; - } else if (a.atype == T_A) { /* ADDRESS */ + if (a.atype == T_A) { /* ADDRESS */ memcpy(in, a.rdata, sizeof(*in)); result_buf->h_name = buf; result_buf->h_addrtype = AF_INET; @@ -1837,6 +1883,8 @@ return NETDB_SUCCESS; } + memset((char *) &a, '\0', sizeof(a)); + for (;;) { BIGLOCK; __nameserversXX=__nameservers; @@ -1915,7 +1963,9 @@ *result=NULL; if (!addr) return EINVAL; - + + memset((char *) &a, '\0', sizeof(a)); + switch (type) { case AF_INET: if (len != sizeof(struct in_addr)) |
||||||||
| Attached Files | |||||||||
|
|
|||||||||
| Copyright © 2000 - 2006 Mantis Group |