|
|
1.1 ! root 1: /* ! 2: ******************************************************************************* ! 3: * ! 4: * send.c -- ! 5: * ! 6: * Routine to send request packets to a name server. ! 7: * ! 8: * Modified version of 4.3BSD BIND res_send.c 5.5 (Berkeley) 9/14/85 ! 9: * ! 10: * Copyright (c) 1985 Regents of the University of California. ! 11: * All rights reserved. The Berkeley software License Agreement ! 12: * specifies the terms and conditions for redistribution. ! 13: * ! 14: ******************************************************************************* ! 15: */ ! 16: ! 17: #ifndef lint ! 18: static char sccsid[] = "@(#)send.c 5.3 (Berkeley) 3/31/86"; ! 19: #endif not lint ! 20: ! 21: #include <sys/types.h> ! 22: #include <sys/time.h> ! 23: #include <sys/socket.h> ! 24: #include <netinet/in.h> ! 25: #include <stdio.h> ! 26: #include <arpa/nameser.h> ! 27: #include <resolv.h> ! 28: #include "res.h" ! 29: ! 30: /* ! 31: * Initialize the socket address info struct. ! 32: */ ! 33: ! 34: static struct sockaddr_in sin = { ! 35: AF_INET, ! 36: }; ! 37: ! 38: ! 39: /* ! 40: ******************************************************************************* ! 41: * ! 42: * SendRequest -- ! 43: * ! 44: * Sends a request packet to a name server whose address ! 45: * is specified by the first argument and returns with ! 46: * the answer packet. ! 47: * ! 48: * Results: ! 49: * SUCCESS - the request was sent and an answer ! 50: * was received. ! 51: * TIME_OUT - the virtual circuit connection timed-out ! 52: * or a reply to a datagram wasn't received. ! 53: * ! 54: * ! 55: ******************************************************************************* ! 56: */ ! 57: ! 58: int ! 59: SendRequest(nsAddrPtr, buf, buflen, answer, anslen, trueLenPtr) ! 60: struct in_addr *nsAddrPtr; ! 61: char *buf; ! 62: int buflen; ! 63: char *answer; ! 64: int anslen; ! 65: int *trueLenPtr; ! 66: { ! 67: struct timeval timeout; ! 68: register int n; ! 69: u_short packetId, len; ! 70: short length; ! 71: char *cp; ! 72: int retry, v_circuit, resplen; ! 73: int dsmask; ! 74: ! 75: int numTimeOuts = 0; ! 76: HEADER *requestPtr = (HEADER *) buf; ! 77: HEADER *answerPtr = (HEADER *) answer; ! 78: ! 79: ! 80: if (_res.options & RES_DEBUG2) { ! 81: printf("SendRequest()\n"); ! 82: Print_query(buf, buf+buflen, 1); ! 83: } ! 84: sockFD = -1; ! 85: ! 86: /* ! 87: * See if a virtual circuit is required or desired. ! 88: */ ! 89: v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; ! 90: ! 91: packetId = requestPtr->id; ! 92: ! 93: sin.sin_port = htons(NAMESERVER_PORT); ! 94: sin.sin_addr = *nsAddrPtr; ! 95: ! 96: /* ! 97: * Send request, RETRY times, or until successful ! 98: */ ! 99: for (retry = _res.retry; --retry >= 0; ) { ! 100: if (v_circuit) { ! 101: /* ! 102: * Use virtual circuit. ! 103: */ ! 104: if (sockFD < 0) ! 105: sockFD = socket(AF_INET, SOCK_STREAM, 0); ! 106: ! 107: if (connect(sockFD, &sin, sizeof(sin)) < 0) { ! 108: if (_res.options & RES_DEBUG) { ! 109: perror("SendRequest"); ! 110: } ! 111: (void) close(sockFD); ! 112: sockFD = -1; ! 113: continue; ! 114: } ! 115: /* ! 116: * Send length & message ! 117: */ ! 118: len = htons(buflen); ! 119: if (write(sockFD, &len, sizeof(len)) != sizeof(len) || ! 120: write(sockFD, buf, buflen) != buflen) { ! 121: if (_res.options & RES_DEBUG) { ! 122: perror("SendRequest"); ! 123: } ! 124: (void) close(sockFD); ! 125: sockFD = -1; ! 126: continue; ! 127: } ! 128: /* ! 129: * Receive length & response ! 130: */ ! 131: cp = answer; ! 132: length = sizeof(short); ! 133: while(length > 0 && (n = read(sockFD, cp, length)) > 0){ ! 134: cp += n; ! 135: length -= n; ! 136: } ! 137: if (n <= 0) { ! 138: if (_res.options & RES_DEBUG) { ! 139: perror("SendRequest"); ! 140: } ! 141: (void) close(sockFD); ! 142: sockFD = -1; ! 143: continue; ! 144: } ! 145: cp = answer; ! 146: resplen = length = ntohs(*(short *)cp); ! 147: while(length > 0 && (n = read(sockFD, cp, length)) > 0){ ! 148: cp += n; ! 149: length -= n; ! 150: } ! 151: if (n <= 0) { ! 152: if (_res.options & RES_DEBUG) { ! 153: perror("SendRequest"); ! 154: } ! 155: (void) close(sockFD); ! 156: sockFD = -1; ! 157: continue; ! 158: } ! 159: } else { ! 160: /* ! 161: * Use datagrams. ! 162: */ ! 163: if (sockFD < 0) ! 164: sockFD = socket(AF_INET, SOCK_DGRAM, 0); ! 165: ! 166: if (sendto(sockFD, buf, buflen, 0, &sin, ! 167: sizeof(sin)) != buflen) { ! 168: if (_res.options & RES_DEBUG) { ! 169: perror("SendRequest"); ! 170: } ! 171: } ! 172: /* ! 173: * Wait for reply ! 174: */ ! 175: timeout.tv_sec = _res.retrans; ! 176: timeout.tv_usec = 0; ! 177: dsmask = 1 << sockFD; ! 178: n = select(sockFD+1, &dsmask, 0, 0, &timeout); ! 179: if (n < 0) { ! 180: if (_res.options & RES_DEBUG) { ! 181: perror("SendRequest"); ! 182: } ! 183: continue; ! 184: } ! 185: if (n == 0) { ! 186: /* ! 187: * timeout ! 188: */ ! 189: if (_res.options & RES_DEBUG) { ! 190: printf("Timeout %d\n", ++numTimeOuts); ! 191: } ! 192: continue; ! 193: } ! 194: if ((resplen = recv(sockFD, answer, anslen, 0)) <= 0) { ! 195: if (_res.options & RES_DEBUG) { ! 196: perror("SendRequest"); ! 197: } ! 198: continue; ! 199: } ! 200: if (packetId != answerPtr->id) { ! 201: /* ! 202: * response from old query, ignore it ! 203: */ ! 204: if (_res.options & RES_DEBUG2) { ! 205: printf("Old answer:\n"); ! 206: Print_query(answer, answer+resplen, 1); ! 207: } ! 208: continue; ! 209: } ! 210: if (!(_res.options & RES_IGNTC) && answerPtr->tc) { ! 211: /* ! 212: * get rest of answer ! 213: */ ! 214: if (_res.options & RES_DEBUG) { ! 215: printf("truncated answer\n"); ! 216: } ! 217: (void) close(sockFD); ! 218: sockFD = -1; ! 219: retry = _res.retry; ! 220: v_circuit = 1; ! 221: continue; ! 222: } ! 223: } ! 224: if (_res.options & RES_DEBUG) { ! 225: if (_res.options & RES_DEBUG2) ! 226: printf("Got answer:\n"); ! 227: Print_query(answer, answer+resplen, 0); ! 228: } ! 229: (void) close(sockFD); ! 230: sockFD = -1; ! 231: *trueLenPtr = resplen; ! 232: return (SUCCESS); ! 233: } ! 234: (void) close(sockFD); ! 235: sockFD = -1; ! 236: return (TIME_OUT); ! 237: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.