|
|
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 provided ! 7: * that: (1) source distributions retain this entire copyright notice and ! 8: * comment, and (2) distributions including binaries display the following ! 9: * acknowledgement: ``This product includes software developed by the ! 10: * University of California, Berkeley and its contributors'' in the ! 11: * documentation or other materials provided with the distribution and in ! 12: * all advertising materials mentioning features or use of this software. ! 13: * Neither the name of the University nor the names of its contributors may ! 14: * be used to endorse or promote products derived from this software without ! 15: * specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: */ ! 20: ! 21: #include "sendmail.h" ! 22: ! 23: #ifndef lint ! 24: #ifdef NAMED_BIND ! 25: static char sccsid[] = "@(#)domain.c 5.22 (Berkeley) 6/1/90 (with name server)"; ! 26: #else ! 27: static char sccsid[] = "@(#)domain.c 5.22 (Berkeley) 6/1/90 (without name server)"; ! 28: #endif ! 29: #endif /* not lint */ ! 30: ! 31: #ifdef NAMED_BIND ! 32: ! 33: #include <sys/param.h> ! 34: #include <errno.h> ! 35: #include <arpa/nameser.h> ! 36: #include <resolv.h> ! 37: #include <netdb.h> ! 38: ! 39: typedef union { ! 40: HEADER qb1; ! 41: char qb2[PACKETSZ]; ! 42: } querybuf; ! 43: ! 44: static char hostbuf[MAXMXHOSTS*PACKETSZ]; ! 45: ! 46: getmxrr(host, mxhosts, localhost, rcode) ! 47: char *host, **mxhosts, *localhost; ! 48: int *rcode; ! 49: { ! 50: extern int h_errno; ! 51: register u_char *eom, *cp; ! 52: register int i, j, n, nmx; ! 53: register char *bp; ! 54: HEADER *hp; ! 55: querybuf answer; ! 56: int ancount, qdcount, buflen, seenlocal; ! 57: u_short pref, localpref, type, prefer[MAXMXHOSTS]; ! 58: ! 59: errno = 0; ! 60: n = res_search(host, C_IN, T_MX, (char *)&answer, sizeof(answer)); ! 61: if (n < 0) ! 62: { ! 63: if (tTd(8, 1)) ! 64: printf("getmxrr: res_search failed (errno=%d, h_errno=%d)\n", ! 65: errno, h_errno); ! 66: switch (h_errno) ! 67: { ! 68: case NO_DATA: ! 69: case NO_RECOVERY: ! 70: /* no MX data on this host */ ! 71: goto punt; ! 72: ! 73: case HOST_NOT_FOUND: ! 74: /* the host just doesn't exist */ ! 75: *rcode = EX_NOHOST; ! 76: break; ! 77: ! 78: case TRY_AGAIN: ! 79: /* couldn't connect to the name server */ ! 80: if (!UseNameServer && errno == ECONNREFUSED) ! 81: goto punt; ! 82: ! 83: /* it might come up later; better queue it up */ ! 84: *rcode = EX_TEMPFAIL; ! 85: break; ! 86: } ! 87: ! 88: /* irreconcilable differences */ ! 89: return (-1); ! 90: } ! 91: ! 92: /* find first satisfactory answer */ ! 93: hp = (HEADER *)&answer; ! 94: cp = (u_char *)&answer + sizeof(HEADER); ! 95: eom = (u_char *)&answer + n; ! 96: for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ) ! 97: if ((n = dn_skipname(cp, eom)) < 0) ! 98: goto punt; ! 99: nmx = 0; ! 100: seenlocal = 0; ! 101: buflen = sizeof(hostbuf); ! 102: bp = hostbuf; ! 103: ancount = ntohs(hp->ancount); ! 104: while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS) { ! 105: if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) ! 106: break; ! 107: cp += n; ! 108: GETSHORT(type, cp); ! 109: cp += sizeof(u_short) + sizeof(u_long); ! 110: GETSHORT(n, cp); ! 111: if (type != T_MX) { ! 112: if (tTd(8, 1) || _res.options & RES_DEBUG) ! 113: printf("unexpected answer type %d, size %d\n", ! 114: type, n); ! 115: cp += n; ! 116: continue; ! 117: } ! 118: GETSHORT(pref, cp); ! 119: if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) ! 120: break; ! 121: cp += n; ! 122: if (!strcasecmp(bp, localhost)) { ! 123: if (seenlocal == 0 || pref < localpref) ! 124: localpref = pref; ! 125: seenlocal = 1; ! 126: continue; ! 127: } ! 128: prefer[nmx] = pref; ! 129: mxhosts[nmx++] = bp; ! 130: n = strlen(bp) + 1; ! 131: bp += n; ! 132: buflen -= n; ! 133: } ! 134: if (nmx == 0) { ! 135: punt: mxhosts[0] = strcpy(hostbuf, host); ! 136: return(1); ! 137: } ! 138: ! 139: /* sort the records */ ! 140: for (i = 0; i < nmx; i++) { ! 141: for (j = i + 1; j < nmx; j++) { ! 142: if (prefer[i] > prefer[j] || ! 143: (prefer[i] == prefer[j] && rand() % 1 == 0)) { ! 144: register int temp; ! 145: register char *temp1; ! 146: ! 147: temp = prefer[i]; ! 148: prefer[i] = prefer[j]; ! 149: prefer[j] = temp; ! 150: temp1 = mxhosts[i]; ! 151: mxhosts[i] = mxhosts[j]; ! 152: mxhosts[j] = temp1; ! 153: } ! 154: } ! 155: if (seenlocal && prefer[i] >= localpref) { ! 156: /* ! 157: * truncate higher pref part of list; if we're ! 158: * the best choice left, we should have realized ! 159: * awhile ago that this was a local delivery. ! 160: */ ! 161: if (i == 0) { ! 162: *rcode = EX_CONFIG; ! 163: return(-1); ! 164: } ! 165: nmx = i; ! 166: break; ! 167: } ! 168: } ! 169: return(nmx); ! 170: } ! 171: ! 172: getcanonname(host, hbsize) ! 173: char *host; ! 174: int hbsize; ! 175: { ! 176: extern int h_errno; ! 177: register u_char *eom, *cp; ! 178: register int n; ! 179: HEADER *hp; ! 180: querybuf answer; ! 181: u_short type; ! 182: int first, ancount, qdcount, loopcnt; ! 183: char nbuf[PACKETSZ]; ! 184: ! 185: loopcnt = 0; ! 186: loop: ! 187: /* ! 188: * Use query type of ANY if possible (NO_WILDCARD_MX), which will ! 189: * find types CNAME, A, and MX, and will cause all existing records ! 190: * to be cached by our local server. If there is (might be) a ! 191: * wildcard MX record in the local domain or its parents that are ! 192: * searched, we can't use ANY; it would cause fully-qualified names ! 193: * to match as names in a local domain. ! 194: */ ! 195: # ifdef NO_WILDCARD_MX ! 196: n = res_search(host, C_IN, T_ANY, (char *)&answer, sizeof(answer)); ! 197: # else ! 198: n = res_search(host, C_IN, T_CNAME, (char *)&answer, sizeof(answer)); ! 199: # endif ! 200: if (n < 0) { ! 201: if (tTd(8, 1)) ! 202: printf("getcanonname: res_search failed (errno=%d, h_errno=%d)\n", ! 203: errno, h_errno); ! 204: return; ! 205: } ! 206: ! 207: /* find first satisfactory answer */ ! 208: hp = (HEADER *)&answer; ! 209: ancount = ntohs(hp->ancount); ! 210: ! 211: /* we don't care about errors here, only if we got an answer */ ! 212: if (ancount == 0) { ! 213: if (tTd(8, 1)) ! 214: printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); ! 215: return; ! 216: } ! 217: cp = (u_char *)&answer + sizeof(HEADER); ! 218: eom = (u_char *)&answer + n; ! 219: for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ) ! 220: if ((n = dn_skipname(cp, eom)) < 0) ! 221: return; ! 222: ! 223: /* ! 224: * just in case someone puts a CNAME record after another record, ! 225: * check all records for CNAME; otherwise, just take the first ! 226: * name found. ! 227: */ ! 228: for (first = 1; --ancount >= 0 && cp < eom; cp += n) { ! 229: if ((n = dn_expand((char *)&answer, eom, cp, nbuf, ! 230: sizeof(nbuf))) < 0) ! 231: break; ! 232: if (first) { /* XXX */ ! 233: (void)strncpy(host, nbuf, hbsize); ! 234: host[hbsize - 1] = '\0'; ! 235: first = 0; ! 236: } ! 237: cp += n; ! 238: GETSHORT(type, cp); ! 239: cp += sizeof(u_short) + sizeof(u_long); ! 240: GETSHORT(n, cp); ! 241: if (type == T_CNAME) { ! 242: /* ! 243: * assume that only one cname will be found. More ! 244: * than one is undefined. Copy so that if dn_expand ! 245: * fails, `host' is still okay. ! 246: */ ! 247: if ((n = dn_expand((char *)&answer, eom, cp, nbuf, ! 248: sizeof(nbuf))) < 0) ! 249: break; ! 250: (void)strncpy(host, nbuf, hbsize); /* XXX */ ! 251: host[hbsize - 1] = '\0'; ! 252: if (++loopcnt > 8) /* never be more than 1 */ ! 253: return; ! 254: goto loop; ! 255: } ! 256: } ! 257: } ! 258: ! 259: #else /* not NAMED_BIND */ ! 260: ! 261: #include <netdb.h> ! 262: ! 263: getcanonname(host, hbsize) ! 264: char *host; ! 265: int hbsize; ! 266: { ! 267: struct hostent *hp; ! 268: ! 269: hp = gethostbyname(host); ! 270: if (hp == NULL) ! 271: return; ! 272: ! 273: if (strlen(hp->h_name) >= hbsize) ! 274: return; ! 275: ! 276: (void) strcpy(host, hp->h_name); ! 277: } ! 278: ! 279: #endif /* not NAMED_BIND */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.