Annotation of researchv10no/cmd/nupas/ipc/mxconnect.c, revision 1.1.1.1

1.1       root        1: #include <sys/types.h>                 /* needed for socket.h */
                      2: #include <sys/uio.h>                   /* needed for socket.h */
                      3: #include <sys/socket.h>
                      4: #include <sysexits.h>
                      5: #include <netinet/in.h>
                      6: #include <netdb.h>
                      7: #include <stdio.h>
                      8: #include <arpa/nameser.h>
                      9: #include <string.h>
                     10: 
                     11: /* imports */
                     12: extern char *malloc(), *strcpy(), *inet_ntoa();
                     13: 
                     14: extern int ipcdebug;
                     15: extern char syserrstr[];
                     16: 
                     17: /* private */
                     18: #define MAXMXLIST 10
                     19: static struct mxitem {
                     20:        char *host;
                     21:        u_short pref;
                     22:        u_char localflag;
                     23: } MXlist[MAXMXLIST + 1];
                     24: static char *strsave();
                     25: static int buildmxlist();
                     26: static void mxsave(), mxinsert(), mxlocal();
                     27: static struct hostent *getmxhost();
                     28: 
                     29: mx_connect(dest, param)
                     30: char *dest, *param;
                     31: {
                     32:        int s, lport, mxfatal;
                     33:        char **addr;
                     34:        char host[100];
                     35:        struct hostent *hp;
                     36:        struct sockaddr_in sin;
                     37:        struct mxitem *mxp;
                     38:        extern int tcp_service();
                     39:        int port;
                     40:        char *bp;
                     41:        int errtype = 0;
                     42:        char errstr[256];
                     43: 
                     44:        strcpy(host, dest);
                     45: 
                     46:        if ((port = tcp_service(host)) < 0) {
                     47:                ipcsyserr("unknown service");
                     48:                return(-1);
                     49:        }
                     50: 
                     51:        mxfatal = buildmxlist(host);
                     52:        if (MXlist[0].host == 0)
                     53:                return(tcp_connect(dest, param));
                     54:                /*MXlist[0].host = host;*/
                     55: 
                     56:        (void) setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) 0, 0);
                     57: 
                     58:        /* slop in the loop -- i hate the socket dance */
                     59:        for (mxp = MXlist; mxp->host; mxp++) {
                     60:                int i;
                     61: 
                     62:                if ((hp = getmxhost(mxp->host)) == 0) {
                     63:                        if (mxfatal) {
                     64:                                ipcsyserr("stub - can't find useful host"); /*EX_NOHOST*/
                     65:                                return -1;
                     66:                        }
                     67:                        continue;
                     68:                }
                     69:                for (i=0; hp->h_addr_list[i]; i++) {
                     70:                        s = socket(AF_INET, SOCK_STREAM, 0);
                     71:                        if (s < 0) {
                     72:                                ipcsyserr("Can't open socket"); /*EX_OSERR*/
                     73:                                return -1;
                     74:                        }
                     75:                        bzero((char *)&sin, sizeof(sin));
                     76:                        sin.sin_port = port;
                     77:                        sin.sin_family = hp->h_addrtype;
                     78:                        bcopy(hp->h_addr_list[i], (char *) &sin.sin_addr,
                     79:                                hp->h_length);
                     80:                        if (ipcdebug)
                     81:                                 fprintf(stderr, "try %s [%s]\n", mxp->host,
                     82:                                     inet_ntoa(sin.sin_addr));
                     83:                        if (connect(s, (struct sockaddr *)&sin, sizeof(sin))>=0) {
                     84:                                if (ipcdebug)
                     85:                                        fprintf(stderr, " connected\n");
                     86:                                return s;
                     87:                        }
                     88:                        ipcgetsyserr();
                     89:                        fprintf(stderr, "Couldn't connect to %s [%s]: %s\n",
                     90:                                mxp->host, inet_ntoa(sin.sin_addr), syserrstr);
                     91:                        if (errtype == 0 || 
                     92:                           (errtype != EX_TEMPFAIL && ipcmaperror()==EX_TEMPFAIL)) {
                     93:                                errtype = ipcmaperror();
                     94:                                strcpy(errstr, syserrstr);
                     95:                        }
                     96:                        close(s);
                     97:                }
                     98:        }
                     99:        ipcseterror(errtype, errstr, "Can't connect to host");
                    100:        return -1;
                    101: }
                    102: 
                    103: /* return 1 for fatal MX error (authoritative NXDOMAIN), 0 o.w. */
                    104: static int
                    105: buildmxlist(host)
                    106:        char *host;
                    107: {      register HEADER *hp;
                    108:        register char *cp;
                    109:        register int n;
                    110:        char q[PACKETSZ], a[PACKETSZ];  /* query, answer */
                    111:        char *eom, *bp;
                    112:        int buflen, ancount, qdcount;
                    113:        char hostbuf[BUFSIZ+1];
                    114:        u_short preference, reclen;
                    115:        int niter = 0;
                    116:        char nhostbuf[BUFSIZ+1];
                    117: 
                    118: again:
                    119:        if ((n = res_mkquery(QUERY, host, C_IN, T_MX, (char *) 0,
                    120:            0, (struct rrec *) 0, q, sizeof(q))) < 0)
                    121:                return 0;
                    122:        n = res_send(q, n, a, sizeof(a));
                    123:        if (n < 0)
                    124:                return 0;
                    125:        if (ipcdebug)
                    126:                fprintf(stderr, "buildmxlist got %d\n", n);
                    127:        eom = a + n;
                    128:        hp = (HEADER *) a;
                    129:        ancount = ntohs(hp->ancount);
                    130:        qdcount = ntohs(hp->qdcount);
                    131:        if (ipcdebug)
                    132:                fprintf(stderr, "buildmx rcode %d ancount %d qdcount %d aa %d\n",
                    133:                 hp->rcode, ancount, qdcount, hp->aa);
                    134:        if (hp->rcode != NOERROR || ancount == 0) {
                    135:                if (hp->aa == 0)
                    136:                        return 0;       /* non-authoritative in any event */
                    137:                return hp->rcode == NOERROR || hp->rcode == NXDOMAIN;
                    138:        }
                    139:        bp = hostbuf;
                    140:        buflen = sizeof(hostbuf);
                    141:        cp = a + sizeof(HEADER);
                    142:        if (ipcdebug>1) {
                    143:                int i;
                    144:                fprintf(stderr, "buildmx got:");
                    145:                for (i=0; i<n; i++)
                    146:                        if (a[i]>=' '&& a[i]<0177)
                    147:                                fprintf(stderr, "%c", a[i]);
                    148:                        else fprintf(stderr, "\\%.3o", a[i]&0377);
                    149:                fprintf(stderr, "\n");
                    150:        }
                    151:        while (--qdcount >= 0)
                    152:                cp += dn_skipname(cp,eom) + QFIXEDSZ;
                    153:        /* TODO: if type is CNAME, reissue query */
                    154:        while (--ancount >= 0 && cp < eom) {
                    155:                int type;
                    156:                cp += dn_skipname(cp,eom);      /* name */
                    157:                type = _getshort(cp);   
                    158:                cp += sizeof(u_short)   /* type */
                    159:                    + sizeof(u_short)   /* class */
                    160:                    + sizeof(u_long);   /* ttl (see rfc973) */
                    161:                reclen = _getshort(cp);
                    162:                cp += sizeof(u_short);
                    163:                if (type==T_CNAME) {    /* canonical name */
                    164:                        if (dn_expand(a, eom, cp, nhostbuf, BUFSIZ) < 0)
                    165:                                if (ipcdebug)
                    166:                                        fprintf(stderr, "CNAME? in mxexpand\n");
                    167:                        host = nhostbuf;
                    168:                        if (++niter>10)
                    169:                                return 0;
                    170:                        if (ipcdebug)
                    171:                                fprintf(stderr, "CNAME, try with %s\n", host);
                    172:                        goto again;
                    173:                }
                    174:                preference = _getshort(cp);
                    175:                if ((n = dn_expand(a, eom, cp + sizeof(u_short), bp, buflen)) < 0)
                    176:                        break;
                    177:                mxsave(bp, preference);
                    178:                cp += reclen;
                    179:        }
                    180:        mxlocal();
                    181:        return 0;
                    182: }
                    183: 
                    184: /* NOT TODO: issue WKS query.  (just try to connect.) */
                    185: 
                    186: static void
                    187: mxsave(host, pref)
                    188:        char *host;
                    189:        u_short pref;
                    190: {      struct mxitem *mxp;
                    191:        int localflag;
                    192:        static char thishost[64];
                    193: 
                    194:        if (*thishost == 0)
                    195:                gethostname(thishost, sizeof(thishost));
                    196:        if (ipcdebug)
                    197:                fprintf(stderr, "MXsave %s\n", host);
                    198: 
                    199:        if (MXlist[MAXMXLIST].host)
                    200:                return;                         /* full */
                    201: 
                    202:        localflag = (strcmp(thishost, host) == 0);
                    203: 
                    204:        /* insertion sort */
                    205:        for (mxp = MXlist; mxp < MXlist + MAXMXLIST; mxp++) {
                    206:                if (mxp->host == 0) {
                    207:                        mxinsert(mxp, host, pref, localflag);
                    208:                        return;
                    209:                }
                    210:                if (pref < mxp->pref) {
                    211:                        mxinsert(mxp, host, pref, localflag);
                    212:                        return;
                    213:                }
                    214:                if (pref == mxp->pref) {
                    215:                        if (mxp->localflag)
                    216:                                return;
                    217:                        if (localflag) {
                    218:                                mxp->host = strsave(host);
                    219:                                mxp->pref = pref;
                    220:                                mxp->localflag = localflag;
                    221:                                (++mxp)->host = 0;
                    222:                                return;
                    223:                        }
                    224:                        mxinsert(mxp, host, pref, localflag);
                    225:                        return;
                    226:                }
                    227:        }
                    228: }
                    229: 
                    230: static void
                    231: mxinsert(mxlistp, host, pref, localflag)
                    232:        struct mxitem *mxlistp;
                    233:        char *host;
                    234:        u_short pref;
                    235: {      register struct mxitem *mxp;
                    236: 
                    237:        for (mxp = MXlist + MAXMXLIST - 1; mxp > mxlistp; --mxp)
                    238:                *mxp = mxp[-1];
                    239:        mxp->host = strsave(host);
                    240:        mxp->pref = pref;
                    241:        mxp->localflag = localflag;
                    242: }
                    243: 
                    244: static char *
                    245: strsave(str)
                    246:        register char *str;
                    247: {      register char *rval;
                    248: 
                    249:        if ((rval = malloc(strlen(str) + 1)) == 0) {
                    250:                ipcsyserr("mx connect malloc");
                    251:                exit(1);
                    252:        }
                    253:        strcpy(rval, str);
                    254:        return rval;
                    255: }
                    256: 
                    257: static void
                    258: mxlocal()
                    259: {      register struct mxitem *mxp;
                    260: 
                    261:        if (MXlist[0].host == 0)
                    262:                return;
                    263: 
                    264:        for (mxp = MXlist; mxp->host; mxp++) {
                    265:                if (mxp->localflag) {
                    266:                        mxp->host = 0;
                    267:                        break;
                    268:                }
                    269:        }
                    270: }
                    271: 
                    272: static struct hostent *
                    273: getmxhost(host)
                    274:        char *host;
                    275: {      struct hostent *hp, *gethostbyname();
                    276:        long inet_addr();
                    277:        int err;
                    278:        char errbuf[256];
                    279:        static struct in_addr ia;
                    280:        static char *hlist[2] = {0, 0};
                    281:        static struct hostent he =
                    282:                {0, 0, AF_INET, sizeof(struct in_addr), hlist};
                    283: 
                    284:        if (!host)
                    285:                return 0;
                    286: 
                    287:        if ((hp = gethostbyname(host)) != 0)
                    288:                return hp;
                    289:        ipcgetsyserr();
                    290: 
                    291:        if ((ia.s_addr = inet_addr(host)) != -1) {
                    292:                he.h_addr = (char *)&ia;
                    293:                return &he;
                    294:        }
                    295:        sprintf(errbuf, "Error looking up MX Host '%s'.\n", host);
                    296:        ipcsyserr(errbuf);
                    297:        return 0;
                    298: }

unix.superglobalmegacorp.com

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