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: }