libc: gethostbyname: better DNS response parser

This commit is contained in:
K. Lange 2023-09-18 06:25:07 -04:00
parent 4a31a09ba2
commit 4ee7335001

View File

@ -358,6 +358,36 @@ struct hostent * gethostbyname(const char * name) {
return NULL;
}
uint16_t answers = ntohs(response->answers);
uint16_t queries = ntohs(response->questions);
const unsigned char * d = response->data;
for (uint16_t i = 0; i < queries; ++i) {
while (1) {
if (d - response->data >= len) goto _nope;
int l = *d++;
if ((l & 0xc0) == 0xc0) { d++; break; }
if (!l) break;
d += l;
}
d += 4;
}
for (uint16_t i = 0; i < answers; ++i) {
while (1) {
if (d - response->data >= len) goto _nope;
int l = *d++;
if ((l & 0xc0) == 0xc0) { d++; break; }
if (!l) break;
d += l;
}
if (d - response->data > len + 10) goto _nope;
d += 2; /* skip type */
uint16_t cls = d[0] * 256 + d[1]; d += 2;
d += 4; /* skip ttl */
uint16_t dlen = d[0] * 256 + d[1]; d += 2;
if (dlen == 4 && cls == 1) {
if (d - response->data > len + dlen) goto _nope;
/* Get a return value */
_hostent.h_name = (char*)name;
_hostent.h_aliases = NULL;
@ -365,9 +395,15 @@ struct hostent * gethostbyname(const char * name) {
_hostent.h_length = sizeof(uint32_t);
_hostent.h_addr_list = _host_entry_list;
_host_entry_list[0] = (char*)&_hostent_addr;
_hostent_addr = *(uint32_t*)(buf+len-4);
_hostent_addr = *(uint32_t*)(d);
return &_hostent;
}
d += dlen;
}
_nope:
fprintf(stderr, "gethostbyname: no viable answer\n");
return NULL;
}
int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,