|
|
1.1 root 1: /*
2: * Copyright (c) 1986 Eric P. Allman
3: * Copyright (c) 1988 Regents of the University of California.
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms are permitted
7: * provided that the above copyright notice and this paragraph are
8: * duplicated in all such forms and that any documentation,
9: * advertising materials, and other materials related to such
10: * distribution and use acknowledge that the software was developed
11: * by the University of California, Berkeley. The name of the
12: * University may not be used to endorse or promote products derived
13: * from this software without specific prior written permission.
14: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17: */
18:
19: #ifndef lint
20: static char sccsid[] = "@(#)domain.c 5.15 (Berkeley) 6/30/88";
21: #endif /* not lint */
22:
23: #include <sendmail.h>
24: #include <sys/param.h>
25: #include <arpa/nameser.h>
26: #include <resolv.h>
27: #include <netdb.h>
28:
29: typedef union {
30: HEADER qb1;
31: char qb2[PACKETSZ];
32: } querybuf;
33:
34: static char hostbuf[MAXMXHOSTS*PACKETSZ];
35:
36: getmxrr(host, mxhosts, localhost, rcode)
37: char *host, **mxhosts, *localhost;
38: int *rcode;
39: {
40: extern int h_errno;
41: register u_char *eom, *cp;
42: register int i, j, n, nmx;
43: register char *bp;
44: HEADER *hp;
45: querybuf answer;
46: int ancount, qdcount, buflen, seenlocal;
47: u_short pref, localpref, type, prefer[MAXMXHOSTS];
48:
49: n = res_search(host, C_IN, T_MX, (char *)&answer, sizeof(answer));
50: if (n < 0) {
51: #ifdef DEBUG
52: if (tTd(8, 1))
53: printf("getmxrr: res_search failed (errno=%d, h_errno=%d)\n",
54: errno, h_errno);
55: #endif
56: switch(h_errno) {
57: case NO_DATA:
58: case NO_RECOVERY:
59: goto punt;
60: case HOST_NOT_FOUND:
61: *rcode = EX_NOHOST;
62: break;
63: case TRY_AGAIN:
64: *rcode = EX_TEMPFAIL;
65: break;
66: }
67: return(-1);
68: }
69:
70: /* find first satisfactory answer */
71: hp = (HEADER *)&answer;
72: cp = (u_char *)&answer + sizeof(HEADER);
73: eom = (u_char *)&answer + n;
74: for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
75: if ((n = dn_skipname(cp, eom)) < 0)
76: goto punt;
77: nmx = 0;
78: seenlocal = 0;
79: buflen = sizeof(hostbuf);
80: bp = hostbuf;
81: ancount = ntohs(hp->ancount);
82: while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS) {
83: if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0)
84: break;
85: cp += n;
86: GETSHORT(type, cp);
87: cp += sizeof(u_short) + sizeof(u_long);
88: GETSHORT(n, cp);
89: if (type != T_MX) {
90: #ifdef DEBUG
91: if (tTd(8, 1) || _res.options & RES_DEBUG)
92: printf("unexpected answer type %d, size %d\n",
93: type, n);
94: #endif
95: cp += n;
96: continue;
97: }
98: GETSHORT(pref, cp);
99: if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0)
100: break;
101: cp += n;
102: if (!strcasecmp(bp, localhost)) {
103: if (seenlocal == 0 || pref < localpref)
104: localpref = pref;
105: seenlocal = 1;
106: continue;
107: }
108: prefer[nmx] = pref;
109: mxhosts[nmx++] = bp;
110: n = strlen(bp) + 1;
111: bp += n;
112: buflen -= n;
113: }
114: if (nmx == 0) {
115: punt: mxhosts[0] = strcpy(hostbuf, host);
116: return(1);
117: }
118:
119: /* sort the records */
120: for (i = 0; i < nmx; i++) {
121: for (j = i + 1; j < nmx; j++) {
122: if (prefer[i] > prefer[j]) {
123: register int temp;
124: register char *temp1;
125:
126: temp = prefer[i];
127: prefer[i] = prefer[j];
128: prefer[j] = temp;
129: temp1 = mxhosts[i];
130: mxhosts[i] = mxhosts[j];
131: mxhosts[j] = temp1;
132: }
133: }
134: if (seenlocal && prefer[i] >= localpref) {
135: /*
136: * truncate higher pref part of list; if we're
137: * the best choice left, we should have realized
138: * awhile ago that this was a local delivery.
139: */
140: if (i == 0) {
141: *rcode = EX_CONFIG;
142: return(-1);
143: }
144: nmx = i;
145: break;
146: }
147: }
148: return(nmx);
149: }
150:
151: getcanonname(host, hbsize)
152: char *host;
153: int hbsize;
154: {
155: register u_char *eom, *cp;
156: register int n;
157: HEADER *hp;
158: querybuf answer;
159: u_short type;
160: int first, ancount, qdcount, loopcnt;
161: char nbuf[PACKETSZ];
162:
163: loopcnt = 0;
164: loop:
165: n = res_search(host, C_IN, T_CNAME, (char *)&answer, sizeof(answer));
166: if (n < 0) {
167: #ifdef DEBUG
168: if (tTd(8, 1))
169: printf("getcanonname: res_search failed (errno=%d, h_errno=%d)\n",
170: errno, h_errno);
171: #endif
172: return;
173: }
174:
175: /* find first satisfactory answer */
176: hp = (HEADER *)&answer;
177: ancount = ntohs(hp->ancount);
178:
179: /* we don't care about errors here, only if we got an answer */
180: if (ancount == 0) {
181: #ifdef DEBUG
182: if (tTd(8, 1))
183: printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
184: #endif
185: return;
186: }
187: cp = (u_char *)&answer + sizeof(HEADER);
188: eom = (u_char *)&answer + n;
189: for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
190: if ((n = dn_skipname(cp, eom)) < 0)
191: return;
192:
193: /*
194: * just in case someone puts a CNAME record after another record,
195: * check all records for CNAME; otherwise, just take the first
196: * name found.
197: */
198: for (first = 1; --ancount >= 0 && cp < eom; cp += n) {
199: if ((n = dn_expand((char *)&answer, eom, cp, nbuf,
200: sizeof(nbuf))) < 0)
201: break;
202: if (first) { /* XXX */
203: (void)strncpy(host, nbuf, hbsize);
204: host[hbsize - 1] = '\0';
205: first = 0;
206: }
207: cp += n;
208: GETSHORT(type, cp);
209: cp += sizeof(u_short) + sizeof(u_long);
210: GETSHORT(n, cp);
211: if (type == T_CNAME) {
212: /*
213: * assume that only one cname will be found. More
214: * than one is undefined. Copy so that if dn_expand
215: * fails, `host' is still okay.
216: */
217: if ((n = dn_expand((char *)&answer, eom, cp, nbuf,
218: sizeof(nbuf))) < 0)
219: break;
220: (void)strncpy(host, nbuf, hbsize); /* XXX */
221: host[hbsize - 1] = '\0';
222: if (++loopcnt > 8) /* never be more than 1 */
223: return;
224: goto loop;
225: }
226: }
227: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.