]> Pileus Git - ~andy/fetchmail/blob - mxget.c
More portation changes.
[~andy/fetchmail] / mxget.c
1 /*
2  * mxget.c -- fetch MX records for given DNS name
3  *
4  * Copyright 1997 by Eric S. Raymond
5  * For license terms, see the file COPYING in this directory.
6  */
7
8 #include "config.h"
9 #ifdef HAVE_RES_SEARCH
10 #include <stdio.h>
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 /*
23  * These are defined in RFC833. Some bind interface headers don't declare them.
24  * Ghod help us if they're ever actually incompatible with what's in 
25  * the arpa/nameser.h header.
26  */
27 #ifndef PACKETSZ
28 #define PACKETSZ        512             /* maximum packet size */
29 #endif
30 #ifndef HFIXEDSZ
31 #define HFIXEDSZ        12              /* #/bytes of fixed data in header */
32 #endif
33 #ifndef INT32SZ
34 #define INT32SZ         4               /* for systems without 32-bit ints */
35 #endif
36 #ifndef INT16SZ
37 #define INT16SZ         2               /* for systems without 16-bit ints */
38 #endif
39
40 /* minimum possible size of MX record in packet */
41 #define MIN_MX_SIZE     8       /* corresp to "a.com 0" w/ terminating space */
42
43 struct mxentry *getmxrecords(const unsigned char *name)
44 /* get MX records for given host */
45 {
46     unsigned char answer[PACKETSZ], *eom, *cp, *bp;
47     int n, ancount, qdcount, buflen, type, pref, ind;
48     static struct mxentry pmx[(PACKETSZ - HFIXEDSZ) / MIN_MX_SIZE];
49     static char MXHostBuf[PACKETSZ - HFIXEDSZ]; 
50     HEADER *hp;
51
52     pmx->name = (char *)NULL;
53     pmx->pref = -1;
54     n = res_search((char *)name,
55                    C_IN,T_MX, (unsigned char*)&answer, sizeof(answer));
56     if (n == -1)
57         return((struct mxentry *)NULL);
58
59     hp = (HEADER *)&answer;
60     cp = answer + HFIXEDSZ;
61     eom = answer + n;
62     h_errno = 0;
63     for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
64         if ((n = dn_skipname(cp, eom)) < 0)
65             return((struct mxentry *)NULL);
66     buflen = sizeof(MXHostBuf) - 1;
67     bp = MXHostBuf;
68     ind = 0;
69     ancount = ntohs(hp->ancount);
70     while (--ancount >= 0 && cp < eom)
71     {
72         if ((n = dn_expand(answer, eom, cp, bp, buflen)) < 0)
73             break;
74         cp += n;
75         GETSHORT(type, cp);
76         cp += INT16SZ + INT32SZ;
77         GETSHORT(n, cp);
78         if (type != T_MX)
79         {
80             cp += n;
81             continue;
82         }
83         GETSHORT(pref, cp);
84         if ((n = dn_expand(answer, eom, cp, bp, buflen)) < 0)
85             break;
86         cp += n;
87
88         pmx[ind].name = bp;
89         pmx[ind].pref = pref;
90         ++ind;
91
92         n = strlen((const char *)bp);
93         bp += n;
94         *bp++ = '\0';
95
96         buflen -= n + 1;
97     }
98
99     pmx[ind].name = (char *)NULL;
100     pmx[ind].pref = -1;
101     return(pmx);
102 }
103 #endif /* HAVE_RES_SEARCH */
104
105 #ifdef TESTMAIN
106 main(int argc, char *argv[])
107 {
108     int count, i;
109     struct mxentry *responses;
110
111     responses = getmxrecords(argv[1]);
112     if (responses == (struct mxentry *)NULL)
113         puts("No MX records found");
114     else
115         do {
116             printf("%s %d\n", responses->name, responses->pref);
117         } while
118             ((++responses)->name);
119 }
120 #endif /* TESTMAIN */
121
122 /* mxget.c ends here */