1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67: #if defined(LIBC_SCCS) && !defined(lint)
68: static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
69: static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixie Exp $";
70: #endif
71:
72:
73:
74:
75:
76: #include <assert.h>
77: #include <sys/types.h>
78: #include <sys/param.h>
79: #include <sys/time.h>
80: #include <sys/socket.h>
81: #include <sys/uio.h>
82: #include <sys/poll.h>
83:
84: #include <netinet/in.h>
85: #include <arpa/nameser.h>
86: #include <arpa/inet.h>
87: #include <sys/ioctl.h>
88:
89: #include <errno.h>
90: #include <fcntl.h>
91: #include <netdb.h>
92: #include <resolv.h>
93: #include <signal.h>
94: #include <stdio.h>
95: #include <stdlib.h>
96: #include <string.h>
97: #include <unistd.h>
98:
99: #if PACKETSZ > 65536
100: #define MAXPACKET PACKETSZ
101: #else
102: #define MAXPACKET 65536
103: #endif
104:
105:
106:
107:
108: static inline void
109: __attribute ((always_inline))
110: evConsIovec(void *buf, size_t cnt, struct iovec *vec) {
111: memset(vec, 0xf5, sizeof (*vec));
112: vec->iov_base = buf;
113: vec->iov_len = cnt;
114: }
115:
116:
117:
118: #define BILLION 1000000000
119:
120: static inline void
121: evConsTime(struct timespec *res, time_t sec, long nsec) {
122: res->tv_sec = sec;
123: res->tv_nsec = nsec;
124: }
125:
126: static inline void
127: evAddTime(struct timespec *res, const struct timespec *addend1,
128: const struct timespec *addend2) {
129: res->tv_sec = addend1->tv_sec + addend2->tv_sec;
130: res->tv_nsec = addend1->tv_nsec + addend2->tv_nsec;
131: if (res->tv_nsec >= BILLION) {
132: res->tv_sec++;
133: res->tv_nsec -= BILLION;
134: }
135: }
136:
137: static inline void
138: evSubTime(struct timespec *res, const struct timespec *minuend,
139: const struct timespec *subtrahend) {
140: res->tv_sec = minuend->tv_sec - subtrahend->tv_sec;
141: if (minuend->tv_nsec >= subtrahend->tv_nsec)
142: res->tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec;
143: else {
144: res->tv_nsec = (BILLION
145: - subtrahend->tv_nsec + minuend->tv_nsec);
146: res->tv_sec--;
147: }
148: }
149:
150: static inline int
151: evCmpTime(struct timespec a, struct timespec b) {
152: long x = a.tv_sec - b.tv_sec;
153:
154: if (x == 0L)
155: x = a.tv_nsec - b.tv_nsec;
156: return (x < 0L ? (-1) : x > 0L ? (1) : (0));
157: }
158:
159: static inline void
160: evNowTime(struct timespec *res) {
161: struct timeval now;
162:
163: if (gettimeofday(&now, NULL) < 0)
164: evConsTime(res, 0, 0);
165: else
166: TIMEVAL_TO_TIMESPEC (&now, res);
167: }
168:
169:
170:
171:
172: #include "res_debug.h"
173:
174: #define EXT(res) ((res)->_u._ext)
175:
176:
177:
178: static int send_vc(res_state, const u_char *, int,
179: u_char **, int *, int *, int, u_char **);
180: static int send_dg(res_state, const u_char *, int,
181: u_char **, int *, int *, int,
182: int *, int *, u_char **);
183: #ifdef DEBUG
184: static void Aerror(const res_state, FILE *, const char *, int,
185: const struct sockaddr *);
186: static void Perror(const res_state, FILE *, const char *, int);
187: #endif
188: static int sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *);
189:
190:
191:
192: static void convaddr4to6(struct sockaddr_in6 *sa);
193: void res_pquery(const res_state, const u_char *, int, FILE *);
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206: int
207: res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
208: {
209: int ns;
210:
211: if (inp->sin6_family == AF_INET) {
212: struct sockaddr_in *in4p = (struct sockaddr_in *) inp;
213: in_port_t port = in4p->sin_port;
214: in_addr_t addr = in4p->sin_addr.s_addr;
215:
216: for (ns = 0; ns < MAXNS; ns++) {
217: const struct sockaddr_in *srv =
218: (struct sockaddr_in *)EXT(statp).nsaddrs[ns];
219:
220: if ((srv != NULL) && (srv->sin_family == AF_INET) &&
221: (srv->sin_port == port) &&
222: (srv->sin_addr.s_addr == INADDR_ANY ||
223: srv->sin_addr.s_addr == addr))
224: return (1);
225: }
226: } else if (inp->sin6_family == AF_INET6) {
227: for (ns = 0; ns < MAXNS; ns++) {
228: const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns];
229: if ((srv != NULL) && (srv->sin6_family == AF_INET6) &&
230: (srv->sin6_port == inp->sin6_port) &&
231: !(memcmp(&srv->sin6_addr, &in6addr_any,
232: sizeof (struct in6_addr)) &&
233: memcmp(&srv->sin6_addr, &inp->sin6_addr,
234: sizeof (struct in6_addr))))
235: return (1);
236: }
237: }
238: return (0);
239: }
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253: int
254: res_nameinquery(const char *name, int type, int class,
255: const u_char *buf, const u_char *eom)
256: {
257: const u_char *cp = buf + HFIXEDSZ;
258: int qdcount = ntohs(((HEADER*)buf)->qdcount);
259:
260: while (qdcount-- > 0) {
261: char tname[MAXDNAME+1];
262: int n, ttype, tclass;
263:
264: n = dn_expand(buf, eom, cp, tname, sizeof tname);
265: if (n < 0)
266: return (-1);
267: cp += n;
268: if (cp + 2 * INT16SZ > eom)
269: return (-1);
270: NS_GET16(ttype, cp);
271: NS_GET16(tclass, cp);
272: if (ttype == type && tclass == class &&
273: ns_samename(tname, name) == 1)
274: return (1);
275: }
276: return (0);
277: }
278: libresolv_hidden_def (res_nameinquery)
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291: int
292: res_queriesmatch(const u_char *buf1, const u_char *eom1,
293: const u_char *buf2, const u_char *eom2)
294: {
295: if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
296: return (-1);
297:
298:
299:
300:
301:
302: if ((((HEADER *)buf1)->opcode == ns_o_update) &&
303: (((HEADER *)buf2)->opcode == ns_o_update))
304: return (1);
305:
306:
307:
308:
309: int qdcount = ((HEADER*)buf1)->qdcount;
310: if (qdcount != ((HEADER*)buf2)->qdcount)
311: return (0);
312:
313: qdcount = htons (qdcount);
314: const u_char *cp = buf1 + HFIXEDSZ;
315:
316: while (qdcount-- > 0) {
317: char tname[MAXDNAME+1];
318: int n, ttype, tclass;
319:
320: n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
321: if (n < 0)
322: return (-1);
323: cp += n;
324: if (cp + 2 * INT16SZ > eom1)
325: return (-1);
326: NS_GET16(ttype, cp);
327: NS_GET16(tclass, cp);
328: if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
329: return (0);
330: }
331: return (1);
332: }
333: libresolv_hidden_def (res_queriesmatch)
334:
335: int
336: __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
337: u_char *ans, int anssiz, u_char **ansp)
338: {
339: int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
340:
341: if (statp->nscount == 0) {
342: __set_errno (ESRCH);
343: return (-1);
344: }
345:
346: if (anssiz < HFIXEDSZ) {
347: __set_errno (EINVAL);
348: return (-1);
349: }
350:
351: if ((statp->qhook || statp->rhook) && anssiz < MAXPACKET && ansp) {
352: u_char *buf = malloc (MAXPACKET);
353: if (buf == NULL)
354: return (-1);
355: memcpy (buf, ans, HFIXEDSZ);
356: *ansp = buf;
357: ans = buf;
358: anssiz = MAXPACKET;
359: }
360:
361: DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
362: (stdout, ";; res_send()\n"), buf, buflen);
363: v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
364: gotsomewhere = 0;
365: terrno = ETIMEDOUT;
366:
367:
368:
369:
370:
371: if (EXT(statp).nsinit) {
372: int needclose = 0;
373:
374: if (EXT(statp).nscount != statp->nscount)
375: needclose++;
376: else
377: for (ns = 0; ns < MAXNS; ns++) {
378: unsigned int map = EXT(statp).nsmap[ns];
379: if (map < MAXNS
380: && !sock_eq((struct sockaddr_in6 *)
381: &statp->nsaddr_list[map],
382: EXT(statp).nsaddrs[ns]))
383: {
384: needclose++;
385: break;
386: }
387: }
388: if (needclose)
389: __res_iclose(statp, false);
390: }
391:
392:
393:
394:
395: if (EXT(statp).nsinit == 0) {
396: unsigned char map[MAXNS];
397:
398: memset (map, MAXNS, sizeof (map));
399: for (n = 0; n < MAXNS; n++) {
400: ns = EXT(statp).nsmap[n];
401: if (ns < statp->nscount)
402: map[ns] = n;
403: else if (ns < MAXNS) {
404: free(EXT(statp).nsaddrs[n]);
405: EXT(statp).nsaddrs[n] = NULL;
406: EXT(statp).nsmap[n] = MAXNS;
407: }
408: }
409: n = statp->nscount;
410: if (statp->nscount > EXT(statp).nscount)
411: for (n = EXT(statp).nscount, ns = 0;
412: n < statp->nscount; n++) {
413: while (ns < MAXNS
414: && EXT(statp).nsmap[ns] != MAXNS)
415: ns++;
416: if (ns == MAXNS)
417: break;
418: EXT(statp).nsmap[ns] = n;
419: map[n] = ns++;
420: }
421: EXT(statp).nscount = n;
422: for (ns = 0; ns < EXT(statp).nscount; ns++) {
423: n = map[ns];
424: if (EXT(statp).nsaddrs[n] == NULL)
425: EXT(statp).nsaddrs[n] =
426: malloc(sizeof (struct sockaddr_in6));
427: if (EXT(statp).nsaddrs[n] != NULL) {
428: memset (mempcpy(EXT(statp).nsaddrs[n],
429: &statp->nsaddr_list[ns],
430: sizeof (struct sockaddr_in)),
431: '\0',
432: sizeof (struct sockaddr_in6)
433: - sizeof (struct sockaddr_in));
434: EXT(statp).nssocks[n] = -1;
435: n++;
436: }
437: }
438: EXT(statp).nsinit = 1;
439: }
440:
441:
442:
443:
444:
445: if ((statp->options & RES_ROTATE) != 0 &&
446: (statp->options & RES_BLAST) == 0) {
447: struct sockaddr_in6 *ina;
448: unsigned int map;
449:
450: n = 0;
451: while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS)
452: n++;
453: if (n < MAXNS) {
454: ina = EXT(statp).nsaddrs[n];
455: map = EXT(statp).nsmap[n];
456: for (;;) {
457: ns = n + 1;
458: while (ns < MAXNS
459: && EXT(statp).nsmap[ns] == MAXNS)
460: ns++;
461: if (ns == MAXNS)
462: break;
463: EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns];
464: EXT(statp).nsmap[n] = EXT(statp).nsmap[ns];
465: n = ns;
466: }
467: EXT(statp).nsaddrs[n] = ina;
468: EXT(statp).nsmap[n] = map;
469: }
470: }
471:
472:
473:
474:
475: for (try = 0; try < statp->retry; try++) {
476: for (ns = 0; ns < MAXNS; ns++)
477: {
478: struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
479:
480: if (nsap == NULL)
481: goto next_ns;
482: same_ns:
483: if (statp->qhook) {
484: int done = 0, loops = 0;
485:
486: do {
487: res_sendhookact act;
488:
489: struct sockaddr_in *nsap4;
490: nsap4 = (struct sockaddr_in *) nsap;
491: act = (*statp->qhook)(&nsap4, &buf, &buflen,
492: ans, anssiz, &resplen);
493: nsap = (struct sockaddr_in6 *) nsap4;
494: switch (act) {
495: case res_goahead:
496: done = 1;
497: break;
498: case res_nextns:
499: __res_iclose(statp, false);
500: goto next_ns;
501: case res_done:
502: return (resplen);
503: case res_modified:
504:
505: if (++loops < 42)
506: break;
507:
508: case res_error:
509:
510: default:
511: return (-1);
512: }
513: } while (!done);
514: }
515:
516: #ifdef DEBUG
517: char tmpbuf[40];
518: #endif
519: Dprint(statp->options & RES_DEBUG,
520: (stdout, ";; Querying server (# %d) address = %s\n",
521: ns + 1, inet_ntop(AF_INET6, &nsap->sin6_addr,
522: tmpbuf, sizeof (tmpbuf))));
523:
524: if (v_circuit) {
525:
526: try = statp->retry;
527: n = send_vc(statp, buf, buflen, &ans, &anssiz, &terrno,
528: ns, ansp);
529: if (n < 0)
530: return (-1);
531: if (n == 0)
532: goto next_ns;
533: resplen = n;
534: