1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
/*
* mxget.c -- fetch MX records for given DNS name
*
* Copyright (C) 1996, 1997, 1998, 2000, 2002 by Eric S. Raymond
* Copyright (C) 2005, 2006, 2007 by Matthias Andree
* For license terms, see the file COPYING in this directory.
*/
#include "config.h"
#include "fetchmail.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_RES_SEARCH
#ifdef HAVE_NET_SOCKET_H
#include <net/socket.h>
#endif
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#ifdef __BEOS__
#include "beos/beos_nameser.h"
#endif
#ifdef HAVE_ARPA_NAMESER_H
#include <arpa/nameser.h>
#endif
#ifdef HAVE_RESOLV_H
#include <resolv.h>
#endif
#include "mx.h"
/*
* This ought to be in the bind library. It's adapted from sendmail.
*/
/*
* These are defined in RFC833. Some bind interface headers don't declare them.
* Ghod help us if they're ever actually incompatible with what's in
* the arpa/nameser.h header.
*/
#ifndef PACKETSZ
#define PACKETSZ 512 /* maximum packet size */
#endif
#ifndef HFIXEDSZ
#define HFIXEDSZ 12 /* #/bytes of fixed data in header */
#endif
#ifndef INT32SZ
#define INT32SZ 4 /* for systems without 32-bit ints */
#endif
#ifndef INT16SZ
#define INT16SZ 2 /* for systems without 16-bit ints */
#endif
/* minimum possible size of MX record in packet */
#define MIN_MX_SIZE 8 /* corresp to "a.com 0" w/ terminating space */
struct mxentry *getmxrecords(const char *name)
/* get MX records for given host */
{
char answer[PACKETSZ], *eom, *cp, *bp;
int n, ancount, qdcount, buflen, type, pref, ind;
static struct mxentry pmx[(PACKETSZ - HFIXEDSZ) / MIN_MX_SIZE];
static char MXHostBuf[PACKETSZ - HFIXEDSZ];
HEADER *hp;
pmx->name = (char *)NULL;
pmx->pref = -1;
n = res_search(name, C_IN,T_MX, (unsigned char *)&answer, sizeof(answer));
if (n == -1)
return((struct mxentry *)NULL);
if ((size_t)n > sizeof(answer))
n = sizeof(answer);
hp = (HEADER *)&answer;
cp = answer + HFIXEDSZ;
eom = answer + n;
h_errno = 0;
for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
if ((n = dn_skipname((unsigned char *)cp, (unsigned char *)eom)) < 0)
return((struct mxentry *)NULL);
buflen = sizeof(MXHostBuf) - 1;
bp = MXHostBuf;
ind = 0;
ancount = ntohs(hp->ancount);
while (--ancount >= 0 && cp < eom)
{
if ((n = dn_expand((unsigned char *)answer, (unsigned char *)eom,
(unsigned char *)cp, bp, buflen)) < 0)
break;
cp += n;
GETSHORT(type, cp);
cp += INT16SZ + INT32SZ;
GETSHORT(n, cp);
if (type != T_MX)
{
cp += n;
continue;
}
GETSHORT(pref, cp);
if ((n = dn_expand((unsigned char *)answer, (unsigned char *)eom,
(unsigned char *)cp, bp, buflen)) < 0)
break;
cp += n;
pmx[ind].name = bp;
pmx[ind].pref = pref;
++ind;
n = strlen((const char *)bp);
bp += n;
*bp++ = '\0';
buflen -= n + 1;
}
pmx[ind].name = (char *)NULL;
pmx[ind].pref = -1;
return(pmx);
}
#endif /* HAVE_RES_SEARCH */
#ifdef STANDALONE
#include <stdlib.h>
int main(int argc, char *argv[])
{
#ifdef HAVE_RES_SEARCH
struct mxentry *responses;
#endif
if (argc != 2 || 0 == strcmp(argv[1], "-h")) {
fprintf(stderr, "Usage: %s domain\n", argv[0]);
exit(1);
}
#ifdef HAVE_RES_SEARCH
responses = getmxrecords(argv[1]);
if (responses == (struct mxentry *)NULL) {
puts("No MX records found");
} else {
do {
printf("%s %d\n", responses->name, responses->pref);
} while ((++responses)->name);
}
#else
puts("This program was compiled without HAS_RES_SEARCH and does nothing.");
#endif
return 0;
}
#endif /* TESTMAIN */
/* mxget.c ends here */
|