Annotation of 43BSDReno/usr.sbin/sendmail/src/domain.c, revision 1.1.1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.