Annotation of 43BSD/lib/libc/net/res_send.c, revision 1.1.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.