diff options
author | nalin <nalin> | 2002-10-02 21:32:50 +0000 |
---|---|---|
committer | nalin <nalin> | 2002-10-02 21:32:50 +0000 |
commit | d9e4545bd36f34f33578b6134fe739defd6d7e74 (patch) | |
tree | b1c44a47f93a2925d4c39ad68ddd0a5246d317a6 /isys/dns.c | |
parent | 0f5200e6b58bf0b78fac4cbf43fc60611f8b944d (diff) | |
download | anaconda-d9e4545bd36f34f33578b6134fe739defd6d7e74.tar.gz anaconda-d9e4545bd36f34f33578b6134fe739defd6d7e74.tar.xz anaconda-d9e4545bd36f34f33578b6134fe739defd6d7e74.zip |
- detect too-short DNS responses
- handle kinda-big DNS responses
Diffstat (limited to 'isys/dns.c')
-rw-r--r-- | isys/dns.c | 80 |
1 files changed, 65 insertions, 15 deletions
diff --git a/isys/dns.c b/isys/dns.c index bc005eab0..c71e0df9c 100644 --- a/isys/dns.c +++ b/isys/dns.c @@ -20,24 +20,48 @@ static int doQuery(char * query, int queryType, int len, ancount, type; u_char * data, * end; char name[MAXDNAME]; - union dns_response response; + union dns_response static_response, *response = &static_response; + size_t response_len = sizeof(static_response); /* Give time to finish ethernet negotiation */ _res.retry = 3; - len = res_search(query, C_IN, queryType, (void *) &response, - sizeof(response)); - if (len <= 0) return -1; - - if (ntohs(response.hdr.rcode) != NOERROR) return -1; - ancount = ntohs(response.hdr.ancount); - if (ancount < 1) return -1; + do { + len = res_search(query, C_IN, queryType, (void*) response, + response_len); + if (len <= 0) return -1; + if (len < response_len) break; + if (response != &static_response) free(response); + if (len > 0x10000) return -1; + response_len = len + 1024; + response = malloc(response_len); + if (response == NULL) return -1; + } while (1); + + if (len < sizeof(response->hdr)) { + if (response != &static_response) free(response); + return -1; + } + if (ntohs(response->hdr.rcode) != NOERROR) { + if (response != &static_response) free(response); + return -1; + } + ancount = ntohs(response->hdr.ancount); + if (ancount < 1) { + if (response != &static_response) free(response); + return -1; + } - data = response.buf + sizeof(HEADER); - end = response.buf + len; + data = response->buf + sizeof(HEADER); + end = response->buf + len; /* skip the question */ - data += dn_skipname(data, end) + QFIXEDSZ; + len = dn_skipname(data, end); + if (len <= 0) { + if (response != &static_response) free(response); + return -1; + } + data += len + QFIXEDSZ; /* parse the answer(s) */ while (--ancount >= 0 && data < end) { @@ -46,19 +70,27 @@ static int doQuery(char * query, int queryType, data += dn_skipname(data, end); /* get RR information */ + if (data + 3 * INT16SZ + INT32SZ > end) { + if (response != &static_response) free(response); + return -1; + } GETSHORT(type, data); - data += INT16SZ; /* skipp class */ - data += INT32SZ; /* skipp TTL */ + data += INT16SZ; /* skip class */ + data += INT32SZ; /* skip TTL */ GETSHORT(len, data); if (type == T_PTR) { /* we got a pointer */ - len = dn_expand(response.buf, end, data, name, sizeof(name)); - if (len <= 0) return -1; + len = dn_expand(response->buf, end, data, name, sizeof(name)); + if (len <= 0) { + if (response != &static_response) free(response); + return -1; + } if (queryType == T_PTR && domainName) { /* we wanted a pointer */ *domainName = malloc(strlen(name) + 1); strcpy(*domainName, name); + if (response != &static_response) free(response); return 0; } } else if (type == T_A) { @@ -66,6 +98,7 @@ static int doQuery(char * query, int queryType, if (queryType == T_A && ipNum) { /* we wanted an address */ memcpy(ipNum, data, sizeof(*ipNum)); + if (response != &static_response) free(response); return 0; } } @@ -74,6 +107,7 @@ static int doQuery(char * query, int queryType, data += len; } + if (response != &static_response) free(response); return -1; } @@ -149,3 +183,19 @@ char * mygethostbyaddr(const char * ipnum) { } #endif + +#if 0 +int +main(int argc, char **argv) +{ + struct in_addr address; + fprintf(stderr, "hostname for %s is %s\n", "152.1.2.22", + mygethostbyaddr("152.1.2.22")); + if (mygethostbyname("www.redhat.com", &address) == 0) { + fprintf(stderr, "ip for www.redhat.com is %d.%d.%d.%d\n", + (address.s_addr >> 0) & 0xff, (address.s_addr >> 8) & 0xff, + (address.s_addr >> 16) & 0xff, (address.s_addr >> 24) & 0xff); + } + return 0; +} +#endif |