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