|
|
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.