xref: /csrg-svn/usr.sbin/sendmail/src/domain.c (revision 29432)
1*29432Sbloom /*
2*29432Sbloom **  Sendmail
3*29432Sbloom **  Copyright (c) 1986  Eric P. Allman
4*29432Sbloom **  Berkeley, California
5*29432Sbloom **
6*29432Sbloom **  Copyright (c) 1986 Regents of the University of California.
7*29432Sbloom **  All rights reserved.  The Berkeley software License Agreement
8*29432Sbloom **  specifies the terms and conditions for redistribution.
9*29432Sbloom */
10*29432Sbloom 
11*29432Sbloom #ifndef lint
12*29432Sbloom static char	SccsId[] = "@(#)domain.c	5.1 (Berkeley) 07/01/86";
13*29432Sbloom #endif not lint
14*29432Sbloom 
15*29432Sbloom # include <sys/param.h>
16*29432Sbloom # include <netinet/in.h>
17*29432Sbloom # include <arpa/nameser.h>
18*29432Sbloom # include <resolv.h>
19*29432Sbloom # include <stdio.h>
20*29432Sbloom # include <netdb.h>
21*29432Sbloom 
22*29432Sbloom typedef union {
23*29432Sbloom 	HEADER qb1;
24*29432Sbloom 	char qb2[PACKETSZ];
25*29432Sbloom } querybuf;
26*29432Sbloom 
27*29432Sbloom static char hostbuf[BUFSIZ];
28*29432Sbloom 
29*29432Sbloom int h_errno;
30*29432Sbloom 
31*29432Sbloom getmxrr(host, mxhosts, maxmx)
32*29432Sbloom 	char *host, **mxhosts;
33*29432Sbloom 	int maxmx;
34*29432Sbloom {
35*29432Sbloom 
36*29432Sbloom 	HEADER *hp;
37*29432Sbloom 	char *eom, *bp, *cp;
38*29432Sbloom 	querybuf buf, answer;
39*29432Sbloom 	int n, n1, i, j, nmx, ancount, qdcount, buflen;
40*29432Sbloom 	u_short prefer[BUFSIZ];
41*29432Sbloom 	u_short pref, type, class;
42*29432Sbloom 
43*29432Sbloom 	n = res_mkquery(QUERY, host, C_IN, T_MX, (char *)NULL, 0, NULL,
44*29432Sbloom 		(char *)&buf, sizeof(buf));
45*29432Sbloom 	if (n < 0) {
46*29432Sbloom #ifdef DEBUG
47*29432Sbloom 		if (tTd(8, 1) || _res.options & RES_DEBUG)
48*29432Sbloom 			printf("res_mkquery failed\n");
49*29432Sbloom #endif
50*29432Sbloom 		return(-1);
51*29432Sbloom 	}
52*29432Sbloom 	n = res_send((char *)&buf, n, (char *)&answer, sizeof(answer));
53*29432Sbloom 	if (n < 0) {
54*29432Sbloom #ifdef DEBUG
55*29432Sbloom 		if (tTd(8, 1) || _res.options & RES_DEBUG)
56*29432Sbloom 			printf("res_send failed\n");
57*29432Sbloom #endif
58*29432Sbloom 		h_errno = TRY_AGAIN;
59*29432Sbloom 		return (-1);
60*29432Sbloom 	}
61*29432Sbloom 	eom = (char *)&answer + n;
62*29432Sbloom 	/*
63*29432Sbloom 	 * find first satisfactory answer
64*29432Sbloom 	 */
65*29432Sbloom 	hp = (HEADER *) &answer;
66*29432Sbloom 	ancount = ntohs(hp->ancount);
67*29432Sbloom 	qdcount = ntohs(hp->qdcount);
68*29432Sbloom 	if (hp->rcode != NOERROR || ancount == 0) {
69*29432Sbloom #ifdef DEBUG
70*29432Sbloom 		if (tTd(8, 1) || _res.options & RES_DEBUG)
71*29432Sbloom 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
72*29432Sbloom #endif
73*29432Sbloom 		switch (hp->rcode) {
74*29432Sbloom 			case NXDOMAIN:
75*29432Sbloom 				/* Check if it's an authoritive answer */
76*29432Sbloom 				if (hp->aa)
77*29432Sbloom 					h_errno = HOST_NOT_FOUND;
78*29432Sbloom 				else
79*29432Sbloom 					h_errno = TRY_AGAIN;
80*29432Sbloom 				break;
81*29432Sbloom 			case SERVFAIL:
82*29432Sbloom 				h_errno = TRY_AGAIN;
83*29432Sbloom 				break;
84*29432Sbloom 			case NOERROR:
85*29432Sbloom 				h_errno = NO_ADDRESS;
86*29432Sbloom 				break;
87*29432Sbloom 			case FORMERR:
88*29432Sbloom 			case NOTIMP:
89*29432Sbloom 			case REFUSED:
90*29432Sbloom 				h_errno = NO_RECOVERY;
91*29432Sbloom 		}
92*29432Sbloom 		return (-1);
93*29432Sbloom 	}
94*29432Sbloom 	bp = hostbuf;
95*29432Sbloom 	nmx = 0;
96*29432Sbloom 	buflen = sizeof(hostbuf);
97*29432Sbloom 	cp = (char *)&answer + sizeof(HEADER);
98*29432Sbloom 	if (qdcount) {
99*29432Sbloom 		cp += dn_skip(cp) + QFIXEDSZ;
100*29432Sbloom 		while (--qdcount > 0)
101*29432Sbloom 			cp += dn_skip(cp) + QFIXEDSZ;
102*29432Sbloom 	}
103*29432Sbloom 	while (--ancount >= 0 && cp < eom && nmx < maxmx) {
104*29432Sbloom 		if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0)
105*29432Sbloom 			break;
106*29432Sbloom 		cp += n;
107*29432Sbloom 		type = getshort(cp);
108*29432Sbloom  		cp += sizeof(u_short);
109*29432Sbloom 		class = getshort(cp);
110*29432Sbloom  		cp += sizeof(u_short) + sizeof(u_long);
111*29432Sbloom 		n = getshort(cp);
112*29432Sbloom 		cp += sizeof(u_short);
113*29432Sbloom 		if (type != T_MX)  {
114*29432Sbloom #ifdef DEBUG
115*29432Sbloom 			if (tTd(8, 1) || _res.options & RES_DEBUG)
116*29432Sbloom 				printf("unexpected answer type %d, size %d\n",
117*29432Sbloom 					type, n);
118*29432Sbloom #endif
119*29432Sbloom 			cp += n;
120*29432Sbloom 			continue;
121*29432Sbloom 		}
122*29432Sbloom 		pref = getshort(cp);
123*29432Sbloom 		cp += sizeof(u_short);
124*29432Sbloom 		if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0)
125*29432Sbloom 			break;
126*29432Sbloom 		prefer[nmx] = pref;
127*29432Sbloom 		mxhosts[nmx++] = bp;
128*29432Sbloom 		n1 = strlen(bp)+1;
129*29432Sbloom 		bp += n1;
130*29432Sbloom 		buflen -= n1;
131*29432Sbloom 		cp += n;
132*29432Sbloom 	}
133*29432Sbloom 	if (nmx == 0)
134*29432Sbloom 		return(-1);
135*29432Sbloom 	/* sort the records */
136*29432Sbloom 	for (i = 0; i < nmx; i++) {
137*29432Sbloom 		for (j = i + 1; j < nmx; j++) {
138*29432Sbloom 			if (prefer[i] > prefer[j]) {
139*29432Sbloom 				int temp;
140*29432Sbloom 				char *temp1;
141*29432Sbloom 
142*29432Sbloom 				temp = prefer[i];
143*29432Sbloom 				prefer[i] = prefer[j];
144*29432Sbloom 				prefer[j] = temp;
145*29432Sbloom 				temp1 = mxhosts[i];
146*29432Sbloom 				mxhosts[i] = mxhosts[j];
147*29432Sbloom 				mxhosts[j] = temp1;
148*29432Sbloom 			}
149*29432Sbloom 		}
150*29432Sbloom 	}
151*29432Sbloom 	return(nmx);
152*29432Sbloom }
153