]> Pileus Git - ~andy/fetchmail/blob - mxget.c
Dave Zarzycki's fixes.
[~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 <string.h>
12 #ifdef HAVE_NET_SOCKET_H
13 #include <net/socket.h>
14 #endif
15 #include <netdb.h>
16 #include <sys/types.h>
17 #include <netinet/in.h>
18
19 #ifdef __BEOS__
20 #include "beos/beos_nameser.h"
21 #endif
22
23 #ifdef HAVE_ARPA_NAMESER_H
24 #include <arpa/nameser.h>
25 #endif
26 #ifdef HAVE_RESOLV_H
27 #include <resolv.h>
28 #endif
29
30 #include "mx.h"
31
32 /*
33  * This ought to be in the bind library.  It's adapted from sendmail.
34  */
35
36 /*
37  * These are defined in RFC833. Some bind interface headers don't declare them.
38  * Ghod help us if they're ever actually incompatible with what's in 
39  * the arpa/nameser.h header.
40  */
41 #ifndef PACKETSZ
42 #define PACKETSZ        512             /* maximum packet size */
43 #endif
44 #ifndef HFIXEDSZ
45 #define HFIXEDSZ        12              /* #/bytes of fixed data in header */
46 #endif
47 #ifndef INT32SZ
48 #define INT32SZ         4               /* for systems without 32-bit ints */
49 #endif
50 #ifndef INT16SZ
51 #define INT16SZ         2               /* for systems without 16-bit ints */
52 #endif
53
54 /* minimum possible size of MX record in packet */
55 #define MIN_MX_SIZE     8       /* corresp to "a.com 0" w/ terminating space */
56
57 struct mxentry *getmxrecords(const char *name)
58 /* get MX records for given host */
59 {
60     char answer[PACKETSZ], *eom, *cp, *bp;
61     int n, ancount, qdcount, buflen, type, pref, ind;
62     static struct mxentry pmx[(PACKETSZ - HFIXEDSZ) / MIN_MX_SIZE];
63     static char MXHostBuf[PACKETSZ - HFIXEDSZ]; 
64     HEADER *hp;
65
66     pmx->name = (char *)NULL;
67     pmx->pref = -1;
68     n = res_search(name, C_IN,T_MX, (unsigned char *)&answer, sizeof(answer));
69     if (n == -1)
70         return((struct mxentry *)NULL);
71
72     hp = (HEADER *)&answer;
73     cp = answer + HFIXEDSZ;
74     eom = answer + n;
75     h_errno = 0;
76     for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
77         if ((n = dn_skipname(cp, eom)) < 0)
78             return((struct mxentry *)NULL);
79     buflen = sizeof(MXHostBuf) - 1;
80     bp = MXHostBuf;
81     ind = 0;
82     ancount = ntohs(hp->ancount);
83     while (--ancount >= 0 && cp < eom)
84     {
85         if ((n = dn_expand(answer, eom, cp, bp, buflen)) < 0)
86             break;
87         cp += n;
88         GETSHORT(type, cp);
89         cp += INT16SZ + INT32SZ;
90         GETSHORT(n, cp);
91         if (type != T_MX)
92         {
93             cp += n;
94             continue;
95         }
96         GETSHORT(pref, cp);
97         if ((n = dn_expand(answer, eom, cp, bp, buflen)) < 0)
98             break;
99         cp += n;
100
101         pmx[ind].name = bp;
102         pmx[ind].pref = pref;
103         ++ind;
104
105         n = strlen((const char *)bp);
106         bp += n;
107         *bp++ = '\0';
108
109         buflen -= n + 1;
110     }
111
112     pmx[ind].name = (char *)NULL;
113     pmx[ind].pref = -1;
114     return(pmx);
115 }
116 #endif /* HAVE_RES_SEARCH */
117
118 #ifdef TESTMAIN
119 main(int argc, char *argv[])
120 {
121     int count, i;
122     struct mxentry *responses;
123
124     responses = getmxrecords(argv[1]);
125     if (responses == (struct mxentry *)NULL)
126         puts("No MX records found");
127     else
128         do {
129             printf("%s %d\n", responses->name, responses->pref);
130         } while
131             ((++responses)->name);
132 }
133 #endif /* TESTMAIN */
134
135 /* mxget.c ends here */