|
|
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.