]> Pileus Git - ~andy/fetchmail/blob - mxget.c
Typesafification.
[~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 char *name)
44 /* get MX records for given host */
45 {
46     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(name, C_IN,T_MX, (unsigned char *)&answer, sizeof(answer));
55     if (n == -1)
56         return((struct mxentry *)NULL);
57
58     hp = (HEADER *)&answer;
59     cp = answer + HFIXEDSZ;
60     eom = answer + n;
61     h_errno = 0;
62     for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
63         if ((n = dn_skipname(cp, eom)) < 0)
64             return((struct mxentry *)NULL);
65     buflen = sizeof(MXHostBuf) - 1;
66     bp = MXHostBuf;
67     ind = 0;
68     ancount = ntohs(hp->ancount);
69     while (--ancount >= 0 && cp < eom)
70     {
71         if ((n = dn_expand(answer, eom, cp, bp, buflen)) < 0)
72             break;
73         cp += n;
74         GETSHORT(type, cp);
75         cp += INT16SZ + INT32SZ;
76         GETSHORT(n, cp);
77         if (type != T_MX)
78         {
79             cp += n;
80             continue;
81         }
82         GETSHORT(pref, cp);
83         if ((n = dn_expand(answer, eom, cp, bp, buflen)) < 0)
84             break;
85         cp += n;
86
87         pmx[ind].name = bp;
88         pmx[ind].pref = pref;
89         ++ind;
90
91         n = strlen((const char *)bp);
92         bp += n;
93         *bp++ = '\0';
94
95         buflen -= n + 1;
96     }
97
98     pmx[ind].name = (char *)NULL;
99     pmx[ind].pref = -1;
100     return(pmx);
101 }
102 #endif /* HAVE_RES_SEARCH */
103
104 #ifdef TESTMAIN
105 main(int argc, char *argv[])
106 {
107     int count, i;
108     struct mxentry *responses;
109
110     responses = getmxrecords(argv[1]);
111     if (responses == (struct mxentry *)NULL)
112         puts("No MX records found");
113     else
114         do {
115             printf("%s %d\n", responses->name, responses->pref);
116         } while
117             ((++responses)->name);
118 }
119 #endif /* TESTMAIN */
120
121 /* mxget.c ends here */