Annotation of researchv10no/cmd/nupas/ipc/mxconnect.c, revision 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.