source: rtems/cpukit/libnetworking/libc/res_query.c @ 0e16fa45

5
Last change on this file since 0e16fa45 was cb68253, checked in by Sebastian Huber <sebastian.huber@…>, on 09/07/18 at 04:19:02

network: Use kernel/user space header files

Add and use <machine/rtems-bsd-kernel-space.h> and
<machine/rtems-bsd-user-space.h> similar to the libbsd to avoid command
line defines and defines scattered throught the code base.

Simplify cpukit/libnetworking/Makefile.am.

Update #3375.

  • Property mode set to 100644
File size: 11.8 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright (c) 1988, 1993
5 *    The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *      This product includes software developed by the University of
18 *      California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36/*
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 */
55
56/*
57 * Portions Copyright (c) 1996 by Internet Software Consortium.
58 *
59 * Permission to use, copy, modify, and distribute this software for any
60 * purpose with or without fee is hereby granted, provided that the above
61 * copyright notice and this permission notice appear in all copies.
62 *
63 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
64 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
65 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
66 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
67 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
68 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
69 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
70 * SOFTWARE.
71 */
72
73#if HAVE_CONFIG_H
74#include "config.h"
75#endif
76
77#include <sys/types.h>
78#include <sys/param.h>
79#include <netinet/in.h>
80#include <arpa/inet.h>
81#include <arpa/nameser.h>
82#include <ctype.h>
83#include <errno.h>
84#include <netdb.h>
85#include <resolv.h>
86#include <stdio.h>
87#include <stdlib.h>
88#include <string.h>
89#ifdef HAVE_STRINGS_H
90#include <strings.h>
91#endif
92
93#include "res_config.h"
94
95#if PACKETSZ > 1024
96#define MAXPACKET       PACKETSZ
97#else
98#define MAXPACKET       1024
99#endif
100
101/*
102 * Formulate a normal query, send, and await answer.
103 * Returned answer is placed in supplied buffer "answer".
104 * Perform preliminary check of answer, returning success only
105 * if no error is indicated and the answer count is nonzero.
106 * Return the size of the response on success, -1 on error.
107 * Error number is left in h_errno.
108 *
109 * Caller must parse answer and determine whether it answers the question.
110 */
111int
112res_query(
113        const char *name,       /* domain name */
114        int class, int type,    /* class and type of query */
115        u_char *answer,         /* buffer to put answer */
116        int anslen)             /* size of answer buffer */
117{
118        u_char buf[MAXPACKET];
119        HEADER *hp = (HEADER *) answer;
120        int n;
121
122        hp->rcode = NOERROR;    /* default */
123
124        if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
125                h_errno = NETDB_INTERNAL;
126                return (-1);
127        }
128#ifdef DEBUG
129        if (_res.options & RES_DEBUG)
130                printf(";; res_query(%s, %d, %d)\n", name, class, type);
131#endif
132
133        n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
134                        buf, sizeof(buf));
135        if (n <= 0) {
136#ifdef DEBUG
137                if (_res.options & RES_DEBUG)
138                        printf(";; res_query: mkquery failed\n");
139#endif
140                h_errno = NO_RECOVERY;
141                return (n);
142        }
143        n = res_send(buf, n, answer, anslen);
144        if (n < 0) {
145#ifdef DEBUG
146                if (_res.options & RES_DEBUG)
147                        printf(";; res_query: send error\n");
148#endif
149                h_errno = TRY_AGAIN;
150                return (n);
151        }
152
153        if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
154#ifdef DEBUG
155                if (_res.options & RES_DEBUG)
156                        printf(";; rcode = %d, ancount=%d\n", hp->rcode,
157                            ntohs(hp->ancount));
158#endif
159                switch (hp->rcode) {
160                case NXDOMAIN:
161                        h_errno = HOST_NOT_FOUND;
162                        break;
163                case SERVFAIL:
164                        h_errno = TRY_AGAIN;
165                        break;
166                case NOERROR:
167                        h_errno = NO_DATA;
168                        break;
169                case FORMERR:
170                case NOTIMP:
171                case REFUSED:
172                default:
173                        h_errno = NO_RECOVERY;
174                        break;
175                }
176                return (-1);
177        }
178        return (n);
179}
180
181/*
182 * Formulate a normal query, send, and retrieve answer in supplied buffer.
183 * Return the size of the response on success, -1 on error.
184 * If enabled, implement search rules until answer or unrecoverable failure
185 * is detected.  Error code, if any, is left in h_errno.
186 */
187int
188res_search(
189        const char *name,       /* domain name */
190        int class, int type,    /* class and type of query */
191        u_char *answer,         /* buffer to put answer */
192        int anslen)             /* size of answer */
193{
194        const char *cp, * const *domain;
195        HEADER *hp = (HEADER *) answer;
196        u_int dots;
197        int trailing_dot, ret, saved_herrno;
198        int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
199
200        if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
201                h_errno = NETDB_INTERNAL;
202                return (-1);
203        }
204        errno = 0;
205        h_errno = HOST_NOT_FOUND;       /* default, if we never query */
206        dots = 0;
207        for (cp = name; *cp; cp++)
208                dots += (*cp == '.');
209        trailing_dot = 0;
210        if (cp > name && *--cp == '.')
211                trailing_dot++;
212
213        /* If there aren't any dots, it could be a user-level alias */
214        if (!dots && (cp = hostalias(name)) != NULL)
215                return (res_query(cp, class, type, answer, anslen));
216
217        /*
218         * If there are dots in the name already, let's just give it a try
219         * 'as is'.  The threshold can be set with the "ndots" option.
220         */
221        saved_herrno = -1;
222        if (dots >= _res.ndots) {
223                ret = res_querydomain(name, NULL, class, type, answer, anslen);
224                if (ret > 0)
225                        return (ret);
226                saved_herrno = h_errno;
227                tried_as_is++;
228        }
229
230        /*
231         * We do at least one level of search if
232         *      - there is no dot and RES_DEFNAME is set, or
233         *      - there is at least one dot, there is no trailing dot,
234         *        and RES_DNSRCH is set.
235         */
236        if ((!dots && (_res.options & RES_DEFNAMES)) ||
237            (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
238                int done = 0;
239
240                for (domain = (const char * const *)_res.dnsrch;
241                     *domain && !done;
242                     domain++) {
243
244                        ret = res_querydomain(name, *domain, class, type,
245                                              answer, anslen);
246                        if (ret > 0)
247                                return (ret);
248
249                        /*
250                         * If no server present, give up.
251                         * If name isn't found in this domain,
252                         * keep trying higher domains in the search list
253                         * (if that's enabled).
254                         * On a NO_DATA error, keep trying, otherwise
255                         * a wildcard entry of another type could keep us
256                         * from finding this entry higher in the domain.
257                         * If we get some other error (negative answer or
258                         * server failure), then stop searching up,
259                         * but try the input name below in case it's
260                         * fully-qualified.
261                         */
262                        if (errno == ECONNREFUSED) {
263                                h_errno = TRY_AGAIN;
264                                return (-1);
265                        }
266
267                        switch (h_errno) {
268                        case NO_DATA:
269                                got_nodata++;
270                                /* FALLTHROUGH */
271                        case HOST_NOT_FOUND:
272                                /* keep trying */
273                                break;
274                        case TRY_AGAIN:
275                                if (hp->rcode == SERVFAIL) {
276                                        /* try next search element, if any */
277                                        got_servfail++;
278                                        break;
279                                }
280                                /* FALLTHROUGH */
281                        default:
282                                /* anything else implies that we're done */
283                                done++;
284                        }
285
286                        /* if we got here for some reason other than DNSRCH,
287                         * we only wanted one iteration of the loop, so stop.
288                         */
289                        if (!(_res.options & RES_DNSRCH))
290                                done++;
291                }
292        }
293
294        /*
295         * If we have not already tried the name "as is", do that now.
296         * note that we do this regardless of how many dots were in the
297         * name or whether it ends with a dot unless NOTLDQUERY is set.
298         */
299        if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) {
300                ret = res_querydomain(name, NULL, class, type, answer, anslen);
301                if (ret > 0)
302                        return (ret);
303        }
304
305        /* if we got here, we didn't satisfy the search.
306         * if we did an initial full query, return that query's h_errno
307         * (note that we wouldn't be here if that query had succeeded).
308         * else if we ever got a nodata, send that back as the reason.
309         * else send back meaningless h_errno, that being the one from
310         * the last DNSRCH we did.
311         */
312        if (saved_herrno != -1)
313                h_errno = saved_herrno;
314        else if (got_nodata)
315                h_errno = NO_DATA;
316        else if (got_servfail)
317                h_errno = TRY_AGAIN;
318        return (-1);
319}
320
321/*
322 * Perform a call on res_query on the concatenation of name and domain,
323 * removing a trailing dot from name if domain is NULL.
324 */
325int
326res_querydomain(
327        const char *name, const char *domain,
328        int class, int type,    /* class and type of query */
329        u_char *answer,         /* buffer to put answer */
330        int anslen)             /* size of answer */
331{
332        char nbuf[MAXDNAME];
333        const char *longname = nbuf;
334        int n, d;
335
336        if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
337                h_errno = NETDB_INTERNAL;
338                return (-1);
339        }
340#ifdef DEBUG
341        if (_res.options & RES_DEBUG)
342                printf(";; res_querydomain(%s, %s, %d, %d)\n",
343                       name, domain?domain:"<Nil>", class, type);
344#endif
345        if (domain == NULL) {
346                /*
347                 * Check for trailing '.';
348                 * copy without '.' if present.
349                 */
350                n = strlen(name);
351                if (n >= MAXDNAME) {
352                        h_errno = NO_RECOVERY;
353                        return (-1);
354                }
355                n--;
356                if (n >= 0 && name[n] == '.') {
357                        strncpy(nbuf, name, n);
358                        nbuf[n] = '\0';
359                } else
360                        longname = name;
361        } else {
362                n = strlen(name);
363                d = strlen(domain);
364                if (n + d + 1 >= MAXDNAME) {
365                        h_errno = NO_RECOVERY;
366                        return (-1);
367                }
368                sprintf(nbuf, "%s.%s", name, domain);
369        }
370        return (res_query(longname, class, type, answer, anslen));
371}
372
373const char *
374hostalias(const char *name)
375{
376        register char *cp1, *cp2;
377        FILE *fp;
378        char *file;
379        char buf[BUFSIZ];
380        static char abuf[MAXDNAME];
381
382        if (_res.options & RES_NOALIASES)
383                return (NULL);
384        if (issetugid())
385                return (NULL);
386        file = getenv("HOSTALIASES");
387        if (file == NULL || (fp = fopen(file, "r")) == NULL)
388                return (NULL);
389        setbuf(fp, NULL);
390        buf[sizeof(buf) - 1] = '\0';
391        while (fgets(buf, sizeof(buf), fp)) {
392                for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1)
393                        ;
394                if (!*cp1)
395                        break;
396                *cp1 = '\0';
397                if (!strcasecmp(buf, name)) {
398                        while (isspace((unsigned char)*++cp1))
399                                ;
400                        if (!*cp1)
401                                break;
402                        for (cp2 = cp1 + 1; *cp2 && !isspace((unsigned char)*cp2); ++cp2)
403                                ;
404                        abuf[sizeof(abuf) - 1] = *cp2 = '\0';
405                        strncpy(abuf, cp1, sizeof(abuf) - 1);
406                        fclose(fp);
407                        return (abuf);
408                }
409        }
410        fclose(fp);
411        return (NULL);
412}
Note: See TracBrowser for help on using the repository browser.