]> Pileus Git - ~andy/fetchmail/blob - mxget.c
More economical buffer sizing.
[~andy/fetchmail] / mxget.c
1 /*
2  * mxget.c -- fetch MX records for given DNS name
3  *
4  * Copyright 1996 by Eric S. Raymond
5  * All rights reserved.
6  * For license terms, see the file COPYING in this directory.
7  */
8
9 #include "config.h"
10 #ifdef HAVE_GETHOSTBYNAME
11 #include <netdb.h>
12 #include <sys/types.h>
13 #include <netinet/in.h>
14 #include <arpa/nameser.h>
15 #include <resolv.h>
16 #include "mx.h"
17
18 /*
19  * This ought to be in the bind library.  It's adapted from sendmail.
20  */
21
22 /* minimum possible size of MX record in packet */
23 #define MIN_MX_SIZE     8       /* corresp to "a.com 0" w/ terminating space */
24
25 struct mxentry *getmxrecords(name)
26 /* get MX records for given host */
27 const char *name;
28 {
29     unsigned char answer[PACKETSZ], *eom, *cp, *bp;
30     int n, ancount, qdcount, buflen, type, pref, ind;
31     static struct mxentry pmx[(PACKETSZ - HFIXEDSZ) / MIN_MX_SIZE];
32     static char MXHostBuf[PACKETSZ - HFIXEDSZ]; 
33     HEADER *hp;
34
35     n = res_search(name,C_IN,T_MX,(unsigned char*)&answer, sizeof(answer));
36     if (n == -1)
37         return((struct mxentry *)NULL);
38
39     hp = (HEADER *)&answer;
40     cp = answer + HFIXEDSZ;
41     eom = answer + n;
42     h_errno = 0;
43     for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
44         if ((n = dn_skipname(cp, eom)) < 0)
45             return((struct mxentry *)NULL);
46     buflen = sizeof(MXHostBuf) - 1;
47     bp = MXHostBuf;
48     ind = 0;
49     ancount = ntohs(hp->ancount);
50     while (--ancount >= 0 && cp < eom)
51     {
52         if ((n = dn_expand(answer, eom, cp, bp, buflen)) < 0)
53             break;
54         cp += n;
55         GETSHORT(type, cp);
56         cp += INT16SZ + INT32SZ;
57         GETSHORT(n, cp);
58         if (type != T_MX)
59         {
60             cp += n;
61             continue;
62         }
63         GETSHORT(pref, cp);
64         if ((n = dn_expand(answer, eom, cp, bp, buflen)) < 0)
65             break;
66         cp += n;
67
68         pmx[ind].name = bp;
69         pmx[ind].pref = pref;
70         ++ind;
71
72         n = strlen(bp);
73         bp += n;
74         *bp++ = '\0';
75
76         buflen -= n + 1;
77     }
78
79     pmx[ind].name = (char *)NULL;
80     pmx[ind].pref = -1;
81     return(pmx);
82 }
83 #endif /* HAVE_GETHOSTBYNAME */
84
85 #ifdef TESTMAIN
86 main(int argc, char *argv[])
87 {
88     int count, i;
89     struct mxentry *responses;
90
91     responses = getmxrecords(argv[1]);
92     if (responses == (struct mxentry *)NULL)
93         puts("No MX records found");
94     else
95         do {
96             printf("%s %d\n", responses->name, responses->pref);
97         } while
98             ((++responses)->name);
99 }
100 #endif /* TESTMAIN */
101
102 /* mxget.c ends here */