]> Pileus Git - ~andy/fetchmail/blob - mxget.c
merge Mirek's fetchmail-signed.patch
[~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 #include <stdio.h>
10 #ifdef HAVE_RES_SEARCH
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     if ((size_t)n > sizeof(answer))
72         n = sizeof(answer);     
73
74     hp = (HEADER *)&answer;
75     cp = answer + HFIXEDSZ;
76     eom = answer + n;
77     h_errno = 0;
78     for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
79       if ((n = dn_skipname((unsigned char *)cp, (unsigned char *)eom)) < 0)
80             return((struct mxentry *)NULL);
81     buflen = sizeof(MXHostBuf) - 1;
82     bp = MXHostBuf;
83     ind = 0;
84     ancount = ntohs(hp->ancount);
85     while (--ancount >= 0 && cp < eom)
86     {
87         if ((n = dn_expand((unsigned char *)answer, (unsigned char *)eom,
88                            (unsigned char *)cp, bp, buflen)) < 0)
89             break;
90         cp += n;
91         GETSHORT(type, cp);
92         cp += INT16SZ + INT32SZ;
93         GETSHORT(n, cp);
94         if (type != T_MX)
95         {
96             cp += n;
97             continue;
98         }
99         GETSHORT(pref, cp);
100         if ((n = dn_expand((unsigned char *)answer, (unsigned char *)eom,
101                            (unsigned char *)cp, bp, buflen)) < 0)
102             break;
103         cp += n;
104
105         pmx[ind].name = bp;
106         pmx[ind].pref = pref;
107         ++ind;
108
109         n = strlen((const char *)bp);
110         bp += n;
111         *bp++ = '\0';
112
113         buflen -= n + 1;
114     }
115
116     pmx[ind].name = (char *)NULL;
117     pmx[ind].pref = -1;
118     return(pmx);
119 }
120 #endif /* HAVE_RES_SEARCH */
121
122 #ifdef STANDALONE
123 #include <stdlib.h>
124
125 int main(int argc, char *argv[])
126 {
127     int count, i;
128     struct mxentry *responses;
129
130     if (argc != 2 || 0 == strcmp(argv[1], "-h")) {
131         fprintf(stderr, "Usage: %s domain\n", argv[0]);
132         exit(1);
133     }
134
135 #ifdef HAVE_RES_SEARCH
136     responses = getmxrecords(argv[1]);
137     if (responses == (struct mxentry *)NULL) {
138         puts("No MX records found");
139     } else {
140         do {
141             printf("%s %d\n", responses->name, responses->pref);
142         } while ((++responses)->name);
143     }
144 #else
145     puts("This program was compiled without HAS_RES_SEARCH and does nothing.");
146 #endif
147
148     return 0;
149 }
150 #endif /* TESTMAIN */
151
152 /* mxget.c ends here */