summaryrefslogtreecommitdiffstats
path: root/dns.c
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2013-02-04 02:40:02 +0100
committermanuel <manuel@mausz.at>2013-02-04 02:40:02 +0100
commita7f5c4dbf52aca7819ff4b8ac50d8d56dbd8dba4 (patch)
tree69d59ff0982237c04fa3ddfb7dd1366e5e289315 /dns.c
parente064c17f7ab8e290864b6bf447e9f51960004581 (diff)
downloadqmail-a7f5c4dbf52aca7819ff4b8ac50d8d56dbd8dba4.tar.gz
qmail-a7f5c4dbf52aca7819ff4b8ac50d8d56dbd8dba4.tar.bz2
qmail-a7f5c4dbf52aca7819ff4b8ac50d8d56dbd8dba4.zip
[PATCH] Adding support for oversize DNS
qmail-103
Diffstat (limited to 'dns.c')
-rw-r--r--dns.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/dns.c b/dns.c
index 055ab76..dc3bd84 100644
--- a/dns.c
+++ b/dns.c
@@ -19,10 +19,12 @@ extern int res_search();
19static unsigned short getshort(c) unsigned char *c; 19static unsigned short getshort(c) unsigned char *c;
20{ unsigned short u; u = c[0]; return (u << 8) + c[1]; } 20{ unsigned short u; u = c[0]; return (u << 8) + c[1]; }
21 21
22static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response; 22static struct { unsigned char *buf; } response;
23static int responsebuflen = 0;
23static int responselen; 24static int responselen;
24static unsigned char *responseend; 25static unsigned char *responseend;
25static unsigned char *responsepos; 26static unsigned char *responsepos;
27static u_long saveresoptions;
26 28
27static int numanswers; 29static int numanswers;
28static char name[MAXDNAME]; 30static char name[MAXDNAME];
@@ -43,18 +45,33 @@ int type;
43 errno = 0; 45 errno = 0;
44 if (!stralloc_copy(&glue,domain)) return DNS_MEM; 46 if (!stralloc_copy(&glue,domain)) return DNS_MEM;
45 if (!stralloc_0(&glue)) return DNS_MEM; 47 if (!stralloc_0(&glue)) return DNS_MEM;
46 responselen = lookup(glue.s,C_IN,type,response.buf,sizeof(response)); 48 if (!responsebuflen)
49 if (response.buf = (unsigned char *)alloc(PACKETSZ+1))
50 responsebuflen = PACKETSZ+1;
51 else return DNS_MEM;
52
53 responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
54 if ((responselen >= responsebuflen) ||
55 (responselen > 0 && (((HEADER *)response.buf)->tc)))
56 {
57 if (responsebuflen < 65536)
58 if (alloc_re(&response.buf, responsebuflen, 65536))
59 responsebuflen = 65536;
60 else return DNS_MEM;
61 saveresoptions = _res.options;
62 _res.options |= RES_USEVC;
63 responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
64 _res.options = saveresoptions;
65 }
47 if (responselen <= 0) 66 if (responselen <= 0)
48 { 67 {
49 if (errno == ECONNREFUSED) return DNS_SOFT; 68 if (errno == ECONNREFUSED) return DNS_SOFT;
50 if (h_errno == TRY_AGAIN) return DNS_SOFT; 69 if (h_errno == TRY_AGAIN) return DNS_SOFT;
51 return DNS_HARD; 70 return DNS_HARD;
52 } 71 }
53 if (responselen >= sizeof(response))
54 responselen = sizeof(response);
55 responseend = response.buf + responselen; 72 responseend = response.buf + responselen;
56 responsepos = response.buf + sizeof(HEADER); 73 responsepos = response.buf + sizeof(HEADER);
57 n = ntohs(response.hdr.qdcount); 74 n = ntohs(((HEADER *)response.buf)->qdcount);
58 while (n-- > 0) 75 while (n-- > 0)
59 { 76 {
60 i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME); 77 i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
@@ -64,7 +81,7 @@ int type;
64 if (i < QFIXEDSZ) return DNS_SOFT; 81 if (i < QFIXEDSZ) return DNS_SOFT;
65 responsepos += QFIXEDSZ; 82 responsepos += QFIXEDSZ;
66 } 83 }
67 numanswers = ntohs(response.hdr.ancount); 84 numanswers = ntohs(((HEADER *)response.buf)->ancount);
68 return 0; 85 return 0;
69} 86}
70 87