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