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