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