OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.18.0/] [newlib/] [libc/] [sys/] [linux/] [net/] [res_send.c] - Blame information for rev 357

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 207 jeremybenn
/*
2
 * Copyright (c) 1985, 1989, 1993
3
 *    The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 4. Neither the name of the University nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
 
30
/*
31
 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
32
 *
33
 * Permission to use, copy, modify, and distribute this software for any
34
 * purpose with or without fee is hereby granted, provided that the above
35
 * copyright notice and this permission notice appear in all copies, and that
36
 * the name of Digital Equipment Corporation not be used in advertising or
37
 * publicity pertaining to distribution of the document or software without
38
 * specific, written prior permission.
39
 *
40
 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
41
 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
42
 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
43
 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
44
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47
 * SOFTWARE.
48
 */
49
 
50
/*
51
 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
52
 *
53
 * Permission to use, copy, modify, and distribute this software for any
54
 * purpose with or without fee is hereby granted, provided that the above
55
 * copyright notice and this permission notice appear in all copies.
56
 *
57
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
58
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
59
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
60
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
61
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
62
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
63
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
64
 * SOFTWARE.
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 /* LIBC_SCCS and not lint */
71
 
72
#define s6_addr32 __u6_addr.__u6_addr32
73
/*
74
 * Send query to name server and wait for reply.
75
 */
76
 
77
#include <assert.h>
78
#include <sys/types.h>
79
#include <sys/param.h>
80
#include <sys/time.h>
81
#include <sys/socket.h>
82
#include <sys/uio.h>
83
#include <sys/poll.h>
84
 
85
#include <netinet/in.h>
86
#include <arpa/nameser.h>
87
#include <arpa/inet.h>
88
#include <sys/ioctl.h>
89
 
90
#include <errno.h>
91
#include <fcntl.h>
92
#include <netdb.h>
93
#include <resolv.h>
94
#include <signal.h>
95
#include <stdio.h>
96
#include <stdlib.h>
97
#include <string.h>
98
#include <unistd.h>
99
#include "libc-symbols.h"
100
 
101
#if PACKETSZ > 65536
102
#define MAXPACKET       PACKETSZ
103
#else
104
#define MAXPACKET       65536
105
#endif
106
 
107
 
108
/* From ev_streams.c.  */
109
 
110
static inline void
111
__attribute ((always_inline))
112
evConsIovec(void *buf, size_t cnt, struct iovec *vec) {
113
        memset(vec, 0xf5, sizeof (*vec));
114
        vec->iov_base = buf;
115
        vec->iov_len = cnt;
116
}
117
 
118
/* From ev_timers.c.  */
119
 
120
#define BILLION 1000000000
121
 
122
static inline void
123
evConsTime(struct timespec *res, time_t sec, long nsec) {
124
        res->tv_sec = sec;
125
        res->tv_nsec = nsec;
126
}
127
 
128
static inline void
129
evAddTime(struct timespec *res, const struct timespec *addend1,
130
          const struct timespec *addend2) {
131
        res->tv_sec = addend1->tv_sec + addend2->tv_sec;
132
        res->tv_nsec = addend1->tv_nsec + addend2->tv_nsec;
133
        if (res->tv_nsec >= BILLION) {
134
                res->tv_sec++;
135
                res->tv_nsec -= BILLION;
136
        }
137
}
138
 
139
static inline void
140
evSubTime(struct timespec *res, const struct timespec *minuend,
141
          const struct timespec *subtrahend) {
142
       res->tv_sec = minuend->tv_sec - subtrahend->tv_sec;
143
        if (minuend->tv_nsec >= subtrahend->tv_nsec)
144
                res->tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec;
145
        else {
146
                res->tv_nsec = (BILLION
147
                                - subtrahend->tv_nsec + minuend->tv_nsec);
148
                res->tv_sec--;
149
        }
150
}
151
 
152
static inline int
153
evCmpTime(struct timespec a, struct timespec b) {
154
        long x = a.tv_sec - b.tv_sec;
155
 
156
        if (x == 0L)
157
                x = a.tv_nsec - b.tv_nsec;
158
        return (x < 0L ? (-1) : x > 0L ? (1) : (0));
159
}
160
 
161
static inline void
162
evNowTime(struct timespec *res) {
163
        struct timeval now;
164
 
165
        if (gettimeofday(&now, NULL) < 0)
166
                evConsTime(res, 0, 0);
167
        else
168
                TIMEVAL_TO_TIMESPEC (&now, res);
169
}
170
 
171
 
172
/* Options.  Leave them on. */
173
/* #undef DEBUG */
174
#include "res_debug.h"
175
 
176
#define EXT(res) ((res)->_u._ext)
177
 
178
/* Forward. */
179
 
180
static int              send_vc(res_state, const u_char *, int,
181
                                u_char **, int *, int *, int, u_char **);
182
static int              send_dg(res_state, const u_char *, int,
183
                                u_char **, int *, int *, int,
184
                                int *, int *, u_char **);
185
#ifdef DEBUG
186
static void             Aerror(const res_state, FILE *, const char *, int,
187
                               const struct sockaddr *);
188
static void             Perror(const res_state, FILE *, const char *, int);
189
#endif
190
static int              sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *);
191
 
192
/* Reachover. */
193
 
194
static void convaddr4to6(struct sockaddr_in6 *sa);
195
void res_pquery(const res_state, const u_char *, int, FILE *);
196
 
197
/* Public. */
198
 
199
/* int
200
 * res_isourserver(ina)
201
 *      looks up "ina" in _res.ns_addr_list[]
202
 * returns:
203
 *      0  : not found
204
 *      >0 : found
205
 * author:
206
 *      paul vixie, 29may94
207
 */
208
int
209
res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
210
{
211
        int ns;
212
 
213
        if (inp->sin6_family == AF_INET) {
214
            struct sockaddr_in *in4p = (struct sockaddr_in *) inp;
215
            in_port_t port = in4p->sin_port;
216
            in_addr_t addr = in4p->sin_addr.s_addr;
217
 
218
            for (ns = 0;  ns < MAXNS;  ns++) {
219
                const struct sockaddr_in *srv =
220
                    (struct sockaddr_in *)EXT(statp).nsaddrs[ns];
221
 
222
                if ((srv != NULL) && (srv->sin_family == AF_INET) &&
223
                    (srv->sin_port == port) &&
224
                    (srv->sin_addr.s_addr == INADDR_ANY ||
225
                     srv->sin_addr.s_addr == addr))
226
                    return (1);
227
            }
228
        } else if (inp->sin6_family == AF_INET6) {
229
            for (ns = 0;  ns < MAXNS;  ns++) {
230
                const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns];
231
                if ((srv != NULL) && (srv->sin6_family == AF_INET6) &&
232
                    (srv->sin6_port == inp->sin6_port) &&
233
                    !(memcmp(&srv->sin6_addr, &in6addr_any,
234
                             sizeof (struct in6_addr)) &&
235
                      memcmp(&srv->sin6_addr, &inp->sin6_addr,
236
                             sizeof (struct in6_addr))))
237
                    return (1);
238
            }
239
        }
240
        return (0);
241
}
242
 
243
/* int
244
 * res_nameinquery(name, type, class, buf, eom)
245
 *      look for (name,type,class) in the query section of packet (buf,eom)
246
 * requires:
247
 *      buf + HFIXEDSZ <= eom
248
 * returns:
249
 *      -1 : format error
250
 *      0  : not found
251
 *      >0 : found
252
 * author:
253
 *      paul vixie, 29may94
254
 */
255
int
256
res_nameinquery(const char *name, int type, int class,
257
                const u_char *buf, const u_char *eom)
258
{
259
        const u_char *cp = buf + HFIXEDSZ;
260
        int qdcount = ntohs(((HEADER*)buf)->qdcount);
261
 
262
        while (qdcount-- > 0) {
263
                char tname[MAXDNAME+1];
264
                int n, ttype, tclass;
265
 
266
                n = dn_expand(buf, eom, cp, tname, sizeof tname);
267
                if (n < 0)
268
                        return (-1);
269
                cp += n;
270
                if (cp + 2 * INT16SZ > eom)
271
                        return (-1);
272
                ttype = ns_get16(cp); cp += INT16SZ;
273
                tclass = ns_get16(cp); cp += INT16SZ;
274
                if (ttype == type && tclass == class &&
275
                    ns_samename(tname, name) == 1)
276
                        return (1);
277
        }
278
        return (0);
279
}
280
libresolv_hidden_def (res_nameinquery)
281
 
282
/* int
283
 * res_queriesmatch(buf1, eom1, buf2, eom2)
284
 *      is there a 1:1 mapping of (name,type,class)
285
 *      in (buf1,eom1) and (buf2,eom2)?
286
 * returns:
287
 *      -1 : format error
288
 *      0  : not a 1:1 mapping
289
 *      >0 : is a 1:1 mapping
290
 * author:
291
 *      paul vixie, 29may94
292
 */
293
int
294
res_queriesmatch(const u_char *buf1, const u_char *eom1,
295
                 const u_char *buf2, const u_char *eom2)
296
{
297
        const u_char *cp = buf1 + HFIXEDSZ;
298
        int qdcount = ntohs(((HEADER*)buf1)->qdcount);
299
 
300
        if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
301
                return (-1);
302
 
303
        /*
304
         * Only header section present in replies to
305
         * dynamic update packets.
306
         */
307
        if ((((HEADER *)buf1)->opcode == ns_o_update) &&
308
            (((HEADER *)buf2)->opcode == ns_o_update))
309
                return (1);
310
 
311
        if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
312
                return (0);
313
        while (qdcount-- > 0) {
314
                char tname[MAXDNAME+1];
315
                int n, ttype, tclass;
316
 
317
                n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
318
                if (n < 0)
319
                        return (-1);
320
                cp += n;
321
                if (cp + 2 * INT16SZ > eom1)
322
                        return (-1);
323
                ttype = ns_get16(cp);   cp += INT16SZ;
324
                tclass = ns_get16(cp); cp += INT16SZ;
325
                if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
326
                        return (0);
327
        }
328
        return (1);
329
}
330
libresolv_hidden_def (res_queriesmatch)
331
 
332
int
333
__libc_res_nsend(res_state statp, const u_char *buf, int buflen,
334
                 u_char *ans, int anssiz, u_char **ansp)
335
{
336
        int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
337
 
338
        if (statp->nscount == 0) {
339
                __set_errno (ESRCH);
340
                return (-1);
341
        }
342
 
343
        if (anssiz < HFIXEDSZ) {
344
                __set_errno (EINVAL);
345
                return (-1);
346
        }
347
 
348
        if ((statp->qhook || statp->rhook) && anssiz < MAXPACKET && ansp) {
349
                u_char *buf = malloc (MAXPACKET);
350
                if (buf == NULL)
351
                        return (-1);
352
                memcpy (buf, ans, HFIXEDSZ);
353
                *ansp = buf;
354
                ans = buf;
355
                anssiz = MAXPACKET;
356
        }
357
 
358
        DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
359
                (stdout, ";; res_send()\n"), buf, buflen);
360
        v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
361
        gotsomewhere = 0;
362
        terrno = ETIMEDOUT;
363
 
364
        /*
365
         * If the ns_addr_list in the resolver context has changed, then
366
         * invalidate our cached copy and the associated timing data.
367
         */
368
        if (EXT(statp).nsinit) {
369
                int needclose = 0;
370
 
371
                if (EXT(statp).nscount != statp->nscount)
372
                        needclose++;
373
                else
374
                        for (ns = 0; ns < MAXNS; ns++) {
375
                                unsigned int map = EXT(statp).nsmap[ns];
376
                                if (map < MAXNS
377
                                    && !sock_eq((struct sockaddr_in6 *)
378
                                                &statp->nsaddr_list[map],
379
                                                EXT(statp).nsaddrs[ns]))
380
                                {
381
                                        needclose++;
382
                                        break;
383
                                }
384
                        }
385
                if (needclose)
386
                        res_nclose(statp);
387
        }
388
 
389
        /*
390
         * Maybe initialize our private copy of the ns_addr_list.
391
         */
392
        if (EXT(statp).nsinit == 0) {
393
                unsigned char map[MAXNS];
394
 
395
                memset (map, MAXNS, sizeof (map));
396
                for (n = 0; n < MAXNS; n++) {
397
                        ns = EXT(statp).nsmap[n];
398
                        if (ns < statp->nscount)
399
                                map[ns] = n;
400
                        else if (ns < MAXNS) {
401
                                free(EXT(statp).nsaddrs[n]);
402
                                EXT(statp).nsaddrs[n] = NULL;
403
                                EXT(statp).nsmap[n] = MAXNS;
404
                        }
405
                }
406
                n = statp->nscount;
407
                if (statp->nscount > EXT(statp).nscount)
408
                        for (n = EXT(statp).nscount, ns = 0;
409
                             n < statp->nscount; n++) {
410
                                while (ns < MAXNS
411
                                       && EXT(statp).nsmap[ns] != MAXNS)
412
                                        ns++;
413
                                if (ns == MAXNS)
414
                                        break;
415
                                EXT(statp).nsmap[ns] = n;
416
                                map[n] = ns++;
417
                        }
418
                EXT(statp).nscount = n;
419
                for (ns = 0; ns < EXT(statp).nscount; ns++) {
420
                        n = map[ns];
421
                        if (EXT(statp).nsaddrs[n] == NULL)
422
                                EXT(statp).nsaddrs[n] =
423
                                    malloc(sizeof (struct sockaddr_in6));
424
                        if (EXT(statp).nsaddrs[n] != NULL) {
425
                                memcpy(EXT(statp).nsaddrs[n],
426
                                       &statp->nsaddr_list[ns],
427
                                       sizeof (struct sockaddr_in));
428
                                EXT(statp).nssocks[n] = -1;
429
                                n++;
430
                        }
431
                }
432
                EXT(statp).nsinit = 1;
433
        }
434
 
435
        /*
436
         * Some resolvers want to even out the load on their nameservers.
437
         * Note that RES_BLAST overrides RES_ROTATE.
438
         */
439
        if ((statp->options & RES_ROTATE) != 0 &&
440
            (statp->options & RES_BLAST) == 0) {
441
                struct sockaddr_in6 *ina;
442
                unsigned int map;
443
 
444
                n = 0;
445
                while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS)
446
                        n++;
447
                if (n < MAXNS) {
448
                        ina = EXT(statp).nsaddrs[n];
449
                        map = EXT(statp).nsmap[n];
450
                        for (;;) {
451
                                ns = n + 1;
452
                                while (ns < MAXNS
453
                                       && EXT(statp).nsmap[ns] == MAXNS)
454
                                        ns++;
455
                                if (ns == MAXNS)
456
                                        break;
457
                                EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns];
458
                                EXT(statp).nsmap[n] = EXT(statp).nsmap[ns];
459
                                n = ns;
460
                        }
461
                        EXT(statp).nsaddrs[n] = ina;
462
                        EXT(statp).nsmap[n] = map;
463
                }
464
        }
465
 
466
        /*
467
         * Send request, RETRY times, or until successful.
468
         */
469
        for (try = 0; try < statp->retry; try++) {
470
            for (ns = 0; ns < MAXNS; ns++)
471
            {
472
                struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
473
 
474
                if (nsap == NULL)
475
                        goto next_ns;
476
 same_ns:
477
                if (statp->qhook) {
478
                        int done = 0, loops = 0;
479
 
480
                        do {
481
                                res_sendhookact act;
482
 
483
                                struct sockaddr_in *nsap4;
484
                                nsap4 = (struct sockaddr_in *) nsap;
485
                                act = (*statp->qhook)(&nsap4, &buf, &buflen,
486
                                                      ans, anssiz, &resplen);
487
                                nsap = (struct sockaddr_in6 *) nsap4;
488
                                switch (act) {
489
                                case res_goahead:
490
                                        done = 1;
491
                                        break;
492
                                case res_nextns:
493
                                        res_nclose(statp);
494
                                        goto next_ns;
495
                                case res_done:
496
                                        return (resplen);
497
                                case res_modified:
498
                                        /* give the hook another try */
499
                                        if (++loops < 42) /*doug adams*/
500
                                                break;
501
                                        /*FALLTHROUGH*/
502
                                case res_error:
503
                                        /*FALLTHROUGH*/
504
                                default:
505
                                        return (-1);
506
                                }
507
                        } while (!done);
508
                }
509
 
510
#ifdef DEBUG
511
                char tmpbuf[40];
512
#endif
513
                Dprint(statp->options & RES_DEBUG,
514
                       (stdout, ";; Querying server (# %d) address = %s\n",
515
                        ns + 1, inet_ntop(AF_INET6, &nsap->sin6_addr,
516
                                          tmpbuf, sizeof (tmpbuf))));
517
 
518
                if (v_circuit) {
519
                        /* Use VC; at most one attempt per server. */
520
                        try = statp->retry;
521
                        n = send_vc(statp, buf, buflen, &ans, &anssiz, &terrno,
522
                                    ns, ansp);
523
                        if (n < 0)
524
                                return (-1);
525
                        if (n == 0)
526
                                goto next_ns;
527
                        resplen = n;
528
                } else {
529
                        /* Use datagrams. */
530
                        n = send_dg(statp, buf, buflen, &ans, &anssiz, &terrno,
531
                                    ns, &v_circuit, &gotsomewhere, ansp);
532
                        if (n < 0)
533
                                return (-1);
534
                        if (n == 0)
535
                                goto next_ns;
536
                        if (v_circuit)
537
                                goto same_ns;
538
                        resplen = n;
539
                }
540
 
541
                Dprint((statp->options & RES_DEBUG) ||
542
                       ((statp->pfcode & RES_PRF_REPLY) &&
543
                        (statp->pfcode & RES_PRF_HEAD1)),
544
                       (stdout, ";; got answer:\n"));
545
 
546
                DprintQ((statp->options & RES_DEBUG) ||
547
                        (statp->pfcode & RES_PRF_REPLY),
548
                        (stdout, "%s", ""),
549
                        ans, (resplen > anssiz) ? anssiz : resplen);
550
 
551
                /*
552
                 * If we have temporarily opened a virtual circuit,
553
                 * or if we haven't been asked to keep a socket open,
554
                 * close the socket.
555
                 */
556
                if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
557
                    (statp->options & RES_STAYOPEN) == 0) {
558
                        res_nclose(statp);
559
                }
560
                if (statp->rhook) {
561
                        int done = 0, loops = 0;
562
 
563
                        do {
564
                                res_sendhookact act;
565
 
566
                                act = (*statp->rhook)((struct sockaddr_in *)
567
                                                      nsap, buf, buflen,
568
                                                      ans, anssiz, &resplen);
569
                                switch (act) {
570
                                case res_goahead:
571
                                case res_done:
572
                                        done = 1;
573
                                        break;
574
                                case res_nextns:
575
                                        res_nclose(statp);
576
                                        goto next_ns;
577
                                case res_modified:
578
                                        /* give the hook another try */
579
                                        if (++loops < 42) /*doug adams*/
580
                                                break;
581
                                        /*FALLTHROUGH*/
582
                                case res_error:
583
                                        /*FALLTHROUGH*/
584
                                default:
585
                                        return (-1);
586
                                }
587
                        } while (!done);
588
 
589
                }
590
                return (resplen);
591
 next_ns: ;
592
           } /*foreach ns*/
593
        } /*foreach retry*/
594
        res_nclose(statp);
595
        if (!v_circuit) {
596
                if (!gotsomewhere)
597
                        __set_errno (ECONNREFUSED);     /* no nameservers found */
598
                else
599
                        __set_errno (ETIMEDOUT);        /* no answer obtained */
600
        } else
601
                __set_errno (terrno);
602
        return (-1);
603
}
604
 
605
int
606
res_nsend(res_state statp,
607
          const u_char *buf, int buflen, u_char *ans, int anssiz)
608
{
609
        return __libc_res_nsend(statp, buf, buflen, ans, anssiz, NULL);
610
}
611
libresolv_hidden_def (res_nsend)
612
 
613
/* Private */
614
 
615
static int
616
send_vc(res_state statp,
617
        const u_char *buf, int buflen, u_char **ansp, int *anssizp,
618
        int *terrno, int ns, u_char **anscp)
619
{
620
        const HEADER *hp = (HEADER *) buf;
621
        u_char *ans = *ansp;
622
        int anssiz = *anssizp;
623
        HEADER *anhp = (HEADER *) ans;
624
        struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
625
        int truncating, connreset, resplen, n;
626
        struct iovec iov[2];
627
        u_short len;
628
        u_char *cp;
629
 
630
        connreset = 0;
631
 same_ns:
632
        truncating = 0;
633
 
634
        /* Are we still talking to whom we want to talk to? */
635
        if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
636
                struct sockaddr_in6 peer;
637
                int size = sizeof peer;
638
 
639
                if (getpeername(statp->_vcsock,
640
                                (struct sockaddr *)&peer, &size) < 0 ||
641
                    !sock_eq(&peer, nsap)) {
642
                        res_nclose(statp);
643
                        statp->_flags &= ~RES_F_VC;
644
                }
645
        }
646
 
647
        if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
648
                if (statp->_vcsock >= 0)
649
                        res_nclose(statp);
650
 
651
                statp->_vcsock = socket(nsap->sin6_family, SOCK_STREAM, 0);
652
                if (statp->_vcsock < 0) {
653
                        *terrno = errno;
654
                        Perror(statp, stderr, "socket(vc)", errno);
655
                        return (-1);
656
                }
657
                __set_errno (0);
658
                if (connect(statp->_vcsock, (struct sockaddr *)nsap,
659
                            sizeof *nsap) < 0) {
660
                        *terrno = errno;
661
                        Aerror(statp, stderr, "connect/vc", errno,
662
                               (struct sockaddr *) nsap);
663
                        res_nclose(statp);
664
                        return (0);
665
                }
666
                statp->_flags |= RES_F_VC;
667
        }
668
 
669
        /*
670
         * Send length & message
671
         */
672
        putshort((u_short)buflen, (u_char*)&len);
673
        evConsIovec(&len, INT16SZ, &iov[0]);
674
        evConsIovec((void*)buf, buflen, &iov[1]);
675
        if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, 2))
676
            != (INT16SZ + buflen)) {
677
                *terrno = errno;
678
                Perror(statp, stderr, "write failed", errno);
679
                res_nclose(statp);
680
                return (0);
681
        }
682
        /*
683
         * Receive length & response
684
         */
685
 read_len:
686
        cp = ans;
687
        len = INT16SZ;
688
        while ((n = TEMP_FAILURE_RETRY (read(statp->_vcsock, (char *)cp,
689
                                             (int)len))) > 0) {
690
                cp += n;
691
                if ((len -= n) <= 0)
692
                        break;
693
        }
694
        if (n <= 0) {
695
                *terrno = errno;
696
                Perror(statp, stderr, "read failed", errno);
697
                res_nclose(statp);
698
                /*
699
                 * A long running process might get its TCP
700
                 * connection reset if the remote server was
701
                 * restarted.  Requery the server instead of
702
                 * trying a new one.  When there is only one
703
                 * server, this means that a query might work
704
                 * instead of failing.  We only allow one reset
705
                 * per query to prevent looping.
706
                 */
707
                if (*terrno == ECONNRESET && !connreset) {
708
                        connreset = 1;
709
                        res_nclose(statp);
710
                        goto same_ns;
711
                }
712
                res_nclose(statp);
713
                return (0);
714
        }
715
        resplen = ns_get16(ans);
716
        if (resplen > anssiz) {
717
                if (anscp) {
718
                        ans = malloc (MAXPACKET);
719
                        if (ans == NULL) {
720
                                *terrno = ENOMEM;
721
                                res_nclose(statp);
722
                                return (0);
723
                        }
724
                        anssiz = MAXPACKET;
725
                        *anssizp = MAXPACKET;
726
                        *ansp = ans;
727
                        *anscp = ans;
728
                        anhp = (HEADER *) ans;
729
                        len = resplen;
730
                } else {
731
                        Dprint(statp->options & RES_DEBUG,
732
                                (stdout, ";; response truncated\n")
733
                        );
734
                        truncating = 1;
735
                        len = anssiz;
736
                }
737
        } else
738
                len = resplen;
739
        if (len < HFIXEDSZ) {
740
                /*
741
                 * Undersized message.
742
                 */
743
                Dprint(statp->options & RES_DEBUG,
744
                       (stdout, ";; undersized: %d\n", len));
745
                *terrno = EMSGSIZE;
746
                res_nclose(statp);
747
                return (0);
748
        }
749
        cp = ans;
750
        while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){
751
                cp += n;
752
                len -= n;
753
        }
754
        if (n <= 0) {
755
                *terrno = errno;
756
                Perror(statp, stderr, "read(vc)", errno);
757
                res_nclose(statp);
758
                return (0);
759
        }
760
        if (truncating) {
761
                /*
762
                 * Flush rest of answer so connection stays in synch.
763
                 */
764
                anhp->tc = 1;
765
                len = resplen - anssiz;
766
                while (len != 0) {
767
                        char junk[PACKETSZ];
768
 
769
                        n = read(statp->_vcsock, junk,
770
                                 (len > sizeof junk) ? sizeof junk : len);
771
                        if (n > 0)
772
                                len -= n;
773
                        else
774
                                break;
775
                }
776
        }
777
        /*
778
         * If the calling applicating has bailed out of
779
         * a previous call and failed to arrange to have
780
         * the circuit closed or the server has got
781
         * itself confused, then drop the packet and
782
         * wait for the correct one.
783
         */
784
        if (hp->id != anhp->id) {
785
                DprintQ((statp->options & RES_DEBUG) ||
786
                        (statp->pfcode & RES_PRF_REPLY),
787
                        (stdout, ";; old answer (unexpected):\n"),
788
                        ans, (resplen > anssiz) ? anssiz: resplen);
789
                goto read_len;
790
        }
791
 
792
        /*
793
         * All is well, or the error is fatal.  Signal that the
794
         * next nameserver ought not be tried.
795
         */
796
        return (resplen);
797
}
798
 
799
static int
800
send_dg(res_state statp,
801
        const u_char *buf, int buflen, u_char **ansp, int *anssizp,
802
        int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp)
803
{
804
        const HEADER *hp = (HEADER *) buf;
805
        u_char *ans = *ansp;
806
        int anssiz = *anssizp;
807
        HEADER *anhp = (HEADER *) ans;
808
        struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
809
        struct timespec now, timeout, finish;
810
        struct pollfd pfd[1];
811
        int ptimeout;
812
        struct sockaddr_in6 from;
813
        static int socket_pf = 0;
814
        int fromlen, resplen, seconds, n;
815
 
816
        if (EXT(statp).nssocks[ns] == -1) {
817
                /* only try IPv6 if IPv6 NS and if not failed before */
818
                if ((EXT(statp).nscount6 > 0) && (socket_pf != PF_INET)) {
819
                        EXT(statp).nssocks[ns] =
820
                            socket(PF_INET6, SOCK_DGRAM, 0);
821
                        socket_pf = EXT(statp).nssocks[ns] < 0 ? PF_INET
822
                                                               : PF_INET6;
823
                }
824
                if (EXT(statp).nssocks[ns] < 0)
825
                        EXT(statp).nssocks[ns] = socket(PF_INET, SOCK_DGRAM, 0);
826
                if (EXT(statp).nssocks[ns] < 0) {
827
                        *terrno = errno;
828
                        Perror(statp, stderr, "socket(dg)", errno);
829
                        return (-1);
830
                }
831
                /* If IPv6 socket and nsap is IPv4, make it IPv4-mapped */
832
                if ((socket_pf == PF_INET6) && (nsap->sin6_family == AF_INET))
833
                        convaddr4to6(nsap);
834
                /*
835
                 * On a 4.3BSD+ machine (client and server,
836
                 * actually), sending to a nameserver datagram
837
                 * port with no nameserver will cause an
838
                 * ICMP port unreachable message to be returned.
839
                 * If our datagram socket is "connected" to the
840
                 * server, we get an ECONNREFUSED error on the next
841
                 * socket operation, and select returns if the
842
                 * error message is received.  We can thus detect
843
                 * the absence of a nameserver without timing out.
844
                 */
845
                if (connect(EXT(statp).nssocks[ns], (struct sockaddr *)nsap,
846
                            sizeof *nsap) < 0) {
847
                        Aerror(statp, stderr, "connect(dg)", errno,
848
                               (struct sockaddr *) nsap);
849
                        res_nclose(statp);
850
                        return (0);
851
                }
852
                /* Make socket non-blocking.  */
853
                int fl = fcntl (EXT(statp).nssocks[ns], F_GETFL);
854
                if  (fl != -1)
855
                        fcntl (EXT(statp).nssocks[ns], F_SETFL,
856
                                 fl | O_NONBLOCK);
857
                Dprint(statp->options & RES_DEBUG,
858
                       (stdout, ";; new DG socket\n"))
859
        }
860
 
861
        /*
862
         * Compute time for the total operation.
863
         */
864
        seconds = (statp->retrans << ns);
865
        if (ns > 0)
866
                seconds /= statp->nscount;
867
        if (seconds <= 0)
868
                seconds = 1;
869
        evNowTime(&now);
870
        evConsTime(&timeout, seconds, 0);
871
        evAddTime(&finish, &now, &timeout);
872
        int need_recompute = 0;
873
        int nwritten = 0;
874
        pfd[0].fd = EXT(statp).nssocks[ns];
875
        pfd[0].events = POLLOUT;
876
 wait:
877
        if (need_recompute) {
878
                evNowTime(&now);
879
                if (evCmpTime(finish, now) <= 0) {
880
                        Perror(statp, stderr, "select", errno);
881
                        res_nclose(statp);
882
                        return (0);
883
                }
884
                evSubTime(&timeout, &finish, &now);
885
        }
886
        /* Convert struct timespec in milliseconds.  */
887
        ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000;
888
 
889
        n = 0;
890
        if (nwritten == 0)
891
          n = poll (pfd, 1, 0);
892
        if (__builtin_expect (n == 0, 0)) {
893
                n = poll (pfd, 1, ptimeout);
894
                need_recompute = 1;
895
        }
896
        if (n == 0) {
897
                Dprint(statp->options & RES_DEBUG, (stdout,
898
                                                    ";; timeout sending\n"));
899
                *gotsomewhere = 1;
900
                return (0);
901
        }
902
        if (n < 0) {
903
                if (errno == EINTR) {
904
                recompute_resend:
905
                        evNowTime(&now);
906
                        if (evCmpTime(finish, now) > 0) {
907
                                evSubTime(&timeout, &finish, &now);
908
                                goto wait;
909
                        }
910
                }
911
                Perror(statp, stderr, "poll", errno);
912
                res_nclose(statp);
913
                return (0);
914
        }
915
        __set_errno (0);
916
        if (pfd[0].revents & POLLOUT) {
917
                if (send(pfd[0].fd, (char*)buf, buflen, 0) != buflen) {
918
                        if (errno == EINTR || errno == EAGAIN)
919
                                goto recompute_resend;
920
                        Perror(statp, stderr, "send", errno);
921
                        res_nclose(statp);
922
                        return (0);
923
                }
924
                pfd[0].events = POLLIN;
925
                ++nwritten;
926
                goto wait;
927
        } else if (pfd[0].revents & POLLIN) {
928
                fromlen = sizeof(struct sockaddr_in6);
929
                if (anssiz < MAXPACKET
930
                    && anscp
931
                    && (ioctl (pfd[0].fd, FIONREAD, &resplen) < 0
932
                || anssiz < resplen)) {
933
                        ans = malloc (MAXPACKET);
934
                        if (ans == NULL)
935
                                ans = *ansp;
936
                        else {
937
                                anssiz = MAXPACKET;
938
                                *anssizp = MAXPACKET;
939
                                *ansp = ans;
940
                                *anscp = ans;
941
                                anhp = (HEADER *) ans;
942
                        }
943
                }
944
                resplen = recvfrom(pfd[0].fd, (char*)ans, anssiz,0,
945
                                   (struct sockaddr *)&from, &fromlen);
946
                if (resplen <= 0) {
947
                        if (errno == EINTR || errno == EAGAIN) {
948
                                need_recompute = 1;
949
                                goto wait;
950
                        }
951
                        Perror(statp, stderr, "recvfrom", errno);
952
                        res_nclose(statp);
953
                        return (0);
954
                }
955
                *gotsomewhere = 1;
956
                if (resplen < HFIXEDSZ) {
957
                        /*
958
                         * Undersized message.
959
                         */
960
                        Dprint(statp->options & RES_DEBUG,
961
                               (stdout, ";; undersized: %d\n",
962
                                resplen));
963
                        *terrno = EMSGSIZE;
964
                        res_nclose(statp);
965
                        return (0);
966
                }
967
                if (hp->id != anhp->id) {
968
                        /*
969
                         * response from old query, ignore it.
970
                         * XXX - potential security hazard could
971
                         *       be detected here.
972
                         */
973
                        DprintQ((statp->options & RES_DEBUG) ||
974
                                (statp->pfcode & RES_PRF_REPLY),
975
                                (stdout, ";; old answer:\n"),
976
                                ans, (resplen > anssiz) ? anssiz : resplen);
977
                        goto wait;
978
                }
979
                if (!(statp->options & RES_INSECURE1) &&
980
                    !res_ourserver_p(statp, &from)) {
981
                        /*
982
                         * response from wrong server? ignore it.
983
                         * XXX - potential security hazard could
984
                         *       be detected here.
985
                         */
986
                        DprintQ((statp->options & RES_DEBUG) ||
987
                                (statp->pfcode & RES_PRF_REPLY),
988
                                (stdout, ";; not our server:\n"),
989
                                ans, (resplen > anssiz) ? anssiz : resplen);
990
                        goto wait;
991
                }
992
                if (!(statp->options & RES_INSECURE2) &&
993
                    !res_queriesmatch(buf, buf + buflen,
994
                                      ans, ans + anssiz)) {
995
                        /*
996
                         * response contains wrong query? ignore it.
997
                         * XXX - potential security hazard could
998
                         *       be detected here.
999
                         */
1000
                        DprintQ((statp->options & RES_DEBUG) ||
1001
                                (statp->pfcode & RES_PRF_REPLY),
1002
                                (stdout, ";; wrong query name:\n"),
1003
                                ans, (resplen > anssiz) ? anssiz : resplen);
1004
                        goto wait;
1005
                }
1006
                if (anhp->rcode == SERVFAIL ||
1007
                    anhp->rcode == NOTIMP ||
1008
                    anhp->rcode == REFUSED) {
1009
                        DprintQ(statp->options & RES_DEBUG,
1010
                                (stdout, "server rejected query:\n"),
1011
                                ans, (resplen > anssiz) ? anssiz : resplen);
1012
                        res_nclose(statp);
1013
                        /* don't retry if called from dig */
1014
                        if (!statp->pfcode)
1015
                                return (0);
1016
                }
1017
                if (!(statp->options & RES_IGNTC) && anhp->tc) {
1018
                        /*
1019
                         * To get the rest of answer,
1020
                         * use TCP with same server.
1021
                         */
1022
                        Dprint(statp->options & RES_DEBUG,
1023
                               (stdout, ";; truncated answer\n"));
1024
                        *v_circuit = 1;
1025
                        res_nclose(statp);
1026
                        return (1);
1027
                }
1028
                /*
1029
                 * All is well, or the error is fatal.  Signal that the
1030
                 * next nameserver ought not be tried.
1031
                 */
1032
                return (resplen);
1033
        } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
1034
                /* Something went wrong.  We can stop trying.  */
1035
                res_nclose(statp);
1036
                return (0);
1037
        }
1038
}
1039
 
1040
#ifdef DEBUG
1041
static void
1042
Aerror(const res_state statp, FILE *file, const char *string, int error,
1043
       const struct sockaddr *address)
1044
{
1045
        int save = errno;
1046
 
1047
        if ((statp->options & RES_DEBUG) != 0) {
1048
                char tmp[sizeof "xxxx.xxxx.xxxx.255.255.255.255"];
1049
 
1050
                fprintf(file, "res_send: %s ([%s].%u): %s\n",
1051
                        string,
1052
                        inet_ntop(address->sa_family, address->sa_data,
1053
                                  tmp, sizeof tmp),
1054
                        (address->sa_family == AF_INET
1055
                         ? ntohs(((struct sockaddr_in *) address)->sin_port)
1056
                         : address->sa_family == AF_INET6
1057
                         ? ntohs(((struct sockaddr_in6 *) address)->sin6_port)
1058
                         : 0),
1059
                        strerror(error));
1060
        }
1061
        __set_errno (save);
1062
}
1063
 
1064
static void
1065
Perror(const res_state statp, FILE *file, const char *string, int error) {
1066
        int save = errno;
1067
 
1068
        if ((statp->options & RES_DEBUG) != 0)
1069
                fprintf(file, "res_send: %s: %s\n",
1070
                        string, strerror(error));
1071
        __set_errno (save);
1072
}
1073
#endif
1074
 
1075
static int
1076
sock_eq(struct sockaddr_in6 *a1, struct sockaddr_in6 *a2) {
1077
        if (a1->sin6_family == a2->sin6_family) {
1078
                if (a1->sin6_family == AF_INET)
1079
                        return ((((struct sockaddr_in *)a1)->sin_port ==
1080
                                 ((struct sockaddr_in *)a2)->sin_port) &&
1081
                                (((struct sockaddr_in *)a1)->sin_addr.s_addr ==
1082
                                 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1083
                else
1084
                        return ((a1->sin6_port == a2->sin6_port) &&
1085
                                !memcmp(&a1->sin6_addr, &a2->sin6_addr,
1086
                                        sizeof (struct in6_addr)));
1087
        }
1088
        if (a1->sin6_family == AF_INET) {
1089
                struct sockaddr_in6 *sap = a1;
1090
                a1 = a2;
1091
                a2 = sap;
1092
        } /* assumes that AF_INET and AF_INET6 are the only possibilities */
1093
        return ((a1->sin6_port == ((struct sockaddr_in *)a2)->sin_port) &&
1094
                IN6_IS_ADDR_V4MAPPED(&a1->sin6_addr) &&
1095
                (a1->sin6_addr.s6_addr32[3] ==
1096
                 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1097
}
1098
 
1099
/*
1100
 * Converts IPv4 family, address and port to
1101
 * IPv6 family, IPv4-mapped IPv6 address and port.
1102
 */
1103
static void
1104
convaddr4to6(struct sockaddr_in6 *sa)
1105
{
1106
    struct sockaddr_in *sa4p = (struct sockaddr_in *) sa;
1107
    in_port_t port = sa4p->sin_port;
1108
    in_addr_t addr = sa4p->sin_addr.s_addr;
1109
 
1110
    sa->sin6_family = AF_INET6;
1111
    sa->sin6_port = port;
1112
    sa->sin6_addr.s6_addr32[0] = 0;
1113
    sa->sin6_addr.s6_addr32[1] = 0;
1114
    sa->sin6_addr.s6_addr32[2] = htonl(0xFFFF);
1115
    sa->sin6_addr.s6_addr32[3] = addr;
1116
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.