2 * Copyright (c) 1985, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
31 * Permission to use, copy, modify, and distribute this software for any
32 * purpose with or without fee is hereby granted, provided that the above
33 * copyright notice and this permission notice appear in all copies, and that
34 * the name of Digital Equipment Corporation not be used in advertising or
35 * publicity pertaining to distribution of the document or software without
36 * specific, written prior permission.
38 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
39 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
40 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
41 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
42 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
43 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
44 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * @(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93
50 * $FreeBSD: src/lib/libc/net/getnetbydns.c,v 1.34 2007/01/09 00:28:02 imp Exp $
51 * $DragonFly: src/lib/libc/net/getnetbydns.c,v 1.5 2005/11/13 02:04:47 swildner Exp $
53 /* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
54 * Dep. Matematica Universidade de Coimbra, Portugal, Europe
56 * Permission to use, copy, modify, and distribute this software for any
57 * purpose with or without fee is hereby granted, provided that the above
58 * copyright notice and this permission notice appear in all copies.
61 #include <sys/param.h>
62 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65 #include <arpa/nameser.h>
79 #include "netdb_private.h"
80 #include "res_config.h"
85 #define MAXPACKET (64*1024)
89 u_char buf
[MAXPACKET
];
98 * Reverse the order of first four dotted entries of in.
99 * Out must contain space for at least strlen(in) characters.
100 * The result does not include any leading 0s of in.
103 ipreverse(char *in
, char *out
)
111 /* Fill-in element positions and lengths: pos[], len[]. */
114 if (*p
== '.' || *p
== '\0') {
116 if (leading
&& p
- start
== 1 && *start
== '0')
138 /* Copy the entries in reverse order */
141 for (i
= 3; i
>= 0; i
--) {
142 memcpy(p
, pos
[i
], len
[i
]);
146 /* Need a . separator? */
147 if (!leading
&& i
> 0 && len
[i
- 1])
154 getnetanswer(querybuf
*answer
, int anslen
, int net_i
, struct netent
*ne
,
155 struct netent_data
*ned
, res_state statp
)
162 int type
, class, ancount
, qdcount
, haveanswer
;
163 char aux
[MAXHOSTNAMELEN
];
164 char ans
[MAXHOSTNAMELEN
];
165 char *in
, *bp
, *ep
, **ap
;
168 * find first satisfactory answer
170 * answer --> +------------+ ( MESSAGE )
173 * | Question | the question for the name server
175 * | Answer | RRs answering the question
177 * | Authority | RRs pointing toward an authority
178 * | Additional | RRs holding additional information
181 eom
= answer
->buf
+ anslen
;
183 ancount
= ntohs(hp
->ancount
); /* #/records in the answer section */
184 qdcount
= ntohs(hp
->qdcount
); /* #/entries in the question section */
186 ep
= ned
->netbuf
+ sizeof(ned
->netbuf
);
187 cp
= answer
->buf
+ HFIXEDSZ
;
190 RES_SET_H_ERRNO(statp
, HOST_NOT_FOUND
);
192 RES_SET_H_ERRNO(statp
, TRY_AGAIN
);
195 while (qdcount
-- > 0)
196 cp
+= __dn_skipname(cp
, eom
) + QFIXEDSZ
;
197 ap
= ned
->net_aliases
;
199 ne
->n_aliases
= ned
->net_aliases
;
201 while (--ancount
>= 0 && cp
< eom
) {
202 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
203 if ((n
< 0) || !res_dnok(bp
))
207 strncpy(&ans
[0], bp
, sizeof(ans
) - 1);
208 ans
[sizeof(ans
) - 1] = '\0';
211 cp
+= INT32SZ
; /* TTL */
213 if (class == C_IN
&& type
== T_PTR
) {
214 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
215 if ((n
< 0) || !res_hnok(bp
)) {
223 ne
->n_addrtype
= (class == C_IN
) ? AF_INET
: AF_UNSPEC
;
231 ne
->n_name
= *ne
->n_aliases
;
238 RES_SET_H_ERRNO(statp
, NETDB_INTERNAL
);
242 strlcpy(bp
, ans
, ep
- bp
);
244 if (strlen(in
) + 1 > sizeof(aux
)) {
245 RES_SET_H_ERRNO(statp
, NETDB_INTERNAL
);
250 ne
->n_net
= inet_network(aux
);
256 RES_SET_H_ERRNO(statp
, TRY_AGAIN
);
261 _dns_getnetbyaddr(void *rval
, void *cb_data
, va_list ap
)
267 int *errnop
, *h_errnop
;
268 struct netent
*nptr
, ne
;
269 struct netent_data
*ned
;
270 unsigned int netbr
[4];
271 int nn
, anslen
, error
;
277 net
= va_arg(ap
, uint32_t);
278 net_type
= va_arg(ap
, int);
279 nptr
= va_arg(ap
, struct netent
*);
280 buffer
= va_arg(ap
, char *);
281 buflen
= va_arg(ap
, size_t);
282 errnop
= va_arg(ap
, int *);
283 h_errnop
= va_arg(ap
, int *);
285 statp
= __res_state();
286 if ((statp
->options
& RES_INIT
) == 0 && res_ninit(statp
) == -1) {
287 RES_SET_H_ERRNO(statp
, NETDB_INTERNAL
);
288 *h_errnop
= statp
->res_h_errno
;
292 if ((ned
= __netent_data_init()) == NULL
) {
293 RES_SET_H_ERRNO(statp
, NETDB_INTERNAL
);
294 *h_errnop
= statp
->res_h_errno
;
298 *((struct netent
**)rval
) = NULL
;
300 if (net_type
!= AF_INET
) {
301 RES_SET_H_ERRNO(statp
, NETDB_INTERNAL
);
302 *h_errnop
= statp
->res_h_errno
;
306 for (nn
= 4, net2
= net
; net2
; net2
>>= 8)
307 netbr
[--nn
] = net2
& 0xff;
309 case 3: /* Class A */
310 sprintf(qbuf
, "0.0.0.%u.in-addr.arpa", netbr
[3]);
312 case 2: /* Class B */
313 sprintf(qbuf
, "0.0.%u.%u.in-addr.arpa", netbr
[3], netbr
[2]);
315 case 1: /* Class C */
316 sprintf(qbuf
, "0.%u.%u.%u.in-addr.arpa", netbr
[3], netbr
[2],
319 case 0: /* Class D - E */
320 sprintf(qbuf
, "%u.%u.%u.%u.in-addr.arpa", netbr
[3], netbr
[2],
324 if ((buf
= malloc(sizeof(*buf
))) == NULL
) {
325 RES_SET_H_ERRNO(statp
, NETDB_INTERNAL
);
326 *h_errnop
= statp
->res_h_errno
;
327 return (NS_NOTFOUND
);
329 anslen
= res_nquery(statp
, qbuf
, C_IN
, T_PTR
, (u_char
*)buf
,
334 if (statp
->options
& RES_DEBUG
)
335 printf("res_nsearch failed\n");
337 *h_errnop
= statp
->res_h_errno
;
339 } else if (anslen
> sizeof(*buf
)) {
342 if (statp
->options
& RES_DEBUG
)
343 printf("res_nsearch static buffer too small\n");
345 *h_errnop
= statp
->res_h_errno
;
348 error
= getnetanswer(buf
, anslen
, BYADDR
, &ne
, ned
, statp
);
351 /* Strip trailing zeros */
352 while ((net
& 0xff) == 0 && net
!= 0)
355 if (__copy_netent(&ne
, nptr
, buffer
, buflen
) != 0) {
356 *h_errnop
= statp
->res_h_errno
;
357 return (NS_NOTFOUND
);
359 *((struct netent
**)rval
) = nptr
;
362 *h_errnop
= statp
->res_h_errno
;
363 return (NS_NOTFOUND
);
367 _dns_getnetbyname(void *rval
, void *cb_data
, va_list ap
)
372 int *errnop
, *h_errnop
;
373 struct netent
*nptr
, ne
;
374 struct netent_data
*ned
;
380 net
= va_arg(ap
, const char *);
381 nptr
= va_arg(ap
, struct netent
*);
382 buffer
= va_arg(ap
, char *);
383 buflen
= va_arg(ap
, size_t);
384 errnop
= va_arg(ap
, int *);
385 h_errnop
= va_arg(ap
, int *);
387 statp
= __res_state();
388 if ((statp
->options
& RES_INIT
) == 0 && res_ninit(statp
) == -1) {
389 RES_SET_H_ERRNO(statp
, NETDB_INTERNAL
);
390 *h_errnop
= statp
->res_h_errno
;
393 if ((ned
= __netent_data_init()) == NULL
) {
394 RES_SET_H_ERRNO(statp
, NETDB_INTERNAL
);
395 *h_errnop
= statp
->res_h_errno
;
398 if ((buf
= malloc(sizeof(*buf
))) == NULL
) {
399 RES_SET_H_ERRNO(statp
, NETDB_INTERNAL
);
400 *h_errnop
= statp
->res_h_errno
;
401 return (NS_NOTFOUND
);
404 *((struct netent
**)rval
) = NULL
;
406 strncpy(qbuf
, net
, sizeof(qbuf
) - 1);
407 qbuf
[sizeof(qbuf
) - 1] = '\0';
408 anslen
= res_nsearch(statp
, qbuf
, C_IN
, T_PTR
, (u_char
*)buf
,
413 if (statp
->options
& RES_DEBUG
)
414 printf("res_nsearch failed\n");
417 } else if (anslen
> sizeof(*buf
)) {
420 if (statp
->options
& RES_DEBUG
)
421 printf("res_search static buffer too small\n");
425 error
= getnetanswer(buf
, anslen
, BYNAME
, &ne
, ned
, statp
);
428 *h_errnop
= statp
->res_h_errno
;
429 return (NS_NOTFOUND
);
431 if (__copy_netent(&ne
, nptr
, buffer
, buflen
) != 0) {
432 *h_errnop
= statp
->res_h_errno
;
433 return (NS_NOTFOUND
);
435 *((struct netent
**)rval
) = nptr
;
440 _setnetdnsent(int stayopen
)
444 statp
= __res_state();
445 if ((statp
->options
& RES_INIT
) == 0 && res_ninit(statp
) == -1)
448 statp
->options
|= RES_STAYOPEN
| RES_USEVC
;
456 statp
= __res_state();
457 statp
->options
&= ~(RES_STAYOPEN
| RES_USEVC
);