Annotation of 43BSD/lib/libc/net/res_send.c, revision 1.1

1.1     ! root        1: 
        !             2: /*
        !             3:  * Copyright (c) 1985 Regents of the University of California.
        !             4:  * All rights reserved.  The Berkeley software License Agreement
        !             5:  * specifies the terms and conditions for redistribution.
        !             6:  */
        !             7: 
        !             8: #if defined(LIBC_SCCS) && !defined(lint)
        !             9: static char sccsid[] = "@(#)res_send.c 6.14 (Berkeley) 7/2/86";
        !            10: #endif LIBC_SCCS and not lint
        !            11: 
        !            12: /*
        !            13:  * Send query to name server and wait for reply.
        !            14:  */
        !            15: 
        !            16: #include <sys/param.h>
        !            17: #include <sys/time.h>
        !            18: #include <sys/socket.h>
        !            19: #include <sys/uio.h>
        !            20: #include <netinet/in.h>
        !            21: #include <stdio.h>
        !            22: #include <errno.h>
        !            23: #include <arpa/nameser.h>
        !            24: #include <resolv.h>
        !            25: 
        !            26: extern int errno;
        !            27: 
        !            28: static int s = -1;     /* socket used for communications */
        !            29: 
        !            30: #define KEEPOPEN (RES_USEVC|RES_STAYOPEN)
        !            31: 
        !            32: res_send(buf, buflen, answer, anslen)
        !            33:        char *buf;
        !            34:        int buflen;
        !            35:        char *answer;
        !            36:        int anslen;
        !            37: {
        !            38:        register int n;
        !            39:        int retry, v_circuit, resplen, ns;
        !            40:        int gotsomewhere = 0;
        !            41:        u_short id, len;
        !            42:        char *cp;
        !            43:        fd_set dsmask;
        !            44:        struct timeval timeout;
        !            45:        HEADER *hp = (HEADER *) buf;
        !            46:        HEADER *anhp = (HEADER *) answer;
        !            47:        struct iovec iov[2];
        !            48:        int terrno = ETIMEDOUT;
        !            49: 
        !            50: #ifdef DEBUG
        !            51:        if (_res.options & RES_DEBUG) {
        !            52:                printf("res_send()\n");
        !            53:                p_query(buf);
        !            54:        }
        !            55: #endif DEBUG
        !            56:        if (!(_res.options & RES_INIT))
        !            57:                if (res_init() == -1) {
        !            58:                        return(-1);
        !            59:                }
        !            60:        v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
        !            61:        id = hp->id;
        !            62:        /*
        !            63:         * Send request, RETRY times, or until successful
        !            64:         */
        !            65:        for (retry = _res.retry; retry > 0; retry--) {
        !            66:           for (ns = 0; ns < _res.nscount; ns++) {
        !            67: #ifdef DEBUG
        !            68:                if (_res.options & RES_DEBUG)
        !            69:                        printf("Querying server (# %d) address = %s\n", ns+1,
        !            70:                              inet_ntoa(_res.nsaddr_list[ns].sin_addr.s_addr));
        !            71: #endif DEBUG
        !            72:                if (v_circuit) {
        !            73:                        /*
        !            74:                         * Use virtual circuit.
        !            75:                         */
        !            76:                        if (s < 0) {
        !            77:                                s = socket(AF_INET, SOCK_STREAM, 0);
        !            78:                                if (s < 0) {
        !            79:                                        terrno = errno;
        !            80: #ifdef DEBUG
        !            81:                                        if (_res.options & RES_DEBUG)
        !            82:                                            perror("socket failed");
        !            83: #endif DEBUG
        !            84:                                        continue;
        !            85:                                }
        !            86:                                if (connect(s, &(_res.nsaddr_list[ns]),
        !            87:                                   sizeof(struct sockaddr)) < 0) {
        !            88:                                        terrno = errno;
        !            89: #ifdef DEBUG
        !            90:                                        if (_res.options & RES_DEBUG)
        !            91:                                            perror("connect failed");
        !            92: #endif DEBUG
        !            93:                                        (void) close(s);
        !            94:                                        s = -1;
        !            95:                                        continue;
        !            96:                                }
        !            97:                        }
        !            98:                        /*
        !            99:                         * Send length & message
        !           100:                         */
        !           101:                        len = htons((u_short)buflen);
        !           102:                        iov[0].iov_base = (caddr_t)&len;
        !           103:                        iov[0].iov_len = sizeof(len);
        !           104:                        iov[1].iov_base = buf;
        !           105:                        iov[1].iov_len = buflen;
        !           106:                        if (writev(s, iov, 2) != sizeof(len) + buflen) {
        !           107:                                terrno = errno;
        !           108: #ifdef DEBUG
        !           109:                                if (_res.options & RES_DEBUG)
        !           110:                                        perror("write failed");
        !           111: #endif DEBUG
        !           112:                                (void) close(s);
        !           113:                                s = -1;
        !           114:                                continue;
        !           115:                        }
        !           116:                        /*
        !           117:                         * Receive length & response
        !           118:                         */
        !           119:                        cp = answer;
        !           120:                        len = sizeof(short);
        !           121:                        while (len != 0 &&
        !           122:                            (n = read(s, (char *)cp, (int)len)) > 0) {
        !           123:                                cp += n;
        !           124:                                len -= n;
        !           125:                        }
        !           126:                        if (n <= 0) {
        !           127:                                terrno = errno;
        !           128: #ifdef DEBUG
        !           129:                                if (_res.options & RES_DEBUG)
        !           130:                                        perror("read failed");
        !           131: #endif DEBUG
        !           132:                                (void) close(s);
        !           133:                                s = -1;
        !           134:                                continue;
        !           135:                        }
        !           136:                        cp = answer;
        !           137:                        resplen = len = ntohs(*(u_short *)cp);
        !           138:                        while (len != 0 &&
        !           139:                           (n = read(s, (char *)cp, (int)len)) > 0) {
        !           140:                                cp += n;
        !           141:                                len -= n;
        !           142:                        }
        !           143:                        if (n <= 0) {
        !           144:                                terrno = errno;
        !           145: #ifdef DEBUG
        !           146:                                if (_res.options & RES_DEBUG)
        !           147:                                        perror("read failed");
        !           148: #endif DEBUG
        !           149:                                (void) close(s);
        !           150:                                s = -1;
        !           151:                                continue;
        !           152:                        }
        !           153:                } else {
        !           154:                        /*
        !           155:                         * Use datagrams.
        !           156:                         */
        !           157:                        if (s < 0)
        !           158:                                s = socket(AF_INET, SOCK_DGRAM, 0);
        !           159: #if    BSD >= 43
        !           160:                        if (connect(s, &_res.nsaddr_list[ns],
        !           161:                            sizeof(struct sockaddr)) < 0 ||
        !           162:                            send(s, buf, buflen, 0) != buflen) {
        !           163: #ifdef DEBUG
        !           164:                                if (_res.options & RES_DEBUG)
        !           165:                                        perror("connect");
        !           166: #endif DEBUG
        !           167:                                continue;
        !           168:                        }
        !           169: #else BSD
        !           170:                        if (sendto(s, buf, buflen, 0, &_res.nsaddr_list[ns],
        !           171:                            sizeof(struct sockaddr)) != buflen) {
        !           172: #ifdef DEBUG
        !           173:                                if (_res.options & RES_DEBUG)
        !           174:                                        perror("sendto");
        !           175: #endif DEBUG
        !           176:                                continue;
        !           177:                        }
        !           178: #endif BSD
        !           179:                        /*
        !           180:                         * Wait for reply
        !           181:                         */
        !           182:                        timeout.tv_sec = (_res.retrans << (_res.retry - retry))
        !           183:                                / _res.nscount;
        !           184:                        if (timeout.tv_sec <= 0)
        !           185:                                timeout.tv_sec = 1;
        !           186:                        timeout.tv_usec = 0;
        !           187: wait:
        !           188:                        FD_ZERO(&dsmask);
        !           189:                        FD_SET(s, &dsmask);
        !           190:                        n = select(s+1, &dsmask, (fd_set *)NULL,
        !           191:                                (fd_set *)NULL, &timeout);
        !           192:                        if (n < 0) {
        !           193: #ifdef DEBUG
        !           194:                                if (_res.options & RES_DEBUG)
        !           195:                                        perror("select");
        !           196: #endif DEBUG
        !           197:                                continue;
        !           198:                        }
        !           199:                        if (n == 0) {
        !           200:                                /*
        !           201:                                 * timeout
        !           202:                                 */
        !           203: #ifdef DEBUG
        !           204:                                if (_res.options & RES_DEBUG)
        !           205:                                        printf("timeout\n");
        !           206: #endif DEBUG
        !           207:                                gotsomewhere = 1;
        !           208:                                continue;
        !           209:                        }
        !           210:                        if ((resplen = recv(s, answer, anslen, 0)) <= 0) {
        !           211: #ifdef DEBUG
        !           212:                                if (_res.options & RES_DEBUG)
        !           213:                                        perror("recvfrom");
        !           214: #endif DEBUG
        !           215:                                continue;
        !           216:                        }
        !           217:                        gotsomewhere = 1;
        !           218:                        if (id != anhp->id) {
        !           219:                                /*
        !           220:                                 * response from old query, ignore it
        !           221:                                 */
        !           222: #ifdef DEBUG
        !           223:                                if (_res.options & RES_DEBUG) {
        !           224:                                        printf("old answer:\n");
        !           225:                                        p_query(answer);
        !           226:                                }
        !           227: #endif DEBUG
        !           228:                                goto wait;
        !           229:                        }
        !           230:                        if (!(_res.options & RES_IGNTC) && anhp->tc) {
        !           231:                                /*
        !           232:                                 * get rest of answer
        !           233:                                 */
        !           234: #ifdef DEBUG
        !           235:                                if (_res.options & RES_DEBUG)
        !           236:                                        printf("truncated answer\n");
        !           237: #endif DEBUG
        !           238:                                (void) close(s);
        !           239:                                s = -1;
        !           240:                                /*
        !           241:                                 * retry decremented on continue
        !           242:                                 * to desired starting value
        !           243:                                 */
        !           244:                                retry = _res.retry + 1;
        !           245:                                v_circuit = 1;
        !           246:                                continue;
        !           247:                        }
        !           248:                }
        !           249: #ifdef DEBUG
        !           250:                if (_res.options & RES_DEBUG) {
        !           251:                        printf("got answer:\n");
        !           252:                        p_query(answer);
        !           253:                }
        !           254: #endif DEBUG
        !           255:                /*
        !           256:                 * We are going to assume that the first server is preferred
        !           257:                 * over the rest (i.e. it is on the local machine) and only
        !           258:                 * keep that one open.
        !           259:                 */
        !           260:                if ((_res.options & KEEPOPEN) == KEEPOPEN && ns == 0) {
        !           261:                        return (resplen);
        !           262:                } else {
        !           263:                        (void) close(s);
        !           264:                        s = -1;
        !           265:                        return (resplen);
        !           266:                }
        !           267:           }
        !           268:        }
        !           269:        if (s >= 0) {
        !           270:                (void) close(s);
        !           271:                s = -1;
        !           272:        }
        !           273:        if (v_circuit == 0)
        !           274:                if (gotsomewhere == 0)
        !           275:                        errno = ECONNREFUSED;
        !           276:                else
        !           277:                        errno = ETIMEDOUT;
        !           278:        else
        !           279:                errno = terrno;
        !           280:        return (-1);
        !           281: }
        !           282: 
        !           283: /*
        !           284:  * This routine is for closing the socket if a virtual circuit is used and
        !           285:  * the program wants to close it.  This provides support for endhostent()
        !           286:  * which expects to close the socket.
        !           287:  *
        !           288:  * This routine is not expected to be user visible.
        !           289:  */
        !           290: _res_close()
        !           291: {
        !           292:        if (s != -1) {
        !           293:                (void) close(s);
        !           294:                s = -1;
        !           295:        }
        !           296: }

unix.superglobalmegacorp.com

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